This series is an attempt to provide device memory hotplug support on ARM virt platform. This is based on Eric's recent works here[1] and carries some of the pc-dimm related patches dropped from his series. The kernel support for arm64 memory hot add was added recently by Robin and hence the guest kernel should be => 5.0-rc1. NVDIM support is not included currently as we still have an unresolved issue while hot adding NVDIMM[2]. However NVDIMM cold plug patches can be included, but not done for now, for keeping it simple. This makes use of GED device to sent hotplug ACPI events to the Guest. GED code is based on Nemu. Thanks to the efforts of Samuel and Sebastien to add the hardware-reduced support to Nemu using GED device[3]. (Please shout if I got the author/signed-off wrong for those patches or missed any names). This is sanity tested on a HiSilicon ARM64 platform and appreciate any further testing. Note: Attempted adding dimm_pxm test case to bios-tables-test for arm/virt. But noticed the issue decribed here[5]. This is under investigation now. upstream url: https://patchwork.kernel.org/cover/11150345/ Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
168 lines
6.2 KiB
Diff
168 lines
6.2 KiB
Diff
From 0b77f242b180f1ae40b9752999cef4894113df8e Mon Sep 17 00:00:00 2001
|
|
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
|
|
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 <shameerali.kolothum.thodi@huawei.com>
|
|
Reviewed-by: Eric Auger <eric.auger@redhat.com>
|
|
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
|
|
Message-Id: <20190918130633.4872-9-shameerali.kolothum.thodi@huawei.com>
|
|
Acked-by: Peter Maydell <peter.maydell@linaro.org>
|
|
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
|
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
|
---
|
|
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
|