[PATCH v6 08/11] hw/loongarch: Implement avec set irq

Song Gao posted 11 patches 2 days, 2 hours ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Song Gao <gaosong@loongson.cn>, Bibo Mao <maobibo@loongson.cn>, Jiaxun Yang <jiaxun.yang@flygoat.com>
[PATCH v6 08/11] hw/loongarch: Implement avec set irq
Posted by Song Gao 2 days, 2 hours ago
Implement avec set irq and update CSR_MSIS.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/intc/loongarch_avec.c         | 58 ++++++++++++++++++++++++++++++--
 include/hw/intc/loongarch_avec.h |  3 ++
 2 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 1f9f376898..03a20a7b60 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -16,6 +16,13 @@
 #include "migration/vmstate.h"
 #include "trace.h"
 #include "hw/qdev-properties.h"
+#include "target/loongarch/cpu.h"
+#include "qemu/error-report.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,13 +30,60 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
     return 0;
 }
 
+static void do_set_vcpu_avec_irq(CPUState *cs, run_on_cpu_data data)
+{
+    AVECCore *core = data.host_ptr;
+    CPULoongArchState *env;
+
+    assert(cs->cpu_index == core->dest_cpu);
+    env = &LOONGARCH_CPU(cs)->env;
+    if (core->level) {
+        set_bit(core->pending, &env->CSR_MSGIS[core->pending / 64]);
+    }
+    g_free(core);
+}
+
+
+static void avec_update_csr(AVECCore *core, int cpu_num,
+                            int irq_num, int level)
+{
+    CPUState *cs = qemu_get_cpu(cpu_num);
+
+    core->pending = irq_num;
+    core->dest_cpu = cpu_num;
+    core->level = level;
+    async_run_on_cpu(cs, do_set_vcpu_avec_irq,
+                         RUN_ON_CPU_HOST_PTR(core));
+}
+
+static void avec_set_irq(LoongArchAVECState *s, int cpu_num,
+                         int irq_num, int level)
+{
+    AVECCore *core;
+
+    core = g_new(AVECCore, 1);
+
+    if (level) {
+        avec_update_csr(core, cpu_num, irq_num, level);
+    }
+    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;
+    CPUState *cs;
+
+    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
+    cs = cpu_by_arch_id(cpu_num);
+    cpu_num = cs->cpu_index;
+    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,
     .write = loongarch_avec_mem_write,
diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
index 3e8cf7d2c1..83656f8df4 100644
--- a/include/hw/intc/loongarch_avec.h
+++ b/include/hw/intc/loongarch_avec.h
@@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, LoongArchAVECClass, LOONGARCH_AVEC)
 typedef struct AVECCore {
     CPUState *cpu;
     qemu_irq parent_irq;
+    uint64_t pending;
+    uint64_t dest_cpu;
+    bool   level;
     uint64_t arch_id;
 } AVECCore;
 
-- 
2.41.0
Re: [PATCH v6 08/11] hw/loongarch: Implement avec set irq
Posted by Bibo Mao 1 day, 4 hours ago

On 2025/9/4 下午8:18, Song Gao wrote:
> Implement avec set irq and update CSR_MSIS.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   hw/intc/loongarch_avec.c         | 58 ++++++++++++++++++++++++++++++--
>   include/hw/intc/loongarch_avec.h |  3 ++
>   2 files changed, 59 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index 1f9f376898..03a20a7b60 100644
> --- a/hw/intc/loongarch_avec.c
> +++ b/hw/intc/loongarch_avec.c
> @@ -16,6 +16,13 @@
>   #include "migration/vmstate.h"
>   #include "trace.h"
>   #include "hw/qdev-properties.h"
> +#include "target/loongarch/cpu.h"
> +#include "qemu/error-report.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,13 +30,60 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
>       return 0;
>   }
>   
> +static void do_set_vcpu_avec_irq(CPUState *cs, run_on_cpu_data data)
> +{
> +    AVECCore *core = data.host_ptr;
> +    CPULoongArchState *env;
> +
> +    assert(cs->cpu_index == core->dest_cpu);
> +    env = &LOONGARCH_CPU(cs)->env;
> +    if (core->level) {
> +        set_bit(core->pending, &env->CSR_MSGIS[core->pending / 64]);
> +    }
> +    g_free(core);
> +}
> +
> +
> +static void avec_update_csr(AVECCore *core, int cpu_num,
> +                            int irq_num, int level)
> +{
> +    CPUState *cs = qemu_get_cpu(cpu_num);
> +
> +    core->pending = irq_num;
> +    core->dest_cpu = cpu_num;
> +    core->level = level;
> +    async_run_on_cpu(cs, do_set_vcpu_avec_irq,
> +                         RUN_ON_CPU_HOST_PTR(core));
> +}
> +
> +static void avec_set_irq(LoongArchAVECState *s, int cpu_num,
> +                         int irq_num, int level)
> +{
> +    AVECCore *core;
> +
> +    core = g_new(AVECCore, 1);
> +
> +    if (level) {
> +        avec_update_csr(core, cpu_num, irq_num, level);
> +    }
> +    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);

