mirror of https://github.com/xemu-project/xemu.git
hw/arm/virt: Add nvdimm hotplug support
This adds support for nvdimm hotplug events through GED and enables nvdimm for the arm/virt. Now Guests with ACPI can have both cold and hot plug of nvdimms. Hot removal functionality is not yet supported. Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Message-Id: <20200421125934.14952-5-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell <peter.maydell@linaro.org> Tested-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
b5a60bee74
commit
c2505d1c56
|
@ -63,7 +63,8 @@ GED IO interface (4 byte access)
|
||||||
bits:
|
bits:
|
||||||
0: Memory hotplug event
|
0: Memory hotplug event
|
||||||
1: System power down event
|
1: System power down event
|
||||||
2-31: Reserved
|
2: NVDIMM hotplug event
|
||||||
|
3-31: Reserved
|
||||||
|
|
||||||
**write_access:**
|
**write_access:**
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "hw/acpi/generic_event_device.h"
|
#include "hw/acpi/generic_event_device.h"
|
||||||
#include "hw/irq.h"
|
#include "hw/irq.h"
|
||||||
#include "hw/mem/pc-dimm.h"
|
#include "hw/mem/pc-dimm.h"
|
||||||
|
#include "hw/mem/nvdimm.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
static const uint32_t ged_supported_events[] = {
|
static const uint32_t ged_supported_events[] = {
|
||||||
ACPI_GED_MEM_HOTPLUG_EVT,
|
ACPI_GED_MEM_HOTPLUG_EVT,
|
||||||
ACPI_GED_PWR_DOWN_EVT,
|
ACPI_GED_PWR_DOWN_EVT,
|
||||||
|
ACPI_GED_NVDIMM_HOTPLUG_EVT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -110,6 +112,11 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev,
|
||||||
aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
|
aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
|
||||||
aml_int(0x80)));
|
aml_int(0x80)));
|
||||||
break;
|
break;
|
||||||
|
case ACPI_GED_NVDIMM_HOTPLUG_EVT:
|
||||||
|
aml_append(if_ctx,
|
||||||
|
aml_notify(aml_name("\\_SB.NVDR"),
|
||||||
|
aml_int(0x80)));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
* Please make sure all the events in ged_supported_events[]
|
* Please make sure all the events in ged_supported_events[]
|
||||||
|
@ -175,7 +182,11 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
|
||||||
AcpiGedState *s = ACPI_GED(hotplug_dev);
|
AcpiGedState *s = ACPI_GED(hotplug_dev);
|
||||||
|
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||||
acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp);
|
if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
|
||||||
|
nvdimm_acpi_plug_cb(hotplug_dev, dev);
|
||||||
|
} else {
|
||||||
|
acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "virt: device plug request for unsupported device"
|
error_setg(errp, "virt: device plug request for unsupported device"
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
" type: %s", object_get_typename(OBJECT(dev)));
|
||||||
|
@ -192,6 +203,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
||||||
sel = ACPI_GED_MEM_HOTPLUG_EVT;
|
sel = ACPI_GED_MEM_HOTPLUG_EVT;
|
||||||
} else if (ev & ACPI_POWER_DOWN_STATUS) {
|
} else if (ev & ACPI_POWER_DOWN_STATUS) {
|
||||||
sel = ACPI_GED_PWR_DOWN_EVT;
|
sel = ACPI_GED_PWR_DOWN_EVT;
|
||||||
|
} else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) {
|
||||||
|
sel = ACPI_GED_NVDIMM_HOTPLUG_EVT;
|
||||||
} else {
|
} else {
|
||||||
/* Unknown event. Return without generating interrupt. */
|
/* Unknown event. Return without generating interrupt. */
|
||||||
warn_report("GED: Unsupported event %d. No irq injected", ev);
|
warn_report("GED: Unsupported event %d. No irq injected", ev);
|
||||||
|
|
|
@ -568,6 +568,10 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
|
||||||
event |= ACPI_GED_MEM_HOTPLUG_EVT;
|
event |= ACPI_GED_MEM_HOTPLUG_EVT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ms->nvdimms_state->is_enabled) {
|
||||||
|
event |= ACPI_GED_NVDIMM_HOTPLUG_EVT;
|
||||||
|
}
|
||||||
|
|
||||||
dev = qdev_create(NULL, TYPE_ACPI_GED);
|
dev = qdev_create(NULL, TYPE_ACPI_GED);
|
||||||
qdev_prop_set_uint32(dev, "ged-event", event);
|
qdev_prop_set_uint32(dev, "ged-event", event);
|
||||||
|
|
||||||
|
@ -2088,19 +2092,20 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
||||||
|
const MachineState *ms = MACHINE(hotplug_dev);
|
||||||
const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
|
const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
|
||||||
|
|
||||||
if (is_nvdimm) {
|
|
||||||
error_setg(errp, "nvdimm is not yet supported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vms->acpi_dev) {
|
if (!vms->acpi_dev) {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"memory hotplug is not enabled: missing acpi-ged device");
|
"memory hotplug is not enabled: missing acpi-ged device");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_nvdimm && !ms->nvdimms_state->is_enabled) {
|
||||||
|
error_setg(errp, "nvdimm is not enabled: add 'nvdimm=on' to '-M'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), NULL, errp);
|
pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), NULL, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2245,6 +2250,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||||
hc->plug = virt_machine_device_plug_cb;
|
hc->plug = virt_machine_device_plug_cb;
|
||||||
hc->unplug_request = virt_machine_device_unplug_request_cb;
|
hc->unplug_request = virt_machine_device_unplug_request_cb;
|
||||||
mc->numa_mem_supported = true;
|
mc->numa_mem_supported = true;
|
||||||
|
mc->nvdimm_supported = true;
|
||||||
mc->auto_enable_numa_with_memhp = true;
|
mc->auto_enable_numa_with_memhp = true;
|
||||||
mc->default_ram_id = "mach-virt.ram";
|
mc->default_ram_id = "mach-virt.ram";
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
*/
|
*/
|
||||||
#define ACPI_GED_MEM_HOTPLUG_EVT 0x1
|
#define ACPI_GED_MEM_HOTPLUG_EVT 0x1
|
||||||
#define ACPI_GED_PWR_DOWN_EVT 0x2
|
#define ACPI_GED_PWR_DOWN_EVT 0x2
|
||||||
|
#define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4
|
||||||
|
|
||||||
typedef struct GEDState {
|
typedef struct GEDState {
|
||||||
MemoryRegion io;
|
MemoryRegion io;
|
||||||
|
|
Loading…
Reference in New Issue