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