Is it possible that qemu_set_irq reaches before async_run_on_cpu?
since it is async function.

Regargs
Bibo Mao
> +}
> +
>   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;
> +    CPUState *cs;
> +
> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> +    cs = cpu_by_arch_id(cpu_num);
> +    cpu_num = cs->cpu_index;
> +    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,
>       .write = loongarch_avec_mem_write,
> diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
> index 3e8cf7d2c1..83656f8df4 100644
> --- a/include/hw/intc/loongarch_avec.h
> +++ b/include/hw/intc/loongarch_avec.h
> @@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, LoongArchAVECClass, LOONGARCH_AVEC)
>   typedef struct AVECCore {
>       CPUState *cpu;
>       qemu_irq parent_irq;
> +    uint64_t pending;
> +    uint64_t dest_cpu;
> +    bool   level;
>       uint64_t arch_id;
>   } AVECCore;
>   
> 


Re: [PATCH v6 08/11] hw/loongarch: Implement avec set irq
Posted by Bibo Mao 7 hours ago

On 2025/9/5 下午6:05, Bibo Mao wrote:
> 
> 
> On 2025/9/4 下午8:18, Song Gao wrote:
>> Implement avec set irq and update CSR_MSIS.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>>   hw/intc/loongarch_avec.c         | 58 ++++++++++++++++++++++++++++++--
>>   include/hw/intc/loongarch_avec.h |  3 ++
>>   2 files changed, 59 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>> index 1f9f376898..03a20a7b60 100644
>> --- a/hw/intc/loongarch_avec.c
>> +++ b/hw/intc/loongarch_avec.c
>> @@ -16,6 +16,13 @@
>>   #include "migration/vmstate.h"
>>   #include "trace.h"
>>   #include "hw/qdev-properties.h"
>> +#include "target/loongarch/cpu.h"
>> +#include "qemu/error-report.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,13 +30,60 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
>>       return 0;
>>   }
>> +static void do_set_vcpu_avec_irq(CPUState *cs, run_on_cpu_data data)
>> +{
>> +    AVECCore *core = data.host_ptr;
>> +    CPULoongArchState *env;
>> +
>> +    assert(cs->cpu_index == core->dest_cpu);
>> +    env = &LOONGARCH_CPU(cs)->env;
>> +    if (core->level) {
>> +        set_bit(core->pending, &env->CSR_MSGIS[core->pending / 64]);
>> +    }
>> +    g_free(core);
>> +}
>> +
>> +
>> +static void avec_update_csr(AVECCore *core, int cpu_num,
>> +                            int irq_num, int level)
>> +{
>> +    CPUState *cs = qemu_get_cpu(cpu_num);
>> +
>> +    core->pending = irq_num;
>> +    core->dest_cpu = cpu_num;
>> +    core->level = level;
>> +    async_run_on_cpu(cs, do_set_vcpu_avec_irq,
>> +                         RUN_ON_CPU_HOST_PTR(core));
>> +}
>> +
>> +static void avec_set_irq(LoongArchAVECState *s, int cpu_num,
>> +                         int irq_num, int level)
>> +{
>> +    AVECCore *core;
>> +
>> +    core = g_new(AVECCore, 1);
>> +
>> +    if (level) {
>> +        avec_update_csr(core, cpu_num, irq_num, level);
>> +    }
>> +    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
> 
> Is it possible that qemu_set_irq reaches before async_run_on_cpu?
> since it is async function.
qemu_set_irq() is also async CPU interrupt inject function with IPI 
interrupt, avec irq and CPU interrupt can be handled together when vCPU 
returns to VM. There should be no problem.

Regards
Bibo MAo
> 
> Regargs
> Bibo Mao
>> +}
>> +
>>   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;
>> +    CPUState *cs;
>> +
>> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>> +    cs = cpu_by_arch_id(cpu_num);
>> +    cpu_num = cs->cpu_index;
>> +    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,
>>       .write = loongarch_avec_mem_write,
>> diff --git a/include/hw/intc/loongarch_avec.h 
>> b/include/hw/intc/loongarch_avec.h
>> index 3e8cf7d2c1..83656f8df4 100644
>> --- a/include/hw/intc/loongarch_avec.h
>> +++ b/include/hw/intc/loongarch_avec.h
>> @@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, 
>> LoongArchAVECClass, LOONGARCH_AVEC)
>>   typedef struct AVECCore {
>>       CPUState *cpu;
>>       qemu_irq parent_irq;
>> +    uint64_t pending;
>> +    uint64_t dest_cpu;
>> +    bool   level;
>>       uint64_t arch_id;
>>   } AVECCore;
>>


