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
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,
>
在 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,
>>
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,
>>>
在 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,
>>>>
© 2016 - 2025 Red Hat, Inc.