diff --git a/docs-specs-Add-ACPI-GED-documentation.patch b/docs-specs-Add-ACPI-GED-documentation.patch new file mode 100644 index 0000000..46e8c17 --- /dev/null +++ b/docs-specs-Add-ACPI-GED-documentation.patch @@ -0,0 +1,107 @@ +From 9c1752703fb8a5b70985cf4c9caabc3388c5953b Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:31 +0100 +Subject: [PATCH] docs/specs: Add ACPI GED documentation + +Documents basic concepts of ACPI Generic Event device(GED) +and interface between QEMU and the ACPI BIOS. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Message-Id: <20190918130633.4872-10-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + docs/specs/acpi_hw_reduced_hotplug.rst | 70 ++++++++++++++++++++++++++ + docs/specs/index.rst | 1 + + 2 files changed, 71 insertions(+) + create mode 100644 docs/specs/acpi_hw_reduced_hotplug.rst + +diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst +new file mode 100644 +index 0000000000..911a98255b +--- /dev/null ++++ b/docs/specs/acpi_hw_reduced_hotplug.rst +@@ -0,0 +1,70 @@ ++================================================== ++QEMU and ACPI BIOS Generic Event Device interface ++================================================== ++ ++The ACPI *Generic Event Device* (GED) is a HW reduced platform ++specific device introduced in ACPI v6.1 that handles all platform ++events, including the hotplug ones. GED is modelled as a device ++in the namespace with a _HID defined to be ACPI0013. This document ++describes the interface between QEMU and the ACPI BIOS. ++ ++GED allows HW reduced platforms to handle interrupts in ACPI ASL ++statements. It follows a very similar approach to the _EVT method ++from GPIO events. All interrupts are listed in _CRS and the handler ++is written in _EVT method. However, the QEMU implementation uses a ++single interrupt for the GED device, relying on an IO memory region ++to communicate the type of device affected by the interrupt. This way, ++we can support up to 32 events with a unique interrupt. ++ ++**Here is an example,** ++ ++:: ++ ++ Device (\_SB.GED) ++ { ++ Name (_HID, "ACPI0013") ++ Name (_UID, Zero) ++ Name (_CRS, ResourceTemplate () ++ { ++ Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) ++ { ++ 0x00000029, ++ } ++ }) ++ OperationRegion (EREG, SystemMemory, 0x09080000, 0x04) ++ Field (EREG, DWordAcc, NoLock, WriteAsZeros) ++ { ++ ESEL, 32 ++ } ++ Method (_EVT, 1, Serialized) ++ { ++ Local0 = ESEL // ESEL = IO memory region which specifies the ++ // device type. ++ If (((Local0 & One) == One)) ++ { ++ MethodEvent1() ++ } ++ If ((Local0 & 0x2) == 0x2) ++ { ++ MethodEvent2() ++ } ++ ... ++ } ++ } ++ ++GED IO interface (4 byte access) ++-------------------------------- ++**read access:** ++ ++:: ++ ++ [0x0-0x3] Event selector bit field (32 bit) set by QEMU. ++ ++ bits: ++ 0: Memory hotplug event ++ 1: System power down event ++ 2-31: Reserved ++ ++**write_access:** ++ ++Nothing is expected to be written into GED IO memory +diff --git a/docs/specs/index.rst b/docs/specs/index.rst +index 40adb97c5e..984ba44029 100644 +--- a/docs/specs/index.rst ++++ b/docs/specs/index.rst +@@ -12,3 +12,4 @@ Contents: + + ppc-xive + ppc-spapr-xive ++ acpi_hw_reduced_hotplug +-- +2.19.1 diff --git a/hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch b/hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch new file mode 100644 index 0000000..dc57aa6 --- /dev/null +++ b/hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch @@ -0,0 +1,478 @@ +From b12d9edd0079d4ee136c25e95333918b0c6d3cd9 Mon Sep 17 00:00:00 2001 +From: Samuel Ortiz +Date: Wed, 18 Sep 2019 14:06:25 +0100 +Subject: [PATCH] hw/acpi: Add ACPI Generic Event Device Support + +The ACPI Generic Event Device (GED) is a hardware-reduced specific +device[ACPI v6.1 Section 5.6.9] that handles all platform events, +including the hotplug ones. This patch generates the AML code that +defines GEDs. + +Platforms need to specify their own GED Event bitmap to describe +what kind of events they want to support through GED. Also this +uses a a single interrupt for the GED device, relying on IO +memory region to communicate the type of device affected by the +interrupt. This way, we can support up to 32 events with a unique +interrupt. + +This supports only memory hotplug for now. + +Signed-off-by: Samuel Ortiz +Signed-off-by: Sebastien Boeuf +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Message-Id: <20190918130633.4872-4-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +--- + hw/acpi/Kconfig | 4 + + hw/acpi/Makefile.objs | 1 + + hw/acpi/generic_event_device.c | 303 +++++++++++++++++++++++++ + include/hw/acpi/generic_event_device.h | 100 ++++++++ + 4 files changed, 408 insertions(+) + create mode 100644 hw/acpi/generic_event_device.c + create mode 100644 include/hw/acpi/generic_event_device.h + +diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig +index 7c59cf900b..12e3f1e86e 100644 +--- a/hw/acpi/Kconfig ++++ b/hw/acpi/Kconfig +@@ -31,3 +31,7 @@ config ACPI_VMGENID + bool + default y + depends on PC ++ ++config ACPI_HW_REDUCED ++ bool ++ depends on ACPI +diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs +index 1a720c381e..e4b5d101a4 100644 +--- a/hw/acpi/Makefile.objs ++++ b/hw/acpi/Makefile.objs +@@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o + common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o + common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o + common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o ++common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o + common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o + + common-obj-y += acpi_interface.o +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +new file mode 100644 +index 0000000000..b94500b08d +--- /dev/null ++++ b/hw/acpi/generic_event_device.c +@@ -0,0 +1,303 @@ ++/* ++ * ++ * Copyright (c) 2018 Intel Corporation ++ * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd ++ * Written by Samuel Ortiz, Shameer Kolothum ++ * ++ * 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 "qapi/error.h" ++#include "exec/address-spaces.h" ++#include "hw/acpi/acpi.h" ++#include "hw/acpi/generic_event_device.h" ++#include "hw/irq.h" ++#include "hw/mem/pc-dimm.h" ++#include "hw/qdev-properties.h" ++#include "migration/vmstate.h" ++#include "qemu/error-report.h" ++ ++static const uint32_t ged_supported_events[] = { ++ ACPI_GED_MEM_HOTPLUG_EVT, ++}; ++ ++/* ++ * The ACPI Generic Event Device (GED) is a hardware-reduced specific ++ * device[ACPI v6.1 Section 5.6.9] that handles all platform events, ++ * including the hotplug ones. Platforms need to specify their own ++ * GED Event bitmap to describe what kind of events they want to support ++ * through GED. This routine uses a single interrupt for the GED device, ++ * relying on IO memory region to communicate the type of device ++ * affected by the interrupt. This way, we can support up to 32 events ++ * with a unique interrupt. ++ */ ++void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, ++ uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base) ++{ ++ AcpiGedState *s = ACPI_GED(hotplug_dev); ++ Aml *crs = aml_resource_template(); ++ Aml *evt, *field; ++ Aml *dev = aml_device("%s", name); ++ Aml *evt_sel = aml_local(0); ++ Aml *esel = aml_name(AML_GED_EVT_SEL); ++ ++ /* _CRS interrupt */ ++ aml_append(crs, aml_interrupt(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH, ++ AML_EXCLUSIVE, &ged_irq, 1)); ++ ++ aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0013"))); ++ aml_append(dev, aml_name_decl("_UID", aml_string(GED_DEVICE))); ++ aml_append(dev, aml_name_decl("_CRS", crs)); ++ ++ /* Append IO region */ ++ aml_append(dev, aml_operation_region(AML_GED_EVT_REG, rs, ++ aml_int(ged_base + ACPI_GED_EVT_SEL_OFFSET), ++ ACPI_GED_EVT_SEL_LEN)); ++ field = aml_field(AML_GED_EVT_REG, AML_DWORD_ACC, AML_NOLOCK, ++ AML_WRITE_AS_ZEROS); ++ aml_append(field, aml_named_field(AML_GED_EVT_SEL, ++ ACPI_GED_EVT_SEL_LEN * BITS_PER_BYTE)); ++ aml_append(dev, field); ++ ++ /* ++ * For each GED event we: ++ * - Add a conditional block for each event, inside a loop. ++ * - Call a method for each supported GED event type. ++ * ++ * The resulting ASL code looks like: ++ * ++ * Local0 = ESEL ++ * If ((Local0 & One) == One) ++ * { ++ * MethodEvent0() ++ * } ++ * ++ * If ((Local0 & 0x2) == 0x2) ++ * { ++ * MethodEvent1() ++ * } ++ * ... ++ */ ++ evt = aml_method("_EVT", 1, AML_SERIALIZED); ++ { ++ Aml *if_ctx; ++ uint32_t i; ++ uint32_t ged_events = ctpop32(s->ged_event_bitmap); ++ ++ /* Local0 = ESEL */ ++ aml_append(evt, aml_store(esel, evt_sel)); ++ ++ for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) { ++ uint32_t event = s->ged_event_bitmap & ged_supported_events[i]; ++ ++ if (!event) { ++ continue; ++ } ++ ++ if_ctx = aml_if(aml_equal(aml_and(evt_sel, aml_int(event), NULL), ++ aml_int(event))); ++ switch (event) { ++ case ACPI_GED_MEM_HOTPLUG_EVT: ++ aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "." ++ MEMORY_SLOT_SCAN_METHOD)); ++ break; ++ default: ++ /* ++ * Please make sure all the events in ged_supported_events[] ++ * are handled above. ++ */ ++ g_assert_not_reached(); ++ } ++ ++ aml_append(evt, if_ctx); ++ ged_events--; ++ } ++ ++ if (ged_events) { ++ error_report("Unsupported events specified"); ++ abort(); ++ } ++ } ++ ++ /* Append _EVT method */ ++ aml_append(dev, evt); ++ ++ aml_append(table, dev); ++} ++ ++/* Memory read by the GED _EVT AML dynamic method */ ++static uint64_t ged_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ uint64_t val = 0; ++ GEDState *ged_st = opaque; ++ ++ switch (addr) { ++ case ACPI_GED_EVT_SEL_OFFSET: ++ /* Read the selector value and reset it */ ++ val = ged_st->sel; ++ ged_st->sel = 0; ++ break; ++ default: ++ break; ++ } ++ ++ return val; ++} ++ ++/* Nothing is expected to be written to the GED memory region */ ++static void ged_write(void *opaque, hwaddr addr, uint64_t data, ++ unsigned int size) ++{ ++} ++ ++static const MemoryRegionOps ged_ops = { ++ .read = ged_read, ++ .write = ged_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++ .valid = { ++ .min_access_size = 4, ++ .max_access_size = 4, ++ }, ++}; ++ ++static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ AcpiGedState *s = ACPI_GED(hotplug_dev); ++ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); ++ } else { ++ error_setg(errp, "virt: device plug request for unsupported device" ++ " type: %s", object_get_typename(OBJECT(dev))); ++ } ++} ++ ++static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) ++{ ++ AcpiGedState *s = ACPI_GED(adev); ++ GEDState *ged_st = &s->ged_state; ++ uint32_t sel; ++ ++ if (ev & ACPI_MEMORY_HOTPLUG_STATUS) { ++ sel = ACPI_GED_MEM_HOTPLUG_EVT; ++ } else { ++ /* Unknown event. Return without generating interrupt. */ ++ warn_report("GED: Unsupported event %d. No irq injected", ev); ++ return; ++ } ++ ++ /* ++ * Set the GED selector field to communicate the event type. ++ * This will be read by GED aml code to select the appropriate ++ * event method. ++ */ ++ ged_st->sel |= sel; ++ ++ /* Trigger the event by sending an interrupt to the guest. */ ++ qemu_irq_pulse(s->irq); ++} ++ ++static Property acpi_ged_properties[] = { ++ DEFINE_PROP_UINT32("ged-event", AcpiGedState, ged_event_bitmap, 0), ++ DEFINE_PROP_END_OF_LIST(), ++}; ++ ++static const VMStateDescription vmstate_memhp_state = { ++ .name = "acpi-ged/memhp", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_MEMORY_HOTPLUG(memhp_state, AcpiGedState), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const VMStateDescription vmstate_ged_state = { ++ .name = "acpi-ged-state", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT32(sel, GEDState), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const VMStateDescription vmstate_acpi_ged = { ++ .name = "acpi-ged", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_STRUCT(ged_state, AcpiGedState, 1, vmstate_ged_state, GEDState), ++ VMSTATE_END_OF_LIST(), ++ }, ++ .subsections = (const VMStateDescription * []) { ++ &vmstate_memhp_state, ++ NULL ++ } ++}; ++ ++static void acpi_ged_initfn(Object *obj) ++{ ++ DeviceState *dev = DEVICE(obj); ++ AcpiGedState *s = ACPI_GED(dev); ++ SysBusDevice *sbd = SYS_BUS_DEVICE(obj); ++ GEDState *ged_st = &s->ged_state; ++ ++ memory_region_init_io(&ged_st->io, obj, &ged_ops, ged_st, ++ TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN); ++ sysbus_init_mmio(sbd, &ged_st->io); ++ ++ sysbus_init_irq(sbd, &s->irq); ++ ++ s->memhp_state.is_enabled = true; ++ /* ++ * GED handles memory hotplug event and acpi-mem-hotplug ++ * memory region gets initialized here. Create an exclusive ++ * container for memory hotplug IO and expose it as GED sysbus ++ * MMIO so that boards can map it separately. ++ */ ++ memory_region_init(&s->container_memhp, OBJECT(dev), "memhp container", ++ MEMORY_HOTPLUG_IO_LEN); ++ sysbus_init_mmio(sbd, &s->container_memhp); ++ acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev), ++ &s->memhp_state, 0); ++} ++ ++static void acpi_ged_class_init(ObjectClass *class, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(class); ++ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(class); ++ AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class); ++ ++ dc->desc = "ACPI Generic Event Device"; ++ dc->props = acpi_ged_properties; ++ dc->vmsd = &vmstate_acpi_ged; ++ ++ hc->plug = acpi_ged_device_plug_cb; ++ ++ adevc->send_event = acpi_ged_send_event; ++} ++ ++static const TypeInfo acpi_ged_info = { ++ .name = TYPE_ACPI_GED, ++ .parent = TYPE_SYS_BUS_DEVICE, ++ .instance_size = sizeof(AcpiGedState), ++ .instance_init = acpi_ged_initfn, ++ .class_init = acpi_ged_class_init, ++ .interfaces = (InterfaceInfo[]) { ++ { TYPE_HOTPLUG_HANDLER }, ++ { TYPE_ACPI_DEVICE_IF }, ++ { } ++ } ++}; ++ ++static void acpi_ged_register_types(void) ++{ ++ type_register_static(&acpi_ged_info); ++} ++ ++type_init(acpi_ged_register_types) +diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h +new file mode 100644 +index 0000000000..2049e8d873 +--- /dev/null ++++ b/include/hw/acpi/generic_event_device.h +@@ -0,0 +1,100 @@ ++/* ++ * ++ * Copyright (c) 2018 Intel Corporation ++ * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd ++ * Written by Samuel Ortiz, Shameer Kolothum ++ * ++ * 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. ++ * ++ * The ACPI Generic Event Device (GED) is a hardware-reduced specific ++ * device[ACPI v6.1 Section 5.6.9] that handles all platform events, ++ * including the hotplug ones. Generic Event Device allows platforms ++ * to handle interrupts in ACPI ASL statements. It follows a very ++ * similar approach like the _EVT method from GPIO events. All ++ * interrupts are listed in _CRS and the handler is written in _EVT ++ * method. Here, we use a single interrupt for the GED device, relying ++ * on IO memory region to communicate the type of device affected by ++ * the interrupt. This way, we can support up to 32 events with a ++ * unique interrupt. ++ * ++ * Here is an example. ++ * ++ * Device (\_SB.GED) ++ * { ++ * Name (_HID, "ACPI0013") ++ * Name (_UID, Zero) ++ * Name (_CRS, ResourceTemplate () ++ * { ++ * Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) ++ * { ++ * 0x00000029, ++ * } ++ * }) ++ * OperationRegion (EREG, SystemMemory, 0x09080000, 0x04) ++ * Field (EREG, DWordAcc, NoLock, WriteAsZeros) ++ * { ++ * ESEL, 32 ++ * } ++ * ++ * Method (_EVT, 1, Serialized) // _EVT: Event ++ * { ++ * Local0 = ESEL // ESEL = IO memory region which specifies the ++ * // device type. ++ * If (((Local0 & One) == One)) ++ * { ++ * MethodEvent1() ++ * } ++ * If ((Local0 & 0x2) == 0x2) ++ * { ++ * MethodEvent2() ++ * } ++ * ... ++ * } ++ * } ++ * ++ */ ++ ++#ifndef HW_ACPI_GED_H ++#define HW_ACPI_GED_H ++ ++#include "hw/sysbus.h" ++#include "hw/acpi/memory_hotplug.h" ++ ++#define TYPE_ACPI_GED "acpi-ged" ++#define ACPI_GED(obj) \ ++ OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED) ++ ++#define ACPI_GED_EVT_SEL_OFFSET 0x0 ++#define ACPI_GED_EVT_SEL_LEN 0x4 ++ ++#define GED_DEVICE "GED" ++#define AML_GED_EVT_REG "EREG" ++#define AML_GED_EVT_SEL "ESEL" ++ ++/* ++ * Platforms need to specify the GED event bitmap ++ * to describe what kind of events they want to support ++ * through GED. ++ */ ++#define ACPI_GED_MEM_HOTPLUG_EVT 0x1 ++ ++typedef struct GEDState { ++ MemoryRegion io; ++ uint32_t sel; ++} GEDState; ++ ++typedef struct AcpiGedState { ++ SysBusDevice parent_obj; ++ MemHotplugState memhp_state; ++ MemoryRegion container_memhp; ++ GEDState ged_state; ++ uint32_t ged_event_bitmap; ++ qemu_irq irq; ++} AcpiGedState; ++ ++void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, ++ uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base); ++ ++#endif +-- +2.19.1 diff --git a/hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch b/hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch new file mode 100644 index 0000000..2926871 --- /dev/null +++ b/hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch @@ -0,0 +1,46 @@ +From 7a08983315bf4d624966a89112259e2b4949de91 Mon Sep 17 00:00:00 2001 +From: Samuel Ortiz +Date: Wed, 18 Sep 2019 14:06:24 +0100 +Subject: [PATCH] hw/acpi: Do not create memory hotplug method when handler is + not defined + +With Hardware-reduced ACPI, the GED device will manage ACPI +hotplug entirely. As a consequence, make the memory specific +events AML generation optional. The code will only be added +when the method name is not NULL. + +Signed-off-by: Samuel Ortiz +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-3-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/acpi/memory_hotplug.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c +index 9a515c0484..8b30356c1a 100644 +--- a/hw/acpi/memory_hotplug.c ++++ b/hw/acpi/memory_hotplug.c +@@ -711,10 +711,12 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + } + aml_append(table, dev_container); + +- method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); +- aml_append(method, +- aml_call0(MEMORY_DEVICES_CONTAINER "." MEMORY_SLOT_SCAN_METHOD)); +- aml_append(table, method); ++ if (event_handler_method) { ++ method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); ++ aml_append(method, aml_call0(MEMORY_DEVICES_CONTAINER "." ++ MEMORY_SLOT_SCAN_METHOD)); ++ aml_append(table, method); ++ } + + g_free(mhp_res_path); + } +-- +2.19.1 diff --git a/hw-acpi-Make-ACPI-IO-address-space-configurable.patch b/hw-acpi-Make-ACPI-IO-address-space-configurable.patch new file mode 100644 index 0000000..cdf597b --- /dev/null +++ b/hw-acpi-Make-ACPI-IO-address-space-configurable.patch @@ -0,0 +1,196 @@ +From 6cd7281c73ca462b2f27969f1e28f1afd3ebe82d Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:23 +0100 +Subject: [PATCH] hw/acpi: Make ACPI IO address space configurable + +This is in preparation for adding support for ARM64 platforms +where it doesn't use port mapped IO for ACPI IO space. We are +making changes so that MMIO region can be accommodated +and board can pass the base address into the aml build function. + +Also move few MEMORY_* definitions to header so that other memory +hotplug event signalling mechanisms (eg. Generic Event Device on +HW-reduced acpi platforms) can use the same from their respective +event handler code. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-2-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/acpi/memory_hotplug.c | 33 ++++++++++++++------------------ + hw/i386/acpi-build.c | 7 ++++++- + hw/i386/pc.c | 3 +++ + include/hw/acpi/memory_hotplug.h | 9 +++++++-- + include/hw/i386/pc.h | 3 +++ + 5 files changed, 33 insertions(+), 22 deletions(-) + +diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c +index 297812d5f7..9a515c0484 100644 +--- a/hw/acpi/memory_hotplug.c ++++ b/hw/acpi/memory_hotplug.c +@@ -29,12 +29,7 @@ + #define MEMORY_SLOT_PROXIMITY_METHOD "MPXM" + #define MEMORY_SLOT_EJECT_METHOD "MEJ0" + #define MEMORY_SLOT_NOTIFY_METHOD "MTFY" +-#define MEMORY_SLOT_SCAN_METHOD "MSCN" + #define MEMORY_HOTPLUG_DEVICE "MHPD" +-#define MEMORY_HOTPLUG_IO_LEN 24 +-#define MEMORY_DEVICES_CONTAINER "\\_SB.MHPC" +- +-static uint16_t memhp_io_base; + + static ACPIOSTInfo *acpi_memory_device_status(int slot, MemStatus *mdev) + { +@@ -209,7 +204,7 @@ static const MemoryRegionOps acpi_memory_hotplug_ops = { + }; + + void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, +- MemHotplugState *state, uint16_t io_base) ++ MemHotplugState *state, hwaddr io_base) + { + MachineState *machine = MACHINE(qdev_get_machine()); + +@@ -218,12 +213,10 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, + return; + } + +- assert(!memhp_io_base); +- memhp_io_base = io_base; + state->devs = g_malloc0(sizeof(*state->devs) * state->dev_count); + memory_region_init_io(&state->io, owner, &acpi_memory_hotplug_ops, state, + "acpi-mem-hotplug", MEMORY_HOTPLUG_IO_LEN); +- memory_region_add_subregion(as, memhp_io_base, &state->io); ++ memory_region_add_subregion(as, io_base, &state->io); + } + + /** +@@ -342,7 +335,8 @@ const VMStateDescription vmstate_memory_hotplug = { + + void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + const char *res_root, +- const char *event_handler_method) ++ const char *event_handler_method, ++ AmlRegionSpace rs, hwaddr memhp_io_base) + { + int i; + Aml *ifctx; +@@ -351,10 +345,6 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + Aml *mem_ctrl_dev; + char *mhp_res_path; + +- if (!memhp_io_base) { +- return; +- } +- + mhp_res_path = g_strdup_printf("%s." MEMORY_HOTPLUG_DEVICE, res_root); + mem_ctrl_dev = aml_device("%s", mhp_res_path); + { +@@ -365,14 +355,19 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + aml_name_decl("_UID", aml_string("Memory hotplug resources"))); + + crs = aml_resource_template(); +- aml_append(crs, +- aml_io(AML_DECODE16, memhp_io_base, memhp_io_base, 0, +- MEMORY_HOTPLUG_IO_LEN) +- ); ++ if (rs == AML_SYSTEM_IO) { ++ aml_append(crs, ++ aml_io(AML_DECODE16, memhp_io_base, memhp_io_base, 0, ++ MEMORY_HOTPLUG_IO_LEN) ++ ); ++ } else { ++ aml_append(crs, aml_memory32_fixed(memhp_io_base, ++ MEMORY_HOTPLUG_IO_LEN, AML_READ_WRITE)); ++ } + aml_append(mem_ctrl_dev, aml_name_decl("_CRS", crs)); + + aml_append(mem_ctrl_dev, aml_operation_region( +- MEMORY_HOTPLUG_IO_REGION, AML_SYSTEM_IO, ++ MEMORY_HOTPLUG_IO_REGION, rs, + aml_int(memhp_io_base), MEMORY_HOTPLUG_IO_LEN) + ); + +diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c +index f3fdfefcd5..749218561a 100644 +--- a/hw/i386/acpi-build.c ++++ b/hw/i386/acpi-build.c +@@ -1871,7 +1871,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, + build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base, + "\\_SB.PCI0", "\\_GPE._E02"); + } +- build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", "\\_GPE._E03"); ++ ++ if (pcms->memhp_io_base && nr_mem) { ++ build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", ++ "\\_GPE._E03", AML_SYSTEM_IO, ++ pcms->memhp_io_base); ++ } + + scope = aml_scope("_GPE"); + { +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index d011733ff7..8a914130b0 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -1936,6 +1936,9 @@ void pc_memory_init(PCMachineState *pcms, + + /* Init default IOAPIC address space */ + pcms->ioapic_as = &address_space_memory; ++ ++ /* Init ACPI memory hotplug IO base address */ ++ pcms->memhp_io_base = ACPI_MEMORY_HOTPLUG_BASE; + } + + /* +diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h +index 77c65765d6..dfe9cf3fde 100644 +--- a/include/hw/acpi/memory_hotplug.h ++++ b/include/hw/acpi/memory_hotplug.h +@@ -5,6 +5,10 @@ + #include "hw/acpi/acpi.h" + #include "hw/acpi/aml-build.h" + ++#define MEMORY_SLOT_SCAN_METHOD "MSCN" ++#define MEMORY_DEVICES_CONTAINER "\\_SB.MHPC" ++#define MEMORY_HOTPLUG_IO_LEN 24 ++ + /** + * MemStatus: + * @is_removing: the memory device in slot has been requested to be ejected. +@@ -29,7 +33,7 @@ typedef struct MemHotplugState { + } MemHotplugState; + + void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, +- MemHotplugState *state, uint16_t io_base); ++ MemHotplugState *state, hwaddr io_base); + + void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st, + DeviceState *dev, Error **errp); +@@ -48,5 +52,6 @@ void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list); + + void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, + const char *res_root, +- const char *event_handler_method); ++ const char *event_handler_method, ++ AmlRegionSpace rs, hwaddr memhp_io_base); + #endif +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 859b64c51d..49b47535cf 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -69,6 +69,9 @@ struct PCMachineState { + /* Address space used by IOAPIC device. All IOAPIC interrupts + * will be translated to MSI messages in the address space. */ + AddressSpace *ioapic_as; ++ ++ /* ACPI Memory hotplug IO base address */ ++ hwaddr memhp_io_base; + }; + + #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" +-- +2.19.1 diff --git a/hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch b/hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch new file mode 100644 index 0000000..f2c0f39 --- /dev/null +++ b/hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch @@ -0,0 +1,72 @@ +From e6b1fd7bfbfe116e9d5df590f7069336c1eb1983 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:29 +0100 +Subject: [PATCH] hw/arm: Factor out powerdown notifier from GPIO + +This is in preparation of using GED device for +system_powerdown event. Make the powerdown notifier +registration independent of create_gpio() fn. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-8-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/arm/virt.c | 12 ++++-------- + include/hw/arm/virt.h | 1 + + 2 files changed, 5 insertions(+), 8 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index ab33cce4b3..aaefa5578e 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -910,10 +910,6 @@ static void virt_powerdown_req(Notifier *n, void *opaque) + qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); + } + +-static Notifier virt_system_powerdown_notifier = { +- .notify = virt_powerdown_req +-}; +- + static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) + { + char *nodename; +@@ -954,10 +950,6 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) + KEY_POWER); + qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff", + "gpios", phandle, 3, 0); +- +- /* connect powerdown request */ +- qemu_register_powerdown_notifier(&virt_system_powerdown_notifier); +- + g_free(nodename); + } + +@@ -1856,6 +1848,10 @@ static void machvirt_init(MachineState *machine) + vms->acpi_dev = create_acpi_ged(vms, pic); + } + ++ /* connect powerdown request */ ++ vms->powerdown_notifier.notify = virt_powerdown_req; ++ qemu_register_powerdown_notifier(&vms->powerdown_notifier); ++ + /* Create mmio transports, so the user can create virtio backends + * (which will be automatically plugged in to the transports). If + * no backend is created the transport will just sit harmlessly idle. +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 0350285136..dcceb9c615 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -139,6 +139,7 @@ typedef struct { + int psci_conduit; + hwaddr highest_gpa; + DeviceState *acpi_dev; ++ Notifier powerdown_notifier; + } VirtMachineState; + + #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) +-- +2.19.1 diff --git a/hw-arm-Use-GED-for-system_powerdown-event.patch b/hw-arm-Use-GED-for-system_powerdown-event.patch new file mode 100644 index 0000000..140f59a --- /dev/null +++ b/hw-arm-Use-GED-for-system_powerdown-event.patch @@ -0,0 +1,167 @@ +From 0b77f242b180f1ae40b9752999cef4894113df8e Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:30 +0100 +Subject: [PATCH] hw/arm: Use GED for system_powerdown event + +For machines 4.2 or higher with ACPI boot use GED for system_powerdown +event instead of GPIO. Guest boot with DT still uses GPIO. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Eric Auger +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-9-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/acpi/generic_event_device.c | 8 ++++++++ + hw/arm/virt-acpi-build.c | 6 +++--- + hw/arm/virt.c | 18 ++++++++++++------ + include/hw/acpi/acpi_dev_interface.h | 1 + + include/hw/acpi/generic_event_device.h | 3 +++ + 5 files changed, 27 insertions(+), 9 deletions(-) + +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +index b94500b08d..9cee90cc70 100644 +--- a/hw/acpi/generic_event_device.c ++++ b/hw/acpi/generic_event_device.c +@@ -22,6 +22,7 @@ + + static const uint32_t ged_supported_events[] = { + ACPI_GED_MEM_HOTPLUG_EVT, ++ ACPI_GED_PWR_DOWN_EVT, + }; + + /* +@@ -104,6 +105,11 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, + aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "." + MEMORY_SLOT_SCAN_METHOD)); + break; ++ case ACPI_GED_PWR_DOWN_EVT: ++ aml_append(if_ctx, ++ aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), ++ aml_int(0x80))); ++ break; + default: + /* + * Please make sure all the events in ged_supported_events[] +@@ -184,6 +190,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) + + if (ev & ACPI_MEMORY_HOTPLUG_STATUS) { + sel = ACPI_GED_MEM_HOTPLUG_EVT; ++ } else if (ev & ACPI_POWER_DOWN_STATUS) { ++ sel = ACPI_GED_PWR_DOWN_EVT; + } else { + /* Unknown event. Return without generating interrupt. */ + warn_report("GED: Unsupported event %d. No irq injected", ev); +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index 9622994e50..f48733d9f2 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -50,7 +50,6 @@ + #include "hw/acpi/acpi-defs.h" + + #define ARM_SPI_BASE 32 +-#define ACPI_POWER_BUTTON_DEVICE "PWRB" + + static void acpi_dsdt_add_psd(Aml *dev, int cpus) + { +@@ -813,13 +812,14 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); + acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE), + vms->highmem, vms->highmem_ecam); +- acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], +- (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); + if (vms->acpi_dev) { + build_ged_aml(scope, "\\_SB."GED_DEVICE, + HOTPLUG_HANDLER(vms->acpi_dev), + irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEMORY, + memmap[VIRT_ACPI_GED].base); ++ } else { ++ acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], ++ (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); + } + + if (vms->acpi_dev) { +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index aaefa5578e..18321e522b 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -639,10 +639,10 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) + DeviceState *dev; + MachineState *ms = MACHINE(vms); + int irq = vms->irqmap[VIRT_ACPI_GED]; +- uint32_t event = 0; ++ uint32_t event = ACPI_GED_PWR_DOWN_EVT; + + if (ms->ram_slots) { +- event = ACPI_GED_MEM_HOTPLUG_EVT; ++ event |= ACPI_GED_MEM_HOTPLUG_EVT; + } + + dev = qdev_create(NULL, TYPE_ACPI_GED); +@@ -906,8 +906,14 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) + static DeviceState *gpio_key_dev; + static void virt_powerdown_req(Notifier *n, void *opaque) + { +- /* use gpio Pin 3 for power button event */ +- qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); ++ VirtMachineState *s = container_of(n, VirtMachineState, powerdown_notifier); ++ ++ if (s->acpi_dev) { ++ acpi_send_event(s->acpi_dev, ACPI_POWER_DOWN_STATUS); ++ } else { ++ /* use gpio Pin 3 for power button event */ ++ qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); ++ } + } + + static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) +@@ -1842,10 +1848,10 @@ static void machvirt_init(MachineState *machine) + + create_pcie(vms, pic); + +- create_gpio(vms, pic); +- + if (has_ged && aarch64 && firmware_loaded && acpi_enabled) { + vms->acpi_dev = create_acpi_ged(vms, pic); ++ } else { ++ create_gpio(vms, pic); + } + + /* connect powerdown request */ +diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h +index 43ff119179..adcb3a816c 100644 +--- a/include/hw/acpi/acpi_dev_interface.h ++++ b/include/hw/acpi/acpi_dev_interface.h +@@ -11,6 +11,7 @@ typedef enum { + ACPI_MEMORY_HOTPLUG_STATUS = 8, + ACPI_NVDIMM_HOTPLUG_STATUS = 16, + ACPI_VMGENID_CHANGE_STATUS = 32, ++ ACPI_POWER_DOWN_STATUS = 64, + } AcpiEventStatusBits; + + #define TYPE_ACPI_DEVICE_IF "acpi-device-interface" +diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h +index 2049e8d873..d157eac088 100644 +--- a/include/hw/acpi/generic_event_device.h ++++ b/include/hw/acpi/generic_event_device.h +@@ -62,6 +62,8 @@ + #include "hw/sysbus.h" + #include "hw/acpi/memory_hotplug.h" + ++#define ACPI_POWER_BUTTON_DEVICE "PWRB" ++ + #define TYPE_ACPI_GED "acpi-ged" + #define ACPI_GED(obj) \ + OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED) +@@ -79,6 +81,7 @@ + * through GED. + */ + #define ACPI_GED_MEM_HOTPLUG_EVT 0x1 ++#define ACPI_GED_PWR_DOWN_EVT 0x2 + + typedef struct GEDState { + MemoryRegion io; +-- +2.19.1 diff --git a/hw-arm-virt-Add-memory-hotplug-framework.patch b/hw-arm-virt-Add-memory-hotplug-framework.patch new file mode 100644 index 0000000..dcb0f21 --- /dev/null +++ b/hw-arm-virt-Add-memory-hotplug-framework.patch @@ -0,0 +1,130 @@ +From e14fadc66d488ad10a10a2076721b72cc239ded9 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Wed, 18 Sep 2019 14:06:26 +0100 +Subject: [PATCH] hw/arm/virt: Add memory hotplug framework + +This patch adds the memory hot-plug/hot-unplug infrastructure +in machvirt. The device memory is not yet exposed to the Guest +either through DT or ACPI and hence both cold/hot plug of memory +is explicitly disabled for now. + +Signed-off-by: Eric Auger +Signed-off-by: Kwangwoo Lee +Signed-off-by: Shameer Kolothum +Reviewed-by: Peter Maydell +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-5-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/arm/Kconfig | 2 ++ + hw/arm/virt.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 54 insertions(+), 1 deletion(-) + +diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig +index ab65ecd216..84961c17ab 100644 +--- a/hw/arm/Kconfig ++++ b/hw/arm/Kconfig +@@ -20,6 +20,8 @@ config ARM_VIRT + select SMBIOS + select VIRTIO_MMIO + select ACPI_PCI ++ select MEM_DEVICE ++ select DIMM + + config CHEETAH + bool +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 23d72aed97..c7c07fe3ac 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -65,6 +65,8 @@ + #include "hw/arm/smmuv3.h" + #include "hw/acpi/acpi.h" + #include "target/arm/internals.h" ++#include "hw/mem/pc-dimm.h" ++#include "hw/mem/nvdimm.h" + + #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ + static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ +@@ -1998,6 +2000,42 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) + return ms->possible_cpus; + } + ++static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp) ++{ ++ ++ /* ++ * The device memory is not yet exposed to the Guest either through ++ * DT or ACPI and hence both cold/hot plug of memory is explicitly ++ * disabled for now. ++ */ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ error_setg(errp, "memory cold/hot plug is not yet supported"); ++ return; ++ } ++ ++ pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), NULL, errp); ++} ++ ++static void virt_memory_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ Error *local_err = NULL; ++ ++ pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); ++ ++ error_propagate(errp, local_err); ++} ++ ++static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ virt_memory_pre_plug(hotplug_dev, dev, errp); ++ } ++} ++ + static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { +@@ -2009,12 +2047,23 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, + SYS_BUS_DEVICE(dev)); + } + } ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { ++ virt_memory_plug(hotplug_dev, dev, errp); ++ } ++} ++ ++static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ error_setg(errp, "device unplug request for unsupported device" ++ " type: %s", object_get_typename(OBJECT(dev))); + } + + static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, + DeviceState *dev) + { +- if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) { ++ if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE) || ++ (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) { + return HOTPLUG_HANDLER(machine); + } + +@@ -2078,7 +2127,9 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + mc->kvm_type = virt_kvm_type; + assert(!mc->get_hotplug_handler); + mc->get_hotplug_handler = virt_machine_get_hotplug_handler; ++ hc->pre_plug = virt_machine_device_pre_plug_cb; + hc->plug = virt_machine_device_plug_cb; ++ hc->unplug_request = virt_machine_device_unplug_request_cb; + mc->numa_mem_supported = true; + } + +-- +2.19.1 diff --git a/hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch b/hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch new file mode 100644 index 0000000..b32b2a0 --- /dev/null +++ b/hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch @@ -0,0 +1,252 @@ +From ce813d8daa2e01df52509f4bb52b9ab774408706 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:27 +0100 +Subject: [PATCH] hw/arm/virt: Enable device memory cold/hot plug with ACPI + boot + +This initializes the GED device with base memory and irq, configures +ged memory hotplug event and builds the corresponding aml code. With +this, both hot and cold plug of device memory is enabled now for Guest +with ACPI boot. Memory cold plug support with Guest DT boot is not yet +supported. + +As DSDT table gets changed by this, update bios-tables-test-allowed-diff.h +to avoid "make check" failure. + +Signed-off-by: Shameer Kolothum +Message-Id: <20190918130633.4872-6-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +--- + hw/arm/Kconfig | 2 ++ + hw/arm/virt-acpi-build.c | 21 ++++++++++++++ + hw/arm/virt.c | 59 +++++++++++++++++++++++++++++++++++----- + include/hw/arm/virt.h | 4 +++ + 4 files changed, 79 insertions(+), 7 deletions(-) + +diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig +index 84961c17ab..ad7f7c089b 100644 +--- a/hw/arm/Kconfig ++++ b/hw/arm/Kconfig +@@ -22,6 +22,8 @@ config ARM_VIRT + select ACPI_PCI + select MEM_DEVICE + select DIMM ++ select ACPI_MEMORY_HOTPLUG ++ select ACPI_HW_REDUCED + + config CHEETAH + bool +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index fe54411f6a..fca53ae01f 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -40,6 +40,8 @@ + #include "hw/acpi/aml-build.h" + #include "hw/acpi/utils.h" + #include "hw/acpi/pci.h" ++#include "hw/acpi/memory_hotplug.h" ++#include "hw/acpi/generic_event_device.h" + #include "hw/pci/pcie_host.h" + #include "hw/pci/pci.h" + #include "hw/arm/virt.h" +@@ -779,6 +781,7 @@ static void + build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + { + Aml *scope, *dsdt; ++ MachineState *ms = MACHINE(vms); + const MemMapEntry *memmap = vms->memmap; + const int *irqmap = vms->irqmap; + +@@ -803,6 +806,24 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + vms->highmem, vms->highmem_ecam); + acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], + (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); ++ if (vms->acpi_dev) { ++ build_ged_aml(scope, "\\_SB."GED_DEVICE, ++ HOTPLUG_HANDLER(vms->acpi_dev), ++ irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEMORY, ++ memmap[VIRT_ACPI_GED].base); ++ } ++ ++ if (vms->acpi_dev) { ++ uint32_t event = object_property_get_uint(OBJECT(vms->acpi_dev), ++ "ged-event", &error_abort); ++ ++ if (event & ACPI_GED_MEM_HOTPLUG_EVT) { ++ build_memory_hotplug_aml(scope, ms->ram_slots, "\\_SB", NULL, ++ AML_SYSTEM_MEMORY, ++ memmap[VIRT_PCDIMM_ACPI].base); ++ } ++ } ++ + acpi_dsdt_add_power_button(scope); + + aml_append(dsdt, scope); +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index c7c07fe3ac..8ccabd5159 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -67,6 +67,7 @@ + #include "target/arm/internals.h" + #include "hw/mem/pc-dimm.h" + #include "hw/mem/nvdimm.h" ++#include "hw/acpi/generic_event_device.h" + + #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ + static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ +@@ -137,6 +138,8 @@ static const MemMapEntry base_memmap[] = { + [VIRT_GPIO] = { 0x09030000, 0x00001000 }, + [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, + [VIRT_SMMU] = { 0x09050000, 0x00020000 }, ++ [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, ++ [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, + [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, + [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 }, + /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ +@@ -173,6 +176,7 @@ static const int a15irqmap[] = { + [VIRT_PCIE] = 3, /* ... to 6 */ + [VIRT_GPIO] = 7, + [VIRT_SECURE_UART] = 8, ++ [VIRT_ACPI_GED] = 9, + [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ + [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */ + [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */ +@@ -630,6 +634,29 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) + } + } + ++static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) ++{ ++ DeviceState *dev; ++ MachineState *ms = MACHINE(vms); ++ int irq = vms->irqmap[VIRT_ACPI_GED]; ++ uint32_t event = 0; ++ ++ if (ms->ram_slots) { ++ event = ACPI_GED_MEM_HOTPLUG_EVT; ++ } ++ ++ dev = qdev_create(NULL, TYPE_ACPI_GED); ++ qdev_prop_set_uint32(dev, "ged-event", event); ++ ++ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); ++ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); ++ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]); ++ ++ qdev_init_nofail(dev); ++ ++ return dev; ++} ++ + static void create_its(VirtMachineState *vms, DeviceState *gicdev) + { + const char *itsclass = its_class_name(); +@@ -1603,6 +1630,7 @@ static void machvirt_init(MachineState *machine) + MemoryRegion *ram = g_new(MemoryRegion, 1); + bool firmware_loaded; + bool aarch64 = true; ++ bool has_ged = !vmc->no_ged; + unsigned int smp_cpus = machine->smp.cpus; + unsigned int max_cpus = machine->smp.max_cpus; + +@@ -1824,6 +1852,10 @@ static void machvirt_init(MachineState *machine) + + create_gpio(vms, pic); + ++ if (has_ged && aarch64 && firmware_loaded && acpi_enabled) { ++ vms->acpi_dev = create_acpi_ged(vms, pic); ++ } ++ + /* Create mmio transports, so the user can create virtio backends + * (which will be automatically plugged in to the transports). If + * no backend is created the transport will just sit harmlessly idle. +@@ -2003,14 +2035,17 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) + static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { ++ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); + +- /* +- * The device memory is not yet exposed to the Guest either through +- * DT or ACPI and hence both cold/hot plug of memory is explicitly +- * disabled for now. +- */ +- if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +- error_setg(errp, "memory cold/hot plug is not yet supported"); ++ if (is_nvdimm) { ++ error_setg(errp, "nvdimm is not yet supported"); ++ return; ++ } ++ ++ if (!vms->acpi_dev) { ++ error_setg(errp, ++ "memory hotplug is not enabled: missing acpi-ged device"); + return; + } + +@@ -2020,11 +2055,18 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + static void virt_memory_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { ++ HotplugHandlerClass *hhc; + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + Error *local_err = NULL; + + pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); ++ if (local_err) { ++ goto out; ++ } + ++ hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev); ++ hhc->plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &error_abort); ++out: + error_propagate(errp, local_err); + } + +@@ -2231,8 +2273,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(4, 1) + + static void virt_machine_4_0_options(MachineClass *mc) + { ++ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); ++ + virt_machine_4_1_options(mc); + compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); ++ vmc->no_ged = true; + } + DEFINE_VIRT_MACHINE(4, 0) + +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index a9d6977afc..0350285136 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -78,6 +78,8 @@ enum { + VIRT_GPIO, + VIRT_SECURE_UART, + VIRT_SECURE_MEM, ++ VIRT_PCDIMM_ACPI, ++ VIRT_ACPI_GED, + VIRT_LOWMEMMAP_LAST, + }; + +@@ -107,6 +109,7 @@ typedef struct { + bool claim_edge_triggered_timers; + bool smbios_old_sys_ver; + bool no_highmem_ecam; ++ bool no_ged; /* Machines < 4.1 has no support for ACPI GED device */ + bool kvm_no_adjvtime; + } VirtMachineClass; + +@@ -135,6 +138,7 @@ typedef struct { + uint32_t iommu_phandle; + int psci_conduit; + hwaddr highest_gpa; ++ DeviceState *acpi_dev; + } VirtMachineState; + + #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) +-- +2.19.1 diff --git a/hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch b/hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch new file mode 100644 index 0000000..0602ab8 --- /dev/null +++ b/hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch @@ -0,0 +1,75 @@ +From 8d287871fd4e1b4654fe9e5011b80614cb44f6d8 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:28 +0100 +Subject: [PATCH] hw/arm/virt-acpi-build: Add PC-DIMM in SRAT + +Generate Memory Affinity Structures for PC-DIMM ranges. + +Also, Linux and Windows need ACPI SRAT table to make memory hotplug +work properly, however currently QEMU doesn't create SRAT table if +numa options aren't present on CLI. Hence add support(>=4.2) to +create numa node automatically (auto_enable_numa_with_memhp) when +QEMU is started with memory hotplug enabled but without '-numa' +options on CLI. + +Signed-off-by: Shameer Kolothum +Signed-off-by: Eric Auger +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-7-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + hw/arm/virt-acpi-build.c | 9 +++++++++ + hw/arm/virt.c | 2 ++ + 2 files changed, 11 insertions(+) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index fca53ae01f..9622994e50 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -592,6 +592,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + int i, srat_start; + uint64_t mem_base; + MachineClass *mc = MACHINE_GET_CLASS(vms); ++ MachineState *ms = MACHINE(vms); + const CPUArchIdList *cpu_list = mc->possible_cpu_arch_ids(MACHINE(vms)); + + srat_start = table_data->len; +@@ -617,6 +618,14 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + } + } + ++ if (ms->device_memory) { ++ numamem = acpi_data_push(table_data, sizeof *numamem); ++ build_srat_memory(numamem, ms->device_memory->base, ++ memory_region_size(&ms->device_memory->mr), ++ nb_numa_nodes - 1, ++ MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); ++ } ++ + build_header(linker, table_data, (void *)(table_data->data + srat_start), + "SRAT", table_data->len - srat_start, 3, NULL, NULL); + } +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 8ccabd5159..ab33cce4b3 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -2173,6 +2173,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + hc->plug = virt_machine_device_plug_cb; + hc->unplug_request = virt_machine_device_unplug_request_cb; + mc->numa_mem_supported = true; ++ mc->auto_enable_numa_with_memhp = true; + } + + static void virt_instance_init(Object *obj) +@@ -2278,6 +2279,7 @@ static void virt_machine_4_0_options(MachineClass *mc) + virt_machine_4_1_options(mc); + compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); + vmc->no_ged = true; ++ mc->auto_enable_numa_with_memhp = false; + } + DEFINE_VIRT_MACHINE(4, 0) + +-- +2.19.1 diff --git a/qemu.spec b/qemu.spec index 77118c9..dd16338 100644 --- a/qemu.spec +++ b/qemu.spec @@ -105,6 +105,20 @@ Patch0092: target-arm-kvm-trivial-Clean-up-header-documentation.patch Patch0093: target-arm-kvm64-kvm64-cpus-have-timer-registers.patch Patch0094: target-arm-kvm-Implement-virtual-time-adjustment.patch Patch0095: target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch +Patch0096: hw-acpi-Make-ACPI-IO-address-space-configurable.patch +Patch0097: hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch +Patch0098: hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch +Patch0099: hw-arm-virt-Add-memory-hotplug-framework.patch +Patch0100: hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch +Patch0101: hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch +Patch0102: hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch +Patch0103: hw-arm-Use-GED-for-system_powerdown-event.patch +Patch0104: docs-specs-Add-ACPI-GED-documentation.patch +Patch0105: tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch +Patch0106: tests-acpi-add-empty-files.patch +Patch0107: tests-allow-empty-expected-files.patch +Patch0108: tests-Add-bios-tests-to-arm-virt.patch +Patch0109: tests-document-how-to-update-acpi-tables.patch BuildRequires: flex @@ -451,6 +465,9 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Wed Apr 22 2020 Huawei Technologies Co., Ltd. +- backport patch to enable arm/virt memory hotplug + * Wed Apr 22 2020 Huawei Technologies Co., Ltd. - backport patch to enable target/arm/kvm Adjust virtual time diff --git a/tests-Add-bios-tests-to-arm-virt.patch b/tests-Add-bios-tests-to-arm-virt.patch new file mode 100644 index 0000000..025afb5 --- /dev/null +++ b/tests-Add-bios-tests-to-arm-virt.patch @@ -0,0 +1,86 @@ +From abbcc35ccb22d81d69a28dc66b5f5d94e673a25e Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:33 +0100 +Subject: [PATCH] tests: Add bios tests to arm/virt + +This adds numamem and memhp tests for arm/virt platform. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Igor Mammedov +Message-Id: <20190918130633.4872-12-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +--- + tests/bios-tables-test.c | 49 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c +index 53a91a8067..5e177b7155 100644 +--- a/tests/bios-tables-test.c ++++ b/tests/bios-tables-test.c +@@ -874,6 +874,53 @@ static void test_acpi_piix4_tcg_dimm_pxm(void) + test_acpi_tcg_dimm_pxm(MACHINE_PC); + } + ++static void test_acpi_virt_tcg_memhp(void) ++{ ++ test_data data = { ++ .machine = "virt", ++ .accel = "tcg", ++ .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", ++ .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", ++ .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", ++ .ram_start = 0x40000000ULL, ++ .scan_len = 256ULL * 1024 * 1024, ++ }; ++ ++ data.variant = ".memhp"; ++ test_acpi_one(" -cpu cortex-a57" ++ " -m 256M,slots=3,maxmem=1G" ++ " -object memory-backend-ram,id=ram0,size=128M" ++ " -object memory-backend-ram,id=ram1,size=128M" ++ " -numa node,memdev=ram0 -numa node,memdev=ram1" ++ " -numa dist,src=0,dst=1,val=21", ++ &data); ++ ++ free_test_data(&data); ++ ++} ++ ++static void test_acpi_virt_tcg_numamem(void) ++{ ++ test_data data = { ++ .machine = "virt", ++ .accel = "tcg", ++ .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", ++ .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", ++ .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", ++ .ram_start = 0x40000000ULL, ++ .scan_len = 128ULL * 1024 * 1024, ++ }; ++ ++ data.variant = ".numamem"; ++ test_acpi_one(" -cpu cortex-a57" ++ " -object memory-backend-ram,id=ram0,size=128M" ++ " -numa node,memdev=ram0", ++ &data); ++ ++ free_test_data(&data); ++ ++} ++ + static void test_acpi_virt_tcg(void) + { + test_data data = { +@@ -920,6 +967,8 @@ int main(int argc, char *argv[]) + qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); + } 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); ++ qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp); + } + ret = g_test_run(); + boot_sector_cleanup(disk); +-- +2.19.1 diff --git a/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch b/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch new file mode 100644 index 0000000..e739883 --- /dev/null +++ b/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch @@ -0,0 +1,44 @@ +From 27e2533e43f0ab2b8a60f1902f58f8752581ea9f Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Wed, 18 Sep 2019 14:06:32 +0100 +Subject: [PATCH] tests: Update ACPI tables list for upcoming arm/virt tests + +This is in preparation to add numamem and memhp tests to +arm/virt platform. The bios-tables-test-allowed-diff.h +is updated with a list of expected ACPI tables that needs to be +present in tests/data/acpi/virt folder. + +Signed-off-by: Shameer Kolothum +Message-Id: <20190918130633.4872-11-shameerali.kolothum.thodi@huawei.com> +Acked-by: Peter Maydell +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Igor Mammedov +--- + tests/bios-tables-test-allowed-diff.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h +index 32a401ae35..3776dd2f3d 100644 +--- a/tests/bios-tables-test-allowed-diff.h ++++ b/tests/bios-tables-test-allowed-diff.h +@@ -1,4 +1,17 @@ + /* List of comma-separated changed AML files to ignore */ + "tests/data/acpi/virt/DSDT", ++"tests/data/acpi/virt/APIC.memhp", ++"tests/data/acpi/virt/APIC.numamem", + "tests/data/acpi/virt/DSDT.memhp", + "tests/data/acpi/virt/DSDT.numamem", ++"tests/data/acpi/virt/FACP.memhp", ++"tests/data/acpi/virt/FACP.numamem", ++"tests/data/acpi/virt/GTDT.memhp", ++"tests/data/acpi/virt/GTDT.numamem", ++"tests/data/acpi/virt/MCFG.memhp", ++"tests/data/acpi/virt/MCFG.numamem", ++"tests/data/acpi/virt/SLIT.memhp", ++"tests/data/acpi/virt/SPCR.memhp", ++"tests/data/acpi/virt/SPCR.numamem", ++"tests/data/acpi/virt/SRAT.memhp", ++"tests/data/acpi/virt/SRAT.numamem", +-- +2.19.1 diff --git a/tests-acpi-add-empty-files.patch b/tests-acpi-add-empty-files.patch new file mode 100644 index 0000000..46e51c0 --- /dev/null +++ b/tests-acpi-add-empty-files.patch @@ -0,0 +1,88 @@ +From c943416df54931cea8b19183fd7c4f2dbd86ec72 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Sun, 29 Sep 2019 10:54:12 -0400 +Subject: [PATCH] tests/acpi: add empty files + +Needed to make tests pass. Will replace with actual files. + +Signed-off-by: Michael S. Tsirkin +--- + tests/data/acpi/virt/APIC.memhp | 0 + tests/data/acpi/virt/APIC.numamem | 0 + tests/data/acpi/virt/DSDT.memhp | 0 + tests/data/acpi/virt/DSDT.numamem | 0 + tests/data/acpi/virt/FACP.memhp | 0 + tests/data/acpi/virt/FACP.numamem | 0 + tests/data/acpi/virt/GTDT.memhp | 0 + tests/data/acpi/virt/GTDT.numamem | 0 + tests/data/acpi/virt/MCFG.memhp | 0 + tests/data/acpi/virt/MCFG.numamem | 0 + tests/data/acpi/virt/SLIT.memhp | 0 + tests/data/acpi/virt/SPCR.memhp | 0 + tests/data/acpi/virt/SPCR.numamem | 0 + tests/data/acpi/virt/SRAT.memhp | 0 + tests/data/acpi/virt/SRAT.numamem | 0 + 15 files changed, 0 insertions(+), 0 deletions(-) + create mode 100644 tests/data/acpi/virt/APIC.memhp + create mode 100644 tests/data/acpi/virt/APIC.numamem + create mode 100644 tests/data/acpi/virt/DSDT.memhp + create mode 100644 tests/data/acpi/virt/DSDT.numamem + create mode 100644 tests/data/acpi/virt/FACP.memhp + create mode 100644 tests/data/acpi/virt/FACP.numamem + create mode 100644 tests/data/acpi/virt/GTDT.memhp + create mode 100644 tests/data/acpi/virt/GTDT.numamem + create mode 100644 tests/data/acpi/virt/MCFG.memhp + create mode 100644 tests/data/acpi/virt/MCFG.numamem + create mode 100644 tests/data/acpi/virt/SLIT.memhp + create mode 100644 tests/data/acpi/virt/SPCR.memhp + create mode 100644 tests/data/acpi/virt/SPCR.numamem + create mode 100644 tests/data/acpi/virt/SRAT.memhp + create mode 100644 tests/data/acpi/virt/SRAT.numamem + +diff --git a/tests/data/acpi/virt/APIC.memhp b/tests/data/acpi/virt/APIC.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/APIC.numamem b/tests/data/acpi/virt/APIC.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/FACP.memhp b/tests/data/acpi/virt/FACP.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/FACP.numamem b/tests/data/acpi/virt/FACP.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/GTDT.memhp b/tests/data/acpi/virt/GTDT.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/GTDT.numamem b/tests/data/acpi/virt/GTDT.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/MCFG.memhp b/tests/data/acpi/virt/MCFG.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/MCFG.numamem b/tests/data/acpi/virt/MCFG.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SLIT.memhp b/tests/data/acpi/virt/SLIT.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SPCR.memhp b/tests/data/acpi/virt/SPCR.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SPCR.numamem b/tests/data/acpi/virt/SPCR.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SRAT.memhp b/tests/data/acpi/virt/SRAT.memhp +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/tests/data/acpi/virt/SRAT.numamem b/tests/data/acpi/virt/SRAT.numamem +new file mode 100644 +index 0000000000..e69de29bb2 +-- +2.19.1 diff --git a/tests-allow-empty-expected-files.patch b/tests-allow-empty-expected-files.patch new file mode 100644 index 0000000..615fb21 --- /dev/null +++ b/tests-allow-empty-expected-files.patch @@ -0,0 +1,31 @@ +From 2ab0636e0c8fcb8b5b1b222f0d5ae7f4dfc663c5 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Sat, 5 Oct 2019 17:09:17 -0400 +Subject: [PATCH] tests: allow empty expected files + +An empty expected file is a handy way to seed the files +without creating merge conflicts. + +Signed-off-by: Michael S. Tsirkin +--- + tests/bios-tables-test.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c +index a356ac3489..53a91a8067 100644 +--- a/tests/bios-tables-test.c ++++ b/tests/bios-tables-test.c +@@ -334,7 +334,10 @@ try_again: + g_assert(ret); + g_assert_no_error(error); + g_assert(exp_sdt.aml); +- g_assert(exp_sdt.aml_len); ++ if (!exp_sdt.aml_len) { ++ fprintf(stderr, "Warning! zero length expected file '%s'\n", ++ aml_file); ++ } + + g_array_append_val(exp_tables, exp_sdt); + } +-- +2.19.1 diff --git a/tests-document-how-to-update-acpi-tables.patch b/tests-document-how-to-update-acpi-tables.patch new file mode 100644 index 0000000..c961069 --- /dev/null +++ b/tests-document-how-to-update-acpi-tables.patch @@ -0,0 +1,53 @@ +From d9642ad522d34f0d803a87654a2c258baf1070dd Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Sat, 5 Oct 2019 17:25:55 -0400 +Subject: [PATCH] tests: document how to update acpi tables + +Looks like no one understands how to do it. +Document the process. + +Signed-off-by: Michael S. Tsirkin +--- + tests/bios-tables-test.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c +index 5e177b7155..d47ee9be99 100644 +--- a/tests/bios-tables-test.c ++++ b/tests/bios-tables-test.c +@@ -10,6 +10,33 @@ + * See the COPYING file in the top-level directory. + */ + ++/* ++ * How to add or update the tests: ++ * Contributor: ++ * 1. add empty files for new tables, if any, under tests/data/acpi ++ * 2. list any changed files in tests/bios-tables-test-allowed-diff.h ++ * 3. commit the above *before* making changes that affect the tables ++ * Maintainer: ++ * After 1-3 above tests will pass but ignore differences with the expected files. ++ * You will also notice that tests/bios-tables-test-allowed-diff.h lists ++ * a bunch of files. This is your hint that you need to do the below: ++ * 4. Run ++ * make check V=1 ++ * this will produce a bunch of warnings about differences ++ * beween actual and expected ACPI tables. If you have IASL installed, ++ * they will also be disassembled so you can look at the disassembled ++ * output. If not - disassemble them yourself in any way you like. ++ * Look at the differences - make sure they make sense and match what the ++ * changes you are merging are supposed to do. ++ * ++ * 5. From build directory, run: ++ * $(SRC_PATH)/tests/data/acpi/rebuild-expected-aml.sh ++ * 6. Now commit any changes. ++ * 7. Before doing a pull request, make sure tests/bios-tables-test-allowed-diff.h ++ * is empty - this will ensure following changes to ACPI tables will ++ * be noticed. ++ */ ++ + #include "qemu/osdep.h" + #include + #include "qemu-common.h" +-- +2.19.1