Re: [PATCH v6 08/11] hw/loongarch: Implement avec set irq
Posted by gaosong 6 hours ago
在 2025/9/6 下午3:13, Bibo Mao 写道:
>
>
> On 2025/9/5 下午6:05, Bibo Mao wrote:
>>
>>
>> On 2025/9/4 下午8:18, Song Gao wrote:
>>> Implement avec set irq and update CSR_MSIS.
>>>
>>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>>> ---
>>>   hw/intc/loongarch_avec.c         | 58 
>>> ++++++++++++++++++++++++++++++--
>>>   include/hw/intc/loongarch_avec.h |  3 ++
>>>   2 files changed, 59 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>>> index 1f9f376898..03a20a7b60 100644
>>> --- a/hw/intc/loongarch_avec.c
>>> +++ b/hw/intc/loongarch_avec.c
>>> @@ -16,6 +16,13 @@
>>>   #include "migration/vmstate.h"
>>>   #include "trace.h"
>>>   #include "hw/qdev-properties.h"
>>> +#include "target/loongarch/cpu.h"
>>> +#include "qemu/error-report.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,13 +30,60 @@ static uint64_t loongarch_avec_mem_read(void 
>>> *opaque,
>>>       return 0;
>>>   }
>>> +static void do_set_vcpu_avec_irq(CPUState *cs, run_on_cpu_data data)
>>> +{
>>> +    AVECCore *core = data.host_ptr;
>>> +    CPULoongArchState *env;
>>> +
>>> +    assert(cs->cpu_index == core->dest_cpu);
>>> +    env = &LOONGARCH_CPU(cs)->env;
>>> +    if (core->level) {
>>> +        set_bit(core->pending, &env->CSR_MSGIS[core->pending / 64]);
>>> +    }
>>> +    g_free(core);
>>> +}
>>> +
>>> +
>>> +static void avec_update_csr(AVECCore *core, int cpu_num,
>>> +                            int irq_num, int level)
>>> +{
>>> +    CPUState *cs = qemu_get_cpu(cpu_num);
>>> +
>>> +    core->pending = irq_num;
>>> +    core->dest_cpu = cpu_num;
>>> +    core->level = level;
>>> +    async_run_on_cpu(cs, do_set_vcpu_avec_irq,
>>> +                         RUN_ON_CPU_HOST_PTR(core));
>>> +}
>>> +
>>> +static void avec_set_irq(LoongArchAVECState *s, int cpu_num,
>>> +                         int irq_num, int level)
>>> +{
>>> +    AVECCore *core;
>>> +
>>> +    core = g_new(AVECCore, 1);
>>> +
>>> +    if (level) {
>>> +        avec_update_csr(core, cpu_num, irq_num, level);
>>> +    }
>>> +    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
>>
>> Is it possible that qemu_set_irq reaches before async_run_on_cpu?
>> since it is async function.
> qemu_set_irq() is also async CPU interrupt inject function with IPI 
> interrupt, avec irq and CPU interrupt can be handled together when 
> vCPU returns to VM. There should be no problem.
>
Thanks for your explanation.

Thanks.
Song Gao
> Regards
> Bibo MAo
>>
>> Regargs
>> Bibo Mao
>>> +}
>>> +
>>>   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;
>>> +    CPUState *cs;
>>> +
>>> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>>> +    cs = cpu_by_arch_id(cpu_num);
>>> +    cpu_num = cs->cpu_index;
>>> +    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,
>>>       .write = loongarch_avec_mem_write,
>>> diff --git a/include/hw/intc/loongarch_avec.h 
>>> b/include/hw/intc/loongarch_avec.h
>>> index 3e8cf7d2c1..83656f8df4 100644
>>> --- a/include/hw/intc/loongarch_avec.h
>>> +++ b/include/hw/intc/loongarch_avec.h
>>> @@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, 
>>> LoongArchAVECClass, LOONGARCH_AVEC)
>>>   typedef struct AVECCore {
>>>       CPUState *cpu;
>>>       qemu_irq parent_irq;
>>> +    uint64_t pending;
>>> +    uint64_t dest_cpu;
>>> +    bool   level;
>>>       uint64_t arch_id;
>>>   } AVECCore;
>>>


