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----- 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>
This commit is contained in:
commit
dec9742cbc
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -41,6 +41,24 @@
|
||||
#define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET)
|
||||
#define EXTIOI_SIZE 0x800
|
||||
|
||||
#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);
|
||||
@ -52,6 +70,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];
|
||||
@ -65,5 +85,6 @@ struct LoongArchExtIOI {
|
||||
qemu_irq irq[EXTIOI_IRQS];
|
||||
ExtIOICore *cpu;
|
||||
MemoryRegion extioi_system_mem;
|
||||
MemoryRegion virt_extend;
|
||||
};
|
||||
#endif /* LOONGARCH_EXTIOI_H */
|
||||
|
@ -50,6 +50,7 @@ struct LoongArchVirtMachineState {
|
||||
Notifier machine_done;
|
||||
Notifier powerdown_notifier;
|
||||
OnOffAuto acpi;
|
||||
OnOffAuto veiointc;
|
||||
char *oem_id;
|
||||
char *oem_table_id;
|
||||
DeviceState *acpi_ged;
|
||||
|
@ -707,7 +707,7 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY);
|
||||
qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 ","
|
||||
" PRCFG3=%016" PRIx64 "\n",
|
||||
env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3);
|
||||
env->CSR_PRCFG1, env->CSR_PRCFG2, env->CSR_PRCFG3);
|
||||
qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
|
||||
qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV);
|
||||
qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA);
|
||||
|
@ -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
|
||||
|
||||
|
114
tests/qtest/libqos/loongarch-virt-machine.c
Normal file
114
tests/qtest/libqos/loongarch-virt-machine.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* libqos driver framework
|
||||
*
|
||||
* Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "../libqtest.h"
|
||||
#include "qemu/module.h"
|
||||
#include "libqos-malloc.h"
|
||||
#include "qgraph.h"
|
||||
#include "virtio-mmio.h"
|
||||
#include "generic-pcihost.h"
|
||||
#include "hw/pci/pci_regs.h"
|
||||
|
||||
#define LOONGARCH_PAGE_SIZE 0x1000
|
||||
#define LOONGARCH_VIRT_RAM_ADDR 0x100000
|
||||
#define LOONGARCH_VIRT_RAM_SIZE 0xFF00000
|
||||
|
||||
#define LOONGARCH_VIRT_PIO_BASE 0x18000000
|
||||
#define LOONGARCH_VIRT_PCIE_PIO_OFFSET 0x4000
|
||||
#define LOONGARCH_VIRT_PCIE_PIO_LIMIT 0x10000
|
||||
#define LOONGARCH_VIRT_PCIE_ECAM_BASE 0x20000000
|
||||
#define LOONGARCH_VIRT_PCIE_MMIO32_BASE 0x40000000
|
||||
#define LOONGARCH_VIRT_PCIE_MMIO32_LIMIT 0x80000000
|
||||
|
||||
typedef struct QVirtMachine QVirtMachine;
|
||||
|
||||
struct QVirtMachine {
|
||||
QOSGraphObject obj;
|
||||
QGuestAllocator alloc;
|
||||
QVirtioMMIODevice virtio_mmio;
|
||||
QGenericPCIHost bridge;
|
||||
};
|
||||
|
||||
static void virt_destructor(QOSGraphObject *obj)
|
||||
{
|
||||
QVirtMachine *machine = (QVirtMachine *) obj;
|
||||
alloc_destroy(&machine->alloc);
|
||||
}
|
||||
|
||||
static void *virt_get_driver(void *object, const char *interface)
|
||||
{
|
||||
QVirtMachine *machine = object;
|
||||
if (!g_strcmp0(interface, "memory")) {
|
||||
return &machine->alloc;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s not present in loongarch/virtio\n", interface);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static QOSGraphObject *virt_get_device(void *obj, const char *device)
|
||||
{
|
||||
QVirtMachine *machine = obj;
|
||||
if (!g_strcmp0(device, "generic-pcihost")) {
|
||||
return &machine->bridge.obj;
|
||||
} else if (!g_strcmp0(device, "virtio-mmio")) {
|
||||
return &machine->virtio_mmio.obj;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s not present in loongarch/virt\n", device);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static void loongarch_config_qpci_bus(QGenericPCIBus *qpci)
|
||||
{
|
||||
qpci->gpex_pio_base = LOONGARCH_VIRT_PIO_BASE;
|
||||
qpci->bus.pio_alloc_ptr = LOONGARCH_VIRT_PCIE_PIO_OFFSET;
|
||||
qpci->bus.pio_limit = LOONGARCH_VIRT_PCIE_PIO_LIMIT;
|
||||
qpci->bus.mmio_alloc_ptr = LOONGARCH_VIRT_PCIE_MMIO32_BASE;
|
||||
qpci->bus.mmio_limit = LOONGARCH_VIRT_PCIE_MMIO32_LIMIT;
|
||||
qpci->ecam_alloc_ptr = LOONGARCH_VIRT_PCIE_ECAM_BASE;
|
||||
}
|
||||
|
||||
static void *qos_create_machine_loongarch_virt(QTestState *qts)
|
||||
{
|
||||
QVirtMachine *machine = g_new0(QVirtMachine, 1);
|
||||
|
||||
alloc_init(&machine->alloc, 0,
|
||||
LOONGARCH_VIRT_RAM_ADDR,
|
||||
LOONGARCH_VIRT_RAM_ADDR + LOONGARCH_VIRT_RAM_SIZE,
|
||||
LOONGARCH_PAGE_SIZE);
|
||||
|
||||
qos_create_generic_pcihost(&machine->bridge, qts, &machine->alloc);
|
||||
loongarch_config_qpci_bus(&machine->bridge.pci);
|
||||
|
||||
machine->obj.get_device = virt_get_device;
|
||||
machine->obj.get_driver = virt_get_driver;
|
||||
machine->obj.destructor = virt_destructor;
|
||||
return machine;
|
||||
}
|
||||
|
||||
static void virt_machine_register_nodes(void)
|
||||
{
|
||||
qos_node_create_machine_args("loongarch64/virt",
|
||||
qos_create_machine_loongarch_virt,
|
||||
" -cpu la464");
|
||||
qos_node_contains("loongarch64/virt", "generic-pcihost", NULL);
|
||||
}
|
||||
|
||||
libqos_init(virt_machine_register_nodes);
|
@ -61,6 +61,7 @@ libqos_srcs = files(
|
||||
'ppc64_pseries-machine.c',
|
||||
'x86_64_pc-machine.c',
|
||||
'riscv-virt-machine.c',
|
||||
'loongarch-virt-machine.c',
|
||||
)
|
||||
|
||||
if have_virtfs
|
||||
|
@ -140,7 +140,7 @@ qtests_hppa = ['boot-serial-test'] + \
|
||||
(config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : [])
|
||||
|
||||
qtests_loongarch64 = qtests_filter + \
|
||||
['boot-serial-test']
|
||||
['boot-serial-test', 'numa-test']
|
||||
|
||||
qtests_m68k = ['boot-serial-test'] + \
|
||||
qtests_filter
|
||||
|
@ -265,6 +265,54 @@ static void aarch64_numa_cpu(const void *data)
|
||||
qtest_quit(qts);
|
||||
}
|
||||
|
||||
static void loongarch64_numa_cpu(const void *data)
|
||||
{
|
||||
QDict *resp;
|
||||
QList *cpus;
|
||||
QObject *e;
|
||||
QTestState *qts;
|
||||
g_autofree char *cli = NULL;
|
||||
|
||||
cli = make_cli(data, "-machine "
|
||||
"smp.cpus=2,smp.sockets=2,smp.cores=1,smp.threads=1 "
|
||||
"-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 "
|
||||
"-numa cpu,node-id=0,socket-id=1,core-id=0,thread-id=0 "
|
||||
"-numa cpu,node-id=1,socket-id=0,core-id=0,thread-id=0");
|
||||
qts = qtest_init(cli);
|
||||
cpus = get_cpus(qts, &resp);
|
||||
g_assert(cpus);
|
||||
|
||||
while ((e = qlist_pop(cpus))) {
|
||||
QDict *cpu, *props;
|
||||
int64_t socket, core, thread, node;
|
||||
|
||||
cpu = qobject_to(QDict, e);
|
||||
g_assert(qdict_haskey(cpu, "props"));
|
||||
props = qdict_get_qdict(cpu, "props");
|
||||
|
||||
g_assert(qdict_haskey(props, "node-id"));
|
||||
node = qdict_get_int(props, "node-id");
|
||||
g_assert(qdict_haskey(props, "socket-id"));
|
||||
socket = qdict_get_int(props, "socket-id");
|
||||
g_assert(qdict_haskey(props, "core-id"));
|
||||
core = qdict_get_int(props, "core-id");
|
||||
g_assert(qdict_haskey(props, "thread-id"));
|
||||
thread = qdict_get_int(props, "thread-id");
|
||||
|
||||
if (socket == 0 && core == 0 && thread == 0) {
|
||||
g_assert_cmpint(node, ==, 1);
|
||||
} else if (socket == 1 && core == 0 && thread == 0) {
|
||||
g_assert_cmpint(node, ==, 0);
|
||||
} else {
|
||||
g_assert(false);
|
||||
}
|
||||
qobject_unref(e);
|
||||
}
|
||||
|
||||
qobject_unref(resp);
|
||||
qtest_quit(qts);
|
||||
}
|
||||
|
||||
static void pc_dynamic_cpu_cfg(const void *data)
|
||||
{
|
||||
QObject *e;
|
||||
@ -593,6 +641,11 @@ int main(int argc, char **argv)
|
||||
aarch64_numa_cpu);
|
||||
}
|
||||
|
||||
if (!strcmp(arch, "loongarch64")) {
|
||||
qtest_add_data_func("/numa/loongarch64/cpu/explicit", args,
|
||||
loongarch64_numa_cpu);
|
||||
}
|
||||
|
||||
out:
|
||||
return g_test_run();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user