qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support
@ 2025-09-04 12:18 Song Gao
  2025-09-04 12:18 ` [PATCH v6 01/11] target/loongarch: move some machine define to virt.h Song Gao
                   ` (10 more replies)
  0 siblings, 11 replies; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 UTC (permalink / raw)
  To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang

Hi,

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 the start scripts is kernel.sh at[3] and then
run 'ifconfig eth0 192.168.122.12' or
test avec plug and unplug interfaces
1 run kernel.sh[3]
2 telnet localhost 4418;
3 run QOM 'device_add la464-loongarch-cpu,socket-id=2,core-id=0,thread-id=0,id=cpu-2'
4 run vm 'ifconfig eth0 192.168.122.12';
5 run QOM 'device_de cpu-2'
6 run vm 'ifconfig eth0 192.168.122.11';

[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

v6:
  1: Change some code to support KVM mode, and will add a patch in late.
  2: Use async_run_on_cpu() to update CSR_MSGIS;
  3: Rebase.

v5:
  1: rebase and R_b;
  2; change patch2 and patch3 commit message;
  3, change virt_is_avecintc_enabled() to virt_has_avecintc();
  4: remove set and clean CSR_ECFG.bit15;
  5; patch11 add some check lvms->avec, beacuse someone my set avecintc=off.

v4:
  1: Implemetnt the AVEC plug/unplug interface. test with devcice-add
cpu and device-add and then setup the virtio-net nic. new patch11;
  2: add a new patch1 move some machine define to virt.h;
  3; add a new patch3 to implemet write/raad misc' avec feature and
status bit.
  4: Simplification of patch8 and patch10 as per bibo's suggestion.

v3:
  1: Implement the read-clear feature for CSR_MSGIR register
  2: Fix some code style;
  3: Merge patch8 and patch9 into one patch8;
  4: Fix patch7 get wrong cpu_num and irq_num;
  5: Add vmstate_msg for messag-interrupt registers migrate;
  6: Update test scripts use  '-bios', because kernel use avec need acpi
support. the bios is qemu/pc_bios/edk2-loongarch64-code.fd.bz2.

Thanks.
Song Gao


Song Gao (11):
  target/loongarch: move some machine define to virt.h
  hw/loongarch: add virt feature avecintc support
  hw/loongarch: add misc register supoort avecintc
  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: Implement avec set irq
  target/loongarch: Add CSR_ESTAT.bit15 and CSR_ECFG.bit15 for msg
    interrupts.
  target/loongarch:Implement csrrd CSR_MSGIR register
  hw/loongarch: Implement AVEC plug/unplug interfaces

 hw/intc/Kconfig                               |   3 +
 hw/intc/loongarch_avec.c                      | 237 ++++++++++++++++++
 hw/intc/meson.build                           |   1 +
 hw/loongarch/Kconfig                          |   1 +
 hw/loongarch/virt.c                           |  99 +++++++-
 include/hw/intc/loongarch_avec.h              |  39 +++
 include/hw/loongarch/virt.h                   |  34 +++
 include/hw/pci-host/ls7a.h                    |   2 +
 target/loongarch/cpu-csr.h                    |   9 +-
 target/loongarch/cpu.h                        |  35 +--
 target/loongarch/csr.c                        |   5 +
 target/loongarch/machine.c                    |  27 +-
 target/loongarch/tcg/csr_helper.c             |  21 ++
 target/loongarch/tcg/helper.h                 |   1 +
 .../tcg/insn_trans/trans_privileged.c.inc     |   1 +
 15 files changed, 488 insertions(+), 27 deletions(-)
 create mode 100644 hw/intc/loongarch_avec.c
 create mode 100644 include/hw/intc/loongarch_avec.h

-- 
2.41.0



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH v6 01/11] target/loongarch: move some machine define to virt.h
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-04 12:18 ` [PATCH v6 02/11] hw/loongarch: add virt feature avecintc support Song Gao
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 UTC (permalink / raw)
  To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang

move some machine define to virt.h

Signed-off-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
---
 include/hw/loongarch/virt.h | 19 +++++++++++++++++++
 target/loongarch/cpu.h      | 21 ---------------------
 2 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 602feab0f0..7120b46714 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -13,6 +13,25 @@
 #include "hw/block/flash.h"
 #include "hw/loongarch/boot.h"
 
+#define IOCSRF_TEMP             0
+#define IOCSRF_NODECNT          1
+#define IOCSRF_MSI              2
+#define IOCSRF_EXTIOI           3
+#define IOCSRF_CSRIPI           4
+#define IOCSRF_FREQCSR          5
+#define IOCSRF_FREQSCALE        6
+#define IOCSRF_DVFSV1           7
+#define IOCSRF_GMOD             9
+#define IOCSRF_VM               11
+
+#define VERSION_REG             0x0
+#define FEATURE_REG             0x8
+#define VENDOR_REG              0x10
+#define CPUNAME_REG             0x20
+#define MISC_FUNC_REG           0x420
+#define IOCSRM_EXTIOI_EN        48
+#define IOCSRM_EXTIOI_INT_ENCODE 49
+
 #define LOONGARCH_MAX_CPUS      256
 
 #define VIRT_FWCFG_BASE         0x1e020000UL
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 9538e8d61d..56fc4a1459 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -21,27 +21,6 @@
 #include "cpu-csr.h"
 #include "cpu-qom.h"
 
-#define IOCSRF_TEMP             0
-#define IOCSRF_NODECNT          1
-#define IOCSRF_MSI              2
-#define IOCSRF_EXTIOI           3
-#define IOCSRF_CSRIPI           4
-#define IOCSRF_FREQCSR          5
-#define IOCSRF_FREQSCALE        6
-#define IOCSRF_DVFSV1           7
-#define IOCSRF_GMOD             9
-#define IOCSRF_VM               11
-
-#define VERSION_REG             0x0
-#define FEATURE_REG             0x8
-#define VENDOR_REG              0x10
-#define CPUNAME_REG             0x20
-#define MISC_FUNC_REG           0x420
-#define IOCSRM_EXTIOI_EN        48
-#define IOCSRM_EXTIOI_INT_ENCODE 49
-
-#define IOCSR_MEM_SIZE          0x428
-
 #define FCSR0_M1    0x1f         /* FCSR1 mask, Enables */
 #define FCSR0_M2    0x1f1f0000   /* FCSR2 mask, Cause and Flags */
 #define FCSR0_M3    0x300        /* FCSR3 mask, Round Mode */
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v6 02/11] hw/loongarch: add virt feature avecintc support
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
  2025-09-04 12:18 ` [PATCH v6 01/11] target/loongarch: move some machine define to virt.h Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-05  8:35   ` Bibo Mao
  2025-09-04 12:18 ` [PATCH v6 03/11] hw/loongarch: add misc register supoort avecintc Song Gao
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 UTC (permalink / raw)
  To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang

Avecintc feature is added in LoongArchVirtMachinState, and it is used
to check whether virt machine supports the advanced interrupt controller
and by default set avecintc with ON_OFF_AUTO_ON.
LoongArchVirtMachineState adds misc_feature and misc_status for misc
features and status. and set the default avec feature bit.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/loongarch/virt.c         | 30 ++++++++++++++++++++++++++++++
 include/hw/loongarch/virt.h | 14 ++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index b15ada2078..1a2aa92c25 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -47,6 +47,27 @@
 #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);
