diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2024-06-06 11:54:46 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2024-06-06 11:54:46 -0700 |
commit | dec9742cbc59415a8b83e382e7ae36395394e4bd (patch) | |
tree | 4c1f59f0ba2030175357ba19550767f3fca3a59b /hw | |
parent | 064f26ee396afc09812570ca14bb7f7eddf4d6da (diff) | |
parent | 78f932ea1f7b3b9b0ac628dc2a91281318fe51fa (diff) | |
download | qemu-dec9742cbc59415a8b83e382e7ae36395394e4bd.zip qemu-dec9742cbc59415a8b83e382e7ae36395394e4bd.tar.gz qemu-dec9742cbc59415a8b83e382e7ae36395394e4bd.tar.bz2 |
Merge tag 'pull-loongarch-20240606' of https://gitlab.com/gaosong/qemu into staging
pull-loongarch-20240606
# -----BEGIN PGP SIGNATURE-----
#
# iLMEAAEKAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZmE0HwAKCRBAov/yOSY+
# 396sA/90m/zr91pLQlkhFuYLHg958Ow3L5ysblcuAAmcTXGi8iE9IeTTeZru6WEO
# H/CL/njUkIgP+/Tio0n0Lx6rWkxOzGxWCpvzqrabsPGvs4GUtFEjI/2pvEWP6C9/
# S6Jon3py0oZeoVx8D6Tr/CJrhD0IBptbEn1aiQNDRuSzeuCo1Q==
# =xpjH
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 05 Jun 2024 08:59:27 PM PDT
# gpg: using RSA key B8FF1DA0D2FDCB2DA09C6C2C40A2FFF239263EDF
# gpg: Good signature from "Song Gao <m17746591750@163.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: B8FF 1DA0 D2FD CB2D A09C 6C2C 40A2 FFF2 3926 3EDF
* tag 'pull-loongarch-20240606' of https://gitlab.com/gaosong/qemu:
target/loongarch: fix a wrong print in cpu dump
hw/loongarch/virt: Enable extioi virt extension
hw/loongarch/virt: Use MemTxAttrs interface for misc ops
hw/intc/loongarch_extioi: Add extioi virt extension definition
tests/qtest: Add numa test for loongarch system
tests/libqos: Add loongarch virt machine node
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/intc/loongarch_extioi.c | 88 | ||||
-rw-r--r-- | hw/loongarch/virt.c | 184 |
2 files changed, 235 insertions, 37 deletions
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c index 0b35854..1e8e011 100644 --- a/hw/intc/loongarch_extioi.c +++ b/hw/intc/loongarch_extioi.c @@ -143,10 +143,13 @@ 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; val = val >> 8; + if (!(s->status & BIT(EXTIOI_ENABLE_CPU_ENCODE))) { + cpu = ctz32(cpu); + cpu = (cpu >= 4) ? 0 : cpu; + } + if (s->sw_coremap[irq + i] == cpu) { continue; } @@ -265,6 +268,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: + g_assert_not_reached(); + } + + 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: + g_assert_not_reached(); + } + 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 +342,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 +372,13 @@ static void loongarch_extioi_finalize(Object *obj) g_free(s->cpu); } +static void loongarch_extioi_reset(DeviceState *d) +{ + LoongArchExtIOI *s = LOONGARCH_EXTIOI(d); + + s->status = 0; +} + static int vmstate_extioi_post_load(void *opaque, int version_id) { LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque); @@ -333,8 +408,8 @@ static const VMStateDescription vmstate_extioi_core = { static const VMStateDescription vmstate_loongarch_extioi = { .name = TYPE_LOONGARCH_EXTIOI, - .version_id = 2, - .minimum_version_id = 2, + .version_id = 3, + .minimum_version_id = 3, .post_load = vmstate_extioi_post_load, .fields = (const VMStateField[]) { VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT), @@ -347,12 +422,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 +440,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 3e6e93e..66cef20 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -11,6 +11,7 @@ #include "hw/boards.h" #include "hw/char/serial.h" #include "sysemu/kvm.h" +#include "sysemu/tcg.h" #include "sysemu/sysemu.h" #include "sysemu/qtest.h" #include "sysemu/runstate.h" @@ -45,8 +46,34 @@ #include "sysemu/tpm.h" #include "sysemu/block-backend.h" #include "hw/block/flash.h" +#include "hw/virtio/virtio-iommu.h" #include "qemu/error-report.h" +static bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms) +{ + if (lvms->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) +{ + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj); + OnOffAuto veiointc = lvms->veiointc; + + visit_type_OnOffAuto(v, name, &veiointc, errp); +} + +static void virt_set_veiointc(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj); + + visit_type_OnOffAuto(v, name, &lvms->veiointc, errp); +} + static PFlashCFI01 *virt_flash_create1(LoongArchVirtMachineState *lvms, const char *name, const char *alias_prop_name) @@ -717,25 +744,47 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) uint32_t cpuintc_phandle, eiointc_phandle, pch_pic_phandle, pch_msi_phandle; /* - * The connection of interrupts: - * +-----+ +---------+ +-------+ - * | IPI |--> | CPUINTC | <-- | Timer | - * +-----+ +---------+ +-------+ - * ^ - * | - * +---------+ - * | EIOINTC | - * +---------+ - * ^ ^ - * | | - * +---------+ +---------+ - * | PCH-PIC | | PCH-MSI | - * +---------+ +---------+ - * ^ ^ ^ - * | | | - * +--------+ +---------+ +---------+ - * | UARTs | | Devices | | Devices | - * +--------+ +---------+ +---------+ + * Extended IRQ model. + * | + * +-----------+ +-------------|--------+ +-----------+ + * | IPI/Timer | --> | CPUINTC(0-3)|(4-255) | <-- | IPI/Timer | + * +-----------+ +-------------|--------+ +-----------+ + * ^ | + * | + * +---------+ + * | EIOINTC | + * +---------+ + * ^ ^ + * | | + * +---------+ +---------+ + * | PCH-PIC | | PCH-MSI | + * +---------+ +---------+ + * ^ ^ ^ + * | | | + * +--------+ +---------+ +---------+ + * | UARTs | | Devices | | Devices | + * +--------+ +---------+ +---------+ + * + * Virt extended IRQ model. + * + * +-----+ +---------------+ +-------+ + * | IPI |--> | CPUINTC(0-255)| <-- | Timer | + * +-----+ +---------------+ +-------+ + * ^ + * | + * +-----------+ + * | V-EIOINTC | + * +-----------+ + * ^ ^ + * | | + * +---------+ +---------+ + * | PCH-PIC | | PCH-MSI | + * +---------+ +---------+ + * ^ ^ ^ + * | | | + * +--------+ +---------+ +---------+ + * | UARTs | | Devices | | Devices | + * +--------+ +---------+ +---------+ */ /* Create IPI device */ @@ -767,9 +816,16 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) /* Create EXTIOI device */ extioi = qdev_new(TYPE_LOONGARCH_EXTIOI); qdev_prop_set_uint32(extioi, "num-cpu", ms->smp.cpus); + if (virt_is_veiointc_enabled(lvms)) { + qdev_prop_set_bit(extioi, "has-virtualization-extension", true); + } sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal); memory_region_add_subregion(&lvms->system_iocsr, APIC_BASE, - sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 0)); + sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 0)); + if (virt_is_veiointc_enabled(lvms)) { + memory_region_add_subregion(&lvms->system_iocsr, EXTIOI_VIRT_BASE, + sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 1)); + } /* * connect ext irq to the cpu irq @@ -876,38 +932,91 @@ static void virt_firmware_init(LoongArchVirtMachineState *lvms) } } - -static void virt_iocsr_misc_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) +static MemTxResult virt_iocsr_misc_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size, + MemTxAttrs attrs) { + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(opaque); + uint64_t features; + + switch (addr) { + case MISC_FUNC_REG: + if (!virt_is_veiointc_enabled(lvms)) { + return MEMTX_OK; + } + + features = address_space_ldl(&lvms->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(&lvms->as_iocsr, + EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG, + features, attrs, NULL); + break; + default: + g_assert_not_reached(); + } + + return MEMTX_OK; } -static uint64_t virt_iocsr_misc_read(void *opaque, hwaddr addr, unsigned size) +static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr, + uint64_t *data, + unsigned size, MemTxAttrs attrs) { - uint64_t ret; + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(opaque); + uint64_t ret = 0; + int features; switch (addr) { case VERSION_REG: - return 0x11ULL; + ret = 0x11ULL; + break; case FEATURE_REG: ret = BIT(IOCSRF_MSI) | BIT(IOCSRF_EXTIOI) | BIT(IOCSRF_CSRIPI); if (kvm_enabled()) { ret |= BIT(IOCSRF_VM); } - return ret; + 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 BIT_ULL(IOCSRM_EXTIOI_EN); + if (!virt_is_veiointc_enabled(lvms)) { + ret |= BIT_ULL(IOCSRM_EXTIOI_EN); + break; + } + + features = address_space_ldl(&lvms->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; + default: + g_assert_not_reached(); } - return 0ULL; + + *data = ret; + return MEMTX_OK; } static const MemoryRegionOps virt_iocsr_misc_ops = { - .read = virt_iocsr_misc_read, - .write = virt_iocsr_misc_write, + .read_with_attrs = virt_iocsr_misc_read, + .write_with_attrs = virt_iocsr_misc_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 4, @@ -1117,6 +1226,9 @@ static void virt_initfn(Object *obj) { LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj); + if (tcg_enabled()) { + lvms->veiointc = ON_OFF_AUTO_OFF; + } 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); @@ -1213,6 +1325,7 @@ static HotplugHandler *virt_get_hotplug_handler(MachineState *machine, MachineClass *mc = MACHINE_GET_CLASS(machine); if (device_is_dynamic_sysbus(mc, dev) || + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) || memhp_type_supported(dev)) { return HOTPLUG_HANDLER(machine); } @@ -1302,6 +1415,11 @@ static void virt_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); |