Re: [PATCH v6 08/11] hw/loongarch: Implement avec set irq
Posted by Bibo Mao 1 day, 4 hours ago

On 2025/9/4 下午8:18, Song Gao wrote:
> Implement avec set irq and update CSR_MSIS.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   hw/intc/loongarch_avec.c         | 58 ++++++++++++++++++++++++++++++--
>   include/hw/intc/loongarch_avec.h |  3 ++
>   2 files changed, 59 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index 1f9f376898..03a20a7b60 100644
> --- a/hw/intc/loongarch_avec.c
> +++ b/hw/intc/loongarch_avec.c
> @@ -16,6 +16,13 @@
>   #include "migration/vmstate.h"
>   #include "trace.h"
>   #include "hw/qdev-properties.h"
> +#include "target/loongarch/cpu.h"
> +#include "qemu/error-report.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,13 +30,60 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
>       return 0;
>   }
>   
> +static void do_set_vcpu_avec_irq(CPUState *cs, run_on_cpu_data data)
> +{
> +    AVECCore *core = data.host_ptr;
> +    CPULoongArchState *env;
> +
> +    assert(cs->cpu_index == core->dest_cpu);
cpu_synchronize_state(cs) is needed even with TCG mode.

> +    env = &LOONGARCH_CPU(cs)->env;
> +    if (core->level) {
> +        set_bit(core->pending, &env->CSR_MSGIS[core->pending / 64]);
why it is core->pending / 64 here, I think it should be
            set_bit(core->pending, &env->CSR_MSGIS);
> +    }
> +    g_free(core);
> +}
> +
> +
> +static void avec_update_csr(AVECCore *core, int cpu_num,
> +                            int irq_num, int level)
> +{
> +    CPUState *cs = qemu_get_cpu(cpu_num);
> +
> +    core->pending = irq_num;
> +    core->dest_cpu = cpu_num;
> +    core->level = level;
> +    async_run_on_cpu(cs, do_set_vcpu_avec_irq,
> +                         RUN_ON_CPU_HOST_PTR(core));
> +}
> +
> +static void avec_set_irq(LoongArchAVECState *s, int cpu_num,
> +                         int irq_num, int level)
> +{
> +    AVECCore *core;
> +
> +    core = g_new(AVECCore, 1);
malloc/free memory in irq inject context may expensive.

how about using irq_num directly if the condition level == 0 is not 
necessary, such as
   async_run_on_cpu(cs, do_set_vcpu_avec_irq,
                          RUN_ON_CPU_HOST_INT(irq_num));

Regards
Bibo Mao
> +
> +    if (level) {
> +        avec_update_csr(core, cpu_num, irq_num, level);
> +    }
> +    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;
> +    CPUState *cs;
> +
> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> +    cs = cpu_by_arch_id(cpu_num);
> +    cpu_num = cs->cpu_index;
> +    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,
>       .write = loongarch_avec_mem_write,
> diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
> index 3e8cf7d2c1..83656f8df4 100644
> --- a/include/hw/intc/loongarch_avec.h
> +++ b/include/hw/intc/loongarch_avec.h
> @@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, LoongArchAVECClass, LOONGARCH_AVEC)
>   typedef struct AVECCore {
>       CPUState *cpu;
>       qemu_irq parent_irq;
> +    uint64_t pending;
> +    uint64_t dest_cpu;
> +    bool   level;
>       uint64_t arch_id;
>   } AVECCore;
>   
> 


