All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 00/21] Microvm 20200917 patches
@ 2020-09-17 13:53 Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 01/21] microvm: name qboot binary qboot.rom Gerd Hoffmann
                   ` (21 more replies)
  0 siblings, 22 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

The following changes since commit 8ee612722dc08830761516e761dde934c3753a14:

  Merge remote-tracking branch 'remotes/cschoenebeck/tags/pull-9p-20200915' into staging (2020-09-16 14:47:50 +0100)

are available in the Git repository at:

  git://git.kraxel.org/qemu tags/microvm-20200917-pull-request

for you to fetch changes up to 63bcfe7be09787ad6425afcaab5501b53bc26095:

  microvm: enable ramfb (2020-09-17 14:16:19 +0200)

----------------------------------------------------------------
microvm: add acpi support

----------------------------------------------------------------

Gerd Hoffmann (21):
  microvm: name qboot binary qboot.rom
  seabios: add microvm config, update build rules
  seabios: add bios-microvm.bin binary
  acpi: ged: add control regs
  acpi: ged: add x86 device variant.
  acpi: move acpi_dsdt_add_power_button() to ged
  microvm: make virtio irq base runtime configurable
  microvm/acpi: add minimal acpi support
  microvm/acpi: add acpi_dsdt_add_virtio() for x86
  microvm/acpi: use GSI 16-23 for virtio
  microvm/acpi: use seabios with acpi=on
  microvm/acpi: disable virtio-mmio cmdline hack
  x86: constify x86_machine_is_*_enabled
  x86: move acpi_dev from pc/microvm
  x86: move cpu hotplug from pc to x86
  microvm: wire up hotplug
  tests/acpi: allow microvm test data updates.
  tests/acpi: allow override blkdev
  tests/acpi: add microvm test
  tests/acpi: update expected data files for microvm
  microvm: enable ramfb

 hw/i386/acpi-microvm.h                 |   8 +
 include/hw/acpi/generic_event_device.h |  17 ++
 include/hw/i386/microvm.h              |  10 +-
 include/hw/i386/pc.h                   |   1 -
 include/hw/i386/x86.h                  |  15 +-
 hw/acpi/generic_event_device.c         |  52 +++++
 hw/arm/virt-acpi-build.c               |   8 -
 hw/i386/acpi-build.c                   |   2 +-
 hw/i386/acpi-microvm.c                 | 240 ++++++++++++++++++++
 hw/i386/generic_event_device_x86.c     |  36 +++
 hw/i386/microvm.c                      | 108 ++++++++-
 hw/i386/pc.c                           | 297 ++-----------------------
 hw/i386/pc_piix.c                      |   2 +-
 hw/i386/pc_q35.c                       |   2 +-
 hw/i386/x86.c                          | 275 ++++++++++++++++++++++-
 tests/qtest/bios-tables-test.c         |  21 +-
 hw/i386/Kconfig                        |   1 +
 hw/i386/meson.build                    |   3 +-
 pc-bios/bios-microvm.bin               | Bin 65536 -> 131072 bytes
 pc-bios/meson.build                    |   1 +
 pc-bios/qboot.rom                      | Bin 0 -> 65536 bytes
 roms/Makefile                          |  11 +-
 roms/config.seabios-microvm            |  26 +++
 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
 26 files changed, 823 insertions(+), 313 deletions(-)
 create mode 100644 hw/i386/acpi-microvm.h
 create mode 100644 hw/i386/acpi-microvm.c
 create mode 100644 hw/i386/generic_event_device_x86.c
 create mode 100644 pc-bios/qboot.rom
 create mode 100644 roms/config.seabios-microvm
 create mode 100644 tests/data/acpi/microvm/APIC
 create mode 100644 tests/data/acpi/microvm/DSDT
 create mode 100644 tests/data/acpi/microvm/FACP

-- 
2.27.0




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PULL 01/21] microvm: name qboot binary qboot.rom
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 02/21] seabios: add microvm config, update build rules Gerd Hoffmann
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov,
	Philippe Mathieu-Daudé,
	Richard Henderson

qboot isn't a bios and shouldnt be named that way.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-id: 20200915120909.20838-2-kraxel@redhat.com
---
 hw/i386/microvm.c                       |   4 ++--
 pc-bios/meson.build                     |   2 +-
 pc-bios/{bios-microvm.bin => qboot.rom} | Bin
 roms/Makefile                           |   6 +++---
 4 files changed, 6 insertions(+), 6 deletions(-)
 rename pc-bios/{bios-microvm.bin => qboot.rom} (100%)

diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index 81d0888930d1..b1dc7e49c159 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/meson.build b/pc-bios/meson.build
index 182d5ebb35de..9759dba09714 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/bios-microvm.bin b/pc-bios/qboot.rom
similarity index 100%
rename from pc-bios/bios-microvm.bin
rename to pc-bios/qboot.rom
diff --git a/roms/Makefile b/roms/Makefile
index 3726f06fe7eb..1395a46695be 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)
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 02/21] seabios: add microvm config, update build rules
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 01/21] microvm: name qboot binary qboot.rom Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 03/21] seabios: add bios-microvm.bin binary Gerd Hoffmann
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
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 1395a46695be..1489d47350f2 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 000000000000..a253e2edc6ec
--- /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
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 03/21] seabios: add bios-microvm.bin binary
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 01/21] microvm: name qboot binary qboot.rom Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 02/21] seabios: add microvm config, update build rules Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 04/21] acpi: ged: add control regs Gerd Hoffmann
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
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 0000000000000000000000000000000000000000..eefd32197e8d637be0266e3410551f711728c6d0
GIT binary patch
literal 131072
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

literal 0
HcmV?d00001

diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index 9759dba09714..a0d21be4321a 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',
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 04/21] acpi: ged: add control regs
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 03/21] seabios: add bios-microvm.bin binary Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2021-06-24  9:17   ` Peter Maydell
  2020-09-17 13:53 ` [PULL 05/21] acpi: ged: add x86 device variant Gerd Hoffmann
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Add control regs (sleep, reset) for hw-reduced acpi.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-id: 20200915120909.20838-5-kraxel@redhat.com
---
 include/hw/acpi/generic_event_device.h | 12 +++++++
 hw/acpi/generic_event_device.c         | 44 ++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
index 1be05a3c0f8c..38aec526f944 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;
 
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index b8abdefa1c77..491df80a5cc7 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)
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 05/21] acpi: ged: add x86 device variant.
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 04/21] acpi: ged: add control regs Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 06/21] acpi: move acpi_dsdt_add_power_button() to ged Gerd Hoffmann
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Set AcpiDeviceIfClass->madt_cpu,
otherwise identical to TYPE_ACPI_GED.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-id: 20200915120909.20838-6-kraxel@redhat.com
---
 include/hw/acpi/generic_event_device.h |  4 +++
 hw/i386/generic_event_device_x86.c     | 36 ++++++++++++++++++++++++++
 hw/i386/meson.build                    |  1 +
 3 files changed, 41 insertions(+)
 create mode 100644 hw/i386/generic_event_device_x86.c

diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
index 38aec526f944..241151662b45 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
 
diff --git a/hw/i386/generic_event_device_x86.c b/hw/i386/generic_event_device_x86.c
new file mode 100644
index 000000000000..e26fb02a2ef6
--- /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 63918fbe22f9..1a7d1a685d77 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',
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 06/21] acpi: move acpi_dsdt_add_power_button() to ged
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 05/21] acpi: ged: add x86 device variant Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 07/21] microvm: make virtio irq base runtime configurable Gerd Hoffmann
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov,
	Philippe Mathieu-Daudé,
	Richard Henderson

Allow reuse for microvm.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-id: 20200915120909.20838-7-kraxel@redhat.com
---
 include/hw/acpi/generic_event_device.h | 1 +
 hw/acpi/generic_event_device.c         | 8 ++++++++
 hw/arm/virt-acpi-build.c               | 8 --------
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
index 241151662b45..ac921e9f0c15 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
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 491df80a5cc7..6df400e1ee16 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 9efd7a388150..6bff5e373872 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);
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 07/21] microvm: make virtio irq base runtime configurable
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 06/21] acpi: move acpi_dsdt_add_power_button() to ged Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 08/21] microvm/acpi: add minimal acpi support Gerd Hoffmann
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-id: 20200915120909.20838-8-kraxel@redhat.com
---
 include/hw/i386/microvm.h |  2 +-
 hw/i386/microvm.c         | 11 +++++++----
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h
index 36dbcdd12351..87593694eb0e 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;
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index b1dc7e49c159..e4501f2cdfbd 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);
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 08/21] microvm/acpi: add minimal acpi support
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 07/21] microvm: make virtio irq base runtime configurable Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 09/21] microvm/acpi: add acpi_dsdt_add_virtio() for x86 Gerd Hoffmann
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

$subject says all.  Can be controlled using -M microvm,acpi=on/off.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-id: 20200915120909.20838-9-kraxel@redhat.com
---
 hw/i386/acpi-microvm.h    |   8 ++
 include/hw/i386/microvm.h |   9 ++
 hw/i386/acpi-microvm.c    | 187 ++++++++++++++++++++++++++++++++++++++
 hw/i386/microvm.c         |  40 ++++++++
 hw/i386/Kconfig           |   1 +
 hw/i386/meson.build       |   2 +-
 6 files changed, 246 insertions(+), 1 deletion(-)
 create mode 100644 hw/i386/acpi-microvm.h
 create mode 100644 hw/i386/acpi-microvm.c

diff --git a/hw/i386/acpi-microvm.h b/hw/i386/acpi-microvm.h
new file mode 100644
index 000000000000..dfe853690e15
--- /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/include/hw/i386/microvm.h b/include/hw/i386/microvm.h
index 87593694eb0e..d75dcf8203b7 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;
 
diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c
new file mode 100644
index 000000000000..06ef33949f5f
--- /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 <kevin@koconnor.net>
+ * Copyright (C) 2006 Fabrice Bellard
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#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/microvm.c b/hw/i386/microvm.c
index e4501f2cdfbd..e1b86da8a92e 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/hw/i386/Kconfig b/hw/i386/Kconfig
index 03e347b2078f..d0bd8b537d55 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/meson.build b/hw/i386/meson.build
index 1a7d1a685d77..e5d109f5c64d 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'))
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 09/21] microvm/acpi: add acpi_dsdt_add_virtio() for x86
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 08/21] microvm/acpi: add minimal acpi support Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 10/21] microvm/acpi: use GSI 16-23 for virtio Gerd Hoffmann
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Makes x86 linux kernel find virtio-mmio devices automatically.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
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 06ef33949f5f..b9ce3768b263 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 */
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 10/21] microvm/acpi: use GSI 16-23 for virtio
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 09/21] microvm/acpi: add acpi_dsdt_add_virtio() for x86 Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 11/21] microvm/acpi: use seabios with acpi=on Gerd Hoffmann
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

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 <kraxel@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
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 e1b86da8a92e..ca0c9983f137 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,
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 11/21] microvm/acpi: use seabios with acpi=on
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 10/21] microvm/acpi: use GSI 16-23 for virtio Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 12/21] microvm/acpi: disable virtio-mmio cmdline hack Gerd Hoffmann
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

With acpi=off continue to use qboot.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
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 ca0c9983f137..54510a03f754 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);
 }
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 12/21] microvm/acpi: disable virtio-mmio cmdline hack
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (10 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 11/21] microvm/acpi: use seabios with acpi=on Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 13/21] x86: constify x86_machine_is_*_enabled Gerd Hoffmann
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

... in case we are using ACPI.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
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 54510a03f754..04209eb38fbe 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;
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 13/21] x86: constify x86_machine_is_*_enabled
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (11 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 12/21] microvm/acpi: disable virtio-mmio cmdline hack Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 14/21] x86: move acpi_dev from pc/microvm Gerd Hoffmann
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov,
	Philippe Mathieu-Daudé,
	Richard Henderson

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-id: 20200915120909.20838-14-kraxel@redhat.com
---
 include/hw/i386/x86.h | 4 ++--
 hw/i386/x86.c         | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index 1a188a7deabb..25c904638c11 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 */
 
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index c1954db152eb..e2a5005f389c 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;
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 14/21] x86: move acpi_dev from pc/microvm
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (12 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 13/21] x86: constify x86_machine_is_*_enabled Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 15/21] x86: move cpu hotplug from pc to x86 Gerd Hoffmann
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Both pc and microvm machine types have a acpi_dev field.
Move it to the common base type.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-id: 20200915120909.20838-15-kraxel@redhat.com
---
 include/hw/i386/microvm.h |  1 -
 include/hw/i386/pc.h      |  1 -
 include/hw/i386/x86.h     |  1 +
 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 +-
 9 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h
index d75dcf8203b7..be2d95af4d74 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 421a77acc223..c14e14dfe0c7 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 25c904638c11..f540e801a837 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;
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 7a5a8b3521b0..0e0535d2e30c 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 b9ce3768b263..df39c5d3bd90 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 04209eb38fbe..9df15354ce0f 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 d11daacc23cf..a18140421e92 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 33fa035fb7fe..6f3e78bb6053 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 0cb9c18cd44d..622d0397172a 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,
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 15/21] x86: move cpu hotplug from pc to x86
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (13 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 14/21] x86: move acpi_dev from pc/microvm Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 16/21] microvm: wire up hotplug Gerd Hoffmann
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

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 <kraxel@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-id: 20200915120909.20838-16-kraxel@redhat.com
---
 include/hw/i386/x86.h |  10 ++
 hw/i386/pc.c          | 281 +-----------------------------------------
 hw/i386/x86.c         | 271 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 286 insertions(+), 276 deletions(-)

diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index f540e801a837..0eef9fb0c0d7 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);
 
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index a18140421e92..b55369357e5d 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 e2a5005f389c..c2ea989579c9 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)
 {
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 16/21] microvm: wire up hotplug
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (14 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 15/21] x86: move cpu hotplug from pc to x86 Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 17/21] tests/acpi: allow microvm test data updates Gerd Hoffmann
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

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 <kraxel@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
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 9df15354ce0f..8de8ca864963 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 },
          { }
     },
 };
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 17/21] tests/acpi: allow microvm test data updates.
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (15 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 16/21] microvm: wire up hotplug Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 18/21] tests/acpi: allow override blkdev Gerd Hoffmann
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Also add empty test data files.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20200915120909.20838-18-kraxel@redhat.com
---
 tests/qtest/bios-tables-test-allowed-diff.h | 3 +++
 tests/data/acpi/microvm/APIC                | 0
 tests/data/acpi/microvm/DSDT                | 0
 tests/data/acpi/microvm/FACP                | 0
 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/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8bf4..97c3fa621b7f 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",
diff --git a/tests/data/acpi/microvm/APIC b/tests/data/acpi/microvm/APIC
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/tests/data/acpi/microvm/DSDT b/tests/data/acpi/microvm/DSDT
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/tests/data/acpi/microvm/FACP b/tests/data/acpi/microvm/FACP
new file mode 100644
index 000000000000..e69de29bb2d1
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 18/21] tests/acpi: allow override blkdev
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (16 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 17/21] tests/acpi: allow microvm test data updates Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 19/21] tests/acpi: add microvm test Gerd Hoffmann
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

microvm needs virtio-blk instead of ide.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
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 504b810af583..1779af1cc889 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);
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 19/21] tests/acpi: add microvm test
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (17 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 18/21] tests/acpi: allow override blkdev Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 20/21] tests/acpi: update expected data files for microvm Gerd Hoffmann
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
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 1779af1cc889..a9c8d478aee3 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);
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 20/21] tests/acpi: update expected data files for microvm
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (18 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 19/21] tests/acpi: add microvm test Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-17 13:53 ` [PULL 21/21] microvm: enable ramfb Gerd Hoffmann
  2020-09-18  9:35 ` [PULL 00/21] Microvm 20200917 patches Peter Maydell
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Also clear tests/qtest/bios-tables-test-allowed-diff.h

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20200915120909.20838-21-kraxel@redhat.com
---
 tests/qtest/bios-tables-test-allowed-diff.h |   3 ---
 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
 4 files changed, 3 deletions(-)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index 97c3fa621b7f..dfb8523c8bf4 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",
diff --git a/tests/data/acpi/microvm/APIC b/tests/data/acpi/microvm/APIC
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7472c7e830b6c7139720e93dd544d4441556661d 100644
GIT binary patch
literal 70
zcmZ<^@N{-#U|?Xp?&R<65v<@85#a0y6k`O6f!H9Lf#JbFFwFr}2jnsGfW!{`1CcCj
H|A7Jk<Z=uF