+    if (lvms->avecintc == ON_OFF_AUTO_OFF) {
+        lvms->misc_feature &= ~BIT(IOCSRF_AVEC);
+        lvms->misc_status &= ~BIT(IOCSRM_AVEC_EN);
+    }
+}
+
 static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
                               void *opaque, Error **errp)
 {
@@ -846,6 +867,9 @@ static void virt_initfn(Object *obj)
     if (tcg_enabled()) {
         lvms->veiointc = ON_OFF_AUTO_OFF;
     }
+
+    lvms->misc_feature = BIT(IOCSRF_AVEC);
+    lvms->avecintc = ON_OFF_AUTO_ON;
     lvms->acpi = ON_OFF_AUTO_AUTO;
     lvms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
     lvms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
@@ -1238,6 +1262,12 @@ 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.");
+    if (tcg_enabled()) {
+        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 7120b46714..68b8e92e99 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -23,6 +23,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
@@ -31,6 +32,7 @@
 #define MISC_FUNC_REG           0x420
 #define IOCSRM_EXTIOI_EN        48
 #define IOCSRM_EXTIOI_INT_ENCODE 49
+#define IOCSRM_AVEC_EN          51
 
 #define LOONGARCH_MAX_CPUS      256
 
@@ -69,6 +71,7 @@ struct LoongArchVirtMachineState {
     Notifier     powerdown_notifier;
     OnOffAuto    acpi;
     OnOffAuto    veiointc;
+    OnOffAuto    avecintc;
     char         *oem_id;
     char         *oem_table_id;
     DeviceState  *acpi_ged;
@@ -84,6 +87,8 @@ struct LoongArchVirtMachineState {
     DeviceState *extioi;
     struct memmap_entry *memmap_table;
     unsigned int memmap_entries;
+    uint64_t misc_feature;
+    uint64_t misc_status;
 };
 
 #define TYPE_LOONGARCH_VIRT_MACHINE  MACHINE_TYPE_NAME("virt")
@@ -91,6 +96,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
 void virt_acpi_setup(LoongArchVirtMachineState *lvms);
 void virt_fdt_setup(LoongArchVirtMachineState *lvms);
 
+static inline bool virt_has_avecintc(LoongArchVirtMachineState *lvms)
+{
+    if (!(lvms->misc_feature & BIT(IOCSRF_AVEC))) {
+        return false;
+    }
+
+    return true;
+}
+
 static inline bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
 {
     if (lvms->veiointc == ON_OFF_AUTO_OFF) {
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v6 03/11] hw/loongarch: add misc register supoort avecintc
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
  2025-09-04 12:18 ` [PATCH v6 01/11] target/loongarch: move some machine define to virt.h Song Gao
  2025-09-04 12:18 ` [PATCH v6 02/11] hw/loongarch: add virt feature avecintc support Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-05  8:40   ` Bibo Mao
  2025-09-04 12:18 ` [PATCH v6 04/11] loongarch: add a advance interrupt controller device Song Gao
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 UTC (permalink / raw)
  To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang

Add feature register and misc register for avecintc feature checking and
setting

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/loongarch/virt.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 1a2aa92c25..124f96af03 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -560,6 +560,10 @@ static MemTxResult virt_iocsr_misc_write(void *opaque, hwaddr addr,
             return MEMTX_OK;
         }
 
+        if (val & BIT(IOCSRM_AVEC_EN)) {
+            lvms->misc_status |= BIT(IOCSRM_AVEC_EN);
+        }
+
         features = address_space_ldl(&lvms->as_iocsr,
                                      EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
                                      attrs, NULL);
@@ -595,6 +599,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);
+        if (virt_has_avecintc(lvms)) {
+            ret |= BIT(IOCSRF_AVEC);
+        }
         if (kvm_enabled()) {
             ret |= BIT(IOCSRF_VM);
         }
@@ -624,6 +631,10 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
         if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
             ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
         }
+        if (virt_has_avecintc(lvms) &&
+            (lvms->misc_status & BIT(IOCSRM_AVEC_EN))) {
+            ret |= BIT_ULL(IOCSRM_AVEC_EN);
+        }
         break;
     default:
         g_assert_not_reached();
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v6 04/11] loongarch: add a advance interrupt controller device
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
                   ` (2 preceding siblings ...)
  2025-09-04 12:18 ` [PATCH v6 03/11] hw/loongarch: add misc register supoort avecintc Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-05  8:44   ` Bibo Mao
  2025-09-04 12:18 ` [PATCH v6 05/11] target/loongarch: add msg interrupt CSR registers Song Gao
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 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 3137521a4a..cf2c47cd53 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -80,3 +80,4 @@ specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_
 specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c', 'loongarch_extioi_common.c'))
 specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_LOONGARCH_EXTIOI'],
                if_true: files('loongarch_extioi_kvm.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..92e2ca9590
--- /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;
+    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.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v6 05/11] target/loongarch: add msg interrupt CSR registers
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
                   ` (3 preceding siblings ...)
  2025-09-04 12:18 ` [PATCH v6 04/11] loongarch: add a advance interrupt controller device Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-05  8:55   ` Bibo Mao
  2025-09-04 12:18 ` [PATCH v6 06/11] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 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-csr.h |  3 +++
 target/loongarch/cpu.h     | 11 +++++++++++
 target/loongarch/machine.c | 27 +++++++++++++++++++++++++--
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 0834e91f30..4792677086 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -186,6 +186,9 @@ FIELD(CSR_MERRCTL, ISMERR, 0, 1)
 
 #define LOONGARCH_CSR_CTAG           0x98 /* TagLo + TagHi */
 
+#define LOONGARCH_CSR_MSGIS(N)       (0xa0 + N)
+#define LOONGARCH_CSR_MSGIR               0xa4
+
 /* Direct map windows CSRs*/
 #define LOONGARCH_CSR_DMW(N)         (0x180 + N)
 FIELD(CSR_DMW, PLV0, 0, 1)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 56fc4a1459..f083c31bb4 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -233,6 +233,13 @@ FIELD(TLB_MISC, ASID, 1, 10)
 FIELD(TLB_MISC, VPPN, 13, 35)
 FIELD(TLB_MISC, PS, 48, 6)
 
+/*Msg interrupt registers */
+#define N_MSGIS                4
+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)
 
@@ -350,6 +357,10 @@ typedef struct CPUArchState {
     uint64_t CSR_DBG;
     uint64_t CSR_DERA;
     uint64_t CSR_DSAVE;
+    /* Msg interrupt registers */
+    uint64_t CSR_MSGIS[N_MSGIS];
+    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..996fbeb501 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -10,6 +10,7 @@
 #include "migration/cpu.h"
 #include "system/tcg.h"
 #include "vec.h"
+#include "hw/loongarch/virt.h"
 
 static const VMStateDescription vmstate_fpu_reg = {
     .name = "fpu_reg",
@@ -45,6 +46,27 @@ static const VMStateDescription vmstate_fpu = {
     },
 };
 
+static bool msg_needed(void *opaque)
+{
+    MachineState *ms = MACHINE(qdev_get_machine());
+    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms);
+
+    return virt_has_avecintc(lvms);
+}
+
+static const VMStateDescription vmstate_msg = {
+    .name = "cpu/msg",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = msg_needed,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT64_ARRAY(env.CSR_MSGIS, LoongArchCPU, N_MSGIS),
+        VMSTATE_UINT64(env.CSR_MSGIR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_MSGIE, LoongArchCPU),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
 static const VMStateDescription vmstate_lsxh_reg = {
     .name = "lsxh_reg",
     .version_id = 1,
@@ -168,8 +190,8 @@ static const VMStateDescription vmstate_tlb = {
 /* LoongArch CPU state */
 const VMStateDescription vmstate_loongarch_cpu = {
     .name = "cpu",
-    .version_id = 3,
-    .minimum_version_id = 3,
+    .version_id = 4,
+    .minimum_version_id = 4,
     .fields = (const VMStateField[]) {
         VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
         VMSTATE_UINTTL(env.pc, LoongArchCPU),
@@ -245,6 +267,7 @@ const VMStateDescription vmstate_loongarch_cpu = {
         &vmstate_tlb,
 #endif
         &vmstate_lbt,
+        &vmstate_msg,
         NULL
     }
 };
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v6 06/11] hw/loongarch: AVEC controller add a MemoryRegion
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
                   ` (4 preceding siblings ...)
  2025-09-04 12:18 ` [PATCH v6 05/11] target/loongarch: add msg interrupt CSR registers Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-05  8:58   ` Bibo Mao
  2025-09-04 12:18 ` [PATCH v6 07/11] hw/loongarch: Implement avec controller imput and output pins Song Gao
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 UTC (permalink / raw)
  To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang

the AVEC controller use [2fe00000-2ff000000) Memory.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/intc/loongarch_avec.c         | 24 ++++++++++++++++++++
 hw/loongarch/virt.c              | 39 +++++++++++++++++++++++++++++++-
 include/hw/intc/loongarch_avec.h |  1 +
 include/hw/loongarch/virt.h      |  1 +
 include/hw/pci-host/ls7a.h       |  2 ++
 5 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 5a3e7ecc03..253bab5461 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,12 @@ 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, VIRT_AVEC_MSG_OFFSET);
+    sysbus_init_mmio(shd, &s->avec_mmio);
+    msi_nonbroken = true;
     return;
 }
 
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 124f96af03..1b390fb876 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"
@@ -382,7 +383,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;
 
@@ -428,6 +429,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 */
@@ -435,6 +463,15 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
     lvms->ipi = ipi;
     sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
 
+    /* Create AVEC device*/
+    if (virt_has_avecintc(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_AVEC_BASE,
+                        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 92e2ca9590..3e8cf7d2c1 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 68b8e92e99..bc3cee705d 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -89,6 +89,7 @@ struct LoongArchVirtMachineState {
     unsigned int memmap_entries;
     uint64_t misc_feature;
     uint64_t misc_status;
+    DeviceState *avec;
 };
 
 #define TYPE_LOONGARCH_VIRT_MACHINE  MACHINE_TYPE_NAME("virt")
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
index 79d4ea8501..199f47ecc0 100644
--- a/include/hw/pci-host/ls7a.h
+++ b/include/hw/pci-host/ls7a.h
@@ -24,6 +24,8 @@
 #define VIRT_PCH_REG_BASE        0x10000000UL
 #define VIRT_IOAPIC_REG_BASE     (VIRT_PCH_REG_BASE)
 #define VIRT_PCH_MSI_ADDR_LOW    0x2FF00000UL
+#define VIRT_AVEC_MSG_OFFSET     0x1000000UL
+#define VIRT_AVEC_BASE           (VIRT_PCH_MSI_ADDR_LOW - VIRT_AVEC_MSG_OFFSET)
 #define VIRT_PCH_REG_SIZE        0x400
 #define VIRT_PCH_MSI_SIZE        0x8
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v6 07/11] hw/loongarch: Implement avec controller imput and output pins
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
                   ` (5 preceding siblings ...)
  2025-09-04 12:18 ` [PATCH v6 06/11] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-05  9:15   ` Bibo Mao
  2025-09-04 12:18 ` [PATCH v6 08/11] hw/loongarch: Implement avec set irq Song Gao
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 UTC (permalink / raw)
  To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang

the AVEC controller supports 256*256 irqs input, all the irqs connect CPU INT_AVEC irq

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/intc/loongarch_avec.c | 20 ++++++++++++++++++++
 hw/loongarch/virt.c      | 10 +++++++++-
 target/loongarch/cpu.h   |  3 ++-
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 253bab5461..1f9f376898 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -38,7 +38,12 @@ static const MemoryRegionOps loongarch_avec_ops = {
 
 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;
 
     Error *local_err = NULL;
     lac->parent_realize(dev, &local_err);
@@ -47,6 +52,21 @@ 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);
+        qdev_init_gpio_out(dev, &s->cpu[i].parent_irq, 1);
+    }
+
     return;
 }
 
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 1b390fb876..a3f8f4c854 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -383,9 +383,11 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
 static void virt_irq_init(LoongArchVirtMachineState *lvms)
 {
     DeviceState *pch_pic, *pch_msi;
-    DeviceState *ipi, *extioi, *avec;
+    DeviceState *ipi, *extioi, *avec, *cpudev;
     SysBusDevice *d;
     int i, start, num;
+    CPUState *cpu_state;
+    MachineState *ms;
 
     /*
      * Extended IRQ model.
@@ -470,6 +472,12 @@ 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_AVEC_BASE,
                         sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
+        ms = MACHINE(lvms);
+        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 */
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index f083c31bb4..55a5dc33f2 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -217,9 +217,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.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v6 08/11] hw/loongarch: Implement avec set irq
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
                   ` (6 preceding siblings ...)
  2025-09-04 12:18 ` [PATCH v6 07/11] hw/loongarch: Implement avec controller imput and output pins Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-05  9:52   ` Bibo Mao
  2025-09-05 10:05   ` Bibo Mao
  2025-09-04 12:18 ` [PATCH v6 09/11] target/loongarch: Add CSR_ESTAT.bit15 and CSR_ECFG.bit15 for msg interrupts Song Gao
                   ` (2 subsequent siblings)
  10 siblings, 2 replies; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 UTC (permalink / raw)
  To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang

Implement avec set irq and update CSR_MSIS.

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

diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 1f9f376898..03a20a7b60 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -16,6 +16,13 @@
 #include "migration/vmstate.h"
 #include "trace.h"
 #include "hw/qdev-properties.h"
+#include "target/loongarch/cpu.h"
+#include "qemu/error-report.h"
+
+/* msg addr field */
+FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
+FIELD(MSG_ADDR, CPU_NUM, 12, 8)
+FIELD(MSG_ADDR, FIX, 28, 12)
 
 static uint64_t loongarch_avec_mem_read(void *opaque,
                                         hwaddr addr, unsigned size)
@@ -23,13 +30,60 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
     return 0;
 }
 
+static void do_set_vcpu_avec_irq(CPUState *cs, run_on_cpu_data data)
+{
+    AVECCore *core = data.host_ptr;
+    CPULoongArchState *env;
+
+    assert(cs->cpu_index == core->dest_cpu);
+    env = &LOONGARCH_CPU(cs)->env;
+    if (core->level) {
+        set_bit(core->pending, &env->CSR_MSGIS[core->pending / 64]);
+    }
+    g_free(core);
+}
+
+
+static void avec_update_csr(AVECCore *core, int cpu_num,
+                            int irq_num, int level)
+{
+    CPUState *cs = qemu_get_cpu(cpu_num);
+
+    core->pending = irq_num;
+    core->dest_cpu = cpu_num;
+    core->level = level;
+    async_run_on_cpu(cs, do_set_vcpu_avec_irq,
+                         RUN_ON_CPU_HOST_PTR(core));
+}
+
+static void avec_set_irq(LoongArchAVECState *s, int cpu_num,
+                         int irq_num, int level)
+{
+    AVECCore *core;
+
+    core = g_new(AVECCore, 1);
+
+    if (level) {
+        avec_update_csr(core, cpu_num, irq_num, level);
+    }
+    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
+}
+
 static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
                                      uint64_t val, unsigned size)
 {
-    return;
+    int irq_num, cpu_num = 0;
+    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
+    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
+    CPUState *cs;
+
+    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
+    cs = cpu_by_arch_id(cpu_num);
+    cpu_num = cs->cpu_index;
+    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
+    avec_set_irq(s, cpu_num, irq_num, 1);
 }
 
-
 static const MemoryRegionOps loongarch_avec_ops = {
     .read = loongarch_avec_mem_read,
     .write = loongarch_avec_mem_write,
diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
index 3e8cf7d2c1..83656f8df4 100644
--- a/include/hw/intc/loongarch_avec.h
+++ b/include/hw/intc/loongarch_avec.h
@@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, LoongArchAVECClass, LOONGARCH_AVEC)
 typedef struct AVECCore {
     CPUState *cpu;
     qemu_irq parent_irq;
+    uint64_t pending;
+    uint64_t dest_cpu;
+    bool   level;
     uint64_t arch_id;
 } AVECCore;
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v6 09/11] target/loongarch: Add CSR_ESTAT.bit15 and CSR_ECFG.bit15 for msg interrupts.
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
                   ` (7 preceding siblings ...)
  2025-09-04 12:18 ` [PATCH v6 08/11] hw/loongarch: Implement avec set irq Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-06  7:18   ` Bibo Mao
  2025-09-04 12:18 ` [PATCH v6 10/11] target/loongarch:Implement csrrd CSR_MSGIR register Song Gao
  2025-09-04 12:18 ` [PATCH v6 11/11] hw/loongarch: Implement AVEC plug/unplug interfaces Song Gao
  10 siblings, 1 reply; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 UTC (permalink / raw)
  To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang

Add CSR_ESTAT.bit15 and CSR_ECFG.bit15 for AVEC irq.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/cpu-csr.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 4792677086..6ec13d13d1 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -34,11 +34,13 @@ FIELD(CSR_MISC, ALCL, 12, 4)
 FIELD(CSR_MISC, DWPL, 16, 3)
 
 #define LOONGARCH_CSR_ECFG           0x4 /* Exception config */
-FIELD(CSR_ECFG, LIE, 0, 13)
+FIELD(CSR_ECFG, LIE, 0, 15)        /*bit 15 is msg interrupt enabled */
+FIELD(CSR_ECFG, MSGINT, 14, 1)
 FIELD(CSR_ECFG, VS, 16, 3)
 
 #define LOONGARCH_CSR_ESTAT          0x5 /* Exception status */
-FIELD(CSR_ESTAT, IS, 0, 13)
+FIELD(CSR_ESTAT, IS, 0, 15)        /*bit 15 is msg interrupt enabled */
+FIELD(CSR_ESTAT, MSGINT, 14, 1)
 FIELD(CSR_ESTAT, ECODE, 16, 6)
 FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v6 10/11] target/loongarch:Implement csrrd CSR_MSGIR register
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
                   ` (8 preceding siblings ...)
  2025-09-04 12:18 ` [PATCH v6 09/11] target/loongarch: Add CSR_ESTAT.bit15 and CSR_ECFG.bit15 for msg interrupts Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-06  7:20   ` Bibo Mao
  2025-09-04 12:18 ` [PATCH v6 11/11] hw/loongarch: Implement AVEC plug/unplug interfaces Song Gao
  10 siblings, 1 reply; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 UTC (permalink / raw)
  To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang

implement the read-clear feature for CSR_MSGIR register.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/csr.c                        |  5 +++++
 target/loongarch/tcg/csr_helper.c             | 21 +++++++++++++++++++
 target/loongarch/tcg/helper.h                 |  1 +
 .../tcg/insn_trans/trans_privileged.c.inc     |  1 +
 4 files changed, 28 insertions(+)

diff --git a/target/loongarch/csr.c b/target/loongarch/csr.c
index 7ea0a30450..f973780bba 100644
--- a/target/loongarch/csr.c
+++ b/target/loongarch/csr.c
@@ -97,6 +97,11 @@ static CSRInfo csr_info[] = {
     CSR_OFF(DBG),
     CSR_OFF(DERA),
     CSR_OFF(DSAVE),
+    CSR_OFF_ARRAY(MSGIS, 0),
+    CSR_OFF_ARRAY(MSGIS, 1),
+    CSR_OFF_ARRAY(MSGIS, 2),
+    CSR_OFF_ARRAY(MSGIS, 3),
+    CSR_OFF(MSGIR),
 };
 
 CSRInfo *get_csr(unsigned int csr_num)
diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c
index 28b1bb86bd..347dca84b8 100644
--- a/target/loongarch/tcg/csr_helper.c
+++ b/target/loongarch/tcg/csr_helper.c
@@ -72,6 +72,27 @@ target_ulong helper_csrrd_tval(CPULoongArchState *env)
     return cpu_loongarch_get_constant_timer_ticks(cpu);
 }
 
+target_ulong helper_csrrd_msgir(CPULoongArchState *env)
+{
+    int irq, new;
+
+    irq = find_first_bit(env->CSR_MSGIS, 256);
+    if (irq < 256) {
+        clear_bit(irq, env->CSR_MSGIS);
+        new = find_first_bit(env->CSR_MSGIS, 256);
+        if (new < 256) {
+            return irq;
+        }
+
+        env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
+    } else {
+        /* bit 31 set 1 for no invalid irq */
+        irq = BIT(31);
+    }
+
+    return irq;
+}
+
 target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val)
 {
     int64_t old_v = env->CSR_ESTAT;
diff --git a/target/loongarch/tcg/helper.h b/target/loongarch/tcg/helper.h
index 1d5cb0198c..db57dbfc16 100644
--- a/target/loongarch/tcg/helper.h
+++ b/target/loongarch/tcg/helper.h
@@ -100,6 +100,7 @@ DEF_HELPER_1(rdtime_d, i64, env)
 DEF_HELPER_1(csrrd_pgd, i64, env)
 DEF_HELPER_1(csrrd_cpuid, i64, env)
 DEF_HELPER_1(csrrd_tval, i64, env)
+DEF_HELPER_1(csrrd_msgir, i64, env)
 DEF_HELPER_2(csrwr_stlbps, i64, env, tl)
 DEF_HELPER_2(csrwr_estat, i64, env, tl)
 DEF_HELPER_2(csrwr_asid, i64, env, tl)
diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
index 34cfab8879..a407ab51b7 100644
--- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
@@ -83,6 +83,7 @@ void loongarch_csr_translate_init(void)
     SET_CSR_FUNC(TCFG,  NULL, gen_helper_csrwr_tcfg);
     SET_CSR_FUNC(TVAL,  gen_helper_csrrd_tval, NULL);
     SET_CSR_FUNC(TICLR, NULL, gen_helper_csrwr_ticlr);
+    SET_CSR_FUNC(MSGIR, gen_helper_csrrd_msgir, NULL);
 }
 #undef SET_CSR_FUNC
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v6 11/11] hw/loongarch: Implement AVEC plug/unplug interfaces
  2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
                   ` (9 preceding siblings ...)
  2025-09-04 12:18 ` [PATCH v6 10/11] target/loongarch:Implement csrrd CSR_MSGIR register Song Gao
@ 2025-09-04 12:18 ` Song Gao
  2025-09-06  7:22   ` Bibo Mao
  10 siblings, 1 reply; 28+ messages in thread
From: Song Gao @ 2025-09-04 12:18 UTC (permalink / raw)
  To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang

when cpu added, connect avec irq to cpu INT_AVEC irq pin.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/intc/loongarch_avec.c | 71 ++++++++++++++++++++++++++++++++++++++++
 hw/loongarch/virt.c      | 11 +++++++
 2 files changed, 82 insertions(+)

diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 03a20a7b60..f4b0ff29fa 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -140,14 +140,81 @@ static void loongarch_avec_init(Object *obj)
     return;
 }
 
+static AVECCore *loongarch_avec_get_cpu(LoongArchAVECState *s,
+                                        DeviceState *dev)
+{
+    CPUClass *k = CPU_GET_CLASS(dev);
+    uint64_t arch_id = k->get_arch_id(CPU(dev));
+    int i;
+
+    for (i = 0; i < s->num_cpu; i++) {
+        if (s->cpu[i].arch_id == arch_id) {
+            return &s->cpu[i];
+        }
+    }
+
+    return NULL;
+}
+
+static void loongarch_avec_cpu_plug(HotplugHandler *hotplug_dev,
+                                   DeviceState *dev, Error **errp)
+{
+    LoongArchAVECState *s = LOONGARCH_AVEC(hotplug_dev);
+    Object *obj = OBJECT(dev);
+    AVECCore *core;
+    int index;
+
+    if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
+        warn_report("LoongArch AVEC: Invalid %s device type",
+                                       object_get_typename(obj));
+        return;
+    }
+    core = loongarch_avec_get_cpu(s, dev);
+    if (!core) {
+        return;
+    }
+
+    core->cpu = CPU(dev);
+    index = core - s->cpu;
+
+    /* connect avec msg irq to cpu irq */
+    qdev_connect_gpio_out(DEVICE(s), index, qdev_get_gpio_in(dev, INT_AVEC));
+    return;
+}
+
+static void loongarch_avec_cpu_unplug(HotplugHandler *hotplug_dev,
+                                     DeviceState *dev, Error **errp)
+{
+    LoongArchAVECState *s = LOONGARCH_AVEC(hotplug_dev);
+    Object *obj = OBJECT(dev);
+    AVECCore *core;
+
+    if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
+        warn_report("LoongArch AVEC: Invalid %s device type",
+                                       object_get_typename(obj));
+        return;
+    }
+
+    core = loongarch_avec_get_cpu(s, dev);
+
+    if (!core) {
+        return;
+    }
+
+    core->cpu = NULL;
+}
+
 static void loongarch_avec_class_init(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    HotplugHandlerClass *hc = HOTPLUG_HANDLER_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);
+    hc->plug = loongarch_avec_cpu_plug;
+    hc->unplug = loongarch_avec_cpu_unplug;
 }
 
 static const TypeInfo loongarch_avec_info = {
@@ -156,6 +223,10 @@ static const TypeInfo loongarch_avec_info = {
     .instance_size = sizeof(LoongArchAVECState),
     .instance_init = loongarch_avec_init,
     .class_init    = loongarch_avec_class_init,
+    .interfaces    = (const InterfaceInfo[]) {
+        { TYPE_HOTPLUG_HANDLER },
+        { }
+    },
 };
 
 static void loongarch_avec_register_types(void)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index a3f8f4c854..ad78dd3f19 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -377,6 +377,10 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
                              &error_abort);
         hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), DEVICE(cs),
                              &error_abort);
+        if (lvms->avec) {
+            hotplug_handler_plug(HOTPLUG_HANDLER(lvms->avec), DEVICE(cs),
+                                 &error_abort);
+        }
     }
 }
 
@@ -1089,6 +1093,9 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev,
     /* Notify ipi and extioi irqchip to remove interrupt routing to CPU */
     hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->ipi), dev, &error_abort);
     hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->extioi), dev, &error_abort);
+    if (lvms->avec) {
+        hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->avec), dev, &error_abort);
+    }
 
     /* Notify acpi ged CPU removed */
     hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->acpi_ged), dev, &error_abort);
@@ -1112,6 +1119,10 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
         hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), dev, &error_abort);
     }
 
+    if (lvms->avec) {
+        hotplug_handler_plug(HOTPLUG_HANDLER(lvms->avec), dev, &error_abort);
+    }
+
     if (lvms->acpi_ged) {
         hotplug_handler_plug(HOTPLUG_HANDLER(lvms->acpi_ged), dev,
                              &error_abort);
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 02/11] hw/loongarch: add virt feature avecintc support
  2025-09-04 12:18 ` [PATCH v6 02/11] hw/loongarch: add virt feature avecintc support Song Gao
