[PATCH v3 7/9] hw/loongarch: Implement avec set irq

Song Gao posted 9 patches 4 months, 3 weeks ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Song Gao <gaosong@loongson.cn>, Bibo Mao <maobibo@loongson.cn>, Jiaxun Yang <jiaxun.yang@flygoat.com>
There is a newer version of this series
[PATCH v3 7/9] hw/loongarch: Implement avec set irq
Posted by Song Gao 4 months, 3 weeks ago
Implement avec set irq and update CSR_MSIS and CSR_MSGIR.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/intc/loongarch_avec.c | 44 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index c686ac9483..5959d05d13 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -16,6 +16,12 @@
 #include "migration/vmstate.h"
 #include "trace.h"
 #include "hw/qdev-properties.h"
+#include "target/loongarch/cpu.h"
+
+/* msg addr field */
+FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
+FIELD(MSG_ADDR, CPU_NUM, 12, 8)
+FIELD(MSG_ADDR, FIX, 28, 12)
 
 static uint64_t loongarch_avec_mem_read(void *opaque,
                                         hwaddr addr, unsigned size)
@@ -23,12 +29,46 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
     return 0;
 }
 
+static void avec_set_irq(LoongArchAVECState *s, int cpu_num, int irq_num, int level)
+{
+    MachineState *machine = MACHINE(qdev_get_machine());
+    MachineClass *mc = MACHINE_GET_CLASS(machine);
+    const CPUArchIdList *id_list = NULL;
+    CPUState *cpu;
+    CPULoongArchState *env;
+    int i;
+
+    assert(mc->possible_cpu_arch_ids(machine));
+    id_list = mc->possible_cpu_arch_ids(machine);
+    cpu = id_list->cpus[cpu_num].cpu;
+    env = &LOONGARCH_CPU(cpu)->env;
+
+    if (level) {
+        set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
+        env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, irq_num);
+        env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
+
+        for (i = 0; i < ARRAY_SIZE(env->CSR_MSGIS); i++) {
+            if (env->CSR_MSGIS[i]) {
+                return;
+            }
+        }
+        qemu_set_irq(s->cpu[cpu_num].parent_irq, 0);
+    }
+    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
+}
+
 static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
                                      uint64_t val, unsigned size)
 {
-    return;
-}
+    int irq_num, cpu_num = 0;
+    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
+    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
 