Re: [PATCH v6 08/11] hw/loongarch: Implement avec set irq
Posted by gaosong 6 hours ago
在 2025/9/5 下午5:52, Bibo Mao 写道:
>
>
> On 2025/9/4 下午8:18, Song Gao wrote:
>> Implement avec set irq and update CSR_MSIS.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>>   hw/intc/loongarch_avec.c         | 58 ++++++++++++++++++++++++++++++--
>>   include/hw/intc/loongarch_avec.h |  3 ++
>>   2 files changed, 59 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>> index 1f9f376898..03a20a7b60 100644
>> --- a/hw/intc/loongarch_avec.c
>> +++ b/hw/intc/loongarch_avec.c
>> @@ -16,6 +16,13 @@
>>   #include "migration/vmstate.h"
>>   #include "trace.h"
>>   #include "hw/qdev-properties.h"
>> +#include "target/loongarch/cpu.h"
>> +#include "qemu/error-report.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,13 +30,60 @@ static uint64_t loongarch_avec_mem_read(void 
>> *opaque,
>>       return 0;
>>   }
>>   +static void do_set_vcpu_avec_irq(CPUState *cs, run_on_cpu_data data)
>> +{
>> +    AVECCore *core = data.host_ptr;
>> +    CPULoongArchState *env;
>> +
>> +    assert(cs->cpu_index == core->dest_cpu);
> cpu_synchronize_state(cs) is needed even with TCG mode.
>
>> +    env = &LOONGARCH_CPU(cs)->env;
>> +    if (core->level) {
>> +        set_bit(core->pending, &env->CSR_MSGIS[core->pending / 64]);
> why it is core->pending / 64 here, I think it should be
>            set_bit(core->pending, &env->CSR_MSGIS);
>> +    }
>> +    g_free(core);
>> +}
>> +
>> +
>> +static void avec_update_csr(AVECCore *core, int cpu_num,
>> +                            int irq_num, int level)
>> +{
>> +    CPUState *cs = qemu_get_cpu(cpu_num);
>> +
>> +    core->pending = irq_num;
>> +    core->dest_cpu = cpu_num;
>> +    core->level = level;
>> +    async_run_on_cpu(cs, do_set_vcpu_avec_irq,
>> +                         RUN_ON_CPU_HOST_PTR(core));
>> +}
>> +
>> +static void avec_set_irq(LoongArchAVECState *s, int cpu_num,
>> +                         int irq_num, int level)
>> +{
>> +    AVECCore *core;
>> +
>> +    core = g_new(AVECCore, 1);
> malloc/free memory in irq inject context may expensive.
>
> how about using irq_num directly if the condition level == 0 is not 
> necessary, such as
>   async_run_on_cpu(cs, do_set_vcpu_avec_irq,
>                          RUN_ON_CPU_HOST_INT(irq_num));
>
I will delete some useless code.

> Regards
> Bibo Mao
>> +
>> +    if (level) {
>> +        avec_update_csr(core, cpu_num, irq_num, level);
>> +    }
>> +    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;
>> +    CPUState *cs;
>> +
>> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>> +    cs = cpu_by_arch_id(cpu_num);
>> +    cpu_num = cs->cpu_index;
>> +    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,
>>       .write = loongarch_avec_mem_write,
>> diff --git a/include/hw/intc/loongarch_avec.h 
>> b/include/hw/intc/loongarch_avec.h
>> index 3e8cf7d2c1..83656f8df4 100644
>> --- a/include/hw/intc/loongarch_avec.h
>> +++ b/include/hw/intc/loongarch_avec.h
>> @@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, 
>> LoongArchAVECClass, LOONGARCH_AVEC)
>>   typedef struct AVECCore {
>>       CPUState *cpu;
>>       qemu_irq parent_irq;
>> +    uint64_t pending;
>> +    uint64_t dest_cpu;
>> +    bool   level;
this code also useless.

Thanks.
Song Gao
>>
>>       uint64_t arch_id;
>>   } AVECCore;
>>