@ 2025-09-05  8:35   ` Bibo Mao
  0 siblings, 0 replies; 28+ messages in thread
From: Bibo Mao @ 2025-09-05  8:35 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



On 2025/9/4 下午8:18, Song Gao wrote:
> Avecintc feature is added in LoongArchVirtMachinState, and it is used
> to check whether virt machine supports the advanced interrupt controller
> and by default set avecintc with ON_OFF_AUTO_ON.
> LoongArchVirtMachineState adds misc_feature and misc_status for misc
> features and status. and set the default avec feature bit.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   hw/loongarch/virt.c         | 30 ++++++++++++++++++++++++++++++
>   include/hw/loongarch/virt.h | 14 ++++++++++++++
>   2 files changed, 44 insertions(+)
> 
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index b15ada2078..1a2aa92c25 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -47,6 +47,27 @@
>   #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);
> +    if (lvms->avecintc == ON_OFF_AUTO_OFF) {
> +        lvms->misc_feature &= ~BIT(IOCSRF_AVEC);
> +        lvms->misc_status &= ~BIT(IOCSRM_AVEC_EN);
> +    }
> +}
> +
>   static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
>                                 void *opaque, Error **errp)
>   {
> @@ -846,6 +867,9 @@ static void virt_initfn(Object *obj)
>       if (tcg_enabled()) {
>           lvms->veiointc = ON_OFF_AUTO_OFF;
>       }
> +
> +    lvms->misc_feature = BIT(IOCSRF_AVEC);
> +    lvms->avecintc = ON_OFF_AUTO_ON;
>       lvms->acpi = ON_OFF_AUTO_AUTO;
>       lvms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
>       lvms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
> @@ -1238,6 +1262,12 @@ 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.");
> +    if (tcg_enabled()) {
> +        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 7120b46714..68b8e92e99 100644
> --- a/include/hw/loongarch/virt.h
> +++ b/include/hw/loongarch/virt.h
> @@ -23,6 +23,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
> @@ -31,6 +32,7 @@
>   #define MISC_FUNC_REG           0x420
>   #define IOCSRM_EXTIOI_EN        48
>   #define IOCSRM_EXTIOI_INT_ENCODE 49
> +#define IOCSRM_AVEC_EN          51
>   
>   #define LOONGARCH_MAX_CPUS      256
>   
> @@ -69,6 +71,7 @@ struct LoongArchVirtMachineState {
>       Notifier     powerdown_notifier;
>       OnOffAuto    acpi;
>       OnOffAuto    veiointc;
> +    OnOffAuto    avecintc;
>       char         *oem_id;
>       char         *oem_table_id;
>       DeviceState  *acpi_ged;
> @@ -84,6 +87,8 @@ struct LoongArchVirtMachineState {
>       DeviceState *extioi;
>       struct memmap_entry *memmap_table;
>       unsigned int memmap_entries;
> +    uint64_t misc_feature;
> +    uint64_t misc_status;
>   };
>   
>   #define TYPE_LOONGARCH_VIRT_MACHINE  MACHINE_TYPE_NAME("virt")
> @@ -91,6 +96,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
>   void virt_acpi_setup(LoongArchVirtMachineState *lvms);
>   void virt_fdt_setup(LoongArchVirtMachineState *lvms);
>   
> +static inline bool virt_has_avecintc(LoongArchVirtMachineState *lvms)
> +{
> +    if (!(lvms->misc_feature & BIT(IOCSRF_AVEC))) {
> +        return false;
> +    }
> +
> +    return true;
> +}
> +
>   static inline bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
>   {
>       if (lvms->veiointc == ON_OFF_AUTO_OFF) {
> 
Reviewed-by: Bibo Mao <maobibo@loongson.cn>



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 03/11] hw/loongarch: add misc register supoort avecintc
  2025-09-04 12:18 ` [PATCH v6 03/11] hw/loongarch: add misc register supoort avecintc Song Gao
@ 2025-09-05  8:40   ` Bibo Mao
  2025-09-06  1:42     ` gaosong
  0 siblings, 1 reply; 28+ messages in thread
From: Bibo Mao @ 2025-09-05  8:40 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



On 2025/9/4 下午8:18, Song Gao wrote:
> Add feature register and misc register for avecintc feature checking and
> setting
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   hw/loongarch/virt.c | 11 +++++++++++
>   1 file changed, 11 insertions(+)
> 
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 1a2aa92c25..124f96af03 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -560,6 +560,10 @@ static MemTxResult virt_iocsr_misc_write(void *opaque, hwaddr addr,
>               return MEMTX_OK;
>           }
>   
> +        if (val & BIT(IOCSRM_AVEC_EN)) {
> +            lvms->misc_status |= BIT(IOCSRM_AVEC_EN);
> +        }
> +
how about adding virt_has_avecintc(lvms) here, such as
            if (virt_has_avecintc(lvms) && val & BIT(IOCSRM_AVEC_EN)) {
                lvms->misc_status |= BIT(IOCSRM_AVEC_EN);
            }

Otherwise looks good to me.
Reviewed-by: Bibo Mao <maobibo@loongson.cn>


Regards
Bibo Mao

>           features = address_space_ldl(&lvms->as_iocsr,
>                                        EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
>                                        attrs, NULL);
> @@ -595,6 +599,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);
> +        if (virt_has_avecintc(lvms)) {
> +            ret |= BIT(IOCSRF_AVEC);
> +        }
>           if (kvm_enabled()) {
>               ret |= BIT(IOCSRF_VM);
>           }
> @@ -624,6 +631,10 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
>           if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
>               ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
>           }
> +        if (virt_has_avecintc(lvms) &&
> +            (lvms->misc_status & BIT(IOCSRM_AVEC_EN))) {
> +            ret |= BIT_ULL(IOCSRM_AVEC_EN);
> +        }
>           break;
>       default:
>           g_assert_not_reached();
> 



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 04/11] loongarch: add a advance interrupt controller device
  2025-09-04 12:18 ` [PATCH v6 04/11] loongarch: add a advance interrupt controller device Song Gao
@ 2025-09-05  8:44   ` Bibo Mao
  0 siblings, 0 replies; 28+ messages in thread
From: Bibo Mao @ 2025-09-05  8:44 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



On 2025/9/4 下午8:18, Song Gao wrote:
> Add Loongarch  advance interrupt controller device base Definition.
Two space here with "Loongarch  advance", maybe advanced is better.

Otherwise looks good to me.

Reviewed-by: Bibo Mao <maobibo@loongson.cn>