literal 0
HcmV?d00001

diff --git a/tests/data/acpi/microvm/DSDT b/tests/data/acpi/microvm/DSDT
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b43f427a222a933d3f34aceab6224a2c6115c365 100644
GIT binary patch
literal 365
zcmX9(%SyvQ6upy2n@pNIKA<QF#Sf5arMONe(=?DaG1G?-VTyaft+=UO6kPiQ{RBV7
z&*`dor`gOs_nbMLa}$-!-w1&98W&=s`tfrq66BBqgUw{=rB<=7xA)_f7<+n>CE=5t
zE;#2y@U)soH1M>j)Okp0N|?)B()oaTI~2uqaQfeg{#@eeMV8=e3}=mj(J&<k`(T52
z$G~{<Rw@(SghZmuI3GM<2s%R)5Sg4V4Zd4o6Cc~5X(KC{LI+@fq)z=6m{mw6^ZwPX
zmdm;SZkF|){d}&e1=QM=t170OdV6g^6IRYjF1Tp2ut@AIEB@GM`K&7N+EF9YHntEE
jUShi3(B94m0^Q#uSOD0Iklv{mV=rh>BYn|!sEgD;a<EMS

literal 0
HcmV?d00001

diff --git a/tests/data/acpi/microvm/FACP b/tests/data/acpi/microvm/FACP
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0ba5795d622349e1521138e4123544637b4ab9af 100644
GIT binary patch
literal 268
zcmZ>BbPnKQWME*ebMklg2v%^42yk`-iUEZfKx`0ARlp*^z`()4z{IrRAIMxMsv1tD
QVL<yCp!S2@!U$yp0N^VO0RR91

literal 0
HcmV?d00001

-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PULL 21/21] microvm: enable ramfb
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (19 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 20/21] tests/acpi: update expected data files for microvm Gerd Hoffmann
@ 2020-09-17 13:53 ` Gerd Hoffmann
  2020-09-18  9:35 ` [PULL 00/21] Microvm 20200917 patches Peter Maydell
  21 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2020-09-17 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Peter Maydell, Thomas Huth, Eduardo Habkost,
	Sergio Lopez, Michael S. Tsirkin, Shannon Zhao, qemu-arm,
	Gerd Hoffmann, Paolo Bonzini, Igor Mammedov, Richard Henderson

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
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 8de8ca864963..60d32722301f 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 = {
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PULL 00/21] Microvm 20200917 patches
  2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
                   ` (20 preceding siblings ...)
  2020-09-17 13:53 ` [PULL 21/21] microvm: enable ramfb Gerd Hoffmann
@ 2020-09-18  9:35 ` Peter Maydell
  21 siblings, 0 replies; 25+ messages in thread
From: Peter Maydell @ 2020-09-18  9:35 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: Laurent Vivier, Thomas Huth, Eduardo Habkost, Sergio Lopez,
	Michael S. Tsirkin, QEMU Developers, Shannon Zhao, qemu-arm,
	Paolo Bonzini, Igor Mammedov, Richard Henderson

On Thu, 17 Sep 2020 at 14:53, Gerd Hoffmann <kraxel@redhat.com> wrote:
>
> The following changes since commit 8ee612722dc08830761516e761dde934c3753a14:
>
>   Merge remote-tracking branch 'remotes/cschoenebeck/tags/pull-9p-20200915' into staging (2020-09-16 14:47:50 +0100)
>
> are available in the Git repository at:
>
>   git://git.kraxel.org/qemu tags/microvm-20200917-pull-request
>
> for you to fetch changes up to 63bcfe7be09787ad6425afcaab5501b53bc26095:
>
>   microvm: enable ramfb (2020-09-17 14:16:19 +0200)
>
> ----------------------------------------------------------------
> microvm: add acpi support
>
> ----------------------------------------------------------------


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/5.2
for any user-visible changes.

-- PMM


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PULL 04/21] acpi: ged: add control regs
  2020-09-17 13:53 ` [PULL 04/21] acpi: ged: add control regs Gerd Hoffmann
@ 2021-06-24  9:17   ` Peter Maydell
  2021-06-24  9:42     ` Gerd Hoffmann
  0 siblings, 1 reply; 25+ messages in thread
From: Peter Maydell @ 2021-06-24  9:17 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: Laurent Vivier, Thomas Huth, Eduardo Habkost, Sergio Lopez,
	Michael S. Tsirkin, QEMU Developers, Shannon Zhao, qemu-arm,
	Paolo Bonzini, Igor Mammedov, Richard Henderson

On Thu, 17 Sept 2020 at 14:53, Gerd Hoffmann <kraxel@redhat.com> wrote:
>
> Add control regs (sleep, reset) for hw-reduced acpi.
>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> Reviewed-by: Igor Mammedov <imammedo@redhat.com>
> Message-id: 20200915120909.20838-5-kraxel@redhat.com
> ---
>  include/hw/acpi/generic_event_device.h | 12 +++++++
>  hw/acpi/generic_event_device.c         | 44 ++++++++++++++++++++++++++
>  2 files changed, 56 insertions(+)

Hi; I've just run across this code because I found a bug in
a different device and was doing a grep to see if anybody
else had made the same mistake...

> +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);

Here we call qemu_system_reset_request(), but we pass it a cause
value of GUEST_SHUTDOWN. Is this trying to do a reset (in which
case it should probably be SHUTDOWN_CAUSE_GUEST_RESET) or a shutdown
(in which case it needs to call qemu_system_shutdown_request()) ?

> +        }
> +        return;
> +    }
> +}

