1 Star 0 Fork 121

侯景博/qemu

forked from src-openEuler/qemu 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
hw-intc-loongarch_extioi-Add-virt-extension-support.patch 14.72 KB
一键复制 编辑 原始数据 按行查看 历史
gaosong 提交于 2024-05-20 17:35 . QEMU update to version 8.2.0-13
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
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/Destiny_zhuohua/qemu.git
[email protected]:Destiny_zhuohua/qemu.git
Destiny_zhuohua
qemu
qemu
master

搜索帮助