> 
> 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 3137521a4a..cf2c47cd53 100644
> --- a/hw/intc/meson.build
> +++ b/hw/intc/meson.build
> @@ -80,3 +80,4 @@ specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_
>   specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c', 'loongarch_extioi_common.c'))
>   specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_LOONGARCH_EXTIOI'],
>                  if_true: files('loongarch_extioi_kvm.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..92e2ca9590
> --- /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;
> +    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;
> +};
> 



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 05/11] target/loongarch: add msg interrupt CSR registers
  2025-09-04 12:18 ` [PATCH v6 05/11] target/loongarch: add msg interrupt CSR registers Song Gao
@ 2025-09-05  8:55   ` Bibo Mao
  2025-09-06  2:22     ` gaosong
  0 siblings, 1 reply; 28+ messages in thread
From: Bibo Mao @ 2025-09-05  8:55 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



On 2025/9/4 下午8:18, Song Gao wrote:
> include CSR_MSGIS0-3, CSR_MSGIR and CSR_MSGIE.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   target/loongarch/cpu-csr.h |  3 +++
>   target/loongarch/cpu.h     | 11 +++++++++++
>   target/loongarch/machine.c | 27 +++++++++++++++++++++++++--
>   3 files changed, 39 insertions(+), 2 deletions(-)
> 
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> index 0834e91f30..4792677086 100644
> --- a/target/loongarch/cpu-csr.h
> +++ b/target/loongarch/cpu-csr.h
> @@ -186,6 +186,9 @@ FIELD(CSR_MERRCTL, ISMERR, 0, 1)
>   
>   #define LOONGARCH_CSR_CTAG           0x98 /* TagLo + TagHi */
>   
> +#define LOONGARCH_CSR_MSGIS(N)       (0xa0 + N)
> +#define LOONGARCH_CSR_MSGIR               0xa4
> +
>   /* Direct map windows CSRs*/
>   #define LOONGARCH_CSR_DMW(N)         (0x180 + N)
>   FIELD(CSR_DMW, PLV0, 0, 1)
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index 56fc4a1459..f083c31bb4 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -233,6 +233,13 @@ FIELD(TLB_MISC, ASID, 1, 10)
>   FIELD(TLB_MISC, VPPN, 13, 35)
>   FIELD(TLB_MISC, PS, 48, 6)
>   
> +/*Msg interrupt registers */
> +#define N_MSGIS                4
> +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)
>   
> @@ -350,6 +357,10 @@ typedef struct CPUArchState {
>       uint64_t CSR_DBG;
>       uint64_t CSR_DERA;
>       uint64_t CSR_DSAVE;
> +    /* Msg interrupt registers */
> +    uint64_t CSR_MSGIS[N_MSGIS];
> +    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..996fbeb501 100644
> --- a/target/loongarch/machine.c
> +++ b/target/loongarch/machine.c
> @@ -10,6 +10,7 @@
>   #include "migration/cpu.h"
>   #include "system/tcg.h"
>   #include "vec.h"
> +#include "hw/loongarch/virt.h"
>   
>   static const VMStateDescription vmstate_fpu_reg = {
>       .name = "fpu_reg",
> @@ -45,6 +46,27 @@ static const VMStateDescription vmstate_fpu = {
>       },
>   };
>   
> +static bool msg_needed(void *opaque)
> +{
> +    MachineState *ms = MACHINE(qdev_get_machine());
The avec CSR registers CSR_MSGIR etc is part of CPU, I just think
it will be better to check avec CPU feature rather than board feature.

> +    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms);
> +
> +    return virt_has_avecintc(lvms);
It supposes that LoongArch CPU must be together with virt machine :)

> +}
> +
> +static const VMStateDescription vmstate_msg = {
how about rename it as vmstate_avec?  the same with msg_needed.


Regards
Bibo Mao


> +    .name = "cpu/msg",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .needed = msg_needed,
> +    .fields = (const VMStateField[]) {
> +        VMSTATE_UINT64_ARRAY(env.CSR_MSGIS, LoongArchCPU, N_MSGIS),
> +        VMSTATE_UINT64(env.CSR_MSGIR, LoongArchCPU),
> +        VMSTATE_UINT64(env.CSR_MSGIE, LoongArchCPU),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +
>   static const VMStateDescription vmstate_lsxh_reg = {
>       .name = "lsxh_reg",
>       .version_id = 1,
> @@ -168,8 +190,8 @@ static const VMStateDescription vmstate_tlb = {
>   /* LoongArch CPU state */
>   const VMStateDescription vmstate_loongarch_cpu = {
>       .name = "cpu",
> -    .version_id = 3,
> -    .minimum_version_id = 3,
> +    .version_id = 4,
> +    .minimum_version_id = 4,
>       .fields = (const VMStateField[]) {
>           VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
>           VMSTATE_UINTTL(env.pc, LoongArchCPU),
> @@ -245,6 +267,7 @@ const VMStateDescription vmstate_loongarch_cpu = {
>           &vmstate_tlb,
>   #endif
>           &vmstate_lbt,
> +        &vmstate_msg,
>           NULL
>       }
>   };
> 



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 06/11] hw/loongarch: AVEC controller add a MemoryRegion
  2025-09-04 12:18 ` [PATCH v6 06/11] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
@ 2025-09-05  8:58   ` Bibo Mao
  0 siblings, 0 replies; 28+ messages in thread
From: Bibo Mao @ 2025-09-05  8:58 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



On 2025/9/4 下午8:18, Song Gao wrote:
> the AVEC controller use [2fe00000-2ff000000) Memory.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   hw/intc/loongarch_avec.c         | 24 ++++++++++++++++++++
>   hw/loongarch/virt.c              | 39 +++++++++++++++++++++++++++++++-
>   include/hw/intc/loongarch_avec.h |  1 +
>   include/hw/loongarch/virt.h      |  1 +
>   include/hw/pci-host/ls7a.h       |  2 ++
>   5 files changed, 66 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index 5a3e7ecc03..253bab5461 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,12 @@ 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, VIRT_AVEC_MSG_OFFSET);
> +    sysbus_init_mmio(shd, &s->avec_mmio);
> +    msi_nonbroken = true;
>       return;
>   }
>   
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 124f96af03..1b390fb876 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"
> @@ -382,7 +383,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;
>   
> @@ -428,6 +429,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 */
> @@ -435,6 +463,15 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
>       lvms->ipi = ipi;
>       sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
>   
> +    /* Create AVEC device*/
> +    if (virt_has_avecintc(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_AVEC_BASE,
> +                        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 92e2ca9590..3e8cf7d2c1 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 68b8e92e99..bc3cee705d 100644
> --- a/include/hw/loongarch/virt.h
> +++ b/include/hw/loongarch/virt.h
> @@ -89,6 +89,7 @@ struct LoongArchVirtMachineState {
>       unsigned int memmap_entries;
>       uint64_t misc_feature;Reviewed-by: Bibo Mao <maobibo@loongson.cn>
>       uint64_t misc_status;
> +    DeviceState *avec;
>   };
>   
>   #define TYPE_LOONGARCH_VIRT_MACHINE  MACHINE_TYPE_NAME("virt")
> diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
> index 79d4ea8501..199f47ecc0 100644
> --- a/include/hw/pci-host/ls7a.h
> +++ b/include/hw/pci-host/ls7a.h
> @@ -24,6 +24,8 @@
>   #define VIRT_PCH_REG_BASE        0x10000000UL
>   #define VIRT_IOAPIC_REG_BASE     (VIRT_PCH_REG_BASE)
>   #define VIRT_PCH_MSI_ADDR_LOW    0x2FF00000UL
> +#define VIRT_AVEC_MSG_OFFSET     0x1000000UL
> +#define VIRT_AVEC_BASE           (VIRT_PCH_MSI_ADDR_LOW - VIRT_AVEC_MSG_OFFSET)
>   #define VIRT_PCH_REG_SIZE        0x400
>   #define VIRT_PCH_MSI_SIZE        0x8
>   
> 
Reviewed-by: Bibo Mao <maobibo@loongson.cn>



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 07/11] hw/loongarch: Implement avec controller imput and output pins
  2025-09-04 12:18 ` [PATCH v6 07/11] hw/loongarch: Implement avec controller imput and output pins Song Gao
@ 2025-09-05  9:15   ` Bibo Mao
  0 siblings, 0 replies; 28+ messages in thread
From: Bibo Mao @ 2025-09-05  9:15 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



On 2025/9/4 下午8:18, Song Gao wrote:
> the AVEC controller supports 256*256 irqs input, all the irqs connect CPU INT_AVEC irq
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   hw/intc/loongarch_avec.c | 20 ++++++++++++++++++++
>   hw/loongarch/virt.c      | 10 +++++++++-
>   target/loongarch/cpu.h   |  3 ++-
>   3 files changed, 31 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index 253bab5461..1f9f376898 100644
> --- a/hw/intc/loongarch_avec.c
> +++ b/hw/intc/loongarch_avec.c
> @@ -38,7 +38,12 @@ static const MemoryRegionOps loongarch_avec_ops = {
>   
>   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;
>   
>       Error *local_err = NULL;
>       lac->parent_realize(dev, &local_err);
> @@ -47,6 +52,21 @@ 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);
> +        qdev_init_gpio_out(dev, &s->cpu[i].parent_irq, 1);
> +    }
> +
>       return;
>   }
>   
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 1b390fb876..a3f8f4c854 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -383,9 +383,11 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
>   static void virt_irq_init(LoongArchVirtMachineState *lvms)
>   {
>       DeviceState *pch_pic, *pch_msi;
> -    DeviceState *ipi, *extioi, *avec;
> +    DeviceState *ipi, *extioi, *avec, *cpudev;
>       SysBusDevice *d;
>       int i, start, num;
> +    CPUState *cpu_state;
> +    MachineState *ms;
>   
>       /*
>        * Extended IRQ model.
> @@ -470,6 +472,12 @@ 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_AVEC_BASE,
>                           sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
> +        ms = MACHINE(lvms);
> +        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));
> +        }
I think it can be moved to hotplug interface of avec.

Regards
Bibo Mao
>       }
>   
>       /* Create EXTIOI device */
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index f083c31bb4..55a5dc33f2 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -217,9 +217,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] 28+ messages in thread

* Re: [PATCH v6 08/11] hw/loongarch: Implement avec set irq
  2025-09-04 12:18 ` [PATCH v6 08/11] hw/loongarch: Implement avec set irq Song Gao
