the AVEC controller supports 256*256 irqs, all the irqs connect CPU INT_AVEC irq
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_avec.c | 28 ++++++++++++++++++++++++++++
hw/loongarch/virt.c | 11 +++++++++--
target/loongarch/cpu.h | 3 ++-
3 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 50956e7e4e..c692fef43c 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -36,9 +36,19 @@ static const MemoryRegionOps loongarch_avec_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static void avec_irq_handler(void *opaque, int irq, int level)
+{
+ return;
+}
+
static void loongarch_avec_realize(DeviceState *dev, Error **errp)
{
+ LoongArchAVECState *s = LOONGARCH_AVEC(dev);
LoongArchAVECClass *lac = LOONGARCH_AVEC_GET_CLASS(dev);
+ MachineState *machine = MACHINE(qdev_get_machine());
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
+ const CPUArchIdList *id_list;
+ int i, irq;
Error *local_err = NULL;
lac->parent_realize(dev, &local_err);
@@ -47,6 +57,24 @@ static void loongarch_avec_realize(DeviceState *dev, Error **errp)
return;
}
+ assert(mc->possible_cpu_arch_ids);
+ id_list = mc->possible_cpu_arch_ids(machine);
+ s->num_cpu = id_list->len;
+ s->cpu = g_new(AVECCore, s->num_cpu);
+ if (s->cpu == NULL) {
+ error_setg(errp, "Memory allocation for AVECCore fail");
+ return;
+ }
+
+ for (i = 0; i < s->num_cpu; i++) {
+ s->cpu[i].arch_id = id_list->cpus[i].arch_id;
+ s->cpu[i].cpu = CPU(id_list->cpus[i].cpu);
+ for (irq = 0; irq < NR_VECTORS; irq++) {
+ qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[irq], 1);
+ }
+ }
+ qdev_init_gpio_in(dev, avec_irq_handler, NR_VECTORS * s->num_cpu);
+
return;
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 272355da2d..718b5b4f92 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -363,7 +363,7 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
}
}
-static void virt_irq_init(LoongArchVirtMachineState *lvms)
+static void virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
{
DeviceState *pch_pic, *pch_msi;
DeviceState *ipi, *extioi, *avec;
@@ -459,6 +459,13 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
sysbus_realize_and_unref(SYS_BUS_DEVICE(avec), &error_fatal);
memory_region_add_subregion(get_system_memory(), VIRT_PCH_MSI_ADDR_LOW,
sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
+ CPUState *cpu_state;
+ DeviceState *cpudev;
+ for (int cpu = 0; cpu < ms->smp.cpus; cpu++) {
+ cpu_state = qemu_get_cpu(cpu);
+ cpudev = DEVICE(cpu_state);
+ qdev_connect_gpio_out(avec, cpu, qdev_get_gpio_in(cpudev, INT_AVEC));
+ }
}
/* Create EXTIOI device */
@@ -799,7 +806,7 @@ static void virt_init(MachineState *machine)
}
/* Initialize the IO interrupt subsystem */
- virt_irq_init(lvms);
+ virt_irq_init(lvms, machine);
lvms->machine_done.notify = virt_done;
qemu_add_machine_init_done_notifier(&lvms->machine_done);
/* connect powerdown request */
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index a1918a85da..b96df1cb2a 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -240,9 +240,10 @@ FIELD(CSR_CRMD, WE, 9, 1)
extern const char * const regnames[32];
extern const char * const fregnames[32];
-#define N_IRQS 13
+#define N_IRQS 15
#define IRQ_TIMER 11
#define IRQ_IPI 12
+#define INT_AVEC 14
#define LOONGARCH_STLB 2048 /* 2048 STLB */
#define LOONGARCH_MTLB 64 /* 64 MTLB */
--
2.34.1
On 2025/6/9 下午6:48, Song Gao wrote:
> the AVEC controller supports 256*256 irqs, all the irqs connect CPU INT_AVEC irq
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/intc/loongarch_avec.c | 28 ++++++++++++++++++++++++++++
> hw/loongarch/virt.c | 11 +++++++++--
> target/loongarch/cpu.h | 3 ++-
> 3 files changed, 39 insertions(+), 3 deletions(-)
>
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index 50956e7e4e..c692fef43c 100644
> --- a/hw/intc/loongarch_avec.c
> +++ b/hw/intc/loongarch_avec.c
> @@ -36,9 +36,19 @@ static const MemoryRegionOps loongarch_avec_ops = {
> .endianness = DEVICE_LITTLE_ENDIAN,
> };
>
> +static void avec_irq_handler(void *opaque, int irq, int level)
> +{
> + return;
> +}
> +
> static void loongarch_avec_realize(DeviceState *dev, Error **errp)
> {
> + LoongArchAVECState *s = LOONGARCH_AVEC(dev);
> LoongArchAVECClass *lac = LOONGARCH_AVEC_GET_CLASS(dev);
> + MachineState *machine = MACHINE(qdev_get_machine());
> + MachineClass *mc = MACHINE_GET_CLASS(machine);
> + const CPUArchIdList *id_list;
> + int i, irq;
>
> Error *local_err = NULL;
> lac->parent_realize(dev, &local_err);
> @@ -47,6 +57,24 @@ static void loongarch_avec_realize(DeviceState *dev, Error **errp)
> return;
> }
>
> + assert(mc->possible_cpu_arch_ids);
> + id_list = mc->possible_cpu_arch_ids(machine);
> + s->num_cpu = id_list->len;
> + s->cpu = g_new(AVECCore, s->num_cpu);
> + if (s->cpu == NULL) {
> + error_setg(errp, "Memory allocation for AVECCore fail");
> + return;
> + }
> +
> + for (i = 0; i < s->num_cpu; i++) {
> + s->cpu[i].arch_id = id_list->cpus[i].arch_id;
> + s->cpu[i].cpu = CPU(id_list->cpus[i].cpu);
> + for (irq = 0; irq < NR_VECTORS; irq++) {
> + qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[irq], 1);
> + }
One parent irqline for per-cpu is ok, so the total number of parent
irqline is s->num_cpu, the number of possible cpu.
> + }
> + qdev_init_gpio_in(dev, avec_irq_handler, NR_VECTORS * s->num_cpu);
avec_irq_handler() can be removed here.
Regards
Bibo Mao
> +
> return;
> }
>
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 272355da2d..718b5b4f92 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -363,7 +363,7 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
> }
> }
>
> -static void virt_irq_init(LoongArchVirtMachineState *lvms)
> +static void virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
> {
> DeviceState *pch_pic, *pch_msi;
> DeviceState *ipi, *extioi, *avec;
> @@ -459,6 +459,13 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
> sysbus_realize_and_unref(SYS_BUS_DEVICE(avec), &error_fatal);
> memory_region_add_subregion(get_system_memory(), VIRT_PCH_MSI_ADDR_LOW,
> sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
> + CPUState *cpu_state;
> + DeviceState *cpudev;
> + for (int cpu = 0; cpu < ms->smp.cpus; cpu++) {
> + cpu_state = qemu_get_cpu(cpu);
> + cpudev = DEVICE(cpu_state);
> + qdev_connect_gpio_out(avec, cpu, qdev_get_gpio_in(cpudev, INT_AVEC));
> + }
> }
>
> /* Create EXTIOI device */
> @@ -799,7 +806,7 @@ static void virt_init(MachineState *machine)
> }
>
> /* Initialize the IO interrupt subsystem */
> - virt_irq_init(lvms);
> + virt_irq_init(lvms, machine);
> lvms->machine_done.notify = virt_done;
> qemu_add_machine_init_done_notifier(&lvms->machine_done);
> /* connect powerdown request */
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index a1918a85da..b96df1cb2a 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -240,9 +240,10 @@ FIELD(CSR_CRMD, WE, 9, 1)
> extern const char * const regnames[32];
> extern const char * const fregnames[32];
>
> -#define N_IRQS 13
> +#define N_IRQS 15
> #define IRQ_TIMER 11
> #define IRQ_IPI 12
> +#define INT_AVEC 14
>
> #define LOONGARCH_STLB 2048 /* 2048 STLB */
> #define LOONGARCH_MTLB 64 /* 64 MTLB */
>
在 2025/6/11 下午2:40, Bibo Mao 写道:
>
>
> On 2025/6/9 下午6:48, Song Gao wrote:
>> the AVEC controller supports 256*256 irqs, all the irqs connect CPU
>> INT_AVEC irq
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> hw/intc/loongarch_avec.c | 28 ++++++++++++++++++++++++++++
>> hw/loongarch/virt.c | 11 +++++++++--
>> target/loongarch/cpu.h | 3 ++-
>> 3 files changed, 39 insertions(+), 3 deletions(-)
>>
>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>> index 50956e7e4e..c692fef43c 100644
>> --- a/hw/intc/loongarch_avec.c
>> +++ b/hw/intc/loongarch_avec.c
>> @@ -36,9 +36,19 @@ static const MemoryRegionOps loongarch_avec_ops = {
>> .endianness = DEVICE_LITTLE_ENDIAN,
>> };
>> +static void avec_irq_handler(void *opaque, int irq, int level)
>> +{
>> + return;
>> +}
>> +
>> static void loongarch_avec_realize(DeviceState *dev, Error **errp)
>> {
>> + LoongArchAVECState *s = LOONGARCH_AVEC(dev);
>> LoongArchAVECClass *lac = LOONGARCH_AVEC_GET_CLASS(dev);
>> + MachineState *machine = MACHINE(qdev_get_machine());
>> + MachineClass *mc = MACHINE_GET_CLASS(machine);
>> + const CPUArchIdList *id_list;
>> + int i, irq;
>> Error *local_err = NULL;
>> lac->parent_realize(dev, &local_err);
>> @@ -47,6 +57,24 @@ static void loongarch_avec_realize(DeviceState
>> *dev, Error **errp)
>> return;
>> }
>> + assert(mc->possible_cpu_arch_ids);
>> + id_list = mc->possible_cpu_arch_ids(machine);
>> + s->num_cpu = id_list->len;
>> + s->cpu = g_new(AVECCore, s->num_cpu);
>> + if (s->cpu == NULL) {
>> + error_setg(errp, "Memory allocation for AVECCore fail");
>> + return;
>> + }
>> +
>> + for (i = 0; i < s->num_cpu; i++) {
>> + s->cpu[i].arch_id = id_list->cpus[i].arch_id;
>> + s->cpu[i].cpu = CPU(id_list->cpus[i].cpu);
>> + for (irq = 0; irq < NR_VECTORS; irq++) {
>> + qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[irq], 1);
>> + }
> One parent irqline for per-cpu is ok, so the total number of parent
> irqline is s->num_cpu, the number of possible cpu.
>
emm, yes , so the avec gpio out num is s->num_cpu * s->num_cpu.,
my thought avec should gpio_out = aveec gpio in, and the avec gpio
in is NR_VECTORS * s->num_cpu.
>> + }
>> + qdev_init_gpio_in(dev, avec_irq_handler, NR_VECTORS * s->num_cpu);
> avec_irq_handler() can be removed here.
>
yes. i 'll remove on v2.
thanks.
Song Gao
> Regards
> Bibo Mao
>> +
>> return;
>> }
>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>> index 272355da2d..718b5b4f92 100644
>> --- a/hw/loongarch/virt.c
>> +++ b/hw/loongarch/virt.c
>> @@ -363,7 +363,7 @@ static void
>> virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
>> }
>> }
>> -static void virt_irq_init(LoongArchVirtMachineState *lvms)
>> +static void virt_irq_init(LoongArchVirtMachineState *lvms,
>> MachineState *ms)
>> {
>> DeviceState *pch_pic, *pch_msi;
>> DeviceState *ipi, *extioi, *avec;
>> @@ -459,6 +459,13 @@ static void
>> virt_irq_init(LoongArchVirtMachineState *lvms)
>> sysbus_realize_and_unref(SYS_BUS_DEVICE(avec), &error_fatal);
>> memory_region_add_subregion(get_system_memory(),
>> VIRT_PCH_MSI_ADDR_LOW,
>> sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
>> + CPUState *cpu_state;
>> + DeviceState *cpudev;
>> + for (int cpu = 0; cpu < ms->smp.cpus; cpu++) {
>> + cpu_state = qemu_get_cpu(cpu);
>> + cpudev = DEVICE(cpu_state);
>> + qdev_connect_gpio_out(avec, cpu,
>> qdev_get_gpio_in(cpudev, INT_AVEC));
here connect all avec gpio_out to cpu gpio_in INT_AVEC.
>> + }
>> }
>> /* Create EXTIOI device */
>> @@ -799,7 +806,7 @@ static void virt_init(MachineState *machine)
>> }
>> /* Initialize the IO interrupt subsystem */
>> - virt_irq_init(lvms);
>> + virt_irq_init(lvms, machine);
>> lvms->machine_done.notify = virt_done;
>> qemu_add_machine_init_done_notifier(&lvms->machine_done);
>> /* connect powerdown request */
>> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
>> index a1918a85da..b96df1cb2a 100644
>> --- a/target/loongarch/cpu.h
>> +++ b/target/loongarch/cpu.h
>> @@ -240,9 +240,10 @@ FIELD(CSR_CRMD, WE, 9, 1)
>> extern const char * const regnames[32];
>> extern const char * const fregnames[32];
>> -#define N_IRQS 13
>> +#define N_IRQS 15
>> #define IRQ_TIMER 11
>> #define IRQ_IPI 12
>> +#define INT_AVEC 14
>> #define LOONGARCH_STLB 2048 /* 2048 STLB */
>> #define LOONGARCH_MTLB 64 /* 64 MTLB */
>>
© 2016 - 2025 Red Hat, Inc.