* [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support
@ 2025-06-09 10:48 Song Gao
2025-06-09 10:48 ` [PATCH 01/10] hw/loongarch: add a new type iocsr read for Avdance interrupt controller Song Gao
` (9 more replies)
0 siblings, 10 replies; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Introduce the advanced extended interrupt controllers (AVECINTC). This
feature will allow each core to have 256 independent interrupt vectors
and MSI interrupts can be independently routed to any vector on any CPU.
The whole topology of irqchips in LoongArch machines looks like this if
AVECINTC is supported:
+-----+ +-----------------------+ +-------+
| IPI | --> | CPUINTC | <-- | Timer |
+-----+ +-----------------------+ +-------+
^ ^ ^
| | |
+---------+ +----------+ +---------+ +-------+
| EIOINTC | | AVECINTC | | LIOINTC | <-- | UARTs |
+---------+ +----------+ +---------+ +-------+
^ ^
| |
+---------+ +---------+
| PCH-PIC | | PCH-MSI |
+---------+ +---------+
^ ^ ^
| | |
+---------+ +---------+ +---------+
| Devices | | PCH-LPC | | Devices |
+---------+ +---------+ +---------+
^
|
+---------+
| Devices |
+---------+
We can see more about AVECINTC on linux driver code[1]
and loongarch msg interrupts on volI 6.2 Message-Interrupts
Tested the code using the virion-net NIC, but there's a bit of a problem so far, the NIC doesn't seem to be working correctly, there's a lot of dmesg prints
'
[ 44.068699] virtio_net virtio0 eth0: NETDEV WATCHDOG: CPU: 3: transmit queue 0 timed out 30500 ms
[ 44.069472] virtio_net virtio0 eth0: TX timeout on queue: 0, sq: output.0, vq: 0x1, name: output.0, 30500000 usecs ago
'
So the series with a title 'RFC'
the start scripts is kernel.sh at[3]
[1]: https://github.com/torvalds/linux/blob/master/drivers/irqchip/irq-loongarch-avec.c
[2]: https://github.com/loongson/LoongArch-Documentation/releases/download/2023.04.20/LoongArch-Vol1-v1.10-EN.pdf
[3]: https://github.com/gaosong715/qemu/releases/download/pull-loongarch-20250514/kernel.sh
Feel free to point out any flaws!
thanks.
Song Gao
Song Gao (10):
hw/loongarch: add a new type iocsr read for Avdance interrupt
controller
loongarch: add virt feature avecintc support
loongarch: add a advance interrupt controller device
target/loongarch: add msg interrupt CSR registers
hw/loongarch: AVEC controller add a MemoryRegion
hw/loongarch: Implement avec controller imput and output pins
hw/loongarch: connect pch_msi controller to avec controller
hw/loongarch: Implement avec set_irq
target/loongarch: loongarch CPU supoort avec irqs
target/loongarch: cpu_do_interrupt support msg interrupt.
hw/intc/Kconfig | 3 +
hw/intc/loongarch_avec.c | 152 +++++++++++++++++++++++++++++++
hw/intc/meson.build | 1 +
hw/loongarch/Kconfig | 1 +
hw/loongarch/virt.c | 95 +++++++++++++++++--
include/hw/intc/loongarch_avec.h | 36 ++++++++
include/hw/loongarch/virt.h | 10 ++
target/loongarch/cpu-csr.h | 2 +
target/loongarch/cpu.c | 53 ++++++++++-
target/loongarch/cpu.h | 15 ++-
target/loongarch/machine.c | 5 +
11 files changed, 362 insertions(+), 11 deletions(-)
create mode 100644 hw/intc/loongarch_avec.c
create mode 100644 include/hw/intc/loongarch_avec.h
--
2.34.1
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 01/10] hw/loongarch: add a new type iocsr read for Avdance interrupt controller
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-09 10:48 ` [PATCH 02/10] loongarch: add virt feature avecintc support Song Gao
` (8 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Use the IOCSRF_AVEC bit for avdance interrupt controller drivers
avecintc_enable[1] and set the default value of the MISC_FUNC_REG bit IOCSRM_AVEC_EN.
and set the default value of the MISC_FUNC_REG bit IOCSRM_AVEC_EN.
[1]:https://github.com/torvalds/linux/blob/master/drivers/irqchip/irq-loongarch-avec.c
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/virt.c | 4 ++++
target/loongarch/cpu.h | 2 ++
2 files changed, 6 insertions(+)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 1b504047db..90d4643721 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -548,6 +548,8 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
break;
case FEATURE_REG:
ret = BIT(IOCSRF_MSI) | BIT(IOCSRF_EXTIOI) | BIT(IOCSRF_CSRIPI);
+ /*TODO: check bit IOCSRF_AVEC with virt_is_avec_enabled */
+ ret |= BIT(IOCSRF_AVEC);
if (kvm_enabled()) {
ret |= BIT(IOCSRF_VM);
}
@@ -573,6 +575,8 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
}
+ /* enable avec default */
+ ret |= BIT_ULL(IOCSRM_AVEC_EN);
break;
default:
g_assert_not_reached();
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 262bf87f7b..7cceec1204 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -31,6 +31,7 @@
#define IOCSRF_DVFSV1 7
#define IOCSRF_GMOD 9
#define IOCSRF_VM 11
+#define IOCSRF_AVEC 15
#define VERSION_REG 0x0
#define FEATURE_REG 0x8
@@ -39,6 +40,7 @@
#define MISC_FUNC_REG 0x420
#define IOCSRM_EXTIOI_EN 48
#define IOCSRM_EXTIOI_INT_ENCODE 49
+#define IOCSRM_AVEC_EN 51
#define IOCSR_MEM_SIZE 0x428
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 02/10] loongarch: add virt feature avecintc support
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
2025-06-09 10:48 ` [PATCH 01/10] hw/loongarch: add a new type iocsr read for Avdance interrupt controller Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 6:46 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 03/10] loongarch: add a advance interrupt controller device Song Gao
` (7 subsequent siblings)
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
LoongArchVirtMachinState add avecintc features, and
it use to check whether virt machine support advance interrupt controller
and default is on.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/virt.c | 31 +++++++++++++++++++++++++++----
include/hw/loongarch/virt.h | 9 +++++++++
2 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 90d4643721..35643a4e0b 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -47,6 +47,23 @@
#include "hw/virtio/virtio-iommu.h"
#include "qemu/error-report.h"
+static void virt_get_avecintc(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
+ OnOffAuto avecintc = lvms->avecintc;
+
+ visit_type_OnOffAuto(v, name, &avecintc, errp);
+
+}
+static void virt_set_avecintc(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
+
+ visit_type_OnOffAuto(v, name, &lvms->avecintc, errp);
+}
+
static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -548,8 +565,9 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
break;
case FEATURE_REG:
ret = BIT(IOCSRF_MSI) | BIT(IOCSRF_EXTIOI) | BIT(IOCSRF_CSRIPI);
- /*TODO: check bit IOCSRF_AVEC with virt_is_avec_enabled */
- ret |= BIT(IOCSRF_AVEC);
+ if (virt_is_avecintc_enabled(lvms)) {
+ ret |= BIT(IOCSRF_AVEC);
+ }
if (kvm_enabled()) {
ret |= BIT(IOCSRF_VM);
}
@@ -575,8 +593,9 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
}
- /* enable avec default */
- ret |= BIT_ULL(IOCSRM_AVEC_EN);
+ if (virt_is_avecintc_enabled(lvms)) {
+ ret |= BIT_ULL(IOCSRM_AVEC_EN);
+ }
break;
default:
g_assert_not_reached();
@@ -1212,6 +1231,10 @@ static void virt_class_init(ObjectClass *oc, const void *data)
NULL, NULL);
object_class_property_set_description(oc, "v-eiointc",
"Enable Virt Extend I/O Interrupt Controller.");
+ object_class_property_add(oc, "avecintc", "OnOffAuto",
+ virt_get_avecintc, virt_set_avecintc, NULL, NULL);
+ object_class_property_set_description(oc, "avecintc",
+ "Enable Advance Interrupt Controller.");
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
#ifdef CONFIG_TPM
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 2b7d19953f..3a81f048e8 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -50,6 +50,7 @@ struct LoongArchVirtMachineState {
Notifier powerdown_notifier;
OnOffAuto acpi;
OnOffAuto veiointc;
+ OnOffAuto avecintc;
char *oem_id;
char *oem_table_id;
DeviceState *acpi_ged;
@@ -70,6 +71,14 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
void virt_acpi_setup(LoongArchVirtMachineState *lvms);
void virt_fdt_setup(LoongArchVirtMachineState *lvms);
+static inline bool virt_is_avecintc_enabled(LoongArchVirtMachineState *lvms)
+{
+ if (lvms->avecintc == ON_OFF_AUTO_OFF) {
+ return false;
+ }
+ return true;
+}
+
static inline bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
{
if (lvms->veiointc == ON_OFF_AUTO_OFF) {
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 03/10] loongarch: add a advance interrupt controller device
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
2025-06-09 10:48 ` [PATCH 01/10] hw/loongarch: add a new type iocsr read for Avdance interrupt controller Song Gao
2025-06-09 10:48 ` [PATCH 02/10] loongarch: add virt feature avecintc support Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-09 10:48 ` [PATCH 04/10] target/loongarch: add msg interrupt CSR registers Song Gao
` (6 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Add Loongarch advance interrupt controller device base Definition.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/Kconfig | 3 ++
hw/intc/loongarch_avec.c | 68 ++++++++++++++++++++++++++++++++
hw/intc/meson.build | 1 +
hw/loongarch/Kconfig | 1 +
include/hw/intc/loongarch_avec.h | 35 ++++++++++++++++
5 files changed, 108 insertions(+)
create mode 100644 hw/intc/loongarch_avec.c
create mode 100644 include/hw/intc/loongarch_avec.h
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 7547528f2c..b9266dc269 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -109,3 +109,6 @@ config LOONGARCH_PCH_MSI
config LOONGARCH_EXTIOI
bool
+
+config LOONGARCH_AVEC
+ bool
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
new file mode 100644
index 0000000000..5a3e7ecc03
--- /dev/null
+++ b/hw/intc/loongarch_avec.c
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson Advance interrupt controller.
+ *
+ * Copyright (C) 2025 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "hw/intc/loongarch_avec.h"
+#include "hw/pci/msi.h"
+#include "hw/misc/unimp.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+#include "hw/qdev-properties.h"
+
+
+static void loongarch_avec_realize(DeviceState *dev, Error **errp)
+{
+ LoongArchAVECClass *lac = LOONGARCH_AVEC_GET_CLASS(dev);
+
+ Error *local_err = NULL;
+ lac->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ return;
+}
+
+static void loongarch_avec_unrealize(DeviceState *dev)
+{
+ return;
+}
+
+static void loongarch_avec_init(Object *obj)
+{
+ return;
+}
+
+static void loongarch_avec_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ LoongArchAVECClass *lac = LOONGARCH_AVEC_CLASS(klass);
+
+ dc->unrealize = loongarch_avec_unrealize;
+ device_class_set_parent_realize(dc, loongarch_avec_realize,
+ &lac->parent_realize);
+}
+
+static const TypeInfo loongarch_avec_info = {
+ .name = TYPE_LOONGARCH_AVEC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(LoongArchAVECState),
+ .instance_init = loongarch_avec_init,
+ .class_init = loongarch_avec_class_init,
+};
+
+static void loongarch_avec_register_types(void)
+{
+ type_register_static(&loongarch_avec_info);
+}
+
+type_init(loongarch_avec_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 602da304b0..6c7c0c6468 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -74,3 +74,4 @@ specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c'))
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c', 'loongarch_pic_common.c'))
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c'))
specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c', 'loongarch_extioi_common.c'))
+specific_ss.add(when: 'CONFIG_LOONGARCH_AVEC', if_true: files('loongarch_avec.c'))
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index bb2838b7b5..1bf240b1e2 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -15,6 +15,7 @@ config LOONGARCH_VIRT
select LOONGARCH_PCH_PIC
select LOONGARCH_PCH_MSI
select LOONGARCH_EXTIOI
+ select LOONGARCH_AVEC
select LS7A_RTC
select SMBIOS
select ACPI_CPU_HOTPLUG
diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
new file mode 100644
index 0000000000..3c68593a7c
--- /dev/null
+++ b/include/hw/intc/loongarch_avec.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch Advance interrupt controller definitions
+ *
+ * Copyright (C) 2025 Loongson Technology Corporation Limited
+ */
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "hw/loongarch/virt.h"
+
+
+#define NR_VECTORS 256
+
+#define TYPE_LOONGARCH_AVEC "loongarch_avec"
+OBJECT_DECLARE_TYPE(LoongArchAVECState, LoongArchAVECClass, LOONGARCH_AVEC)
+
+typedef struct AVECCore {
+ CPUState *cpu;
+ qemu_irq parent_irq[NR_VECTORS];
+ uint64_t arch_id;
+} AVECCore;
+
+struct LoongArchAVECState {
+ SysBusDevice parent_obj;
+ AVECCore *cpu;
+ uint32_t num_cpu;
+};
+
+struct LoongArchAVECClass {
+ SysBusDeviceClass parent_class;
+
+ DeviceRealize parent_realize;
+ DeviceUnrealize parent_unrealize;
+};
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 04/10] target/loongarch: add msg interrupt CSR registers
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (2 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 03/10] loongarch: add a advance interrupt controller device Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-09 10:48 ` [PATCH 05/10] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
` (5 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
include CSR_MSGIS0-3, CSR_MSGIR and CSR_MSGIE.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu.c | 7 +++++++
target/loongarch/cpu.h | 10 ++++++++++
target/loongarch/machine.c | 5 +++++
3 files changed, 22 insertions(+)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index abad84c054..bde9f917fc 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -523,6 +523,13 @@ static void loongarch_la464_initfn(Object *obj)
env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7);
env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8);
+ env->CSR_MSGIS[0] = 0;
+ env->CSR_MSGIS[1] = 0;
+ env->CSR_MSGIS[2] = 0;
+ env->CSR_MSGIS[3] = 0;
+ env->CSR_MSGIR = 0;
+ env->CSR_MSGIE = 0;
+
loongarch_la464_init_csr(obj);
loongarch_cpu_post_init(obj);
}
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 7cceec1204..a1918a85da 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -256,6 +256,12 @@ FIELD(TLB_MISC, ASID, 1, 10)
FIELD(TLB_MISC, VPPN, 13, 35)
FIELD(TLB_MISC, PS, 48, 6)
+/*Msg interrupt registers */
+FIELD(CSR_MSGIS, IS, 0, 63)
+FIELD(CSR_MSGIR, INTNUM, 0, 8)
+FIELD(CSR_MSGIR, ACTIVE, 31, 1)
+FIELD(CSR_MSGIE, PT, 0, 8)
+
#define LSX_LEN (128)
#define LASX_LEN (256)
@@ -373,6 +379,10 @@ typedef struct CPUArchState {
uint64_t CSR_DBG;
uint64_t CSR_DERA;
uint64_t CSR_DSAVE;
+ /* Msg interrupt registers */
+ uint64_t CSR_MSGIS[4];
+ uint64_t CSR_MSGIR;
+ uint64_t CSR_MSGIE;
struct {
uint64_t guest_addr;
} stealtime;
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
index 4e70f5c879..7d5ee34f90 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -231,6 +231,11 @@ const VMStateDescription vmstate_loongarch_cpu = {
VMSTATE_UINT64(env.CSR_DERA, LoongArchCPU),
VMSTATE_UINT64(env.CSR_DSAVE, LoongArchCPU),
+ /* Msg interrupt CSRs */
+ VMSTATE_UINT64_ARRAY(env.CSR_MSGIS, LoongArchCPU, 4),
+ VMSTATE_UINT64(env.CSR_MSGIR, LoongArchCPU),
+ VMSTATE_UINT64(env.CSR_MSGIE, LoongArchCPU),
+
VMSTATE_UINT64(kvm_state_counter, LoongArchCPU),
/* PV steal time */
VMSTATE_UINT64(env.stealtime.guest_addr, LoongArchCPU),
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 05/10] hw/loongarch: AVEC controller add a MemoryRegion
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (3 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 04/10] target/loongarch: add msg interrupt CSR registers Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-09 10:48 ` [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins Song Gao
` (4 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
the AVEC controller use 2ff00000-2fffffff Memory.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_avec.c | 25 ++++++++++++++++++++
hw/loongarch/virt.c | 39 +++++++++++++++++++++++++++++++-
include/hw/intc/loongarch_avec.h | 1 +
include/hw/loongarch/virt.h | 1 +
4 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 5a3e7ecc03..50956e7e4e 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -17,6 +17,24 @@
#include "trace.h"
#include "hw/qdev-properties.h"
+static uint64_t loongarch_avec_mem_read(void *opaque,
+ hwaddr addr, unsigned size)
+{
+ return 0;
+}
+
+static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+ return;
+}
+
+
+static const MemoryRegionOps loongarch_avec_ops = {
+ .read = loongarch_avec_mem_read,
+ .write = loongarch_avec_mem_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
static void loongarch_avec_realize(DeviceState *dev, Error **errp)
{
@@ -39,6 +57,13 @@ static void loongarch_avec_unrealize(DeviceState *dev)
static void loongarch_avec_init(Object *obj)
{
+ LoongArchAVECState *s = LOONGARCH_AVEC(obj);
+ SysBusDevice *shd = SYS_BUS_DEVICE(obj);
+ memory_region_init_io(&s->avec_mmio, OBJECT(s), &loongarch_avec_ops,
+ s, TYPE_LOONGARCH_AVEC, 0x100000);
+ sysbus_init_mmio(shd, &s->avec_mmio);
+ msi_nonbroken = true;
+
return;
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 35643a4e0b..272355da2d 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -28,6 +28,7 @@
#include "hw/intc/loongarch_extioi.h"
#include "hw/intc/loongarch_pch_pic.h"
#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/intc/loongarch_avec.h"
#include "hw/pci-host/ls7a.h"
#include "hw/pci-host/gpex.h"
#include "hw/misc/unimp.h"
@@ -365,7 +366,7 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
static void virt_irq_init(LoongArchVirtMachineState *lvms)
{
DeviceState *pch_pic, *pch_msi;
- DeviceState *ipi, *extioi;
+ DeviceState *ipi, *extioi, *avec;
SysBusDevice *d;
int i, start, num;
@@ -411,6 +412,33 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
* +--------+ +---------+ +---------+
* | UARTs | | Devices | | Devices |
* +--------+ +---------+ +---------+
+ *
+ *
+ * Advanced Extended IRQ model
+ *
+ * +-----+ +-----------------------+ +-------+
+ * | IPI | --> | CPUINTC | <-- | Timer |
+ * +-----+ +-----------------------+ +-------+
+ * ^ ^ ^
+ * | | |
+ * +---------+ +----------+ +---------+ +-------+
+ * | EIOINTC | | AVECINTC | | LIOINTC | <-- | UARTs |
+ * +---------+ +----------+ +---------+ +-------+
+ * ^ ^
+ * | |
+ * +---------+ +---------+
+ * | PCH-PIC | | PCH-MSI |
+ * +---------+ +---------+
+ * ^ ^ ^
+ * | | |
+ * +---------+ +---------+ +---------+
+ * | Devices | | PCH-LPC | | Devices |
+ * +---------+ +---------+ +---------+
+ * ^
+ * |
+ * +---------+
+ * | Devices |
+ * +---------+
*/
/* Create IPI device */
@@ -424,6 +452,15 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
memory_region_add_subregion(&lvms->system_iocsr, MAIL_SEND_ADDR,
sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
+ /* Create AVEC device*/
+ if (virt_is_avecintc_enabled(lvms)) {
+ avec = qdev_new(TYPE_LOONGARCH_AVEC);
+ lvms->avec = avec;
+ 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));
+ }
+
/* Create EXTIOI device */
extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
lvms->extioi = extioi;
diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
index 3c68593a7c..274b284641 100644
--- a/include/hw/intc/loongarch_avec.h
+++ b/include/hw/intc/loongarch_avec.h
@@ -23,6 +23,7 @@ typedef struct AVECCore {
struct LoongArchAVECState {
SysBusDevice parent_obj;
+ MemoryRegion avec_mmio;
AVECCore *cpu;
uint32_t num_cpu;
};
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 3a81f048e8..172f40711d 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -64,6 +64,7 @@ struct LoongArchVirtMachineState {
struct loongarch_boot_info bootinfo;
DeviceState *ipi;
DeviceState *extioi;
+ DeviceState *avec;
};
#define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (4 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 05/10] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 6:40 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller Song Gao
` (3 subsequent siblings)
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
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
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (5 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 6:36 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 08/10] hw/loongarch: Implement avec set_irq Song Gao
` (2 subsequent siblings)
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/virt.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 718b5b4f92..6b670e7936 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -503,11 +503,19 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
d = SYS_BUS_DEVICE(pch_msi);
sysbus_realize_and_unref(d, &error_fatal);
- sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
- for (i = 0; i < num; i++) {
- /* Connect pch_msi irqs to extioi */
- qdev_connect_gpio_out(DEVICE(d), i,
- qdev_get_gpio_in(extioi, i + start));
+ if (virt_is_avecintc_enabled(lvms)) {
+ for (i = 0; i < num; i++) {
+ /* Connect pch_msi irqs to avec */
+ qdev_connect_gpio_out(DEVICE(d), i,
+ qdev_get_gpio_in(avec, i + start));
+ }
+ } else {
+ sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
+ for (i = 0; i < num; i++) {
+ /* Connect pch_msi irqs to extioi */
+ qdev_connect_gpio_out(DEVICE(d), i,
+ qdev_get_gpio_in(extioi, i + start));
+ }
}
virt_devices_init(pch_pic, lvms);
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 08/10] hw/loongarch: Implement avec set_irq
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (6 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 6:26 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs Song Gao
2025-06-09 10:48 ` [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt Song Gao
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_avec.c | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index c692fef43c..f609ed9aaa 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,32 @@ 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;
+
+ assert(mc->possible_cpu_arch_ids(machine));
+ id_list = mc->possible_cpu_arch_ids(machine);
+ CPUState *cpu = id_list->cpus[cpu_num].cpu;
+ CPULoongArchState *env = &LOONGARCH_CPU(cpu)->env;
+ set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
+ qemu_set_irq(s->cpu[cpu_num].parent_irq[irq_num], 1);
+}
+
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_PCH_MSI_ADDR_LOW;
+
+ cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
+ irq_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
+ avec_set_irq(s, cpu_num, irq_num, 1);
+}
static const MemoryRegionOps loongarch_avec_ops = {
.read = loongarch_avec_mem_read,
@@ -38,7 +64,12 @@ static const MemoryRegionOps loongarch_avec_ops = {
static void avec_irq_handler(void *opaque, int irq, int level)
{
- return;
+ int cpu_num, irq_num = 0;
+ LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
+ cpu_num = irq / 256;
+ irq_num = irq % 256;
+
+ avec_set_irq(s, cpu_num, irq_num, level);
}
static void loongarch_avec_realize(DeviceState *dev, Error **errp)
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (7 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 08/10] hw/loongarch: Implement avec set_irq Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 4:04 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt Song Gao
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu-csr.h | 1 +
target/loongarch/cpu.c | 17 +++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 0834e91f30..83f6cb081a 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -39,6 +39,7 @@ FIELD(CSR_ECFG, VS, 16, 3)
#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
FIELD(CSR_ESTAT, IS, 0, 13)
+FIELD(CSR_ESTAT, MSGINT, 14, 1)
FIELD(CSR_ESTAT, ECODE, 16, 6)
FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index bde9f917fc..207d11266f 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -127,6 +127,23 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
return;
}
+ /* do INTC_AVEC irqs */
+ if (irq == INT_AVEC) {
+ for (int i = 256; i >= 0; i--) {
+ if (test_bit(i, &(env->CSR_MSGIS[i / 64]))) {
+ env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, i);
+ env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
+ env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ clear_bit(i, &(env->CSR_MSGIS[i / 64]));
+ }
+ }
+ } else {
+ env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
+ env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
+ return;
+ }
+
if (kvm_enabled()) {
kvm_loongarch_set_interrupt(cpu, irq, level);
} else if (tcg_enabled()) {
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt.
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (8 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 3:44 ` Bibo Mao
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
we use CSR_ESTAT and CSR_ECFG bit 15 for msg interrupt.
and loongarch_cpu_do_interrupt support msg interrupts.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu-csr.h | 3 ++-
target/loongarch/cpu.c | 35 ++++++++++++++++++++++++++++++-----
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 83f6cb081a..5a00cf3366 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -35,11 +35,12 @@ FIELD(CSR_MISC, DWPL, 16, 3)
#define LOONGARCH_CSR_ECFG 0x4 /* Exception config */
FIELD(CSR_ECFG, LIE, 0, 13)
+FIELD(CSR_ECFG, MSGINT, 14, 1) /* used for msg */
FIELD(CSR_ECFG, VS, 16, 3)
#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
FIELD(CSR_ESTAT, IS, 0, 13)
-FIELD(CSR_ESTAT, MSGINT, 14, 1)
+FIELD(CSR_ESTAT, MSGINT, 14, 1) /* used for msg */
FIELD(CSR_ESTAT, ECODE, 16, 6)
FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 207d11266f..b92463101e 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -117,6 +117,13 @@ static vaddr loongarch_cpu_get_pc(CPUState *cs)
#ifndef CONFIG_USER_ONLY
#include "hw/loongarch/virt.h"
+static uint32_t loongarch_cpu_has_interrupt(CPULoongArchState *env)
+{
+ uint32_t ret = 0;
+ ret = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
+ ret |= FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
+ return ret;
+}
void loongarch_cpu_set_irq(void *opaque, int irq, int level)
{
LoongArchCPU *cpu = opaque;
@@ -134,21 +141,20 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, i);
env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
- cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 1);
clear_bit(i, &(env->CSR_MSGIS[i / 64]));
}
}
} else {
env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
- env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
- return;
+ env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
}
if (kvm_enabled()) {
kvm_loongarch_set_interrupt(cpu, irq, level);
} else if (tcg_enabled()) {
env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
- if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+ if (loongarch_cpu_has_interrupt(env)) {
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
} else {
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
@@ -166,12 +172,24 @@ static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env)
return ret;
}
+static inline bool cpu_loongarch_hw_interrupt_msg_pending(CPULoongArchState *env)
+{
+ bool pending_msg = 0;
+ bool status_msg = 0;
+
+ pending_msg = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
+ status_msg = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, MSGINT);
+
+ return (pending_msg & status_msg) != 0;
+}
/* Check if there is pending and not masked out interrupt */
static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
{
uint32_t pending;
uint32_t status;
-
+ if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
+ return true;
+ }
pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
status = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
@@ -285,6 +303,13 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
uint32_t vector = 0;
uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
+ if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
+ env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
+ env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
+ set_pc(env, env->CSR_EENTRY + \
+ (EXCCODE_EXTERNAL_INT + INT_AVEC) * vec_size);
+ return;
+ }
/* Find the highest-priority interrupt. */
vector = 31 - clz32(pending);
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt.
2025-06-09 10:48 ` [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt Song Gao
@ 2025-06-11 3:44 ` Bibo Mao
0 siblings, 0 replies; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 3:44 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> we use CSR_ESTAT and CSR_ECFG bit 15 for msg interrupt.
> and loongarch_cpu_do_interrupt support msg interrupts.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> target/loongarch/cpu-csr.h | 3 ++-
> target/loongarch/cpu.c | 35 ++++++++++++++++++++++++++++++-----
> 2 files changed, 32 insertions(+), 6 deletions(-)
>
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> index 83f6cb081a..5a00cf3366 100644
> --- a/target/loongarch/cpu-csr.h
> +++ b/target/loongarch/cpu-csr.h
> @@ -35,11 +35,12 @@ FIELD(CSR_MISC, DWPL, 16, 3)
>
> #define LOONGARCH_CSR_ECFG 0x4 /* Exception config */
> FIELD(CSR_ECFG, LIE, 0, 13)
> +FIELD(CSR_ECFG, MSGINT, 14, 1) /* used for msg */
how about only modify LIE such as FIELD(CSR_ECFG, LIE, 0, 15)?
> FIELD(CSR_ECFG, VS, 16, 3)
>
> #define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
> FIELD(CSR_ESTAT, IS, 0, 13)
> -FIELD(CSR_ESTAT, MSGINT, 14, 1)
> +FIELD(CSR_ESTAT, MSGINT, 14, 1) /* used for msg */
ditto, how about modify IS such as FIELD(CSR_ESTAT, IS, 0, 15)?
Regards
Bibo Mao
> FIELD(CSR_ESTAT, ECODE, 16, 6)
> FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
>
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index 207d11266f..b92463101e 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -117,6 +117,13 @@ static vaddr loongarch_cpu_get_pc(CPUState *cs)
> #ifndef CONFIG_USER_ONLY
> #include "hw/loongarch/virt.h"
>
> +static uint32_t loongarch_cpu_has_interrupt(CPULoongArchState *env)
> +{
> + uint32_t ret = 0;
> + ret = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
> + ret |= FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
> + return ret;
> +}
> void loongarch_cpu_set_irq(void *opaque, int irq, int level)
> {
> LoongArchCPU *cpu = opaque;
> @@ -134,21 +141,20 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
> env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, i);
> env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
> env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
> - cpu_interrupt(cs, CPU_INTERRUPT_HARD);
> + env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 1);
> clear_bit(i, &(env->CSR_MSGIS[i / 64]));
> }
> }
> } else {
> env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
> - env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
> - return;
> + env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
> }
>
> if (kvm_enabled()) {
> kvm_loongarch_set_interrupt(cpu, irq, level);
> } else if (tcg_enabled()) {
> env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
> - if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
> + if (loongarch_cpu_has_interrupt(env)) {
> cpu_interrupt(cs, CPU_INTERRUPT_HARD);
> } else {
> cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
> @@ -166,12 +172,24 @@ static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env)
> return ret;
> }
>
> +static inline bool cpu_loongarch_hw_interrupt_msg_pending(CPULoongArchState *env)
> +{
> + bool pending_msg = 0;
> + bool status_msg = 0;
> +
> + pending_msg = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
> + status_msg = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, MSGINT);
> +
> + return (pending_msg & status_msg) != 0;
> +}
> /* Check if there is pending and not masked out interrupt */
> static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
> {
> uint32_t pending;
> uint32_t status;
> -
> + if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
> + return true;
> + }
> pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
> status = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
>
> @@ -285,6 +303,13 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
> uint32_t vector = 0;
> uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
> pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
> + if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
> + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
> + env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
> + set_pc(env, env->CSR_EENTRY + \
> + (EXCCODE_EXTERNAL_INT + INT_AVEC) * vec_size);
> + return;
> + }
>
> /* Find the highest-priority interrupt. */
> vector = 31 - clz32(pending);
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs
2025-06-09 10:48 ` [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs Song Gao
@ 2025-06-11 4:04 ` Bibo Mao
0 siblings, 0 replies; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 4:04 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> target/loongarch/cpu-csr.h | 1 +
> target/loongarch/cpu.c | 17 +++++++++++++++++
> 2 files changed, 18 insertions(+)
>
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> index 0834e91f30..83f6cb081a 100644
> --- a/target/loongarch/cpu-csr.h
> +++ b/target/loongarch/cpu-csr.h
> @@ -39,6 +39,7 @@ FIELD(CSR_ECFG, VS, 16, 3)
>
> #define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
> FIELD(CSR_ESTAT, IS, 0, 13)
> +FIELD(CSR_ESTAT, MSGINT, 14, 1)
> FIELD(CSR_ESTAT, ECODE, 16, 6)
> FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
>
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index bde9f917fc..207d11266f 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -127,6 +127,23 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
> return;
> }
>
> + /* do INTC_AVEC irqs */
> + if (irq == INT_AVEC) {
> + for (int i = 256; i >= 0; i--) {
> + if (test_bit(i, &(env->CSR_MSGIS[i / 64]))) {
> + env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, i);
> + env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
Modification with CSR_MSGIR should be moved to function avec_set_irq(),
or there is extra sub_irq parameter in loongarch_cpu_set_irq()
> + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
> + cpu_interrupt(cs, CPU_INTERRUPT_HARD);
it is unnecessary and there is such code in tcg_enabled() loop sentence.
> + clear_bit(i, &(env->CSR_MSGIS[i / 64]));
CSR_MSGIS is unnecessary, it is pure software state.
> + }
> + }
> + } else {
> + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
> + env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
> + return;
> + }
what is the use about else {} sentences? Does it change interrupt logic
if AVEC is disabled?
Also I think it should be removed to the following (tcg_enabled().
Regards
Bibo Mao
> +
> if (kvm_enabled()) {
> kvm_loongarch_set_interrupt(cpu, irq, level);
> } else if (tcg_enabled()) {
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 08/10] hw/loongarch: Implement avec set_irq
2025-06-09 10:48 ` [PATCH 08/10] hw/loongarch: Implement avec set_irq Song Gao
@ 2025-06-11 6:26 ` Bibo Mao
2025-06-17 2:05 ` gaosong
0 siblings, 1 reply; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 6:26 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/intc/loongarch_avec.c | 37 ++++++++++++++++++++++++++++++++++---
> 1 file changed, 34 insertions(+), 3 deletions(-)
>
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index c692fef43c..f609ed9aaa 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,32 @@ 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;
> +
> + assert(mc->possible_cpu_arch_ids(machine));
> + id_list = mc->possible_cpu_arch_ids(machine);
> + CPUState *cpu = id_list->cpus[cpu_num].cpu;
> + CPULoongArchState *env = &LOONGARCH_CPU(cpu)->env;
The format is strange here. Variable env is declared after normal
sentence, there is such issue in many places.
id_list = mc->possible_cpu_arch_ids(machine);
> + set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
> + qemu_set_irq(s->cpu[cpu_num].parent_irq[irq_num], 1);
Why is parent_irq array here? I think one parent irq line is enough.
> +}
> +
> 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_PCH_MSI_ADDR_LOW;
> +
> + cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
> + irq_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>
blank line here.
> + avec_set_irq(s, cpu_num, irq_num, 1);
> +}
>
> static const MemoryRegionOps loongarch_avec_ops = {
> .read = loongarch_avec_mem_read,
> @@ -38,7 +64,12 @@ static const MemoryRegionOps loongarch_avec_ops = {
>
> static void avec_irq_handler(void *opaque, int irq, int level)
> {
> - return;
> + int cpu_num, irq_num = 0;
> + LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
> + cpu_num = irq / 256;
> + irq_num = irq % 256;
> +
> + avec_set_irq(s, cpu_num, irq_num, level);
> }
When is the function avec_irq_handler() called?
Regards
Bibo Mao
>
> static void loongarch_avec_realize(DeviceState *dev, Error **errp)
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller
2025-06-09 10:48 ` [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller Song Gao
@ 2025-06-11 6:36 ` Bibo Mao
2025-06-17 1:58 ` gaosong
0 siblings, 1 reply; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 6:36 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/loongarch/virt.c | 18 +++++++++++++-----
> 1 file changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 718b5b4f92..6b670e7936 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -503,11 +503,19 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
> qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
> d = SYS_BUS_DEVICE(pch_msi);
> sysbus_realize_and_unref(d, &error_fatal);
> - sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
> - for (i = 0; i < num; i++) {
> - /* Connect pch_msi irqs to extioi */
> - qdev_connect_gpio_out(DEVICE(d), i,
> - qdev_get_gpio_in(extioi, i + start));
> + if (virt_is_avecintc_enabled(lvms)) {
> + for (i = 0; i < num; i++) {
> + /* Connect pch_msi irqs to avec */
> + qdev_connect_gpio_out(DEVICE(d), i,
> + qdev_get_gpio_in(avec, i + start));
one parent irqline for avec is enough. Variable num is the number
allocated for pch_msi when connecting to extioi. So variable num is
meaningless with avec.
Also there is no msi memory map region for avec such as
sysbus_mmio_map() in the following.
> + }
> + } else {In the first, I think irqchip avec and pch_msi can coexist together.
MSI memory area for avec is
[VIRT_PCH_MSI_ADDR_LOW - 0x100000, VIRT_PCH_MSI_ADDR_LOW)
for pch_msi is
[VIRT_PCH_MSI_ADDR_LOW, VIRT_PCH_MSI_ADDR_LOW + 0x8)
For parent line, AVEC is connected to CPU MSGINT BIT14 and pch_msi is
connected to extioi.
So they can coexists together, it only depends on how guest kernel use
MSI controller.
Regards
Bibo Mao
> + sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
> + for (i = 0; i < num; i++) {
> + /* Connect pch_msi irqs to extioi */
> + qdev_connect_gpio_out(DEVICE(d), i,
> + qdev_get_gpio_in(extioi, i + start));
> + }
> }
>
> virt_devices_init(pch_pic, lvms);
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins
2025-06-09 10:48 ` [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins Song Gao
@ 2025-06-11 6:40 ` Bibo Mao
2025-06-17 1:28 ` gaosong
0 siblings, 1 reply; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 6:40 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
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 */
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 02/10] loongarch: add virt feature avecintc support
2025-06-09 10:48 ` [PATCH 02/10] loongarch: add virt feature avecintc support Song Gao
@ 2025-06-11 6:46 ` Bibo Mao
2025-06-13 7:54 ` gaosong
0 siblings, 1 reply; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 6:46 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> LoongArchVirtMachinState add avecintc features, and
> it use to check whether virt machine support advance interrupt controller
> and default is on.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/loongarch/virt.c | 31 +++++++++++++++++++++++++++----
> include/hw/loongarch/virt.h | 9 +++++++++
> 2 files changed, 36 insertions(+), 4 deletions(-)
>
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 90d4643721..35643a4e0b 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -47,6 +47,23 @@
> #include "hw/virtio/virtio-iommu.h"
> #include "qemu/error-report.h"
>
> +static void virt_get_avecintc(Object *obj, Visitor *v, const char *name,
> + void *opaque, Error **errp)
> +{
> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
> + OnOffAuto avecintc = lvms->avecintc;
> +
> + visit_type_OnOffAuto(v, name, &avecintc, errp);
> +
> +}
> +static void virt_set_avecintc(Object *obj, Visitor *v, const char *name,
> + void *opaque, Error **errp)
> +{
> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
> +
> + visit_type_OnOffAuto(v, name, &lvms->avecintc, errp);
> +}
> +
> static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
> void *opaque, Error **errp)
> {
> @@ -548,8 +565,9 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
> break;
> case FEATURE_REG:
> ret = BIT(IOCSRF_MSI) | BIT(IOCSRF_EXTIOI) | BIT(IOCSRF_CSRIPI);
> - /*TODO: check bit IOCSRF_AVEC with virt_is_avec_enabled */
> - ret |= BIT(IOCSRF_AVEC);
> + if (virt_is_avecintc_enabled(lvms)) {
> + ret |= BIT(IOCSRF_AVEC);
> + }
> if (kvm_enabled()) {
> ret |= BIT(IOCSRF_VM);
> }
> @@ -575,8 +593,9 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
> if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
> ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
> }
> - /* enable avec default */
> - ret |= BIT_ULL(IOCSRM_AVEC_EN);
> + if (virt_is_avecintc_enabled(lvms)) {
> + ret |= BIT_ULL(IOCSRM_AVEC_EN);
> + }
Is it really that reading of MISC_FUNC_REG will return
BIT_ULL(IOCSRM_AVEC_EN) if there is avec?
Where is the write operation with register MISC_FUNC_REG?
Regard
Bibo Mao
> break;
> default:
> g_assert_not_reached();
> @@ -1212,6 +1231,10 @@ static void virt_class_init(ObjectClass *oc, const void *data)
> NULL, NULL);
> object_class_property_set_description(oc, "v-eiointc",
> "Enable Virt Extend I/O Interrupt Controller.");
> + object_class_property_add(oc, "avecintc", "OnOffAuto",
> + virt_get_avecintc, virt_set_avecintc, NULL, NULL);
> + object_class_property_set_description(oc, "avecintc",
> + "Enable Advance Interrupt Controller.");
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
> #ifdef CONFIG_TPM
> diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
> index 2b7d19953f..3a81f048e8 100644
> --- a/include/hw/loongarch/virt.h
> +++ b/include/hw/loongarch/virt.h
> @@ -50,6 +50,7 @@ struct LoongArchVirtMachineState {
> Notifier powerdown_notifier;
> OnOffAuto acpi;
> OnOffAuto veiointc;
> + OnOffAuto avecintc;
> char *oem_id;
> char *oem_table_id;
> DeviceState *acpi_ged;
> @@ -70,6 +71,14 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
> void virt_acpi_setup(LoongArchVirtMachineState *lvms);
> void virt_fdt_setup(LoongArchVirtMachineState *lvms);
>
> +static inline bool virt_is_avecintc_enabled(LoongArchVirtMachineState *lvms)
> +{
> + if (lvms->avecintc == ON_OFF_AUTO_OFF) {
> + return false;
> + }
> + return true;
> +}
> +
> static inline bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
> {
> if (lvms->veiointc == ON_OFF_AUTO_OFF) {
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 02/10] loongarch: add virt feature avecintc support
2025-06-11 6:46 ` Bibo Mao
@ 2025-06-13 7:54 ` gaosong
2025-06-16 1:09 ` Bibo Mao
0 siblings, 1 reply; 24+ messages in thread
From: gaosong @ 2025-06-13 7:54 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 2025/6/11 下午2:46, Bibo Mao 写道:
>
>
> On 2025/6/9 下午6:48, Song Gao wrote:
>> LoongArchVirtMachinState add avecintc features, and
>> it use to check whether virt machine support advance interrupt
>> controller
>> and default is on.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> hw/loongarch/virt.c | 31 +++++++++++++++++++++++++++----
>> include/hw/loongarch/virt.h | 9 +++++++++
>> 2 files changed, 36 insertions(+), 4 deletions(-)
>>
>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>> index 90d4643721..35643a4e0b 100644
>> --- a/hw/loongarch/virt.c
>> +++ b/hw/loongarch/virt.c
>> @@ -47,6 +47,23 @@
>> #include "hw/virtio/virtio-iommu.h"
>> #include "qemu/error-report.h"
>> +static void virt_get_avecintc(Object *obj, Visitor *v, const char
>> *name,
>> + void *opaque, Error **errp)
>> +{
>> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
>> + OnOffAuto avecintc = lvms->avecintc;
>> +
>> + visit_type_OnOffAuto(v, name, &avecintc, errp);
>> +
>> +}
>> +static void virt_set_avecintc(Object *obj, Visitor *v, const char
>> *name,
>> + void *opaque, Error **errp)
>> +{
>> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
>> +
>> + visit_type_OnOffAuto(v, name, &lvms->avecintc, errp);
>> +}
>> +
>> static void virt_get_veiointc(Object *obj, Visitor *v, const char
>> *name,
>> void *opaque, Error **errp)
>> {
>> @@ -548,8 +565,9 @@ static MemTxResult virt_iocsr_misc_read(void
>> *opaque, hwaddr addr,
>> break;
>> case FEATURE_REG:
>> ret = BIT(IOCSRF_MSI) | BIT(IOCSRF_EXTIOI) |
>> BIT(IOCSRF_CSRIPI);
>> - /*TODO: check bit IOCSRF_AVEC with virt_is_avec_enabled */
>> - ret |= BIT(IOCSRF_AVEC);
>> + if (virt_is_avecintc_enabled(lvms)) {
>> + ret |= BIT(IOCSRF_AVEC);
>> + }
>> if (kvm_enabled()) {
>> ret |= BIT(IOCSRF_VM);
>> }
>> @@ -575,8 +593,9 @@ static MemTxResult virt_iocsr_misc_read(void
>> *opaque, hwaddr addr,
>> if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
>> ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
>> }
>> - /* enable avec default */
>> - ret |= BIT_ULL(IOCSRM_AVEC_EN);
>> + if (virt_is_avecintc_enabled(lvms)) {
>> + ret |= BIT_ULL(IOCSRM_AVEC_EN);
>> + }
> Is it really that reading of MISC_FUNC_REG will return
> BIT_ULL(IOCSRM_AVEC_EN) if there is avec?
>
no, it is IOCSRM_AVEC_EN after drivier enable avecintc.
static inline void avecintc_enable(void)
{
u64 value;
value = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC);
value |= IOCSR_MISC_FUNC_AVEC_EN;
iocsr_write64(value, LOONGARCH_IOCSR_MISC_FUNC);
}
my thought is that qemu has enabled avec by default,
so I just add a variable OnOffAuto avecintc on
LoongArchVirtMachineState,
> Where is the write operation with register MISC_FUNC_REG?
>
no, I will add it on v2?
how about add features and status on LoongArchVirtMachineState for the
macine misc fetureas and status?
like LoongArchExtIOICommonState
Thanks.
Song Gao
> Regard
> Bibo Mao
>> break;
>> default:
>> g_assert_not_reached();
>> @@ -1212,6 +1231,10 @@ static void virt_class_init(ObjectClass *oc,
>> const void *data)
>> NULL, NULL);
>> object_class_property_set_description(oc, "v-eiointc",
>> "Enable Virt Extend I/O Interrupt
>> Controller.");
>> + object_class_property_add(oc, "avecintc", "OnOffAuto",
>> + virt_get_avecintc, virt_set_avecintc, NULL, NULL);
>> + object_class_property_set_description(oc, "avecintc",
>> + "Enable Advance Interrupt Controller.");
>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
>> #ifdef CONFIG_TPM
>> diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
>> index 2b7d19953f..3a81f048e8 100644
>> --- a/include/hw/loongarch/virt.h
>> +++ b/include/hw/loongarch/virt.h
>> @@ -50,6 +50,7 @@ struct LoongArchVirtMachineState {
>> Notifier powerdown_notifier;
>> OnOffAuto acpi;
>> OnOffAuto veiointc;
>> + OnOffAuto avecintc;
>> char *oem_id;
>> char *oem_table_id;
>> DeviceState *acpi_ged;
>> @@ -70,6 +71,14 @@
>> OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState,
>> LOONGARCH_VIRT_MACHINE)
>> void virt_acpi_setup(LoongArchVirtMachineState *lvms);
>> void virt_fdt_setup(LoongArchVirtMachineState *lvms);
>> +static inline bool
>> virt_is_avecintc_enabled(LoongArchVirtMachineState *lvms)
>> +{
>> + if (lvms->avecintc == ON_OFF_AUTO_OFF) {
>> + return false;
>> + }
>> + return true;
>> +}
>> +
>> static inline bool
>> virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
>> {
>> if (lvms->veiointc == ON_OFF_AUTO_OFF) {
>>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 02/10] loongarch: add virt feature avecintc support
2025-06-13 7:54 ` gaosong
@ 2025-06-16 1:09 ` Bibo Mao
0 siblings, 0 replies; 24+ messages in thread
From: Bibo Mao @ 2025-06-16 1:09 UTC (permalink / raw)
To: gaosong; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/13 下午3:54, gaosong wrote:
> 在 2025/6/11 下午2:46, Bibo Mao 写道:
>>
>>
>> On 2025/6/9 下午6:48, Song Gao wrote:
>>> LoongArchVirtMachinState add avecintc features, and
>>> it use to check whether virt machine support advance interrupt
>>> controller
>>> and default is on.
>>>
>>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>>> ---
>>> hw/loongarch/virt.c | 31 +++++++++++++++++++++++++++----
>>> include/hw/loongarch/virt.h | 9 +++++++++
>>> 2 files changed, 36 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>>> index 90d4643721..35643a4e0b 100644
>>> --- a/hw/loongarch/virt.c
>>> +++ b/hw/loongarch/virt.c
>>> @@ -47,6 +47,23 @@
>>> #include "hw/virtio/virtio-iommu.h"
>>> #include "qemu/error-report.h"
>>> +static void virt_get_avecintc(Object *obj, Visitor *v, const char
>>> *name,
>>> + void *opaque, Error **errp)
>>> +{
>>> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
>>> + OnOffAuto avecintc = lvms->avecintc;
>>> +
>>> + visit_type_OnOffAuto(v, name, &avecintc, errp);
>>> +
>>> +}
>>> +static void virt_set_avecintc(Object *obj, Visitor *v, const char
>>> *name,
>>> + void *opaque, Error **errp)
>>> +{
>>> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
>>> +
>>> + visit_type_OnOffAuto(v, name, &lvms->avecintc, errp);
>>> +}
>>> +
>>> static void virt_get_veiointc(Object *obj, Visitor *v, const char
>>> *name,
>>> void *opaque, Error **errp)
>>> {
>>> @@ -548,8 +565,9 @@ static MemTxResult virt_iocsr_misc_read(void
>>> *opaque, hwaddr addr,
>>> break;
>>> case FEATURE_REG:
>>> ret = BIT(IOCSRF_MSI) | BIT(IOCSRF_EXTIOI) |
>>> BIT(IOCSRF_CSRIPI);
>>> - /*TODO: check bit IOCSRF_AVEC with virt_is_avec_enabled */
>>> - ret |= BIT(IOCSRF_AVEC);
>>> + if (virt_is_avecintc_enabled(lvms)) {
>>> + ret |= BIT(IOCSRF_AVEC);
>>> + }
>>> if (kvm_enabled()) {
>>> ret |= BIT(IOCSRF_VM);
>>> }
>>> @@ -575,8 +593,9 @@ static MemTxResult virt_iocsr_misc_read(void
>>> *opaque, hwaddr addr,
>>> if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
>>> ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
>>> }
>>> - /* enable avec default */
>>> - ret |= BIT_ULL(IOCSRM_AVEC_EN);
>>> + if (virt_is_avecintc_enabled(lvms)) {
>>> + ret |= BIT_ULL(IOCSRM_AVEC_EN);
>>> + }
>> Is it really that reading of MISC_FUNC_REG will return
>> BIT_ULL(IOCSRM_AVEC_EN) if there is avec?
>>
> no, it is IOCSRM_AVEC_EN after drivier enable avecintc.
> static inline void avecintc_enable(void)
> {
> u64 value;
>
> value = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC);
> value |= IOCSR_MISC_FUNC_AVEC_EN;
> iocsr_write64(value, LOONGARCH_IOCSR_MISC_FUNC);
> }
>
> my thought is that qemu has enabled avec by default,
> so I just add a variable OnOffAuto avecintc on
> LoongArchVirtMachineState,
>> Where is the write operation with register MISC_FUNC_REG?
>>
> no, I will add it on v2?
>
> how about add features and status on LoongArchVirtMachineState for the
> macine misc fetureas and status?
> like LoongArchExtIOICommonState
That sounds good to me.
Regards
Bibo Mao
>
> Thanks.
> Song Gao
>> Regard
>> Bibo Mao
>>> break;
>>> default:
>>> g_assert_not_reached();
>>> @@ -1212,6 +1231,10 @@ static void virt_class_init(ObjectClass *oc,
>>> const void *data)
>>> NULL, NULL);
>>> object_class_property_set_description(oc, "v-eiointc",
>>> "Enable Virt Extend I/O Interrupt
>>> Controller.");
>>> + object_class_property_add(oc, "avecintc", "OnOffAuto",
>>> + virt_get_avecintc, virt_set_avecintc, NULL, NULL);
>>> + object_class_property_set_description(oc, "avecintc",
>>> + "Enable Advance Interrupt Controller.");
>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
>>> #ifdef CONFIG_TPM
>>> diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
>>> index 2b7d19953f..3a81f048e8 100644
>>> --- a/include/hw/loongarch/virt.h
>>> +++ b/include/hw/loongarch/virt.h
>>> @@ -50,6 +50,7 @@ struct LoongArchVirtMachineState {
>>> Notifier powerdown_notifier;
>>> OnOffAuto acpi;
>>> OnOffAuto veiointc;
>>> + OnOffAuto avecintc;
>>> char *oem_id;
>>> char *oem_table_id;
>>> DeviceState *acpi_ged;
>>> @@ -70,6 +71,14 @@
>>> OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState,
>>> LOONGARCH_VIRT_MACHINE)
>>> void virt_acpi_setup(LoongArchVirtMachineState *lvms);
>>> void virt_fdt_setup(LoongArchVirtMachineState *lvms);
>>> +static inline bool
>>> virt_is_avecintc_enabled(LoongArchVirtMachineState *lvms)
>>> +{
>>> + if (lvms->avecintc == ON_OFF_AUTO_OFF) {
>>> + return false;
>>> + }
>>> + return true;
>>> +}
>>> +
>>> static inline bool
>>> virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
>>> {
>>> if (lvms->veiointc == ON_OFF_AUTO_OFF) {
>>>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins
2025-06-11 6:40 ` Bibo Mao
@ 2025-06-17 1:28 ` gaosong
0 siblings, 0 replies; 24+ messages in thread
From: gaosong @ 2025-06-17 1:28 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 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 */
>>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller
2025-06-11 6:36 ` Bibo Mao
@ 2025-06-17 1:58 ` gaosong
2025-06-17 7:34 ` Bibo Mao
0 siblings, 1 reply; 24+ messages in thread
From: gaosong @ 2025-06-17 1:58 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 2025/6/11 下午2:36, Bibo Mao 写道:
>
>
> On 2025/6/9 下午6:48, Song Gao wrote:
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> hw/loongarch/virt.c | 18 +++++++++++++-----
>> 1 file changed, 13 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>> index 718b5b4f92..6b670e7936 100644
>> --- a/hw/loongarch/virt.c
>> +++ b/hw/loongarch/virt.c
>> @@ -503,11 +503,19 @@ static void
>> virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
>> qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
>> d = SYS_BUS_DEVICE(pch_msi);
>> sysbus_realize_and_unref(d, &error_fatal);
>> - sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
>> - for (i = 0; i < num; i++) {
>> - /* Connect pch_msi irqs to extioi */
>> - qdev_connect_gpio_out(DEVICE(d), i,
>> - qdev_get_gpio_in(extioi, i + start));
>> + if (virt_is_avecintc_enabled(lvms)) {
>> + for (i = 0; i < num; i++) {
>> + /* Connect pch_msi irqs to avec */
>> + qdev_connect_gpio_out(DEVICE(d), i,
>> + qdev_get_gpio_in(avec, i + start));
> one parent irqline for avec is enough. Variable num is the number
> allocated for pch_msi when connecting to extioi. So variable num is
> meaningless with avec.
>
hi,
here is pch_msi [start-256] gpio_out connect to avec gpio_in [start,
256], not the avec connect to cpu.
and I think the 'one parent lrqline for avec' is avec connect cpu
gpio_in INT_AVEC at patch 6
'qdev_connect_gpio_out(avec, cpu, qdev_get_gpio_in(cpudev, INT_AVEC));'
or all pch_msi gpio_out connect one avec gpio_in ? I'm a little
confused here.
> Also there is no msi memory map region for avec such as
> sysbus_mmio_map() in the following.
>
emm, the region add at patch 6
memory_region_add_subregion(get_system_memory(), VIRT_PCH_MSI_ADDR_LOW,
sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
I will adjust the patch order and the code order.
>> + }
>> + } else {In the first, I think irqchip avec and pch_msi can
>> coexist together.
> MSI memory area for avec is
> [VIRT_PCH_MSI_ADDR_LOW - 0x100000, VIRT_PCH_MSI_ADDR_LOW)
yes, you're right. memory area for avec should be 2fe0000000-2ff0000000;
> for pch_msi is
> [VIRT_PCH_MSI_ADDR_LOW, VIRT_PCH_MSI_ADDR_LOW + 0x8)
>
> For parent line, AVEC is connected to CPU MSGINT BIT14 and pch_msi is
> connected to extioi.
>
> So they can coexists together, it only depends on how guest kernel use
> MSI controller.
>
emm, in case avec exists we should pick avec.
thanks.
Song Gao.
> Regards
> Bibo Mao
>> + sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
>> + for (i = 0; i < num; i++) {
>> + /* Connect pch_msi irqs to extioi */
>> + qdev_connect_gpio_out(DEVICE(d), i,
>> + qdev_get_gpio_in(extioi, i + start));
>> + }
>> }
>> virt_devices_init(pch_pic, lvms);
>>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 08/10] hw/loongarch: Implement avec set_irq
2025-06-11 6:26 ` Bibo Mao
@ 2025-06-17 2:05 ` gaosong
0 siblings, 0 replies; 24+ messages in thread
From: gaosong @ 2025-06-17 2:05 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 2025/6/11 下午2:26, Bibo Mao 写道:
>
>
> On 2025/6/9 下午6:48, Song Gao wrote:
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> hw/intc/loongarch_avec.c | 37 ++++++++++++++++++++++++++++++++++---
>> 1 file changed, 34 insertions(+), 3 deletions(-)
>>
>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>> index c692fef43c..f609ed9aaa 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,32 @@ 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;
>> +
>> + assert(mc->possible_cpu_arch_ids(machine));
>> + id_list = mc->possible_cpu_arch_ids(machine);
>> + CPUState *cpu = id_list->cpus[cpu_num].cpu;
>> + CPULoongArchState *env = &LOONGARCH_CPU(cpu)->env;
> The format is strange here. Variable env is declared after normal
> sentence, there is such issue in many places.
> id_list = mc->possible_cpu_arch_ids(machine);
>
>> + set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
>> + qemu_set_irq(s->cpu[cpu_num].parent_irq[irq_num], 1);
> Why is parent_irq array here? I think one parent irq line is enough.
>
ok , i'll correct on v3.
>> +}
>> +
>> 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_PCH_MSI_ADDR_LOW;
>> +
>> + cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
>> + irq_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> blank line here.
Got it.
>> + avec_set_irq(s, cpu_num, irq_num, 1);
>> +}
>> static const MemoryRegionOps loongarch_avec_ops = {
>> .read = loongarch_avec_mem_read,
>> @@ -38,7 +64,12 @@ static const MemoryRegionOps loongarch_avec_ops = {
>> static void avec_irq_handler(void *opaque, int irq, int level)
>> {
>> - return;
>> + int cpu_num, irq_num = 0;
>> + LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
>> + cpu_num = irq / 256;
>> + irq_num = irq % 256;
>> +
>> + avec_set_irq(s, cpu_num, irq_num, level);
>> }
> When is the function avec_irq_handler() called?
>
when some deviec gpio_out connect to avec gpio_in, since we define the
avec qdev_init_gpio_in at
avec realize and the avec_Irq_handler is the callback function.
Thanks.
Song Gao
> Regards
> Bibo Mao
>> static void loongarch_avec_realize(DeviceState *dev, Error **errp)
>>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller
2025-06-17 1:58 ` gaosong
@ 2025-06-17 7:34 ` Bibo Mao
2025-06-18 3:55 ` gaosong
0 siblings, 1 reply; 24+ messages in thread
From: Bibo Mao @ 2025-06-17 7:34 UTC (permalink / raw)
To: gaosong; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/17 上午9:58, gaosong wrote:
> 在 2025/6/11 下午2:36, Bibo Mao 写道:
>>
>>
>> On 2025/6/9 下午6:48, Song Gao wrote:
>>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>>> ---
>>> hw/loongarch/virt.c | 18 +++++++++++++-----
>>> 1 file changed, 13 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>>> index 718b5b4f92..6b670e7936 100644
>>> --- a/hw/loongarch/virt.c
>>> +++ b/hw/loongarch/virt.c
>>> @@ -503,11 +503,19 @@ static void
>>> virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
>>> qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
>>> d = SYS_BUS_DEVICE(pch_msi);
>>> sysbus_realize_and_unref(d, &error_fatal);
>>> - sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
>>> - for (i = 0; i < num; i++) {
>>> - /* Connect pch_msi irqs to extioi */
>>> - qdev_connect_gpio_out(DEVICE(d), i,
>>> - qdev_get_gpio_in(extioi, i + start));
>>> + if (virt_is_avecintc_enabled(lvms)) {
>>> + for (i = 0; i < num; i++) {
>>> + /* Connect pch_msi irqs to avec */
>>> + qdev_connect_gpio_out(DEVICE(d), i,
>>> + qdev_get_gpio_in(avec, i + start));
>> one parent irqline for avec is enough. Variable num is the number
>> allocated for pch_msi when connecting to extioi. So variable num is
>> meaningless with avec.
>>
> hi,
> here is pch_msi [start-256] gpio_out connect to avec gpio_in [start,
> 256], not the avec connect to cpu.
pch_msi is always connected to eiointc, and it is not connected to avec
gpio_in. There is two MSI controllers coexisting together: pch_msi and
avec, guest OS can choose use one of them or both.
Regards
Bibo Mao
> and I think the 'one parent lrqline for avec' is avec connect cpu
> gpio_in INT_AVEC at patch 6
> 'qdev_connect_gpio_out(avec, cpu, qdev_get_gpio_in(cpudev, INT_AVEC));'
> or all pch_msi gpio_out connect one avec gpio_in ? I'm a little
> confused here.
>
>> Also there is no msi memory map region for avec such as
>> sysbus_mmio_map() in the following.
>>
> emm, the region add at patch 6
> memory_region_add_subregion(get_system_memory(), VIRT_PCH_MSI_ADDR_LOW,
> sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
>
> I will adjust the patch order and the code order.
>
>>> + }
>>> + } else {In the first, I think irqchip avec and pch_msi can
>>> coexist together.
>> MSI memory area for avec is
>> [VIRT_PCH_MSI_ADDR_LOW - 0x100000, VIRT_PCH_MSI_ADDR_LOW)
> yes, you're right. memory area for avec should be 2fe0000000-2ff0000000;
>> for pch_msi is
>> [VIRT_PCH_MSI_ADDR_LOW, VIRT_PCH_MSI_ADDR_LOW + 0x8)
>>
>> For parent line, AVEC is connected to CPU MSGINT BIT14 and pch_msi is
>> connected to extioi.
>>
>> So they can coexists together, it only depends on how guest kernel use
>> MSI controller.
>>
> emm, in case avec exists we should pick avec.
>
> thanks.
> Song Gao.
>> Regards
>> Bibo Mao
>>> + sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
>>> + for (i = 0; i < num; i++) {
>>> + /* Connect pch_msi irqs to extioi */
>>> + qdev_connect_gpio_out(DEVICE(d), i,
>>> + qdev_get_gpio_in(extioi, i + start));
>>> + }
>>> }
>>> virt_devices_init(pch_pic, lvms);
>>>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller
2025-06-17 7:34 ` Bibo Mao
@ 2025-06-18 3:55 ` gaosong
0 siblings, 0 replies; 24+ messages in thread
From: gaosong @ 2025-06-18 3:55 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 2025/6/17 下午3:34, Bibo Mao 写道:
>>>
>> hi,
>> here is pch_msi [start-256] gpio_out connect to avec gpio_in
>> [start, 256], not the avec connect to cpu.
> pch_msi is always connected to eiointc, and it is not connected to
> avec gpio_in. There is two MSI controllers coexisting together:
> pch_msi and avec, guest OS can choose use one of them or both.
you're right. I got it now.
thanks.
Song Gao
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2025-06-18 3:54 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
2025-06-09 10:48 ` [PATCH 01/10] hw/loongarch: add a new type iocsr read for Avdance interrupt controller Song Gao
2025-06-09 10:48 ` [PATCH 02/10] loongarch: add virt feature avecintc support Song Gao
2025-06-11 6:46 ` Bibo Mao
2025-06-13 7:54 ` gaosong
2025-06-16 1:09 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 03/10] loongarch: add a advance interrupt controller device Song Gao
2025-06-09 10:48 ` [PATCH 04/10] target/loongarch: add msg interrupt CSR registers Song Gao
2025-06-09 10:48 ` [PATCH 05/10] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
2025-06-09 10:48 ` [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins Song Gao
2025-06-11 6:40 ` Bibo Mao
2025-06-17 1:28 ` gaosong
2025-06-09 10:48 ` [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller Song Gao
2025-06-11 6:36 ` Bibo Mao
2025-06-17 1:58 ` gaosong
2025-06-17 7:34 ` Bibo Mao
2025-06-18 3:55 ` gaosong
2025-06-09 10:48 ` [PATCH 08/10] hw/loongarch: Implement avec set_irq Song Gao
2025-06-11 6:26 ` Bibo Mao
2025-06-17 2:05 ` gaosong
2025-06-09 10:48 ` [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs Song Gao
2025-06-11 4:04 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt Song Gao
2025-06-11 3:44 ` Bibo Mao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).