@ 2025-09-05  9:52   ` Bibo Mao
  2025-09-06  8:26     ` gaosong
  2025-09-05 10:05   ` Bibo Mao
  1 sibling, 1 reply; 28+ messages in thread
From: Bibo Mao @ 2025-09-05  9:52 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



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

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

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

Regards
Bibo Mao
> +
> +    if (level) {
> +        avec_update_csr(core, cpu_num, irq_num, level);
> +    }
> +    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
> +}
> +
>   static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
>                                        uint64_t val, unsigned size)
>   {
> -    return;
> +    int irq_num, cpu_num = 0;
> +    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
> +    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
> +    CPUState *cs;
> +
> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> +    cs = cpu_by_arch_id(cpu_num);
> +    cpu_num = cs->cpu_index;
> +    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
> +    avec_set_irq(s, cpu_num, irq_num, 1);
>   }
>   
> -
>   static const MemoryRegionOps loongarch_avec_ops = {
>       .read = loongarch_avec_mem_read,
>       .write = loongarch_avec_mem_write,
> diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
> index 3e8cf7d2c1..83656f8df4 100644
> --- a/include/hw/intc/loongarch_avec.h
> +++ b/include/hw/intc/loongarch_avec.h
> @@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, LoongArchAVECClass, LOONGARCH_AVEC)
>   typedef struct AVECCore {
>       CPUState *cpu;
>       qemu_irq parent_irq;
> +    uint64_t pending;
> +    uint64_t dest_cpu;
> +    bool   level;
>       uint64_t arch_id;
>   } AVECCore;
>   
> 



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 08/11] hw/loongarch: Implement avec set irq
  2025-09-04 12:18 ` [PATCH v6 08/11] hw/loongarch: Implement avec set irq Song Gao
  2025-09-05  9:52   ` Bibo Mao
@ 2025-09-05 10:05   ` Bibo Mao
  2025-09-06  7:13     ` Bibo Mao
  1 sibling, 1 reply; 28+ messages in thread
From: Bibo Mao @ 2025-09-05 10:05 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



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

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

Regargs
Bibo Mao
> +}
> +
>   static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
>                                        uint64_t val, unsigned size)
>   {
> -    return;
> +    int irq_num, cpu_num = 0;
> +    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
> +    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
> +    CPUState *cs;
> +
> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> +    cs = cpu_by_arch_id(cpu_num);
> +    cpu_num = cs->cpu_index;
> +    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
> +    avec_set_irq(s, cpu_num, irq_num, 1);
>   }
>   
> -
>   static const MemoryRegionOps loongarch_avec_ops = {
>       .read = loongarch_avec_mem_read,
>       .write = loongarch_avec_mem_write,
> diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
> index 3e8cf7d2c1..83656f8df4 100644
> --- a/include/hw/intc/loongarch_avec.h
> +++ b/include/hw/intc/loongarch_avec.h
> @@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, LoongArchAVECClass, LOONGARCH_AVEC)
>   typedef struct AVECCore {
>       CPUState *cpu;
>       qemu_irq parent_irq;
> +    uint64_t pending;
> +    uint64_t dest_cpu;
> +    bool   level;
>       uint64_t arch_id;
>   } AVECCore;
>   
> 



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 03/11] hw/loongarch: add misc register supoort avecintc
  2025-09-05  8:40   ` Bibo Mao
@ 2025-09-06  1:42     ` gaosong
  0 siblings, 0 replies; 28+ messages in thread
From: gaosong @ 2025-09-06  1:42 UTC (permalink / raw)
  To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang

在 2025/9/5 下午4:40, Bibo Mao 写道:
>
>
> On 2025/9/4 下午8:18, Song Gao wrote:
>> Add feature register and misc register for avecintc feature checking and
>> setting
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>>   hw/loongarch/virt.c | 11 +++++++++++
>>   1 file changed, 11 insertions(+)
>>
>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>> index 1a2aa92c25..124f96af03 100644
>> --- a/hw/loongarch/virt.c
>> +++ b/hw/loongarch/virt.c
>> @@ -560,6 +560,10 @@ static MemTxResult virt_iocsr_misc_write(void 
>> *opaque, hwaddr addr,
>>               return MEMTX_OK;
>>           }
>>   +        if (val & BIT(IOCSRM_AVEC_EN)) {
>> +            lvms->misc_status |= BIT(IOCSRM_AVEC_EN);
>> +        }
>> +
> how about adding virt_has_avecintc(lvms) here, such as
>            if (virt_has_avecintc(lvms) && val & BIT(IOCSRM_AVEC_EN)) {
>                lvms->misc_status |= BIT(IOCSRM_AVEC_EN);
>            }
>
Got it , I will correct it on v7.

Thanks.
Song Gao
> Otherwise looks good to me.
> Reviewed-by: Bibo Mao <maobibo@loongson.cn>
>
>
> Regards
> Bibo Mao
>
>>           features = address_space_ldl(&lvms->as_iocsr,
>>                                        EXTIOI_VIRT_BASE + 
>> EXTIOI_VIRT_CONFIG,
>>                                        attrs, NULL);
>> @@ -595,6 +599,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);
>> +        if (virt_has_avecintc(lvms)) {
>> +            ret |= BIT(IOCSRF_AVEC);
>> +        }
>>           if (kvm_enabled()) {
>>               ret |= BIT(IOCSRF_VM);
>>           }
>> @@ -624,6 +631,10 @@ static MemTxResult virt_iocsr_misc_read(void 
>> *opaque, hwaddr addr,
>>           if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
>>               ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
>>           }
>> +        if (virt_has_avecintc(lvms) &&
>> +            (lvms->misc_status & BIT(IOCSRM_AVEC_EN))) {
>> +            ret |= BIT_ULL(IOCSRM_AVEC_EN);
>> +        }
>>           break;
>>       default:
>>           g_assert_not_reached();
>>



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 05/11] target/loongarch: add msg interrupt CSR registers
  2025-09-05  8:55   ` Bibo Mao
@ 2025-09-06  2:22     ` gaosong
  0 siblings, 0 replies; 28+ messages in thread
From: gaosong @ 2025-09-06  2:22 UTC (permalink / raw)
  To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang

在 2025/9/5 下午4:55, Bibo Mao 写道:
>
>
> On 2025/9/4 下午8:18, Song Gao wrote:
>> include CSR_MSGIS0-3, CSR_MSGIR and CSR_MSGIE.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>>   target/loongarch/cpu-csr.h |  3 +++
>>   target/loongarch/cpu.h     | 11 +++++++++++
>>   target/loongarch/machine.c | 27 +++++++++++++++++++++++++--
>>   3 files changed, 39 insertions(+), 2 deletions(-)
>>
>> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
>> index 0834e91f30..4792677086 100644
>> --- a/target/loongarch/cpu-csr.h
>> +++ b/target/loongarch/cpu-csr.h
>> @@ -186,6 +186,9 @@ FIELD(CSR_MERRCTL, ISMERR, 0, 1)
>>     #define LOONGARCH_CSR_CTAG           0x98 /* TagLo + TagHi */
>>   +#define LOONGARCH_CSR_MSGIS(N)       (0xa0 + N)
>> +#define LOONGARCH_CSR_MSGIR               0xa4
>> +
>>   /* Direct map windows CSRs*/
>>   #define LOONGARCH_CSR_DMW(N)         (0x180 + N)
>>   FIELD(CSR_DMW, PLV0, 0, 1)
>> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
>> index 56fc4a1459..f083c31bb4 100644
>> --- a/target/loongarch/cpu.h
>> +++ b/target/loongarch/cpu.h
>> @@ -233,6 +233,13 @@ FIELD(TLB_MISC, ASID, 1, 10)
>>   FIELD(TLB_MISC, VPPN, 13, 35)
>>   FIELD(TLB_MISC, PS, 48, 6)
>>   +/*Msg interrupt registers */
>> +#define N_MSGIS                4
>> +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)
>>   @@ -350,6 +357,10 @@ typedef struct CPUArchState {
>>       uint64_t CSR_DBG;
>>       uint64_t CSR_DERA;
>>       uint64_t CSR_DSAVE;
>> +    /* Msg interrupt registers */
>> +    uint64_t CSR_MSGIS[N_MSGIS];
>> +    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..996fbeb501 100644
>> --- a/target/loongarch/machine.c
>> +++ b/target/loongarch/machine.c
>> @@ -10,6 +10,7 @@
>>   #include "migration/cpu.h"
>>   #include "system/tcg.h"
>>   #include "vec.h"
>> +#include "hw/loongarch/virt.h"
>>     static const VMStateDescription vmstate_fpu_reg = {
>>       .name = "fpu_reg",
>> @@ -45,6 +46,27 @@ static const VMStateDescription vmstate_fpu = {
>>       },
>>   };
>>   +static bool msg_needed(void *opaque)
>> +{
>> +    MachineState *ms = MACHINE(qdev_get_machine());
> The avec CSR registers CSR_MSGIR etc is part of CPU, I just think
> it will be better to check avec CPU feature rather than board feature.
>
We can check cpucfg[1].bit26. (MSG_INT).
>> +    LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms);
>> +
>> +    return virt_has_avecintc(lvms);
> It supposes that LoongArch CPU must be together with virt machine :)
>
>> +}
>> +
>> +static const VMStateDescription vmstate_msg = {
> how about rename it as vmstate_avec?  the same with msg_needed.
>
OK,  I will correct it on v7.

thanks.
Song Gao
>
> Regards
> Bibo Mao
>
>
>> +    .name = "cpu/msg",
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .needed = msg_needed,
>> +    .fields = (const VMStateField[]) {
>> +        VMSTATE_UINT64_ARRAY(env.CSR_MSGIS, LoongArchCPU, N_MSGIS),
>> +        VMSTATE_UINT64(env.CSR_MSGIR, LoongArchCPU),
>> +        VMSTATE_UINT64(env.CSR_MSGIE, LoongArchCPU),
>> +        VMSTATE_END_OF_LIST()
>> +    },
>> +};
>> +
>>   static const VMStateDescription vmstate_lsxh_reg = {
>>       .name = "lsxh_reg",
>>       .version_id = 1,
>> @@ -168,8 +190,8 @@ static const VMStateDescription vmstate_tlb = {
>>   /* LoongArch CPU state */
>>   const VMStateDescription vmstate_loongarch_cpu = {
>>       .name = "cpu",
>> -    .version_id = 3,
>> -    .minimum_version_id = 3,
>> +    .version_id = 4,
>> +    .minimum_version_id = 4,
>>       .fields = (const VMStateField[]) {
>>           VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
>>           VMSTATE_UINTTL(env.pc, LoongArchCPU),
>> @@ -245,6 +267,7 @@ const VMStateDescription vmstate_loongarch_cpu = {
>>           &vmstate_tlb,
>>   #endif
>>           &vmstate_lbt,
>> +        &vmstate_msg,
>>           NULL
>>       }
>>   };
>>



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 08/11] hw/loongarch: Implement avec set irq
  2025-09-05 10:05   ` Bibo Mao