thanks
-- PMM


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PULL 04/21] acpi: ged: add control regs
  2021-06-24  9:17   ` Peter Maydell
@ 2021-06-24  9:42     ` Gerd Hoffmann
  0 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2021-06-24  9:42 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Laurent Vivier, Thomas Huth, Eduardo Habkost, Sergio Lopez,
	Michael S. Tsirkin, QEMU Developers, Shannon Zhao, qemu-arm,
	Paolo Bonzini, Igor Mammedov, Richard Henderson

  Hi,

> > +    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);
> 
> Here we call qemu_system_reset_request(), but we pass it a cause
> value of GUEST_SHUTDOWN. Is this trying to do a reset (in which
> case it should probably be SHUTDOWN_CAUSE_GUEST_RESET) or a shutdown
> (in which case it needs to call qemu_system_shutdown_request()) ?

It is reset (shutdown is a few lines above and the cause was probably
just copy & pasted ...).

take care,
  Gerd



^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2021-06-24  9:43 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-17 13:53 [PULL 00/21] Microvm 20200917 patches Gerd Hoffmann
2020-09-17 13:53 ` [PULL 01/21] microvm: name qboot binary qboot.rom Gerd Hoffmann
2020-09-17 13:53 ` [PULL 02/21] seabios: add microvm config, update build rules Gerd Hoffmann
2020-09-17 13:53 ` [PULL 03/21] seabios: add bios-microvm.bin binary Gerd Hoffmann
2020-09-17 13:53 ` [PULL 04/21] acpi: ged: add control regs Gerd Hoffmann
2021-06-24  9:17   ` Peter Maydell
2021-06-24  9:42     ` Gerd Hoffmann
2020-09-17 13:53 ` [PULL 05/21] acpi: ged: add x86 device variant Gerd Hoffmann
2020-09-17 13:53 ` [PULL 06/21] acpi: move acpi_dsdt_add_power_button() to ged Gerd Hoffmann
2020-09-17 13:53 ` [PULL 07/21] microvm: make virtio irq base runtime configurable Gerd Hoffmann
2020-09-17 13:53 ` [PULL 08/21] microvm/acpi: add minimal acpi support Gerd Hoffmann
2020-09-17 13:53 ` [PULL 09/21] microvm/acpi: add acpi_dsdt_add_virtio() for x86 Gerd Hoffmann
2020-09-17 13:53 ` [PULL 10/21] microvm/acpi: use GSI 16-23 for virtio Gerd Hoffmann
2020-09-17 13:53 ` [PULL 11/21] microvm/acpi: use seabios with acpi=on Gerd Hoffmann
2020-09-17 13:53 ` [PULL 12/21] microvm/acpi: disable virtio-mmio cmdline hack Gerd Hoffmann
2020-09-17 13:53 ` [PULL 13/21] x86: constify x86_machine_is_*_enabled Gerd Hoffmann
2020-09-17 13:53 ` [PULL 14/21] x86: move acpi_dev from pc/microvm Gerd Hoffmann
2020-09-17 13:53 ` [PULL 15/21] x86: move cpu hotplug from pc to x86 Gerd Hoffmann
2020-09-17 13:53 ` [PULL 16/21] microvm: wire up hotplug Gerd Hoffmann
2020-09-17 13:53 ` [PULL 17/21] tests/acpi: allow microvm test data updates Gerd Hoffmann
2020-09-17 13:53 ` [PULL 18/21] tests/acpi: allow override blkdev Gerd Hoffmann
2020-09-17 13:53 ` [PULL 19/21] tests/acpi: add microvm test Gerd Hoffmann
2020-09-17 13:53 ` [PULL 20/21] tests/acpi: update expected data files for microvm Gerd Hoffmann
2020-09-17 13:53 ` [PULL 21/21] microvm: enable ramfb Gerd Hoffmann
2020-09-18  9:35 ` [PULL 00/21] Microvm 20200917 patches Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.