代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/qemu 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From 04aef27ede108edd63d288dd3bb395e22a603f42 Mon Sep 17 00:00:00 2001
From: Bibo Mao <[email protected]>
Date: Mon, 11 Mar 2024 15:01:31 +0800
Subject: [PATCH] hw/intc/loongarch_extioi: Add virt extension support
With hardware extioi, irq can be routed to four vcpus with hardware
extioi. This patch adds virt extension support, sot that irq can
be routed to 256 vcpus.
Signed-off-by: Song Gao <[email protected]>
Signed-off-by: Bibo Mao <[email protected]>
---
hw/intc/loongarch_extioi.c | 88 ++++++++++++++++++++-
hw/loongarch/virt.c | 122 ++++++++++++++++++++++++++---
include/hw/intc/loongarch_extioi.h | 21 +++++
include/hw/loongarch/virt.h | 3 +
target/loongarch/cpu.h | 1 +
5 files changed, 220 insertions(+), 15 deletions(-)
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index bdfa3b481e..fa23e247ca 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -143,15 +143,17 @@ static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq,
for (i = 0; i < 4; i++) {
cpu = val & 0xff;
- cpu = ctz32(cpu);
- cpu = (cpu >= 4) ? 0 : cpu;
+ if (!(s->status & BIT(EXTIOI_ENABLE_CPU_ENCODE))) {
+ cpu = ctz32(cpu);
+ cpu = (cpu >= 4) ? 0 : cpu;
+ }
val = val >> 8;
if (s->sw_coremap[irq + i] == cpu) {
continue;
}
- if (notify && test_bit(irq, (unsigned long *)s->isr)) {
+ if (notify && test_bit(irq + i, (unsigned long *)s->isr)) {
/*
* lower irq at old cpu and raise irq at new cpu
*/
@@ -265,6 +267,61 @@ static const MemoryRegionOps extioi_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static MemTxResult extioi_virt_readw(void *opaque, hwaddr addr, uint64_t *data,
+ unsigned size, MemTxAttrs attrs)
+{
+ LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+
+ switch (addr) {
+ case EXTIOI_VIRT_FEATURES:
+ *data = s->features;
+ break;
+ case EXTIOI_VIRT_CONFIG:
+ *data = s->status;
+ break;
+ default:
+ break;
+ }
+
+ return MEMTX_OK;
+}
+
+static MemTxResult extioi_virt_writew(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size,
+ MemTxAttrs attrs)
+{
+ LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+
+ switch (addr) {
+ case EXTIOI_VIRT_FEATURES:
+ return MEMTX_ACCESS_ERROR;
+
+ case EXTIOI_VIRT_CONFIG:
+ /*
+ * extioi features can only be set at disabled status
+ */
+ if ((s->status & BIT(EXTIOI_ENABLE)) && val) {
+ return MEMTX_ACCESS_ERROR;
+ }
+
+ s->status = val & s->features;
+ break;
+ default:
+ break;
+ }
+ return MEMTX_OK;
+}
+
+static const MemoryRegionOps extioi_virt_ops = {
+ .read_with_attrs = extioi_virt_readw,
+ .write_with_attrs = extioi_virt_writew,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 8,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
{
LoongArchExtIOI *s = LOONGARCH_EXTIOI(dev);
@@ -284,6 +341,16 @@ static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
memory_region_init_io(&s->extioi_system_mem, OBJECT(s), &extioi_ops,
s, "extioi_system_mem", 0x900);
sysbus_init_mmio(sbd, &s->extioi_system_mem);
+
+ if (s->features & BIT(EXTIOI_HAS_VIRT_EXTENSION)) {
+ memory_region_init_io(&s->virt_extend, OBJECT(s), &extioi_virt_ops,
+ s, "extioi_virt", EXTIOI_VIRT_SIZE);
+ sysbus_init_mmio(sbd, &s->virt_extend);
+ s->features |= EXTIOI_VIRT_HAS_FEATURES;
+ } else {
+ s->status |= BIT(EXTIOI_ENABLE);
+ }
+
s->cpu = g_new0(ExtIOICore, s->num_cpu);
if (s->cpu == NULL) {
error_setg(errp, "Memory allocation for ExtIOICore faile");
@@ -304,6 +371,16 @@ static void loongarch_extioi_finalize(Object *obj)
g_free(s->cpu);
}
+static void loongarch_extioi_reset(DeviceState *d)
+{
+ LoongArchExtIOI *s = LOONGARCH_EXTIOI(d);
+
+ /* use legacy interrupt routing method by default */
+ if (s->features & BIT(EXTIOI_HAS_VIRT_EXTENSION)) {
+ s->status = 0;
+ }
+}
+
static int vmstate_extioi_post_load(void *opaque, int version_id)
{
LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
@@ -347,12 +424,16 @@ static const VMStateDescription vmstate_loongarch_extioi = {
VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu,
vmstate_extioi_core, ExtIOICore),
+ VMSTATE_UINT32(features, LoongArchExtIOI),
+ VMSTATE_UINT32(status, LoongArchExtIOI),
VMSTATE_END_OF_LIST()
}
};
static Property extioi_properties[] = {
DEFINE_PROP_UINT32("num-cpu", LoongArchExtIOI, num_cpu, 1),
+ DEFINE_PROP_BIT("has-virtualization-extension", LoongArchExtIOI, features,
+ EXTIOI_HAS_VIRT_EXTENSION, 0),
DEFINE_PROP_END_OF_LIST(),
};
@@ -361,6 +442,7 @@ static void loongarch_extioi_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = loongarch_extioi_realize;
+ dc->reset = loongarch_extioi_reset;
device_class_set_props(dc, extioi_properties);
dc->vmsd = &vmstate_loongarch_extioi;
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 6ef40fa24a..01e59f3a95 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -15,6 +15,8 @@
#include "sysemu/runstate.h"
#include "sysemu/reset.h"
#include "sysemu/rtc.h"
+#include "sysemu/tcg.h"
+#include "sysemu/kvm.h"
#include "hw/loongarch/virt.h"
#include "exec/address-spaces.h"
#include "hw/irq.h"
@@ -54,6 +56,31 @@ struct loaderparams {
const char *initrd_filename;
};
+static bool virt_is_veiointc_enabled(LoongArchMachineState *lams)
+{
+ if (lams->veiointc == ON_OFF_AUTO_OFF) {
+ return false;
+ }
+ return true;
+}
+
+static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
+ OnOffAuto veiointc = lams->veiointc;
+
+ visit_type_OnOffAuto(v, name, &veiointc, errp);
+}
+
+static void virt_set_veiointc(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
+
+ visit_type_OnOffAuto(v, name, &lams->veiointc, errp);
+}
+
static PFlashCFI01 *virt_flash_create1(LoongArchMachineState *lams,
const char *name,
const char *alias_prop_name)
@@ -618,9 +645,18 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
/* Create EXTIOI device */
extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
qdev_prop_set_uint32(extioi, "num-cpu", ms->smp.cpus);
+ if (virt_is_veiointc_enabled(lams)) {
+ qdev_prop_set_bit(extioi, "has-virtualization-extension", true);
+ }
sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal);
+
memory_region_add_subregion(&lams->system_iocsr, APIC_BASE,
sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 0));
+ if (virt_is_veiointc_enabled(lams)) {
+ memory_region_add_subregion(&lams->system_iocsr, EXTIOI_VIRT_BASE,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 1));
+ }
+ lams->extioi = extioi;
/*
* connect ext irq to the cpu irq
@@ -780,32 +816,87 @@ static void loongarch_direct_kernel_boot(LoongArchMachineState *lams,
}
}
-static void loongarch_qemu_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
+static MemTxResult loongarch_qemu_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size, MemTxAttrs attrs)
{
+ LoongArchMachineState *lams = LOONGARCH_MACHINE(opaque);
+ uint64_t features;
+
+ switch (addr) {
+ case MISC_FUNC_REG:
+ if (!virt_is_veiointc_enabled(lams)) {
+ return MEMTX_OK;
+ }
+
+ features = address_space_ldl(&lams->as_iocsr,
+ EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
+ attrs, NULL);
+ if (val & BIT_ULL(IOCSRM_EXTIOI_EN)) {
+ features |= BIT(EXTIOI_ENABLE);
+ }
+ if (val & BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE)) {
+ features |= BIT(EXTIOI_ENABLE_INT_ENCODE);
+ }
+
+ address_space_stl(&lams->as_iocsr,
+ EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
+ features, attrs, NULL);
+ }
+
+ return MEMTX_OK;
}
-static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size)
+static MemTxResult loongarch_qemu_read(void *opaque, hwaddr addr,
+ uint64_t *data,
+ unsigned size, MemTxAttrs attrs)
{
+ LoongArchMachineState *lams = LOONGARCH_MACHINE(opaque);
+ uint64_t ret = 0;
+ int features;
+
switch (addr) {
case VERSION_REG:
- return 0x11ULL;
+ ret = 0x11ULL;
+ break;
case FEATURE_REG:
- return 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI |
- 1ULL << IOCSRF_CSRIPI;
+ ret = 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI |
+ 1ULL << IOCSRF_CSRIPI;
+ if (kvm_enabled()) {
+ ret |= 1ULL << IOCSRF_VM;
+ }
+ break;
case VENDOR_REG:
- return 0x6e6f73676e6f6f4cULL; /* "Loongson" */
+ ret = 0x6e6f73676e6f6f4cULL; /* "Loongson" */
+ break;
case CPUNAME_REG:
- return 0x303030354133ULL; /* "3A5000" */
+ ret = 0x303030354133ULL; /* "3A5000" */
+ break;
case MISC_FUNC_REG:
- return 1ULL << IOCSRM_EXTIOI_EN;
+ if (!virt_is_veiointc_enabled(lams)) {
+ ret |= BIT_ULL(IOCSRM_EXTIOI_EN);
+ break;
+ }
+
+ features = address_space_ldl(&lams->as_iocsr,
+ EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
+ attrs, NULL);
+ if (features & BIT(EXTIOI_ENABLE)) {
+ ret |= BIT_ULL(IOCSRM_EXTIOI_EN);
+ }
+
+ if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
+ ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
+ }
+ break;
}
- return 0ULL;
+
+ *data = ret;
+ return MEMTX_OK;
}
static const MemoryRegionOps loongarch_qemu_ops = {
- .read = loongarch_qemu_read,
- .write = loongarch_qemu_write,
+ .read_with_attrs = loongarch_qemu_read,
+ .write_with_attrs = loongarch_qemu_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
@@ -1010,6 +1101,9 @@ static void loongarch_machine_initfn(Object *obj)
{
LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
+ if (tcg_enabled()) {
+ lams->veiointc = ON_OFF_AUTO_OFF;
+ }
lams->acpi = ON_OFF_AUTO_AUTO;
lams->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
lams->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
@@ -1197,6 +1291,10 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
NULL, NULL);
object_class_property_set_description(oc, "acpi",
"Enable ACPI");
+ object_class_property_add(oc, "v-eiointc", "OnOffAuto",
+ virt_get_veiointc, virt_set_veiointc, NULL, NULL);
+ object_class_property_set_description(oc, "v-eiointc",
+ "Enable Virt Extend I/O Interrupt Controller");
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
#ifdef CONFIG_TPM
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
index a0a46b888c..98f348c49d 100644
--- a/include/hw/intc/loongarch_extioi.h
+++ b/include/hw/intc/loongarch_extioi.h
@@ -40,6 +40,24 @@
#define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET)
#define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET)
+#define EXTIOI_VIRT_BASE (0x40000000)
+#define EXTIOI_VIRT_SIZE (0x1000)
+#define EXTIOI_VIRT_FEATURES (0x0)
+#define EXTIOI_HAS_VIRT_EXTENSION (0)
+#define EXTIOI_HAS_ENABLE_OPTION (1)
+#define EXTIOI_HAS_INT_ENCODE (2)
+#define EXTIOI_HAS_CPU_ENCODE (3)
+#define EXTIOI_VIRT_HAS_FEATURES (BIT(EXTIOI_HAS_VIRT_EXTENSION) \
+ | BIT(EXTIOI_HAS_ENABLE_OPTION)\
+ | BIT(EXTIOI_HAS_INT_ENCODE) \
+ | BIT(EXTIOI_HAS_CPU_ENCODE))
+#define EXTIOI_VIRT_CONFIG (0x4)
+#define EXTIOI_ENABLE (1)
+#define EXTIOI_ENABLE_INT_ENCODE (2)
+#define EXTIOI_ENABLE_CPU_ENCODE (3)
+#define EXTIOI_VIRT_COREMAP_START (0x40)
+#define EXTIOI_VIRT_COREMAP_END (0x240)
+
typedef struct ExtIOICore {
uint32_t coreisr[EXTIOI_IRQS_GROUP_COUNT];
DECLARE_BITMAP(sw_isr[LS3A_INTC_IP], EXTIOI_IRQS);
@@ -51,6 +69,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchExtIOI, LOONGARCH_EXTIOI)
struct LoongArchExtIOI {
SysBusDevice parent_obj;
uint32_t num_cpu;
+ uint32_t features;
+ uint32_t status;
/* hardware state */
uint32_t nodetype[EXTIOI_IRQS_NODETYPE_COUNT / 2];
uint32_t bounce[EXTIOI_IRQS_GROUP_COUNT];
@@ -64,5 +84,6 @@ struct LoongArchExtIOI {
qemu_irq irq[EXTIOI_IRQS];
ExtIOICore *cpu;
MemoryRegion extioi_system_mem;
+ MemoryRegion virt_extend;
};
#endif /* LOONGARCH_EXTIOI_H */
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 252f7df7f4..99447fd1d6 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -45,16 +45,19 @@ struct LoongArchMachineState {
Notifier machine_done;
Notifier powerdown_notifier;
OnOffAuto acpi;
+ OnOffAuto veiointc;
char *oem_id;
char *oem_table_id;
DeviceState *acpi_ged;
int fdt_size;
DeviceState *platform_bus_dev;
+ DeviceState *extioi;
PCIBus *pci_bus;
PFlashCFI01 *flash[2];
MemoryRegion system_iocsr;
MemoryRegion iocsr_mem;
AddressSpace as_iocsr;
+ int features;
};
#define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt")
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 4aba8aba4c..4749d41c8c 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -36,6 +36,7 @@
#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
--
2.33.0
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。