From 3bee1d1d14c583929af068d8fd6eef54d21046e4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:49 +0200 Subject: microvm: name qboot binary qboot.rom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qboot isn't a bios and shouldnt be named that way. Signed-off-by: Gerd Hoffmann Reviewed-by: Sergio Lopez Reviewed-by: Philippe Mathieu-Daudé Message-id: 20200915120909.20838-2-kraxel@redhat.com --- hw/i386/microvm.c | 4 ++-- pc-bios/bios-microvm.bin | Bin 65536 -> 0 bytes pc-bios/meson.build | 2 +- pc-bios/qboot.rom | Bin 0 -> 65536 bytes roms/Makefile | 6 +++--- 5 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 pc-bios/bios-microvm.bin create mode 100644 pc-bios/qboot.rom diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 81d0888..b1dc7e4 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -47,7 +47,7 @@ #include "kvm_i386.h" #include "hw/xen/start_info.h" -#define MICROVM_BIOS_FILENAME "bios-microvm.bin" +#define MICROVM_QBOOT_FILENAME "qboot.rom" static void microvm_set_rtc(MicrovmMachineState *mms, ISADevice *s) { @@ -158,7 +158,7 @@ static void microvm_devices_init(MicrovmMachineState *mms) } if (bios_name == NULL) { - bios_name = MICROVM_BIOS_FILENAME; + bios_name = MICROVM_QBOOT_FILENAME; } x86_bios_rom_init(get_system_memory(), true); } diff --git a/pc-bios/bios-microvm.bin b/pc-bios/bios-microvm.bin deleted file mode 100644 index 45eabc5..0000000 Binary files a/pc-bios/bios-microvm.bin and /dev/null differ diff --git a/pc-bios/meson.build b/pc-bios/meson.build index 182d5eb..9759dba 100644 --- a/pc-bios/meson.build +++ b/pc-bios/meson.build @@ -27,7 +27,7 @@ endif blobs = files( 'bios.bin', 'bios-256k.bin', - 'bios-microvm.bin', + 'qboot.rom', 'sgabios.bin', 'vgabios.bin', 'vgabios-cirrus.bin', diff --git a/pc-bios/qboot.rom b/pc-bios/qboot.rom new file mode 100644 index 0000000..45eabc5 Binary files /dev/null and b/pc-bios/qboot.rom differ diff --git a/roms/Makefile b/roms/Makefile index 3726f06..1395a46 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -68,7 +68,7 @@ default help: @echo " efi -- update UEFI (edk2) platform firmware" @echo " opensbi32-generic -- update OpenSBI for 32-bit generic machine" @echo " opensbi64-generic -- update OpenSBI for 64-bit generic machine" - @echo " bios-microvm -- update bios-microvm.bin (qboot)" + @echo " qboot -- update qboot" @echo " clean -- delete the files generated by the previous" \ "build targets" @@ -183,9 +183,9 @@ opensbi64-generic: cp opensbi/build/platform/generic/firmware/fw_dynamic.bin ../pc-bios/opensbi-riscv64-generic-fw_dynamic.bin cp opensbi/build/platform/generic/firmware/fw_dynamic.elf ../pc-bios/opensbi-riscv64-generic-fw_dynamic.elf -bios-microvm: +qboot: $(MAKE) -C qboot - cp qboot/bios.bin ../pc-bios/bios-microvm.bin + cp qboot/bios.bin ../pc-bios/qboot.rom npcm7xx_bootrom: $(MAKE) -C vbootrom CROSS_COMPILE=$(arm_cross_prefix) -- cgit v1.1 From be404fa560c72f1810c506cb83673a71ee72cd49 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:50 +0200 Subject: seabios: add microvm config, update build rules Signed-off-by: Gerd Hoffmann Reviewed-by: Sergio Lopez Message-id: 20200915120909.20838-3-kraxel@redhat.com --- roms/Makefile | 5 ++++- roms/config.seabios-microvm | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 roms/config.seabios-microvm diff --git a/roms/Makefile b/roms/Makefile index 1395a46..1489d47 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -72,9 +72,12 @@ default help: @echo " clean -- delete the files generated by the previous" \ "build targets" -bios: build-seabios-config-seabios-128k build-seabios-config-seabios-256k +bios: build-seabios-config-seabios-128k \ + build-seabios-config-seabios-256k \ + build-seabios-config-seabios-microvm cp seabios/builds/seabios-128k/bios.bin ../pc-bios/bios.bin cp seabios/builds/seabios-256k/bios.bin ../pc-bios/bios-256k.bin + cp seabios/builds/seabios-microvm/bios.bin ../pc-bios/bios-microvm.bin vgabios seavgabios: $(patsubst %,seavgabios-%,$(vgabios_variants)) diff --git a/roms/config.seabios-microvm b/roms/config.seabios-microvm new file mode 100644 index 0000000..a253e2e --- /dev/null +++ b/roms/config.seabios-microvm @@ -0,0 +1,26 @@ +CONFIG_QEMU=y +CONFIG_QEMU_HARDWARE=y +CONFIG_PERMIT_UNALIGNED_PCIROM=y +CONFIG_ROM_SIZE=128 +CONFIG_XEN=n +CONFIG_BOOTSPLASH=n +CONFIG_ATA=n +CONFIG_AHCI=n +CONFIG_SDCARD=n +CONFIG_PVSCSI=n +CONFIG_ESP_SCSI=n +CONFIG_LSI_SCSI=n +CONFIG_MEGASAS=n +CONFIG_MPT_SCSI=n +CONFIG_FLOPPY=n +CONFIG_FLASH_FLOPPY=n +CONFIG_NVME=n +CONFIG_PS2PORT=n +CONFIG_USB=n +CONFIG_LPT=n +CONFIG_RTC_TIMER=n +CONFIG_USE_SMM=n +CONFIG_PMTIMER=n +CONFIG_TCGBIOS=n +CONFIG_HARDWARE_IRQ=n +CONFIG_ACPI_PARSE=y -- cgit v1.1 From 38edb514c9c2cba3c3d536504b2cddbfdc915056 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:51 +0200 Subject: seabios: add bios-microvm.bin binary Signed-off-by: Gerd Hoffmann Reviewed-by: Sergio Lopez Message-id: 20200915120909.20838-4-kraxel@redhat.com --- pc-bios/bios-microvm.bin | Bin 0 -> 131072 bytes pc-bios/meson.build | 1 + 2 files changed, 1 insertion(+) create mode 100644 pc-bios/bios-microvm.bin diff --git a/pc-bios/bios-microvm.bin b/pc-bios/bios-microvm.bin new file mode 100644 index 0000000..eefd321 Binary files /dev/null and b/pc-bios/bios-microvm.bin differ diff --git a/pc-bios/meson.build b/pc-bios/meson.build index 9759dba..a0d21be 100644 --- a/pc-bios/meson.build +++ b/pc-bios/meson.build @@ -27,6 +27,7 @@ endif blobs = files( 'bios.bin', 'bios-256k.bin', + 'bios-microvm.bin', 'qboot.rom', 'sgabios.bin', 'vgabios.bin', -- cgit v1.1 From 14404dd2d1c18529f619461e09e3065e1aa46c7b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:52 +0200 Subject: acpi: ged: add control regs Add control regs (sleep, reset) for hw-reduced acpi. Signed-off-by: Gerd Hoffmann Reviewed-by: Igor Mammedov Message-id: 20200915120909.20838-5-kraxel@redhat.com --- hw/acpi/generic_event_device.c | 44 ++++++++++++++++++++++++++++++++++ include/hw/acpi/generic_event_device.h | 12 ++++++++++ 2 files changed, 56 insertions(+) diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index b8abdef..491df80 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -20,6 +20,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qemu/error-report.h" +#include "sysemu/runstate.h" static const uint32_t ged_supported_events[] = { ACPI_GED_MEM_HOTPLUG_EVT, @@ -176,6 +177,45 @@ static const MemoryRegionOps ged_evt_ops = { }, }; +static uint64_t ged_regs_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void ged_regs_write(void *opaque, hwaddr addr, uint64_t data, + unsigned int size) +{ + bool slp_en; + int slp_typ; + + switch (addr) { + case ACPI_GED_REG_SLEEP_CTL: + slp_typ = (data >> 2) & 0x07; + slp_en = (data >> 5) & 0x01; + if (slp_en && slp_typ == 5) { + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } + return; + case ACPI_GED_REG_SLEEP_STS: + return; + case ACPI_GED_REG_RESET: + if (data == ACPI_GED_RESET_VALUE) { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } + return; + } +} + +static const MemoryRegionOps ged_regs_ops = { + .read = ged_regs_read, + .write = ged_regs_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 1, + }, +}; + static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -332,6 +372,10 @@ static void acpi_ged_initfn(Object *obj) sysbus_init_mmio(sbd, &s->container_memhp); acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev), &s->memhp_state, 0); + + memory_region_init_io(&ged_st->regs, obj, &ged_regs_ops, ged_st, + TYPE_ACPI_GED "-regs", ACPI_GED_REG_COUNT); + sysbus_init_mmio(sbd, &ged_st->regs); } static void acpi_ged_class_init(ObjectClass *class, void *data) diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h index 1be05a3..38aec52 100644 --- a/include/hw/acpi/generic_event_device.h +++ b/include/hw/acpi/generic_event_device.h @@ -74,6 +74,17 @@ DECLARE_INSTANCE_CHECKER(AcpiGedState, ACPI_GED, #define ACPI_GED_EVT_SEL_OFFSET 0x0 #define ACPI_GED_EVT_SEL_LEN 0x4 +#define ACPI_GED_REG_SLEEP_CTL 0x00 +#define ACPI_GED_REG_SLEEP_STS 0x01 +#define ACPI_GED_REG_RESET 0x02 +#define ACPI_GED_REG_COUNT 0x03 + +/* ACPI_GED_REG_RESET value for reset*/ +#define ACPI_GED_RESET_VALUE 0x42 + +/* ACPI_GED_REG_SLEEP_CTL.SLP_TYP value for S5 (aka poweroff) */ +#define ACPI_GED_SLP_TYP_S5 0x05 + #define GED_DEVICE "GED" #define AML_GED_EVT_REG "EREG" #define AML_GED_EVT_SEL "ESEL" @@ -89,6 +100,7 @@ DECLARE_INSTANCE_CHECKER(AcpiGedState, ACPI_GED, typedef struct GEDState { MemoryRegion evt; + MemoryRegion regs; uint32_t sel; } GEDState; -- cgit v1.1 From 2025e97dc55107e4f0d2b7553d7eb325bc1f437d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:53 +0200 Subject: acpi: ged: add x86 device variant. Set AcpiDeviceIfClass->madt_cpu, otherwise identical to TYPE_ACPI_GED. Signed-off-by: Gerd Hoffmann Reviewed-by: Igor Mammedov Message-id: 20200915120909.20838-6-kraxel@redhat.com --- hw/i386/generic_event_device_x86.c | 36 ++++++++++++++++++++++++++++++++++ hw/i386/meson.build | 1 + include/hw/acpi/generic_event_device.h | 4 ++++ 3 files changed, 41 insertions(+) create mode 100644 hw/i386/generic_event_device_x86.c diff --git a/hw/i386/generic_event_device_x86.c b/hw/i386/generic_event_device_x86.c new file mode 100644 index 0000000..e26fb02 --- /dev/null +++ b/hw/i386/generic_event_device_x86.c @@ -0,0 +1,36 @@ +/* + * x86 variant of the generic event device for hw reduced acpi + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + */ + +#include "qemu/osdep.h" +#include "hw/acpi/generic_event_device.h" +#include "hw/i386/pc.h" + +static void acpi_ged_x86_class_init(ObjectClass *class, void *data) +{ + AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class); + + adevc->madt_cpu = pc_madt_cpu_entry; +} + +static const TypeInfo acpi_ged_x86_info = { + .name = TYPE_ACPI_GED_X86, + .parent = TYPE_ACPI_GED, + .class_init = acpi_ged_x86_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { TYPE_ACPI_DEVICE_IF }, + { } + } +}; + +static void acpi_ged_x86_register_types(void) +{ + type_register_static(&acpi_ged_x86_info); +} + +type_init(acpi_ged_x86_register_types) diff --git a/hw/i386/meson.build b/hw/i386/meson.build index 63918fb..1a7d1a6 100644 --- a/hw/i386/meson.build +++ b/hw/i386/meson.build @@ -18,6 +18,7 @@ i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c')) i386_ss.add(when: 'CONFIG_VTD', if_true: files('intel_iommu.c')) i386_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-common.c')) +i386_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: files('generic_event_device_x86.c')) i386_ss.add(when: 'CONFIG_PC', if_true: files( 'pc.c', 'pc_sysfw.c', diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h index 38aec52..2411516 100644 --- a/include/hw/acpi/generic_event_device.h +++ b/include/hw/acpi/generic_event_device.h @@ -71,6 +71,10 @@ typedef struct AcpiGedState AcpiGedState; DECLARE_INSTANCE_CHECKER(AcpiGedState, ACPI_GED, TYPE_ACPI_GED) +#define TYPE_ACPI_GED_X86 "acpi-ged-x86" +#define ACPI_GED_X86(obj) \ + OBJECT_CHECK(AcpiGedX86State, (obj), TYPE_ACPI_GED_X86) + #define ACPI_GED_EVT_SEL_OFFSET 0x0 #define ACPI_GED_EVT_SEL_LEN 0x4 -- cgit v1.1 From 7bf2567c12320731b115af83f4991bbc9203df70 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:54 +0200 Subject: acpi: move acpi_dsdt_add_power_button() to ged MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow reuse for microvm. Signed-off-by: Gerd Hoffmann Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Igor Mammedov Message-id: 20200915120909.20838-7-kraxel@redhat.com --- hw/acpi/generic_event_device.c | 8 ++++++++ hw/arm/virt-acpi-build.c | 8 -------- include/hw/acpi/generic_event_device.h | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index 491df80..6df400e 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -142,6 +142,14 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, aml_append(table, dev); } +void acpi_dsdt_add_power_button(Aml *scope) +{ + Aml *dev = aml_device(ACPI_POWER_BUTTON_DEVICE); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C0C"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + aml_append(scope, dev); +} + /* Memory read by the GED _EVT AML dynamic method */ static uint64_t ged_evt_read(void *opaque, hwaddr addr, unsigned size) { diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 9efd7a3..6bff5e3 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -357,14 +357,6 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, aml_append(scope, dev); } -static void acpi_dsdt_add_power_button(Aml *scope) -{ - Aml *dev = aml_device(ACPI_POWER_BUTTON_DEVICE); - aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C0C"))); - aml_append(dev, aml_name_decl("_UID", aml_int(0))); - aml_append(scope, dev); -} - static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms) { PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev); diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h index 2411516..ac921e9 100644 --- a/include/hw/acpi/generic_event_device.h +++ b/include/hw/acpi/generic_event_device.h @@ -120,5 +120,6 @@ struct AcpiGedState { void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base); +void acpi_dsdt_add_power_button(Aml *scope); #endif -- cgit v1.1 From d4e9d577be587c6f2e41557f7e4ac0b185f0bb1b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:55 +0200 Subject: microvm: make virtio irq base runtime configurable Signed-off-by: Gerd Hoffmann Reviewed-by: Sergio Lopez Reviewed-by: Igor Mammedov Message-id: 20200915120909.20838-8-kraxel@redhat.com --- hw/i386/microvm.c | 11 +++++++---- include/hw/i386/microvm.h | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index b1dc7e4..e4501f2 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -121,10 +121,11 @@ static void microvm_devices_init(MicrovmMachineState *mms) kvmclock_create(); + mms->virtio_irq_base = 5; for (i = 0; i < VIRTIO_NUM_TRANSPORTS; i++) { sysbus_create_simple("virtio-mmio", VIRTIO_MMIO_BASE + i * 512, - x86ms->gsi[VIRTIO_IRQ_BASE + i]); + x86ms->gsi[mms->virtio_irq_base + i]); } /* Optional and legacy devices */ @@ -227,7 +228,7 @@ static void microvm_memory_init(MicrovmMachineState *mms) x86ms->ioapic_as = &address_space_memory; } -static gchar *microvm_get_mmio_cmdline(gchar *name) +static gchar *microvm_get_mmio_cmdline(gchar *name, uint32_t virtio_irq_base) { gchar *cmdline; gchar *separator; @@ -247,7 +248,7 @@ static gchar *microvm_get_mmio_cmdline(gchar *name) ret = g_snprintf(cmdline, VIRTIO_CMDLINE_MAXLEN, " virtio_mmio.device=512@0x%lx:%ld", VIRTIO_MMIO_BASE + index * 512, - VIRTIO_IRQ_BASE + index); + virtio_irq_base + index); if (ret < 0 || ret >= VIRTIO_CMDLINE_MAXLEN) { g_free(cmdline); return NULL; @@ -259,6 +260,7 @@ static gchar *microvm_get_mmio_cmdline(gchar *name) static void microvm_fix_kernel_cmdline(MachineState *machine) { X86MachineState *x86ms = X86_MACHINE(machine); + MicrovmMachineState *mms = MICROVM_MACHINE(machine); BusState *bus; BusChild *kid; char *cmdline; @@ -282,7 +284,8 @@ static void microvm_fix_kernel_cmdline(MachineState *machine) BusState *mmio_bus = &mmio_virtio_bus->parent_obj; if (!QTAILQ_EMPTY(&mmio_bus->children)) { - gchar *mmio_cmdline = microvm_get_mmio_cmdline(mmio_bus->name); + gchar *mmio_cmdline = microvm_get_mmio_cmdline + (mmio_bus->name, mms->virtio_irq_base); if (mmio_cmdline) { char *newcmd = g_strjoin(NULL, cmdline, mmio_cmdline, NULL); g_free(mmio_cmdline); diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h index 36dbcdd..8759369 100644 --- a/include/hw/i386/microvm.h +++ b/include/hw/i386/microvm.h @@ -28,7 +28,6 @@ /* Platform virtio definitions */ #define VIRTIO_MMIO_BASE 0xfeb00000 -#define VIRTIO_IRQ_BASE 5 #define VIRTIO_NUM_TRANSPORTS 8 #define VIRTIO_CMDLINE_MAXLEN 64 @@ -59,6 +58,7 @@ struct MicrovmMachineState { bool auto_kernel_cmdline; /* Machine state */ + uint32_t virtio_irq_base; bool kernel_cmdline_fixed; }; typedef struct MicrovmMachineState MicrovmMachineState; -- cgit v1.1 From 8045df14bccaeec39291c3d83fea2f638656b5d0 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:56 +0200 Subject: microvm/acpi: add minimal acpi support $subject says all. Can be controlled using -M microvm,acpi=on/off. Signed-off-by: Gerd Hoffmann Reviewed-by: Igor Mammedov Message-id: 20200915120909.20838-9-kraxel@redhat.com --- hw/i386/Kconfig | 1 + hw/i386/acpi-microvm.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++ hw/i386/acpi-microvm.h | 8 ++ hw/i386/meson.build | 2 +- hw/i386/microvm.c | 40 ++++++++++ include/hw/i386/microvm.h | 9 +++ 6 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 hw/i386/acpi-microvm.c create mode 100644 hw/i386/acpi-microvm.h diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index 03e347b..d0bd8b5 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -103,6 +103,7 @@ config MICROVM select I8259 select MC146818RTC select VIRTIO_MMIO + select ACPI_HW_REDUCED config X86_IOMMU bool diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c new file mode 100644 index 0000000..06ef339 --- /dev/null +++ b/hw/i386/acpi-microvm.c @@ -0,0 +1,187 @@ +/* Support for generating ACPI tables and passing them to Guests + * + * Copyright (C) 2008-2010 Kevin O'Connor + * Copyright (C) 2006 Fabrice Bellard + * Copyright (C) 2013 Red Hat Inc + * + * Author: Michael S. Tsirkin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" + +#include "exec/memory.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/aml-build.h" +#include "hw/acpi/bios-linker-loader.h" +#include "hw/acpi/generic_event_device.h" +#include "hw/acpi/utils.h" +#include "hw/boards.h" +#include "hw/i386/fw_cfg.h" +#include "hw/i386/microvm.h" + +#include "acpi-common.h" +#include "acpi-microvm.h" + +static void +build_dsdt_microvm(GArray *table_data, BIOSLinker *linker, + MicrovmMachineState *mms) +{ + X86MachineState *x86ms = X86_MACHINE(mms); + Aml *dsdt, *sb_scope, *scope, *pkg; + bool ambiguous; + Object *isabus; + + isabus = object_resolve_path_type("", TYPE_ISA_BUS, &ambiguous); + assert(isabus); + assert(!ambiguous); + + dsdt = init_aml_allocator(); + + /* Reserve space for header */ + acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader)); + + sb_scope = aml_scope("_SB"); + fw_cfg_add_acpi_dsdt(sb_scope, x86ms->fw_cfg); + isa_build_aml(ISA_BUS(isabus), sb_scope); + build_ged_aml(sb_scope, GED_DEVICE, HOTPLUG_HANDLER(mms->acpi_dev), + GED_MMIO_IRQ, AML_SYSTEM_MEMORY, GED_MMIO_BASE); + acpi_dsdt_add_power_button(sb_scope); + aml_append(dsdt, sb_scope); + + /* ACPI 5.0: Table 7-209 System State Package */ + scope = aml_scope("\\"); + pkg = aml_package(4); + aml_append(pkg, aml_int(ACPI_GED_SLP_TYP_S5)); + aml_append(pkg, aml_int(0)); /* ignored */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(scope, aml_name_decl("_S5", pkg)); + aml_append(dsdt, scope); + + /* copy AML table into ACPI tables blob and patch header there */ + g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); + build_header(linker, table_data, + (void *)(table_data->data + table_data->len - dsdt->buf->len), + "DSDT", dsdt->buf->len, 2, NULL, NULL); + free_aml_allocator(); +} + +static void acpi_build_microvm(AcpiBuildTables *tables, + MicrovmMachineState *mms) +{ + MachineState *machine = MACHINE(mms); + GArray *table_offsets; + GArray *tables_blob = tables->table_data; + unsigned dsdt, xsdt; + AcpiFadtData pmfadt = { + /* ACPI 5.0: 4.1 Hardware-Reduced ACPI */ + .rev = 5, + .flags = ((1 << ACPI_FADT_F_HW_REDUCED_ACPI) | + (1 << ACPI_FADT_F_RESET_REG_SUP)), + + /* ACPI 5.0: 4.8.3.7 Sleep Control and Status Registers */ + .sleep_ctl = { + .space_id = AML_AS_SYSTEM_MEMORY, + .bit_width = 8, + .address = GED_MMIO_BASE_REGS + ACPI_GED_REG_SLEEP_CTL, + }, + .sleep_sts = { + .space_id = AML_AS_SYSTEM_MEMORY, + .bit_width = 8, + .address = GED_MMIO_BASE_REGS + ACPI_GED_REG_SLEEP_STS, + }, + + /* ACPI 5.0: 4.8.3.6 Reset Register */ + .reset_reg = { + .space_id = AML_AS_SYSTEM_MEMORY, + .bit_width = 8, + .address = GED_MMIO_BASE_REGS + ACPI_GED_REG_RESET, + }, + .reset_val = ACPI_GED_RESET_VALUE, + }; + + table_offsets = g_array_new(false, true /* clear */, + sizeof(uint32_t)); + bios_linker_loader_alloc(tables->linker, + ACPI_BUILD_TABLE_FILE, tables_blob, + 64 /* Ensure FACS is aligned */, + false /* high memory */); + + dsdt = tables_blob->len; + build_dsdt_microvm(tables_blob, tables->linker, mms); + + pmfadt.dsdt_tbl_offset = &dsdt; + pmfadt.xdsdt_tbl_offset = &dsdt; + acpi_add_table(table_offsets, tables_blob); + build_fadt(tables_blob, tables->linker, &pmfadt, NULL, NULL); + + acpi_add_table(table_offsets, tables_blob); + acpi_build_madt(tables_blob, tables->linker, X86_MACHINE(machine), + mms->acpi_dev, false); + + xsdt = tables_blob->len; + build_xsdt(tables_blob, tables->linker, table_offsets, NULL, NULL); + + /* RSDP is in FSEG memory, so allocate it separately */ + { + AcpiRsdpData rsdp_data = { + /* ACPI 2.0: 5.2.4.3 RSDP Structure */ + .revision = 2, /* xsdt needs v2 */ + .oem_id = ACPI_BUILD_APPNAME6, + .xsdt_tbl_offset = &xsdt, + .rsdt_tbl_offset = NULL, + }; + build_rsdp(tables->rsdp, tables->linker, &rsdp_data); + } + + /* Cleanup memory that's no longer used. */ + g_array_free(table_offsets, true); +} + +static void acpi_build_no_update(void *build_opaque) +{ + /* nothing, microvm tables don't change at runtime */ +} + +void acpi_setup_microvm(MicrovmMachineState *mms) +{ + X86MachineState *x86ms = X86_MACHINE(mms); + AcpiBuildTables tables; + + assert(x86ms->fw_cfg); + + if (!x86_machine_is_acpi_enabled(x86ms)) { + return; + } + + acpi_build_tables_init(&tables); + acpi_build_microvm(&tables, mms); + + /* Now expose it all to Guest */ + acpi_add_rom_blob(acpi_build_no_update, NULL, + tables.table_data, + ACPI_BUILD_TABLE_FILE, + ACPI_BUILD_TABLE_MAX_SIZE); + acpi_add_rom_blob(acpi_build_no_update, NULL, + tables.linker->cmd_blob, + "etc/table-loader", 0); + acpi_add_rom_blob(acpi_build_no_update, NULL, + tables.rsdp, + ACPI_BUILD_RSDP_FILE, 0); + + acpi_build_tables_cleanup(&tables, false); +} diff --git a/hw/i386/acpi-microvm.h b/hw/i386/acpi-microvm.h new file mode 100644 index 0000000..dfe8536 --- /dev/null +++ b/hw/i386/acpi-microvm.h @@ -0,0 +1,8 @@ +#ifndef HW_I386_ACPI_MICROVM_H +#define HW_I386_ACPI_MICROVM_H + +#include "hw/i386/microvm.h" + +void acpi_setup_microvm(MicrovmMachineState *mms); + +#endif diff --git a/hw/i386/meson.build b/hw/i386/meson.build index 1a7d1a6..e5d109f 100644 --- a/hw/i386/meson.build +++ b/hw/i386/meson.build @@ -11,7 +11,7 @@ i386_ss.add(when: 'CONFIG_X86_IOMMU', if_true: files('x86-iommu.c'), if_false: files('x86-iommu-stub.c')) i386_ss.add(when: 'CONFIG_AMD_IOMMU', if_true: files('amd_iommu.c')) i386_ss.add(when: 'CONFIG_I440FX', if_true: files('pc_piix.c')) -i386_ss.add(when: 'CONFIG_MICROVM', if_true: files('microvm.c')) +i386_ss.add(when: 'CONFIG_MICROVM', if_true: files('microvm.c', 'acpi-microvm.c')) i386_ss.add(when: 'CONFIG_Q35', if_true: files('pc_q35.c')) i386_ss.add(when: 'CONFIG_VMMOUSE', if_true: files('vmmouse.c')) i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c')) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index e4501f2..e1b86da 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -26,6 +26,8 @@ #include "sysemu/cpus.h" #include "sysemu/numa.h" #include "sysemu/reset.h" +#include "sysemu/runstate.h" +#include "acpi-microvm.h" #include "hw/loader.h" #include "hw/irq.h" @@ -41,6 +43,8 @@ #include "hw/i386/e820_memory_layout.h" #include "hw/i386/fw_cfg.h" #include "hw/virtio/virtio-mmio.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/generic_event_device.h" #include "cpu.h" #include "elf.h" @@ -129,6 +133,17 @@ static void microvm_devices_init(MicrovmMachineState *mms) } /* Optional and legacy devices */ + if (x86_machine_is_acpi_enabled(x86ms)) { + DeviceState *dev = qdev_new(TYPE_ACPI_GED_X86); + qdev_prop_set_uint32(dev, "ged-event", ACPI_GED_PWR_DOWN_EVT); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, GED_MMIO_BASE); + /* sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, GED_MMIO_BASE_MEMHP); */ + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, GED_MMIO_BASE_REGS); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, + x86ms->gsi[GED_MMIO_IRQ]); + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); + mms->acpi_dev = ACPI_DEVICE_IF(dev); + } if (mms->pic == ON_OFF_AUTO_ON || mms->pic == ON_OFF_AUTO_AUTO) { qemu_irq *i8259; @@ -438,6 +453,26 @@ static void microvm_machine_set_auto_kernel_cmdline(Object *obj, bool value, mms->auto_kernel_cmdline = value; } +static void microvm_machine_done(Notifier *notifier, void *data) +{ + MicrovmMachineState *mms = container_of(notifier, MicrovmMachineState, + machine_done); + + acpi_setup_microvm(mms); +} + +static void microvm_powerdown_req(Notifier *notifier, void *data) +{ + MicrovmMachineState *mms = container_of(notifier, MicrovmMachineState, + powerdown_req); + + if (mms->acpi_dev) { + Object *obj = OBJECT(mms->acpi_dev); + AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj); + adevc->send_event(mms->acpi_dev, ACPI_POWER_DOWN_STATUS); + } +} + static void microvm_machine_initfn(Object *obj) { MicrovmMachineState *mms = MICROVM_MACHINE(obj); @@ -452,6 +487,11 @@ static void microvm_machine_initfn(Object *obj) /* State */ mms->kernel_cmdline_fixed = false; + + mms->machine_done.notify = microvm_machine_done; + qemu_add_machine_init_done_notifier(&mms->machine_done); + mms->powerdown_req.notify = microvm_powerdown_req; + qemu_register_powerdown_notifier(&mms->powerdown_req); } static void microvm_class_init(ObjectClass *oc, void *data) diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h index 8759369..d75dcf8 100644 --- a/include/hw/i386/microvm.h +++ b/include/hw/i386/microvm.h @@ -24,6 +24,7 @@ #include "hw/boards.h" #include "hw/i386/x86.h" +#include "hw/acpi/acpi_dev_interface.h" #include "qom/object.h" /* Platform virtio definitions */ @@ -31,6 +32,11 @@ #define VIRTIO_NUM_TRANSPORTS 8 #define VIRTIO_CMDLINE_MAXLEN 64 +#define GED_MMIO_BASE 0xfea00000 +#define GED_MMIO_BASE_MEMHP (GED_MMIO_BASE + 0x100) +#define GED_MMIO_BASE_REGS (GED_MMIO_BASE + 0x200) +#define GED_MMIO_IRQ 9 + /* Machine type options */ #define MICROVM_MACHINE_PIT "pit" #define MICROVM_MACHINE_PIC "pic" @@ -60,6 +66,9 @@ struct MicrovmMachineState { /* Machine state */ uint32_t virtio_irq_base; bool kernel_cmdline_fixed; + Notifier machine_done; + Notifier powerdown_req; + AcpiDeviceIf *acpi_dev; }; typedef struct MicrovmMachineState MicrovmMachineState; -- cgit v1.1 From 3b98c65f75c016d317f70b8b47c86044d0260d53 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:57 +0200 Subject: microvm/acpi: add acpi_dsdt_add_virtio() for x86 Makes x86 linux kernel find virtio-mmio devices automatically. Signed-off-by: Gerd Hoffmann Reviewed-by: Sergio Lopez Reviewed-by: Igor Mammedov Message-id: 20200915120909.20838-10-kraxel@redhat.com --- hw/i386/acpi-microvm.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c index 06ef339..b9ce376 100644 --- a/hw/i386/acpi-microvm.c +++ b/hw/i386/acpi-microvm.c @@ -21,6 +21,7 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "qapi/error.h" #include "exec/memory.h" @@ -32,10 +33,60 @@ #include "hw/boards.h" #include "hw/i386/fw_cfg.h" #include "hw/i386/microvm.h" +#include "hw/virtio/virtio-mmio.h" #include "acpi-common.h" #include "acpi-microvm.h" +static void acpi_dsdt_add_virtio(Aml *scope, + MicrovmMachineState *mms) +{ + gchar *separator; + long int index; + BusState *bus; + BusChild *kid; + + bus = sysbus_get_default(); + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; + Object *obj = object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MMIO); + + if (obj) { + VirtIOMMIOProxy *mmio = VIRTIO_MMIO(obj); + VirtioBusState *mmio_virtio_bus = &mmio->bus; + BusState *mmio_bus = &mmio_virtio_bus->parent_obj; + + if (QTAILQ_EMPTY(&mmio_bus->children)) { + continue; + } + separator = g_strrstr(mmio_bus->name, "."); + if (!separator) { + continue; + } + if (qemu_strtol(separator + 1, NULL, 10, &index) != 0) { + continue; + } + + uint32_t irq = mms->virtio_irq_base + index; + hwaddr base = VIRTIO_MMIO_BASE + index * 512; + hwaddr size = 512; + + Aml *dev = aml_device("VR%02u", (unsigned)index); + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005"))); + aml_append(dev, aml_name_decl("_UID", aml_int(index))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); + + Aml *crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &irq, 1)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + } + } +} + static void build_dsdt_microvm(GArray *table_data, BIOSLinker *linker, MicrovmMachineState *mms) @@ -60,6 +111,7 @@ build_dsdt_microvm(GArray *table_data, BIOSLinker *linker, build_ged_aml(sb_scope, GED_DEVICE, HOTPLUG_HANDLER(mms->acpi_dev), GED_MMIO_IRQ, AML_SYSTEM_MEMORY, GED_MMIO_BASE); acpi_dsdt_add_power_button(sb_scope); + acpi_dsdt_add_virtio(sb_scope, mms); aml_append(dsdt, sb_scope); /* ACPI 5.0: Table 7-209 System State Package */ -- cgit v1.1 From 55c4b069973196b1d9089162e31f5bd7d9f17630 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:58 +0200 Subject: microvm/acpi: use GSI 16-23 for virtio With ACPI enabled and IO-APIC being properly declared in the ACPI tables we can use interrupt lines 16-23 for virtio and avoid shared interrupts. With acpi disabled we continue to use lines 5-12. Signed-off-by: Gerd Hoffmann Reviewed-by: Sergio Lopez Reviewed-by: Igor Mammedov Message-id: 20200915120909.20838-11-kraxel@redhat.com --- hw/i386/microvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index e1b86da..ca0c998 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -125,7 +125,7 @@ static void microvm_devices_init(MicrovmMachineState *mms) kvmclock_create(); - mms->virtio_irq_base = 5; + mms->virtio_irq_base = x86_machine_is_acpi_enabled(x86ms) ? 16 : 5; for (i = 0; i < VIRTIO_NUM_TRANSPORTS; i++) { sysbus_create_simple("virtio-mmio", VIRTIO_MMIO_BASE + i * 512, -- cgit v1.1 From 67eb6a4007fd8f9073020e506453ff5b7c25cb34 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:08:59 +0200 Subject: microvm/acpi: use seabios with acpi=on With acpi=off continue to use qboot. Signed-off-by: Gerd Hoffmann Reviewed-by: Igor Mammedov Reviewed-by: Sergio Lopez Message-id: 20200915120909.20838-12-kraxel@redhat.com --- hw/i386/microvm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index ca0c998..54510a0 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -52,6 +52,7 @@ #include "hw/xen/start_info.h" #define MICROVM_QBOOT_FILENAME "qboot.rom" +#define MICROVM_BIOS_FILENAME "bios-microvm.bin" static void microvm_set_rtc(MicrovmMachineState *mms, ISADevice *s) { @@ -174,7 +175,9 @@ static void microvm_devices_init(MicrovmMachineState *mms) } if (bios_name == NULL) { - bios_name = MICROVM_QBOOT_FILENAME; + bios_name = x86_machine_is_acpi_enabled(x86ms) + ? MICROVM_BIOS_FILENAME + : MICROVM_QBOOT_FILENAME; } x86_bios_rom_init(get_system_memory(), true); } -- cgit v1.1 From f6f7e2d88d0b29d8b6e1a12a5f3f9f31faff9846 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:09:00 +0200 Subject: microvm/acpi: disable virtio-mmio cmdline hack ... in case we are using ACPI. Signed-off-by: Gerd Hoffmann Reviewed-by: Igor Mammedov Reviewed-by: Sergio Lopez Message-id: 20200915120909.20838-13-kraxel@redhat.com --- hw/i386/microvm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 54510a0..04209eb 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -343,7 +343,8 @@ static void microvm_machine_reset(MachineState *machine) CPUState *cs; X86CPU *cpu; - if (machine->kernel_filename != NULL && + if (!x86_machine_is_acpi_enabled(X86_MACHINE(machine)) && + machine->kernel_filename != NULL && mms->auto_kernel_cmdline && !mms->kernel_cmdline_fixed) { microvm_fix_kernel_cmdline(machine); mms->kernel_cmdline_fixed = true; -- cgit v1.1 From 9927a6329a4ce832b4b529903b0a1e1f580cbf0f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:09:01 +0200 Subject: x86: constify x86_machine_is_*_enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gerd Hoffmann Reviewed-by: Sergio Lopez Reviewed-by: Igor Mammedov Reviewed-by: Philippe Mathieu-Daudé Message-id: 20200915120909.20838-14-kraxel@redhat.com --- hw/i386/x86.c | 4 ++-- include/hw/i386/x86.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index c1954db..e2a5005 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -821,7 +821,7 @@ void x86_bios_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw) bios); } -bool x86_machine_is_smm_enabled(X86MachineState *x86ms) +bool x86_machine_is_smm_enabled(const X86MachineState *x86ms) { bool smm_available = false; @@ -863,7 +863,7 @@ static void x86_machine_set_smm(Object *obj, Visitor *v, const char *name, visit_type_OnOffAuto(v, name, &x86ms->smm, errp); } -bool x86_machine_is_acpi_enabled(X86MachineState *x86ms) +bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms) { if (x86ms->acpi == ON_OFF_AUTO_OFF) { return false; diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index 1a188a7..25c9046 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -100,8 +100,8 @@ void x86_load_linux(X86MachineState *x86ms, bool pvh_enabled, bool linuxboot_dma_enabled); -bool x86_machine_is_smm_enabled(X86MachineState *x86ms); -bool x86_machine_is_acpi_enabled(X86MachineState *x86ms); +bool x86_machine_is_smm_enabled(const X86MachineState *x86ms); +bool x86_machine_is_acpi_enabled(const X86MachineState *x86ms); /* Global System Interrupts */ -- cgit v1.1 From 50aef1318166c2a5551d43fb99c5a517f54fcf3c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:09:02 +0200 Subject: x86: move acpi_dev from pc/microvm Both pc and microvm machine types have a acpi_dev field. Move it to the common base type. Signed-off-by: Gerd Hoffmann Reviewed-by: Sergio Lopez Reviewed-by: Igor Mammedov Message-id: 20200915120909.20838-15-kraxel@redhat.com --- hw/i386/acpi-build.c | 2 +- hw/i386/acpi-microvm.c | 5 +++-- hw/i386/microvm.c | 10 ++++++---- hw/i386/pc.c | 34 +++++++++++++++++++--------------- hw/i386/pc_piix.c | 2 +- hw/i386/pc_q35.c | 2 +- include/hw/i386/microvm.h | 1 - include/hw/i386/pc.h | 1 - include/hw/i386/x86.h | 1 + 9 files changed, 32 insertions(+), 26 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 7a5a8b3..0e0535d 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2431,7 +2431,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) acpi_add_table(table_offsets, tables_blob); acpi_build_madt(tables_blob, tables->linker, x86ms, - ACPI_DEVICE_IF(pcms->acpi_dev), true); + ACPI_DEVICE_IF(x86ms->acpi_dev), true); vmgenid_dev = find_vmgenid_dev(); if (vmgenid_dev) { diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c index b9ce376..df39c5d 100644 --- a/hw/i386/acpi-microvm.c +++ b/hw/i386/acpi-microvm.c @@ -108,7 +108,7 @@ build_dsdt_microvm(GArray *table_data, BIOSLinker *linker, sb_scope = aml_scope("_SB"); fw_cfg_add_acpi_dsdt(sb_scope, x86ms->fw_cfg); isa_build_aml(ISA_BUS(isabus), sb_scope); - build_ged_aml(sb_scope, GED_DEVICE, HOTPLUG_HANDLER(mms->acpi_dev), + build_ged_aml(sb_scope, GED_DEVICE, x86ms->acpi_dev, GED_MMIO_IRQ, AML_SYSTEM_MEMORY, GED_MMIO_BASE); acpi_dsdt_add_power_button(sb_scope); acpi_dsdt_add_virtio(sb_scope, mms); @@ -136,6 +136,7 @@ static void acpi_build_microvm(AcpiBuildTables *tables, MicrovmMachineState *mms) { MachineState *machine = MACHINE(mms); + X86MachineState *x86ms = X86_MACHINE(mms); GArray *table_offsets; GArray *tables_blob = tables->table_data; unsigned dsdt, xsdt; @@ -183,7 +184,7 @@ static void acpi_build_microvm(AcpiBuildTables *tables, acpi_add_table(table_offsets, tables_blob); acpi_build_madt(tables_blob, tables->linker, X86_MACHINE(machine), - mms->acpi_dev, false); + ACPI_DEVICE_IF(x86ms->acpi_dev), false); xsdt = tables_blob->len; build_xsdt(tables_blob, tables->linker, table_offsets, NULL, NULL); diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 04209eb..9df1535 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -143,7 +143,7 @@ static void microvm_devices_init(MicrovmMachineState *mms) sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, x86ms->gsi[GED_MMIO_IRQ]); sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal); - mms->acpi_dev = ACPI_DEVICE_IF(dev); + x86ms->acpi_dev = HOTPLUG_HANDLER(dev); } if (mms->pic == ON_OFF_AUTO_ON || mms->pic == ON_OFF_AUTO_AUTO) { @@ -469,11 +469,13 @@ static void microvm_powerdown_req(Notifier *notifier, void *data) { MicrovmMachineState *mms = container_of(notifier, MicrovmMachineState, powerdown_req); + X86MachineState *x86ms = X86_MACHINE(mms); - if (mms->acpi_dev) { - Object *obj = OBJECT(mms->acpi_dev); + if (x86ms->acpi_dev) { + Object *obj = OBJECT(x86ms->acpi_dev); AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj); - adevc->send_event(mms->acpi_dev, ACPI_POWER_DOWN_STATUS); + adevc->send_event(ACPI_DEVICE_IF(x86ms->acpi_dev), + ACPI_POWER_DOWN_STATUS); } } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index d11daac..a181404 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1274,6 +1274,7 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { const PCMachineState *pcms = PC_MACHINE(hotplug_dev); + const X86MachineState *x86ms = X86_MACHINE(hotplug_dev); const PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); const MachineState *ms = MACHINE(hotplug_dev); const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); @@ -1285,7 +1286,7 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, * but pcms->acpi_dev is still created. Check !acpi_enabled in * addition to cover this case. */ - if (!pcms->acpi_dev || !x86_machine_is_acpi_enabled(X86_MACHINE(pcms))) { + if (!x86ms->acpi_dev || !x86_machine_is_acpi_enabled(x86ms)) { error_setg(errp, "memory hotplug is not enabled: missing acpi device or acpi disabled"); return; @@ -1296,7 +1297,7 @@ static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, return; } - hotplug_handler_pre_plug(pcms->acpi_dev, dev, &local_err); + hotplug_handler_pre_plug(x86ms->acpi_dev, dev, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1311,6 +1312,7 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev, { Error *local_err = NULL; PCMachineState *pcms = PC_MACHINE(hotplug_dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); MachineState *ms = MACHINE(hotplug_dev); bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); @@ -1323,7 +1325,7 @@ static void pc_memory_plug(HotplugHandler *hotplug_dev, nvdimm_plug(ms->nvdimms_state); } - hotplug_handler_plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &error_abort); + hotplug_handler_plug(x86ms->acpi_dev, dev, &error_abort); out: error_propagate(errp, local_err); } @@ -1331,14 +1333,14 @@ out: static void pc_memory_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - PCMachineState *pcms = PC_MACHINE(hotplug_dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); /* * When -no-acpi is used with Q35 machine type, no ACPI is built, * but pcms->acpi_dev is still created. Check !acpi_enabled in * addition to cover this case. */ - if (!pcms->acpi_dev || !x86_machine_is_acpi_enabled(X86_MACHINE(pcms))) { + if (!x86ms->acpi_dev || !x86_machine_is_acpi_enabled(x86ms)) { error_setg(errp, "memory hotplug is not enabled: missing acpi device or acpi disabled"); return; @@ -1349,7 +1351,7 @@ static void pc_memory_unplug_request(HotplugHandler *hotplug_dev, return; } - hotplug_handler_unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, + hotplug_handler_unplug_request(x86ms->acpi_dev, dev, errp); } @@ -1357,9 +1359,10 @@ static void pc_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { PCMachineState *pcms = PC_MACHINE(hotplug_dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); Error *local_err = NULL; - hotplug_handler_unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); + hotplug_handler_unplug(x86ms->acpi_dev, dev, &local_err); if (local_err) { goto out; } @@ -1403,10 +1406,10 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev, Error *local_err = NULL; X86CPU *cpu = X86_CPU(dev); PCMachineState *pcms = PC_MACHINE(hotplug_dev); - X86MachineState *x86ms = X86_MACHINE(pcms); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); - if (pcms->acpi_dev) { - hotplug_handler_plug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); + if (x86ms->acpi_dev) { + hotplug_handler_plug(x86ms->acpi_dev, dev, &local_err); if (local_err) { goto out; } @@ -1432,8 +1435,9 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, int idx = -1; X86CPU *cpu = X86_CPU(dev); PCMachineState *pcms = PC_MACHINE(hotplug_dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); - if (!pcms->acpi_dev) { + if (!x86ms->acpi_dev) { error_setg(errp, "CPU hot unplug not supported without ACPI"); return; } @@ -1445,7 +1449,7 @@ static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, return; } - hotplug_handler_unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, + hotplug_handler_unplug_request(x86ms->acpi_dev, dev, errp); } @@ -1456,9 +1460,9 @@ static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev, Error *local_err = NULL; X86CPU *cpu = X86_CPU(dev); PCMachineState *pcms = PC_MACHINE(hotplug_dev); - X86MachineState *x86ms = X86_MACHINE(pcms); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); - hotplug_handler_unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); + hotplug_handler_unplug(x86ms->acpi_dev, dev, &local_err); if (local_err) { goto out; } @@ -1487,7 +1491,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev, CPUX86State *env = &cpu->env; MachineState *ms = MACHINE(hotplug_dev); PCMachineState *pcms = PC_MACHINE(hotplug_dev); - X86MachineState *x86ms = X86_MACHINE(pcms); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); unsigned int smp_cores = ms->smp.cores; unsigned int smp_threads = ms->smp.threads; X86CPUTopoInfo topo_info; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 33fa035..6f3e78b 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -293,7 +293,7 @@ static void pc_init1(MachineState *machine, object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, TYPE_HOTPLUG_HANDLER, - (Object **)&pcms->acpi_dev, + (Object **)&x86ms->acpi_dev, object_property_allow_set_link, OBJ_PROP_LINK_STRONG); object_property_set_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 0cb9c18..622d039 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -240,7 +240,7 @@ static void pc_q35_init(MachineState *machine) object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, TYPE_HOTPLUG_HANDLER, - (Object **)&pcms->acpi_dev, + (Object **)&x86ms->acpi_dev, object_property_allow_set_link, OBJ_PROP_LINK_STRONG); object_property_set_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h index d75dcf8..be2d95a 100644 --- a/include/hw/i386/microvm.h +++ b/include/hw/i386/microvm.h @@ -68,7 +68,6 @@ struct MicrovmMachineState { bool kernel_cmdline_fixed; Notifier machine_done; Notifier powerdown_req; - AcpiDeviceIf *acpi_dev; }; typedef struct MicrovmMachineState MicrovmMachineState; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 421a77a..c14e14d 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -30,7 +30,6 @@ struct PCMachineState { Notifier machine_done; /* Pointers to devices and objects: */ - HotplugHandler *acpi_dev; PCIBus *bus; I2CBus *smbus; PFlashCFI01 *flash[2]; diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index 25c9046..f540e80 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -52,6 +52,7 @@ struct X86MachineState { FWCfgState *fw_cfg; qemu_irq *gsi; GMappedFile *initrd_mapped_file; + HotplugHandler *acpi_dev; /* RAM information (sizes, addresses, configuration): */ ram_addr_t below_4g_mem_size, above_4g_mem_size; -- cgit v1.1 From 0cca1a918b858b37484c571a9a989e2d06eeccae Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:09:03 +0200 Subject: x86: move cpu hotplug from pc to x86 The cpu hotplug code handles the initialization of coldplugged cpus too, so it is needed even in case cpu hotplug is not supported. Move the code from pc to x86, so microvm can use it. Move both plug and unplug to keep everything in one place, even though microvm needs plug only. Signed-off-by: Gerd Hoffmann Reviewed-by: Sergio Lopez Reviewed-by: Igor Mammedov Message-id: 20200915120909.20838-16-kraxel@redhat.com --- hw/i386/pc.c | 281 +------------------------------------------------- hw/i386/x86.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++++ include/hw/i386/x86.h | 10 ++ 3 files changed, 286 insertions(+), 276 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index a181404..b553693 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -803,19 +803,6 @@ void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp) } } -static void rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count) -{ - if (cpus_count > 0xff) { - /* If the number of CPUs can't be represented in 8 bits, the - * BIOS must use "FW_CFG_NB_CPUS". Set RTC field to 0 just - * to make old BIOSes fail more predictably. - */ - rtc_set_memory(rtc, 0x5f, 0); - } else { - rtc_set_memory(rtc, 0x5f, cpus_count - 1); - } -} - static void pc_machine_done(Notifier *notifier, void *data) { @@ -825,7 +812,7 @@ void pc_machine_done(Notifier *notifier, void *data) PCIBus *bus = pcms->bus; /* set the number of CPUs */ - rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); + x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); if (bus) { int extra_hosts = 0; @@ -1373,264 +1360,6 @@ static void pc_memory_unplug(HotplugHandler *hotplug_dev, error_propagate(errp, local_err); } -static int pc_apic_cmp(const void *a, const void *b) -{ - CPUArchId *apic_a = (CPUArchId *)a; - CPUArchId *apic_b = (CPUArchId *)b; - - return apic_a->arch_id - apic_b->arch_id; -} - -/* returns pointer to CPUArchId descriptor that matches CPU's apic_id - * in ms->possible_cpus->cpus, if ms->possible_cpus->cpus has no - * entry corresponding to CPU's apic_id returns NULL. - */ -static CPUArchId *pc_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) -{ - CPUArchId apic_id, *found_cpu; - - apic_id.arch_id = id; - found_cpu = bsearch(&apic_id, ms->possible_cpus->cpus, - ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus), - pc_apic_cmp); - if (found_cpu && idx) { - *idx = found_cpu - ms->possible_cpus->cpus; - } - return found_cpu; -} - -static void pc_cpu_plug(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - CPUArchId *found_cpu; - Error *local_err = NULL; - X86CPU *cpu = X86_CPU(dev); - PCMachineState *pcms = PC_MACHINE(hotplug_dev); - X86MachineState *x86ms = X86_MACHINE(hotplug_dev); - - if (x86ms->acpi_dev) { - hotplug_handler_plug(x86ms->acpi_dev, dev, &local_err); - if (local_err) { - goto out; - } - } - - /* increment the number of CPUs */ - x86ms->boot_cpus++; - if (x86ms->rtc) { - rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); - } - if (x86ms->fw_cfg) { - fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); - } - - found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL); - found_cpu->cpu = OBJECT(dev); -out: - error_propagate(errp, local_err); -} -static void pc_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - int idx = -1; - X86CPU *cpu = X86_CPU(dev); - PCMachineState *pcms = PC_MACHINE(hotplug_dev); - X86MachineState *x86ms = X86_MACHINE(hotplug_dev); - - if (!x86ms->acpi_dev) { - error_setg(errp, "CPU hot unplug not supported without ACPI"); - return; - } - - pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, &idx); - assert(idx != -1); - if (idx == 0) { - error_setg(errp, "Boot CPU is unpluggable"); - return; - } - - hotplug_handler_unplug_request(x86ms->acpi_dev, dev, - errp); -} - -static void pc_cpu_unplug_cb(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - CPUArchId *found_cpu; - Error *local_err = NULL; - X86CPU *cpu = X86_CPU(dev); - PCMachineState *pcms = PC_MACHINE(hotplug_dev); - X86MachineState *x86ms = X86_MACHINE(hotplug_dev); - - hotplug_handler_unplug(x86ms->acpi_dev, dev, &local_err); - if (local_err) { - goto out; - } - - found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL); - found_cpu->cpu = NULL; - qdev_unrealize(dev); - - /* decrement the number of CPUs */ - x86ms->boot_cpus--; - /* Update the number of CPUs in CMOS */ - rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); - fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); - out: - error_propagate(errp, local_err); -} - -static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) -{ - int idx; - CPUState *cs; - CPUArchId *cpu_slot; - X86CPUTopoIDs topo_ids; - X86CPU *cpu = X86_CPU(dev); - CPUX86State *env = &cpu->env; - MachineState *ms = MACHINE(hotplug_dev); - PCMachineState *pcms = PC_MACHINE(hotplug_dev); - X86MachineState *x86ms = X86_MACHINE(hotplug_dev); - unsigned int smp_cores = ms->smp.cores; - unsigned int smp_threads = ms->smp.threads; - X86CPUTopoInfo topo_info; - - if(!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { - error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", - ms->cpu_type); - return; - } - - init_topo_info(&topo_info, x86ms); - - env->nr_dies = x86ms->smp_dies; - - /* - * If APIC ID is not set, - * set it based on socket/die/core/thread properties. - */ - if (cpu->apic_id == UNASSIGNED_APIC_ID) { - int max_socket = (ms->smp.max_cpus - 1) / - smp_threads / smp_cores / x86ms->smp_dies; - - /* - * die-id was optional in QEMU 4.0 and older, so keep it optional - * if there's only one die per socket. - */ - if (cpu->die_id < 0 && x86ms->smp_dies == 1) { - cpu->die_id = 0; - } - - if (cpu->socket_id < 0) { - error_setg(errp, "CPU socket-id is not set"); - return; - } else if (cpu->socket_id > max_socket) { - error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u", - cpu->socket_id, max_socket); - return; - } - if (cpu->die_id < 0) { - error_setg(errp, "CPU die-id is not set"); - return; - } else if (cpu->die_id > x86ms->smp_dies - 1) { - error_setg(errp, "Invalid CPU die-id: %u must be in range 0:%u", - cpu->die_id, x86ms->smp_dies - 1); - return; - } - if (cpu->core_id < 0) { - error_setg(errp, "CPU core-id is not set"); - return; - } else if (cpu->core_id > (smp_cores - 1)) { - error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u", - cpu->core_id, smp_cores - 1); - return; - } - if (cpu->thread_id < 0) { - error_setg(errp, "CPU thread-id is not set"); - return; - } else if (cpu->thread_id > (smp_threads - 1)) { - error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u", - cpu->thread_id, smp_threads - 1); - return; - } - - topo_ids.pkg_id = cpu->socket_id; - topo_ids.die_id = cpu->die_id; - topo_ids.core_id = cpu->core_id; - topo_ids.smt_id = cpu->thread_id; - cpu->apic_id = x86_apicid_from_topo_ids(&topo_info, &topo_ids); - } - - cpu_slot = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, &idx); - if (!cpu_slot) { - MachineState *ms = MACHINE(pcms); - - x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids); - error_setg(errp, - "Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with" - " APIC ID %" PRIu32 ", valid index range 0:%d", - topo_ids.pkg_id, topo_ids.die_id, topo_ids.core_id, topo_ids.smt_id, - cpu->apic_id, ms->possible_cpus->len - 1); - return; - } - - if (cpu_slot->cpu) { - error_setg(errp, "CPU[%d] with APIC ID %" PRIu32 " exists", - idx, cpu->apic_id); - return; - } - - /* if 'address' properties socket-id/core-id/thread-id are not set, set them - * so that machine_query_hotpluggable_cpus would show correct values - */ - /* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn() - * once -smp refactoring is complete and there will be CPU private - * CPUState::nr_cores and CPUState::nr_threads fields instead of globals */ - x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids); - if (cpu->socket_id != -1 && cpu->socket_id != topo_ids.pkg_id) { - error_setg(errp, "property socket-id: %u doesn't match set apic-id:" - " 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id, - topo_ids.pkg_id); - return; - } - cpu->socket_id = topo_ids.pkg_id; - - if (cpu->die_id != -1 && cpu->die_id != topo_ids.die_id) { - error_setg(errp, "property die-id: %u doesn't match set apic-id:" - " 0x%x (die-id: %u)", cpu->die_id, cpu->apic_id, topo_ids.die_id); - return; - } - cpu->die_id = topo_ids.die_id; - - if (cpu->core_id != -1 && cpu->core_id != topo_ids.core_id) { - error_setg(errp, "property core-id: %u doesn't match set apic-id:" - " 0x%x (core-id: %u)", cpu->core_id, cpu->apic_id, - topo_ids.core_id); - return; - } - cpu->core_id = topo_ids.core_id; - - if (cpu->thread_id != -1 && cpu->thread_id != topo_ids.smt_id) { - error_setg(errp, "property thread-id: %u doesn't match set apic-id:" - " 0x%x (thread-id: %u)", cpu->thread_id, cpu->apic_id, - topo_ids.smt_id); - return; - } - cpu->thread_id = topo_ids.smt_id; - - if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) && - !kvm_hv_vpindex_settable()) { - error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX"); - return; - } - - cs = CPU(cpu); - cs->cpu_index = idx; - - numa_cpu_pre_plug(cpu_slot, dev, errp); -} - static void pc_virtio_md_pci_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -1699,7 +1428,7 @@ static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { pc_memory_pre_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { - pc_cpu_pre_plug(hotplug_dev, dev, errp); + x86_cpu_pre_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { pc_virtio_md_pci_pre_plug(hotplug_dev, dev, errp); @@ -1712,7 +1441,7 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { pc_memory_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { - pc_cpu_plug(hotplug_dev, dev, errp); + x86_cpu_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { pc_virtio_md_pci_plug(hotplug_dev, dev, errp); @@ -1725,7 +1454,7 @@ static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { pc_memory_unplug_request(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { - pc_cpu_unplug_request_cb(hotplug_dev, dev, errp); + x86_cpu_unplug_request_cb(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { pc_virtio_md_pci_unplug_request(hotplug_dev, dev, errp); @@ -1741,7 +1470,7 @@ static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { pc_memory_unplug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { - pc_cpu_unplug_cb(hotplug_dev, dev, errp); + x86_cpu_unplug_cb(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { pc_virtio_md_pci_unplug(hotplug_dev, dev, errp); diff --git a/hw/i386/x86.c b/hw/i386/x86.c index e2a5005..c2ea989 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -41,6 +41,7 @@ #include "hw/i386/topology.h" #include "hw/i386/fw_cfg.h" #include "hw/intc/i8259.h" +#include "hw/rtc/mc146818rtc.h" #include "hw/acpi/cpu_hotplug.h" #include "hw/irq.h" @@ -137,6 +138,276 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) } } +void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count) +{ + if (cpus_count > 0xff) { + /* + * If the number of CPUs can't be represented in 8 bits, the + * BIOS must use "FW_CFG_NB_CPUS". Set RTC field to 0 just + * to make old BIOSes fail more predictably. + */ + rtc_set_memory(rtc, 0x5f, 0); + } else { + rtc_set_memory(rtc, 0x5f, cpus_count - 1); + } +} + +static int x86_apic_cmp(const void *a, const void *b) +{ + CPUArchId *apic_a = (CPUArchId *)a; + CPUArchId *apic_b = (CPUArchId *)b; + + return apic_a->arch_id - apic_b->arch_id; +} + +/* + * returns pointer to CPUArchId descriptor that matches CPU's apic_id + * in ms->possible_cpus->cpus, if ms->possible_cpus->cpus has no + * entry corresponding to CPU's apic_id returns NULL. + */ +CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) +{ + CPUArchId apic_id, *found_cpu; + + apic_id.arch_id = id; + found_cpu = bsearch(&apic_id, ms->possible_cpus->cpus, + ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus), + x86_apic_cmp); + if (found_cpu && idx) { + *idx = found_cpu - ms->possible_cpus->cpus; + } + return found_cpu; +} + +void x86_cpu_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + CPUArchId *found_cpu; + Error *local_err = NULL; + X86CPU *cpu = X86_CPU(dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); + + if (x86ms->acpi_dev) { + hotplug_handler_plug(x86ms->acpi_dev, dev, &local_err); + if (local_err) { + goto out; + } + } + + /* increment the number of CPUs */ + x86ms->boot_cpus++; + if (x86ms->rtc) { + x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); + } + if (x86ms->fw_cfg) { + fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); + } + + found_cpu = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, NULL); + found_cpu->cpu = OBJECT(dev); +out: + error_propagate(errp, local_err); +} + +void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + int idx = -1; + X86CPU *cpu = X86_CPU(dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); + + if (!x86ms->acpi_dev) { + error_setg(errp, "CPU hot unplug not supported without ACPI"); + return; + } + + x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, &idx); + assert(idx != -1); + if (idx == 0) { + error_setg(errp, "Boot CPU is unpluggable"); + return; + } + + hotplug_handler_unplug_request(x86ms->acpi_dev, dev, + errp); +} + +void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + CPUArchId *found_cpu; + Error *local_err = NULL; + X86CPU *cpu = X86_CPU(dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); + + hotplug_handler_unplug(x86ms->acpi_dev, dev, &local_err); + if (local_err) { + goto out; + } + + found_cpu = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, NULL); + found_cpu->cpu = NULL; + qdev_unrealize(dev); + + /* decrement the number of CPUs */ + x86ms->boot_cpus--; + /* Update the number of CPUs in CMOS */ + x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); + fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); + out: + error_propagate(errp, local_err); +} + +void x86_cpu_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + int idx; + CPUState *cs; + CPUArchId *cpu_slot; + X86CPUTopoIDs topo_ids; + X86CPU *cpu = X86_CPU(dev); + CPUX86State *env = &cpu->env; + MachineState *ms = MACHINE(hotplug_dev); + X86MachineState *x86ms = X86_MACHINE(hotplug_dev); + unsigned int smp_cores = ms->smp.cores; + unsigned int smp_threads = ms->smp.threads; + X86CPUTopoInfo topo_info; + + if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { + error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", + ms->cpu_type); + return; + } + + init_topo_info(&topo_info, x86ms); + + env->nr_dies = x86ms->smp_dies; + + /* + * If APIC ID is not set, + * set it based on socket/die/core/thread properties. + */ + if (cpu->apic_id == UNASSIGNED_APIC_ID) { + int max_socket = (ms->smp.max_cpus - 1) / + smp_threads / smp_cores / x86ms->smp_dies; + + /* + * die-id was optional in QEMU 4.0 and older, so keep it optional + * if there's only one die per socket. + */ + if (cpu->die_id < 0 && x86ms->smp_dies == 1) { + cpu->die_id = 0; + } + + if (cpu->socket_id < 0) { + error_setg(errp, "CPU socket-id is not set"); + return; + } else if (cpu->socket_id > max_socket) { + error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u", + cpu->socket_id, max_socket); + return; + } + if (cpu->die_id < 0) { + error_setg(errp, "CPU die-id is not set"); + return; + } else if (cpu->die_id > x86ms->smp_dies - 1) { + error_setg(errp, "Invalid CPU die-id: %u must be in range 0:%u", + cpu->die_id, x86ms->smp_dies - 1); + return; + } + if (cpu->core_id < 0) { + error_setg(errp, "CPU core-id is not set"); + return; + } else if (cpu->core_id > (smp_cores - 1)) { + error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u", + cpu->core_id, smp_cores - 1); + return; + } + if (cpu->thread_id < 0) { + error_setg(errp, "CPU thread-id is not set"); + return; + } else if (cpu->thread_id > (smp_threads - 1)) { + error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u", + cpu->thread_id, smp_threads - 1); + return; + } + + topo_ids.pkg_id = cpu->socket_id; + topo_ids.die_id = cpu->die_id; + topo_ids.core_id = cpu->core_id; + topo_ids.smt_id = cpu->thread_id; + cpu->apic_id = x86_apicid_from_topo_ids(&topo_info, &topo_ids); + } + + cpu_slot = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, &idx); + if (!cpu_slot) { + MachineState *ms = MACHINE(x86ms); + + x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids); + error_setg(errp, + "Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with" + " APIC ID %" PRIu32 ", valid index range 0:%d", + topo_ids.pkg_id, topo_ids.die_id, topo_ids.core_id, topo_ids.smt_id, + cpu->apic_id, ms->possible_cpus->len - 1); + return; + } + + if (cpu_slot->cpu) { + error_setg(errp, "CPU[%d] with APIC ID %" PRIu32 " exists", + idx, cpu->apic_id); + return; + } + + /* if 'address' properties socket-id/core-id/thread-id are not set, set them + * so that machine_query_hotpluggable_cpus would show correct values + */ + /* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn() + * once -smp refactoring is complete and there will be CPU private + * CPUState::nr_cores and CPUState::nr_threads fields instead of globals */ + x86_topo_ids_from_apicid(cpu->apic_id, &topo_info, &topo_ids); + if (cpu->socket_id != -1 && cpu->socket_id != topo_ids.pkg_id) { + error_setg(errp, "property socket-id: %u doesn't match set apic-id:" + " 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id, + topo_ids.pkg_id); + return; + } + cpu->socket_id = topo_ids.pkg_id; + + if (cpu->die_id != -1 && cpu->die_id != topo_ids.die_id) { + error_setg(errp, "property die-id: %u doesn't match set apic-id:" + " 0x%x (die-id: %u)", cpu->die_id, cpu->apic_id, topo_ids.die_id); + return; + } + cpu->die_id = topo_ids.die_id; + + if (cpu->core_id != -1 && cpu->core_id != topo_ids.core_id) { + error_setg(errp, "property core-id: %u doesn't match set apic-id:" + " 0x%x (core-id: %u)", cpu->core_id, cpu->apic_id, + topo_ids.core_id); + return; + } + cpu->core_id = topo_ids.core_id; + + if (cpu->thread_id != -1 && cpu->thread_id != topo_ids.smt_id) { + error_setg(errp, "property thread-id: %u doesn't match set apic-id:" + " 0x%x (thread-id: %u)", cpu->thread_id, cpu->apic_id, + topo_ids.smt_id); + return; + } + cpu->thread_id = topo_ids.smt_id; + + if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) && + !kvm_hv_vpindex_settable()) { + error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX"); + return; + } + + cs = CPU(cpu); + cs->cpu_index = idx; + + numa_cpu_pre_plug(cpu_slot, dev, errp); +} + CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index) { diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index f540e80..0eef9fb 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -92,6 +92,16 @@ CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index); int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx); const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms); +CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx); +void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count); +void x86_cpu_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void x86_cpu_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); void x86_bios_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw); -- cgit v1.1 From e3ab9873d28684858b055ff4e964aa2334bdbd73 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:09:04 +0200 Subject: microvm: wire up hotplug The cpu hotplug code handles the initialization of coldplugged cpus too, so it is needed even in case cpu hotplug is not supported. Wire cpu hotplug up for microvm. Without this we get a broken MADT table. Signed-off-by: Gerd Hoffmann Reviewed-by: Igor Mammedov Reviewed-by: Sergio Lopez Message-id: 20200915120909.20838-17-kraxel@redhat.com --- hw/i386/microvm.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 9df1535..8de8ca8 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -320,6 +320,39 @@ static void microvm_fix_kernel_cmdline(MachineState *machine) g_free(cmdline); } +static void microvm_device_pre_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + x86_cpu_pre_plug(hotplug_dev, dev, errp); +} + +static void microvm_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + x86_cpu_plug(hotplug_dev, dev, errp); +} + +static void microvm_device_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + error_setg(errp, "unplug not supported by microvm"); +} + +static void microvm_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + error_setg(errp, "unplug not supported by microvm"); +} + +static HotplugHandler *microvm_get_hotplug_handler(MachineState *machine, + DeviceState *dev) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + return HOTPLUG_HANDLER(machine); + } + return NULL; +} + static void microvm_machine_state_init(MachineState *machine) { MicrovmMachineState *mms = MICROVM_MACHINE(machine); @@ -503,6 +536,7 @@ static void microvm_machine_initfn(Object *obj) static void microvm_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); mc->init = microvm_machine_state_init; @@ -524,6 +558,13 @@ static void microvm_class_init(ObjectClass *oc, void *data) /* Machine class handlers */ mc->reset = microvm_machine_reset; + /* hotplug (for cpu coldplug) */ + mc->get_hotplug_handler = microvm_get_hotplug_handler; + hc->pre_plug = microvm_device_pre_plug_cb; + hc->plug = microvm_device_plug_cb; + hc->unplug_request = microvm_device_unplug_request_cb; + hc->unplug = microvm_device_unplug_cb; + object_class_property_add(oc, MICROVM_MACHINE_PIC, "OnOffAuto", microvm_machine_get_pic, microvm_machine_set_pic, @@ -573,6 +614,7 @@ static const TypeInfo microvm_machine_info = { .class_size = sizeof(MicrovmMachineClass), .class_init = microvm_class_init, .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, { } }, }; -- cgit v1.1 From 34b36c3beeaa843d2ae73d6367484961e8bd3352 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:09:05 +0200 Subject: tests/acpi: allow microvm test data updates. Also add empty test data files. Signed-off-by: Gerd Hoffmann Message-id: 20200915120909.20838-18-kraxel@redhat.com --- tests/data/acpi/microvm/APIC | 0 tests/data/acpi/microvm/DSDT | 0 tests/data/acpi/microvm/FACP | 0 tests/qtest/bios-tables-test-allowed-diff.h | 3 +++ 4 files changed, 3 insertions(+) create mode 100644 tests/data/acpi/microvm/APIC create mode 100644 tests/data/acpi/microvm/DSDT create mode 100644 tests/data/acpi/microvm/FACP diff --git a/tests/data/acpi/microvm/APIC b/tests/data/acpi/microvm/APIC new file mode 100644 index 0000000..e69de29 diff --git a/tests/data/acpi/microvm/DSDT b/tests/data/acpi/microvm/DSDT new file mode 100644 index 0000000..e69de29 diff --git a/tests/data/acpi/microvm/FACP b/tests/data/acpi/microvm/FACP new file mode 100644 index 0000000..e69de29 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523..97c3fa6 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,4 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/microvm/APIC", +"tests/data/acpi/microvm/DSDT", +"tests/data/acpi/microvm/FACP", -- cgit v1.1 From 3cac3784f7fac7642ccb9676613ba2efe2290f0d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:09:06 +0200 Subject: tests/acpi: allow override blkdev microvm needs virtio-blk instead of ide. Signed-off-by: Gerd Hoffmann Reviewed-by: Igor Mammedov Reviewed-by: Sergio Lopez Message-id: 20200915120909.20838-19-kraxel@redhat.com --- tests/qtest/bios-tables-test.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 504b810..1779af1 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -72,6 +72,7 @@ typedef struct { const char *variant; const char *uefi_fl1; const char *uefi_fl2; + const char *blkdev; const char *cd; const uint64_t ram_start; const uint64_t scan_len; @@ -666,9 +667,10 @@ static void test_acpi_one(const char *params, test_data *data) args = g_strdup_printf("-machine %s,kernel-irqchip=off %s -accel tcg " "-net none -display none %s " "-drive id=hd0,if=none,file=%s,format=raw " - "-device ide-hd,drive=hd0 ", + "-device %s,drive=hd0 ", data->machine, data->tcg_only ? "" : "-accel kvm", - params ? params : "", disk); + params ? params : "", disk, + data->blkdev ?: "ide-hd"); } data->qts = qtest_init(args); -- cgit v1.1 From c06cbf3d79c0160629f79a79b94dcf6eca5601dc Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:09:07 +0200 Subject: tests/acpi: add microvm test Signed-off-by: Gerd Hoffmann Reviewed-by: Igor Mammedov Message-id: 20200915120909.20838-20-kraxel@redhat.com --- tests/qtest/bios-tables-test.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 1779af1..a9c8d47 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1044,6 +1044,20 @@ static void test_acpi_virt_tcg_memhp(void) } +static void test_acpi_microvm_tcg(void) +{ + test_data data; + + memset(&data, 0, sizeof(data)); + data.machine = "microvm"; + data.required_struct_types = NULL; /* no smbios */ + data.required_struct_types_len = 0; + data.blkdev = "virtio-blk-device"; + test_acpi_one(" -machine microvm,acpi=on,rtc=off", + &data); + free_test_data(&data); +} + static void test_acpi_virt_tcg_numamem(void) { test_data data = { @@ -1161,6 +1175,7 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat); qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat); + qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); } else if (strcmp(arch, "aarch64") == 0) { qtest_add_func("acpi/virt", test_acpi_virt_tcg); qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); -- cgit v1.1 From 312354f8c9b64278b8f0aef1567f213a98cf0e80 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:09:08 +0200 Subject: tests/acpi: update expected data files for microvm Also clear tests/qtest/bios-tables-test-allowed-diff.h Signed-off-by: Gerd Hoffmann Message-id: 20200915120909.20838-21-kraxel@redhat.com --- tests/data/acpi/microvm/APIC | Bin 0 -> 70 bytes tests/data/acpi/microvm/DSDT | Bin 0 -> 365 bytes tests/data/acpi/microvm/FACP | Bin 0 -> 268 bytes tests/qtest/bios-tables-test-allowed-diff.h | 3 --- 4 files changed, 3 deletions(-) diff --git a/tests/data/acpi/microvm/APIC b/tests/data/acpi/microvm/APIC index e69de29..7472c7e 100644 Binary files a/tests/data/acpi/microvm/APIC and b/tests/data/acpi/microvm/APIC differ diff --git a/tests/data/acpi/microvm/DSDT b/tests/data/acpi/microvm/DSDT index e69de29..b43f427 100644 Binary files a/tests/data/acpi/microvm/DSDT and b/tests/data/acpi/microvm/DSDT differ diff --git a/tests/data/acpi/microvm/FACP b/tests/data/acpi/microvm/FACP index e69de29..0ba5795 100644 Binary files a/tests/data/acpi/microvm/FACP and b/tests/data/acpi/microvm/FACP differ diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index 97c3fa6..dfb8523 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,4 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/microvm/APIC", -"tests/data/acpi/microvm/DSDT", -"tests/data/acpi/microvm/FACP", -- cgit v1.1 From 63bcfe7be09787ad6425afcaab5501b53bc26095 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 Sep 2020 14:09:09 +0200 Subject: microvm: enable ramfb Signed-off-by: Gerd Hoffmann Message-id: 20200915120909.20838-22-kraxel@redhat.com --- hw/i386/microvm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 8de8ca8..60d3272 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -39,6 +39,7 @@ #include "hw/timer/i8254.h" #include "hw/rtc/mc146818rtc.h" #include "hw/char/serial.h" +#include "hw/display/ramfb.h" #include "hw/i386/topology.h" #include "hw/i386/e820_memory_layout.h" #include "hw/i386/fw_cfg.h" @@ -604,6 +605,8 @@ static void microvm_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, MICROVM_MACHINE_AUTO_KERNEL_CMDLINE, "Set off to disable adding virtio-mmio devices to the kernel cmdline"); + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); } static const TypeInfo microvm_machine_info = { -- cgit v1.1