@ 2025-09-06  7:13     ` Bibo Mao
  2025-09-06  8:33       ` gaosong
  0 siblings, 1 reply; 28+ messages in thread
From: Bibo Mao @ 2025-09-06  7:13 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



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

Regards
Bibo MAo
> 
> Regargs
> Bibo Mao
>> +}
>> +
>>   static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
>>                                        uint64_t val, unsigned size)
>>   {
>> -    return;
>> +    int irq_num, cpu_num = 0;
>> +    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
>> +    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
>> +    CPUState *cs;
>> +
>> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>> +    cs = cpu_by_arch_id(cpu_num);
>> +    cpu_num = cs->cpu_index;
>> +    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
>> +    avec_set_irq(s, cpu_num, irq_num, 1);
>>   }
>> -
>>   static const MemoryRegionOps loongarch_avec_ops = {
>>       .read = loongarch_avec_mem_read,
>>       .write = loongarch_avec_mem_write,
>> diff --git a/include/hw/intc/loongarch_avec.h 
>> b/include/hw/intc/loongarch_avec.h
>> index 3e8cf7d2c1..83656f8df4 100644
>> --- a/include/hw/intc/loongarch_avec.h
>> +++ b/include/hw/intc/loongarch_avec.h
>> @@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, 
>> LoongArchAVECClass, LOONGARCH_AVEC)
>>   typedef struct AVECCore {
>>       CPUState *cpu;
>>       qemu_irq parent_irq;
>> +    uint64_t pending;
>> +    uint64_t dest_cpu;
>> +    bool   level;
>>       uint64_t arch_id;
>>   } AVECCore;
>>



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 09/11] target/loongarch: Add CSR_ESTAT.bit15 and CSR_ECFG.bit15 for msg interrupts.
  2025-09-04 12:18 ` [PATCH v6 09/11] target/loongarch: Add CSR_ESTAT.bit15 and CSR_ECFG.bit15 for msg interrupts Song Gao
@ 2025-09-06  7:18   ` Bibo Mao
  0 siblings, 0 replies; 28+ messages in thread
From: Bibo Mao @ 2025-09-06  7:18 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



On 2025/9/4 下午8:18, Song Gao wrote:
> Add CSR_ESTAT.bit15 and CSR_ECFG.bit15 for AVEC irq.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   target/loongarch/cpu-csr.h | 6 ++++--
>   1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> index 4792677086..6ec13d13d1 100644
> --- a/target/loongarch/cpu-csr.h
> +++ b/target/loongarch/cpu-csr.h
> @@ -34,11 +34,13 @@ FIELD(CSR_MISC, ALCL, 12, 4)
>   FIELD(CSR_MISC, DWPL, 16, 3)
>   
>   #define LOONGARCH_CSR_ECFG           0x4 /* Exception config */
> -FIELD(CSR_ECFG, LIE, 0, 13)
> +FIELD(CSR_ECFG, LIE, 0, 15)        /*bit 15 is msg interrupt enabled */
space is needed, bit 14 here?   /* bit 14 is msg interrupt enabled */
> +FIELD(CSR_ECFG, MSGINT, 14, 1)
>   FIELD(CSR_ECFG, VS, 16, 3)
>   
>   #define LOONGARCH_CSR_ESTAT          0x5 /* Exception status */
> -FIELD(CSR_ESTAT, IS, 0, 13)
> +FIELD(CSR_ESTAT, IS, 0, 15)        /*bit 15 is msg interrupt enabled */
ditto   /* bit 14 is msg interrupt enabled */
> +FIELD(CSR_ESTAT, MSGINT, 14, 1)
>   FIELD(CSR_ESTAT, ECODE, 16, 6)
>   FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
>   
> 
otherwise
Reviewed-by: Bibo Mao <maobibo@loongson.cn>



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 10/11] target/loongarch:Implement csrrd CSR_MSGIR register
  2025-09-04 12:18 ` [PATCH v6 10/11] target/loongarch:Implement csrrd CSR_MSGIR register Song Gao
@ 2025-09-06  7:20   ` Bibo Mao
  0 siblings, 0 replies; 28+ messages in thread
From: Bibo Mao @ 2025-09-06  7:20 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



On 2025/9/4 下午8:18, Song Gao wrote:
> implement the read-clear feature for CSR_MSGIR register.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   target/loongarch/csr.c                        |  5 +++++
>   target/loongarch/tcg/csr_helper.c             | 21 +++++++++++++++++++
>   target/loongarch/tcg/helper.h                 |  1 +
>   .../tcg/insn_trans/trans_privileged.c.inc     |  1 +
>   4 files changed, 28 insertions(+)
> 
> diff --git a/target/loongarch/csr.c b/target/loongarch/csr.c
> index 7ea0a30450..f973780bba 100644
> --- a/target/loongarch/csr.c
> +++ b/target/loongarch/csr.c
> @@ -97,6 +97,11 @@ static CSRInfo csr_info[] = {
>       CSR_OFF(DBG),
>       CSR_OFF(DERA),
>       CSR_OFF(DSAVE),
> +    CSR_OFF_ARRAY(MSGIS, 0),
> +    CSR_OFF_ARRAY(MSGIS, 1),
> +    CSR_OFF_ARRAY(MSGIS, 2),
> +    CSR_OFF_ARRAY(MSGIS, 3),
> +    CSR_OFF(MSGIR),
>   };
>   
>   CSRInfo *get_csr(unsigned int csr_num)
> diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c
> index 28b1bb86bd..347dca84b8 100644
> --- a/target/loongarch/tcg/csr_helper.c
> +++ b/target/loongarch/tcg/csr_helper.c
> @@ -72,6 +72,27 @@ target_ulong helper_csrrd_tval(CPULoongArchState *env)
>       return cpu_loongarch_get_constant_timer_ticks(cpu);
>   }
>   
> +target_ulong helper_csrrd_msgir(CPULoongArchState *env)
> +{
> +    int irq, new;
> +
> +    irq = find_first_bit(env->CSR_MSGIS, 256);
> +    if (irq < 256) {
> +        clear_bit(irq, env->CSR_MSGIS);
> +        new = find_first_bit(env->CSR_MSGIS, 256);
> +        if (new < 256) {
> +            return irq;
> +        }
> +
> +        env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
> +    } else {
> +        /* bit 31 set 1 for no invalid irq */
> +        irq = BIT(31);
> +    }
> +
> +    return irq;
> +}
> +
>   target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val)
>   {
>       int64_t old_v = env->CSR_ESTAT;
> diff --git a/target/loongarch/tcg/helper.h b/target/loongarch/tcg/helper.h
> index 1d5cb0198c..db57dbfc16 100644
> --- a/target/loongarch/tcg/helper.h
> +++ b/target/loongarch/tcg/helper.h
> @@ -100,6 +100,7 @@ DEF_HELPER_1(rdtime_d, i64, env)
>   DEF_HELPER_1(csrrd_pgd, i64, env)
>   DEF_HELPER_1(csrrd_cpuid, i64, env)
>   DEF_HELPER_1(csrrd_tval, i64, env)
> +DEF_HELPER_1(csrrd_msgir, i64, env)
>   DEF_HELPER_2(csrwr_stlbps, i64, env, tl)
>   DEF_HELPER_2(csrwr_estat, i64, env, tl)
>   DEF_HELPER_2(csrwr_asid, i64, env, tl)
> diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
> index 34cfab8879..a407ab51b7 100644
> --- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
> +++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
> @@ -83,6 +83,7 @@ void loongarch_csr_translate_init(void)
>       SET_CSR_FUNC(TCFG,  NULL, gen_helper_csrwr_tcfg);
>       SET_CSR_FUNC(TVAL,  gen_helper_csrrd_tval, NULL);
>       SET_CSR_FUNC(TICLR, NULL, gen_helper_csrwr_ticlr);
> +    SET_CSR_FUNC(MSGIR, gen_helper_csrrd_msgir, NULL);
>   }
>   #undef SET_CSR_FUNC
>   
> 
Reviewed-by: Bibo Mao <maobibo@loongson.cn>



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 11/11] hw/loongarch: Implement AVEC plug/unplug interfaces
  2025-09-04 12:18 ` [PATCH v6 11/11] hw/loongarch: Implement AVEC plug/unplug interfaces Song Gao
@ 2025-09-06  7:22   ` Bibo Mao
  0 siblings, 0 replies; 28+ messages in thread
From: Bibo Mao @ 2025-09-06  7:22 UTC (permalink / raw)
  To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang



On 2025/9/4 下午8:18, Song Gao wrote:
> when cpu added, connect avec irq to cpu INT_AVEC irq pin.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   hw/intc/loongarch_avec.c | 71 ++++++++++++++++++++++++++++++++++++++++
>   hw/loongarch/virt.c      | 11 +++++++
>   2 files changed, 82 insertions(+)
> 
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index 03a20a7b60..f4b0ff29fa 100644
> --- a/hw/intc/loongarch_avec.c
> +++ b/hw/intc/loongarch_avec.c
> @@ -140,14 +140,81 @@ static void loongarch_avec_init(Object *obj)
>       return;
>   }
>   
> +static AVECCore *loongarch_avec_get_cpu(LoongArchAVECState *s,
> +                                        DeviceState *dev)
> +{
> +    CPUClass *k = CPU_GET_CLASS(dev);
> +    uint64_t arch_id = k->get_arch_id(CPU(dev));
> +    int i;
> +
> +    for (i = 0; i < s->num_cpu; i++) {
> +        if (s->cpu[i].arch_id == arch_id) {
> +            return &s->cpu[i];
> +        }
> +    }
> +
> +    return NULL;
> +}
> +
> +static void loongarch_avec_cpu_plug(HotplugHandler *hotplug_dev,
> +                                   DeviceState *dev, Error **errp)
> +{
> +    LoongArchAVECState *s = LOONGARCH_AVEC(hotplug_dev);
> +    Object *obj = OBJECT(dev);
> +    AVECCore *core;
> +    int index;
> +
> +    if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
> +        warn_report("LoongArch AVEC: Invalid %s device type",
> +                                       object_get_typename(obj));
> +        return;
> +    }
> +    core = loongarch_avec_get_cpu(s, dev);
> +    if (!core) {
> +        return;
> +    }
> +
> +    core->cpu = CPU(dev);
> +    index = core - s->cpu;
> +
> +    /* connect avec msg irq to cpu irq */
> +    qdev_connect_gpio_out(DEVICE(s), index, qdev_get_gpio_in(dev, INT_AVEC));
> +    return;
> +}
> +
> +static void loongarch_avec_cpu_unplug(HotplugHandler *hotplug_dev,
> +                                     DeviceState *dev, Error **errp)
> +{
> +    LoongArchAVECState *s = LOONGARCH_AVEC(hotplug_dev);
> +    Object *obj = OBJECT(dev);
> +    AVECCore *core;
> +
> +    if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
> +        warn_report("LoongArch AVEC: Invalid %s device type",
> +                                       object_get_typename(obj));
> +        return;
> +    }
> +
> +    core = loongarch_avec_get_cpu(s, dev);
> +
> +    if (!core) {
> +        return;
> +    }
> +
> +    core->cpu = NULL;
> +}
> +
>   static void loongarch_avec_class_init(ObjectClass *klass, const void *data)
>   {
>       DeviceClass *dc = DEVICE_CLASS(klass);
> +    HotplugHandlerClass *hc = HOTPLUG_HANDLER_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);
> +    hc->plug = loongarch_avec_cpu_plug;
> +    hc->unplug = loongarch_avec_cpu_unplug;
>   }
>   
>   static const TypeInfo loongarch_avec_info = {
> @@ -156,6 +223,10 @@ static const TypeInfo loongarch_avec_info = {
>       .instance_size = sizeof(LoongArchAVECState),
>       .instance_init = loongarch_avec_init,
>       .class_init    = loongarch_avec_class_init,
> +    .interfaces    = (const InterfaceInfo[]) {
> +        { TYPE_HOTPLUG_HANDLER },
> +        { }
> +    },
>   };
>   
>   static void loongarch_avec_register_types(void)
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index a3f8f4c854..ad78dd3f19 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -377,6 +377,10 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
>                                &error_abort);
>           hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), DEVICE(cs),
>                                &error_abort);
> +        if (lvms->avec) {
> +            hotplug_handler_plug(HOTPLUG_HANDLER(lvms->avec), DEVICE(cs),
> +                                 &error_abort);
> +        }
>       }
>   }
>   
> @@ -1089,6 +1093,9 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev,
>       /* Notify ipi and extioi irqchip to remove interrupt routing to CPU */
>       hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->ipi), dev, &error_abort);
>       hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->extioi), dev, &error_abort);
> +    if (lvms->avec) {
> +        hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->avec), dev, &error_abort);
> +    }
>   
>       /* Notify acpi ged CPU removed */
>       hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->acpi_ged), dev, &error_abort);
> @@ -1112,6 +1119,10 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
>           hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), dev, &error_abort);
>       }
>   
> +    if (lvms->avec) {
> +        hotplug_handler_plug(HOTPLUG_HANDLER(lvms->avec), dev, &error_abort);
> +    }
> +
>       if (lvms->acpi_ged) {
>           hotplug_handler_plug(HOTPLUG_HANDLER(lvms->acpi_ged), dev,
>                                &error_abort);
> 
Reviewed-by: Bibo Mao <maobibo@loongson.cn>



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 08/11] hw/loongarch: Implement avec set irq
  2025-09-05  9:52   ` Bibo Mao
@ 2025-09-06  8:26     ` gaosong
  0 siblings, 0 replies; 28+ messages in thread
From: gaosong @ 2025-09-06  8:26 UTC (permalink / raw)
  To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang

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

> Regards
> Bibo Mao
>> +
>> +    if (level) {
>> +        avec_update_csr(core, cpu_num, irq_num, level);
>> +    }
>> +    qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
>> +}
>> +
>>   static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
>>                                        uint64_t val, unsigned size)
>>   {
>> -    return;
>> +    int irq_num, cpu_num = 0;
>> +    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
>> +    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
>> +    CPUState *cs;
>> +
>> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>> +    cs = cpu_by_arch_id(cpu_num);
>> +    cpu_num = cs->cpu_index;
>> +    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
>> +    avec_set_irq(s, cpu_num, irq_num, 1);
>>   }
>>   -
>>   static const MemoryRegionOps loongarch_avec_ops = {
>>       .read = loongarch_avec_mem_read,
>>       .write = loongarch_avec_mem_write,
>> diff --git a/include/hw/intc/loongarch_avec.h 
>> b/include/hw/intc/loongarch_avec.h
>> index 3e8cf7d2c1..83656f8df4 100644
>> --- a/include/hw/intc/loongarch_avec.h
>> +++ b/include/hw/intc/loongarch_avec.h
>> @@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, 
>> LoongArchAVECClass, LOONGARCH_AVEC)
>>   typedef struct AVECCore {
>>       CPUState *cpu;
>>       qemu_irq parent_irq;
>> +    uint64_t pending;
>> +    uint64_t dest_cpu;
>> +    bool   level;
this code also useless.

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



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v6 08/11] hw/loongarch: Implement avec set irq
  2025-09-06  7:13     ` Bibo Mao
@ 2025-09-06  8:33       ` gaosong
  0 siblings, 0 replies; 28+ messages in thread
From: gaosong @ 2025-09-06  8:33 UTC (permalink / raw)
  To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang

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

Thanks.
Song Gao
> Regards
> Bibo MAo
>>
>> Regargs
>> Bibo Mao
>>> +}
>>> +
>>>   static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
>>>                                        uint64_t val, unsigned size)
>>>   {
>>> -    return;
>>> +    int irq_num, cpu_num = 0;
>>> +    LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
>>> +    uint64_t msg_addr = addr + VIRT_AVEC_BASE;
>>> +    CPUState *cs;
>>> +
>>> +    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>>> +    cs = cpu_by_arch_id(cpu_num);
>>> +    cpu_num = cs->cpu_index;
>>> +    irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
>>> +    avec_set_irq(s, cpu_num, irq_num, 1);
>>>   }
>>> -
>>>   static const MemoryRegionOps loongarch_avec_ops = {
>>>       .read = loongarch_avec_mem_read,
>>>       .write = loongarch_avec_mem_write,
>>> diff --git a/include/hw/intc/loongarch_avec.h 
>>> b/include/hw/intc/loongarch_avec.h
>>> index 3e8cf7d2c1..83656f8df4 100644
>>> --- a/include/hw/intc/loongarch_avec.h
>>> +++ b/include/hw/intc/loongarch_avec.h
>>> @@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, 
>>> LoongArchAVECClass, LOONGARCH_AVEC)
>>>   typedef struct AVECCore {
>>>       CPUState *cpu;
>>>       qemu_irq parent_irq;
>>> +    uint64_t pending;
>>> +    uint64_t dest_cpu;
>>> +    bool   level;
>>>       uint64_t arch_id;
>>>   } AVECCore;
>>>



^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2025-09-06  8:32 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-04 12:18 [PATCH v6 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
2025-09-04 12:18 ` [PATCH v6 01/11] target/loongarch: move some machine define to virt.h Song Gao
2025-09-04 12:18 ` [PATCH v6 02/11] hw/loongarch: add virt feature avecintc support Song Gao
2025-09-05  8:35   ` Bibo Mao
2025-09-04 12:18 ` [PATCH v6 03/11] hw/loongarch: add misc register supoort avecintc Song Gao
2025-09-05  8:40   ` Bibo Mao
2025-09-06  1:42     ` gaosong
2025-09-04 12:18 ` [PATCH v6 04/11] loongarch: add a advance interrupt controller device Song Gao
2025-09-05  8:44   ` Bibo Mao
2025-09-04 12:18 ` [PATCH v6 05/11] target/loongarch: add msg interrupt CSR registers Song Gao
2025-09-05  8:55   ` Bibo Mao
2025-09-06  2:22     ` gaosong
2025-09-04 12:18 ` [PATCH v6 06/11] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
2025-09-05  8:58   ` Bibo Mao
2025-09-04 12:18 ` [PATCH v6 07/11] hw/loongarch: Implement avec controller imput and output pins Song Gao
2025-09-05  9:15   ` Bibo Mao
2025-09-04 12:18 ` [PATCH v6 08/11] hw/loongarch: Implement avec set irq Song Gao
2025-09-05  9:52   ` Bibo Mao
2025-09-06  8:26     ` gaosong
2025-09-05 10:05   ` Bibo Mao
2025-09-06  7:13     ` Bibo Mao
2025-09-06  8:33       ` gaosong
2025-09-04 12:18 ` [PATCH v6 09/11] target/loongarch: Add CSR_ESTAT.bit15 and CSR_ECFG.bit15 for msg interrupts Song Gao
2025-09-06  7:18   ` Bibo Mao
2025-09-04 12:18 ` [PATCH v6 10/11] target/loongarch:Implement csrrd CSR_MSGIR register Song Gao
2025-09-06  7:20   ` Bibo Mao
2025-09-04 12:18 ` [PATCH v6 11/11] hw/loongarch: Implement AVEC plug/unplug interfaces Song Gao
2025-09-06  7:22   ` 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).