+    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
+    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
+    avec_set_irq(s, cpu_num, irq_num, 1);
+}
 
 static const MemoryRegionOps loongarch_avec_ops = {
     .read = loongarch_avec_mem_read,
-- 
2.34.1
Re: [PATCH v3 7/9] hw/loongarch: Implement avec set irq
Posted by Bibo Mao 4 months, 2 weeks ago

On 2025/6/27 上午11:01, Song Gao wrote:
> Implement avec set irq and update CSR_MSIS and CSR_MSGIR.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   hw/intc/loongarch_avec.c | 44 ++++++++++++++++++++++++++++++++++++++--
>   1 file changed, 42 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index c686ac9483..5959d05d13 100644
> --- a/hw/intc/loongarch_avec.c
> +++ b/hw/intc/loongarch_avec.c
> @@ -16,6 +16,12 @@
>   #include "migration/vmstate.h"
>   #include "trace.h"
>   #include "hw/qdev-properties.h"
> +#include "target/loongarch/cpu.h"
> +
> +/* msg addr field */
> +FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
> +FIELD(MSG_ADDR, CPU_NUM, 12, 8)
> +FIELD(MSG_ADDR, FIX, 28, 12)
>   
>   static uint64_t loongarch_avec_mem_read(void *opaque,
>                                           hwaddr addr, unsigned size)
> @@ -23,12 +29,46 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
>       return 0;
>   }
>   
> +static void avec_set_irq(LoongArchAVECState *s, int cpu_num, int irq_num, int level)
> +{
> +    MachineState *machine = MACHINE(qdev_get_machine());
> +    MachineClass *mc = MACHINE_GET_CLASS(machine);
> +    const CPUArchIdList *id_list = NULL;
> +    CPUState *cpu;
> +    CPULoongArchState *env;
> +    int i;
> +
> +    assert(mc->possible_cpu_arch_ids(machine));
> +    id_list = mc->possible_cpu_arch_ids(machine);
> +    cpu = id_list->cpus[cpu_num].cpu;
> +    env = &LOONGARCH_CPU(cpu)->env;
> +
> +    if (level) {
> +        set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
> +        env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, irq_num);
> +        env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
> +
> +        for (i = 0; i < ARRAY_SIZE(env->CSR_MSGIS); i++) {
> +            if (env->CSR_MSGIS[i]) {
> +                return;
> +            }
> +        }
> +        qemu_set_irq(s->cpu[cpu_num].parent_irq, 0);
Here such code can inject interrupt to cpu side.
   if (level) {
       set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
       qemu_set_irq(s->cpu[cpu_num].parent_irq, 1);
   }

Regards
Bibo Mao
> +    }
> +    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
> +}
> +
>   static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
>                                        uint64_t val, unsigned size)
>   {
> -    return;
> -}
> +    int irq_num, cpu_num = 0;
> +    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
> +    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
>   
> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> +    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
> +    avec_set_irq(s, cpu_num, irq_num, 1);
> +}
>   
>   static const MemoryRegionOps loongarch_avec_ops = {
>       .read = loongarch_avec_mem_read,
> 


Re: [PATCH v3 7/9] hw/loongarch: Implement avec set irq
Posted by gaosong 4 months, 2 weeks ago
在 2025/7/2 上午11:15, Bibo Mao 写道:
>
>
> On 2025/6/27 上午11:01, Song Gao wrote:
>> Implement avec set irq and update CSR_MSIS and CSR_MSGIR.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>>   hw/intc/loongarch_avec.c | 44 ++++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 42 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>> index c686ac9483..5959d05d13 100644
>> --- a/hw/intc/loongarch_avec.c
>> +++ b/hw/intc/loongarch_avec.c
>> @@ -16,6 +16,12 @@
>>   #include "migration/vmstate.h"
>>   #include "trace.h"
>>   #include "hw/qdev-properties.h"
>> +#include "target/loongarch/cpu.h"
>> +
>> +/* msg addr field */
>> +FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
>> +FIELD(MSG_ADDR, CPU_NUM, 12, 8)
>> +FIELD(MSG_ADDR, FIX, 28, 12)
>>     static uint64_t loongarch_avec_mem_read(void *opaque,
>>                                           hwaddr addr, unsigned size)
>> @@ -23,12 +29,46 @@ static uint64_t loongarch_avec_mem_read(void 
>> *opaque,
>>       return 0;
>>   }
>>   +static void avec_set_irq(LoongArchAVECState *s, int cpu_num, int 
>> irq_num, int level)
>> +{
>> +    MachineState *machine = MACHINE(qdev_get_machine());
>> +    MachineClass *mc = MACHINE_GET_CLASS(machine);
>> +    const CPUArchIdList *id_list = NULL;
>> +    CPUState *cpu;
>> +    CPULoongArchState *env;
>> +    int i;
>> +
>> +    assert(mc->possible_cpu_arch_ids(machine));
>> +    id_list = mc->possible_cpu_arch_ids(machine);
>> +    cpu = id_list->cpus[cpu_num].cpu;
>> +    env = &LOONGARCH_CPU(cpu)->env;
>> +
>> +    if (level) {
>> +        set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
>> +        env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, 
>> INTNUM, irq_num);
>> +        env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, 
>> ACTIVE, 0);
>> +
>> +        for (i = 0; i < ARRAY_SIZE(env->CSR_MSGIS); i++) {
>> +            if (env->CSR_MSGIS[i]) {
>> +                return;
>> +            }
>> +        }
>> +        qemu_set_irq(s->cpu[cpu_num].parent_irq, 0);
and thecheck CSR_MSGIS[4] is from v2 comment.
> Here such code can inject interrupt to cpu side.
>   if (level) {
>       set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
>       qemu_set_irq(s->cpu[cpu_num].parent_irq, 1);
>   }
>
but, we also need set CSRIR,  Otherwise, it will cause the kernel to 
faill into a deep loop on avec driver avecintc_irq_dispatch();

Thanks.
Song Gao.
> Regards
> Bibo Mao
>> +    }
>> +    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
>> +}
>> +
>>   static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
>>                                        uint64_t val, unsigned size)
>>   {
>> -    return;
>> -}
>> +    int irq_num, cpu_num = 0;
>> +    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
>> +    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
>>   +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>> +    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
>> +    avec_set_irq(s, cpu_num, irq_num, 1);
>> +}
>>     static const MemoryRegionOps loongarch_avec_ops = {
>>       .read = loongarch_avec_mem_read,
>>


Re: [PATCH v3 7/9] hw/loongarch: Implement avec set irq
Posted by Bibo Mao 4 months, 2 weeks ago

On 2025/7/2 下午3:21, gaosong wrote:
> 在 2025/7/2 上午11:15, Bibo Mao 写道:
>>
>>
>> On 2025/6/27 上午11:01, Song Gao wrote:
>>> Implement avec set irq and update CSR_MSIS and CSR_MSGIR.
>>>
>>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>>> ---
>>>   hw/intc/loongarch_avec.c | 44 ++++++++++++++++++++++++++++++++++++++--
>>>   1 file changed, 42 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>>> index c686ac9483..5959d05d13 100644
>>> --- a/hw/intc/loongarch_avec.c
>>> +++ b/hw/intc/loongarch_avec.c
>>> @@ -16,6 +16,12 @@
>>>   #include "migration/vmstate.h"
>>>   #include "trace.h"
>>>   #include "hw/qdev-properties.h"
>>> +#include "target/loongarch/cpu.h"
>>> +
>>> +/* msg addr field */
>>> +FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
>>> +FIELD(MSG_ADDR, CPU_NUM, 12, 8)
>>> +FIELD(MSG_ADDR, FIX, 28, 12)
>>>     static uint64_t loongarch_avec_mem_read(void *opaque,
>>>                                           hwaddr addr, unsigned size)
>>> @@ -23,12 +29,46 @@ static uint64_t loongarch_avec_mem_read(void 
>>> *opaque,
>>>       return 0;
>>>   }
>>>   +static void avec_set_irq(LoongArchAVECState *s, int cpu_num, int 
>>> irq_num, int level)
>>> +{
>>> +    MachineState *machine = MACHINE(qdev_get_machine());
>>> +    MachineClass *mc = MACHINE_GET_CLASS(machine);
>>> +    const CPUArchIdList *id_list = NULL;
>>> +    CPUState *cpu;
>>> +    CPULoongArchState *env;
>>> +    int i;
>>> +
>>> +    assert(mc->possible_cpu_arch_ids(machine));
>>> +    id_list = mc->possible_cpu_arch_ids(machine);
>>> +    cpu = id_list->cpus[cpu_num].cpu;
>>> +    env = &LOONGARCH_CPU(cpu)->env;
>>> +
>>> +    if (level) {
>>> +        set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
>>> +        env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, 
>>> INTNUM, irq_num);
>>> +        env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, 
>>> ACTIVE, 0);
>>> +
>>> +        for (i = 0; i < ARRAY_SIZE(env->CSR_MSGIS); i++) {
>>> +            if (env->CSR_MSGIS[i]) {
>>> +                return;
>>> +            }
>>> +        }
>>> +        qemu_set_irq(s->cpu[cpu_num].parent_irq, 0);
> and thecheck CSR_MSGIS[4] is from v2 comment.
>> Here such code can inject interrupt to cpu side.
>>   if (level) {
>>       set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
>>       qemu_set_irq(s->cpu[cpu_num].parent_irq, 1);
>>   }
>>
> but, we also need set CSRIR,  Otherwise, it will cause the kernel to 
> faill into a deep loop on avec driver avecintc_irq_dispatch();
It depends on the detailed implementation in patch 9, there is untested 
example code.

target_ulong helper_csrrd_msgir(CPULoongArchState *env)
{
     int irq, new;

     irq = find_first_bit(env->CSR_MSGIS, 256);
     if (irq < 256) {
       clear_bit(irq, env->CSR_MSGIS);

       new = find_first_bit(env->CSR_MSGIS, 256);
       if (new < 256)
           return irq;

       env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
       env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
     } else {
       /* bit 31 set 1 for no invalid irq */
       irq = -1;
     }

     return irq;
}

Regards
Bibo Mao
> 
> Thanks.
> Song Gao.
>> Regards
>> Bibo Mao
>>> +    }
>>> +    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
>>> +}
>>> +
>>>   static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
>>>                                        uint64_t val, unsigned size)
>>>   {
>>> -    return;
>>> -}
>>> +    int irq_num, cpu_num = 0;
>>> +    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
>>> +    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
>>>   +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>>> +    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
>>> +    avec_set_irq(s, cpu_num, irq_num, 1);
>>> +}
>>>     static const MemoryRegionOps loongarch_avec_ops = {
>>>       .read = loongarch_avec_mem_read,
>>>


Re: [PATCH v3 7/9] hw/loongarch: Implement avec set irq
Posted by gaosong 4 months, 2 weeks ago
在 2025/7/2 下午5:59, Bibo Mao 写道:
>
>
> On 2025/7/2 下午3:21, gaosong wrote:
>> 在 2025/7/2 上午11:15, Bibo Mao 写道:
>>>
>>>
>>> On 2025/6/27 上午11:01, Song Gao wrote:
>>>> Implement avec set irq and update CSR_MSIS and CSR_MSGIR.
>>>>
>>>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>>>> ---
>>>>   hw/intc/loongarch_avec.c | 44 
>>>> ++++++++++++++++++++++++++++++++++++++--
>>>>   1 file changed, 42 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>>>> index c686ac9483..5959d05d13 100644
>>>> --- a/hw/intc/loongarch_avec.c
>>>> +++ b/hw/intc/loongarch_avec.c
>>>> @@ -16,6 +16,12 @@
>>>>   #include "migration/vmstate.h"
>>>>   #include "trace.h"
>>>>   #include "hw/qdev-properties.h"
>>>> +#include "target/loongarch/cpu.h"
>>>> +
>>>> +/* msg addr field */
>>>> +FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
>>>> +FIELD(MSG_ADDR, CPU_NUM, 12, 8)
>>>> +FIELD(MSG_ADDR, FIX, 28, 12)
>>>>     static uint64_t loongarch_avec_mem_read(void *opaque,
>>>>                                           hwaddr addr, unsigned size)
>>>> @@ -23,12 +29,46 @@ static uint64_t loongarch_avec_mem_read(void 
>>>> *opaque,
>>>>       return 0;
>>>>   }
>>>>   +static void avec_set_irq(LoongArchAVECState *s, int cpu_num, int 
>>>> irq_num, int level)
>>>> +{
>>>> +    MachineState *machine = MACHINE(qdev_get_machine());
>>>> +    MachineClass *mc = MACHINE_GET_CLASS(machine);
>>>> +    const CPUArchIdList *id_list = NULL;
>>>> +    CPUState *cpu;
>>>> +    CPULoongArchState *env;
>>>> +    int i;
>>>> +
>>>> +    assert(mc->possible_cpu_arch_ids(machine));
>>>> +    id_list = mc->possible_cpu_arch_ids(machine);
>>>> +    cpu = id_list->cpus[cpu_num].cpu;
>>>> +    env = &LOONGARCH_CPU(cpu)->env;
>>>> +
>>>> +    if (level) {
>>>> +        set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
>>>> +        env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, 
>>>> INTNUM, irq_num);
>>>> +        env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, 
>>>> ACTIVE, 0);
>>>> +
>>>> +        for (i = 0; i < ARRAY_SIZE(env->CSR_MSGIS); i++) {
>>>> +            if (env->CSR_MSGIS[i]) {
>>>> +                return;
>>>> +            }
>>>> +        }
>>>> +        qemu_set_irq(s->cpu[cpu_num].parent_irq, 0);
>> and thecheck CSR_MSGIS[4] is from v2 comment.
>>> Here such code can inject interrupt to cpu side.
>>>   if (level) {
>>>       set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
>>>       qemu_set_irq(s->cpu[cpu_num].parent_irq, 1);
>>>   }
>>>
>> but, we also need set CSRIR,  Otherwise, it will cause the kernel to 
>> faill into a deep loop on avec driver avecintc_irq_dispatch();
> It depends on the detailed implementation in patch 9, there is 
> untested example code.
>
> target_ulong helper_csrrd_msgir(CPULoongArchState *env)
> {
>     int irq, new;
>
>     irq = find_first_bit(env->CSR_MSGIS, 256);
>     if (irq < 256) {
>       clear_bit(irq, env->CSR_MSGIS);
>
>       new = find_first_bit(env->CSR_MSGIS, 256);
>       if (new < 256)
>           return irq;
>
>       env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
>       env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
>     } else {
>       /* bit 31 set 1 for no invalid irq */
>       irq = -1;
just set bit 31
env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
and  Thanks for your suggestion , I will  correct it on v3.

Thanks.
Song Gao
>     }
>
>     return irq;
> }
>
> Regards
> Bibo Mao
>>
>> Thanks.
>> Song Gao.
>>> Regards
>>> Bibo Mao
>>>> +    }
>>>> +    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
>>>> +}
>>>> +
>>>>   static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
>>>>                                        uint64_t val, unsigned size)
>>>>   {
>>>> -    return;
>>>> -}
>>>> +    int irq_num, cpu_num = 0;
>>>> +    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
>>>> +    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
>>>>   +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>>>> +    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
>>>> +    avec_set_irq(s, cpu_num, irq_num, 1);
>>>> +}
>>>>     static const MemoryRegionOps loongarch_avec_ops = {
>>>>       .read = loongarch_avec_mem_read,
>>>>