@@ -360,6 +360,14 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
1, "GPO0", NULL, 0));
}
+ if (vms->acpi_nvdimm_state.is_enabled) {
+ /* GPIO Interrupt connection descriptor for NVDIMM hotplug */
+ pin_list[0] = GPIO_NVDIMM;
+ aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
+ AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list,
+ 1, "GPO0", NULL, 0));
+ }
+
aml_append(dev, aml_name_decl("_AEI", aei));
/* _E03 is handle for power button */
@@ -367,6 +375,15 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
aml_int(0x80)));
aml_append(dev, method);
+
+ if (vms->acpi_nvdimm_state.is_enabled) {
+ /* _E04 is for nvdimm hotplug*/
+ method = aml_method("_E04", 0, AML_NOTSERIALIZED);
+ aml_append(method, aml_notify(aml_name("\\_SB.NVDR"),
+ aml_int(0x80)));
+ aml_append(dev, method);
+ }
+
aml_append(scope, dev);
}
@@ -809,6 +809,11 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
if (vms->acpi_memhp_state.is_enabled) {
virt_create_gpio_dev(pl061_dev, GPIO_PCDIMM);
}
+
+ if (vms->acpi_nvdimm_state.is_enabled) {
+ virt_create_gpio_dev(pl061_dev, GPIO_NVDIMM);
+ }
+
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
@@ -1885,10 +1890,6 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
- if (dev->hotplugged && is_nvdimm) {
- error_setg(errp, "nvdimm hotplug is not supported");
- }
-
if (is_nvdimm && !vms->acpi_nvdimm_state.is_enabled) {
error_setg(errp, "nvdimm is not enabled: missing 'nvdimm' in '-M'");
return;
@@ -1898,19 +1899,25 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
}
static void virt_memhp_send_event(HotplugHandler *hotplug_dev, DeviceState *dev,
- Error **errp)
+ bool is_nvdimm, Error **errp)
{
DeviceState *gpio_dev;
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
- gpio_dev = virt_get_gpio_dev(GPIO_PCDIMM);
+ gpio_dev = (is_nvdimm) ? virt_get_gpio_dev(GPIO_NVDIMM) :
+ virt_get_gpio_dev(GPIO_PCDIMM);
if (!gpio_dev) {
error_setg(errp, "No dev interface to send hotplug event");
return;
}
- acpi_memory_plug_cb(hotplug_dev, &vms->acpi_memhp_state,
- dev, errp);
- qemu_set_irq(qdev_get_gpio_in(gpio_dev, 0), 1);
+
+ if (is_nvdimm) {
+ qemu_set_irq(qdev_get_gpio_in(gpio_dev, 0), 1);
+ } else {
+ acpi_memory_plug_cb(hotplug_dev, &vms->acpi_memhp_state,
+ dev, errp);
+ qemu_set_irq(qdev_get_gpio_in(gpio_dev, 0), 1);
+ }
}
static void virt_memory_plug(HotplugHandler *hotplug_dev,
@@ -1929,8 +1936,8 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
nvdimm_plug(&vms->acpi_nvdimm_state);
}
- if (dev->hotplugged && !is_nvdimm) {
- virt_memhp_send_event(hotplug_dev, dev, errp);
+ if (dev->hotplugged) {
+ virt_memhp_send_event(hotplug_dev, dev, is_nvdimm, errp);
}
out:
@@ -144,6 +144,7 @@ typedef struct {
enum {
GPIO_PCDIMM = 2,
GPIO_PWRB,
+ GPIO_NVDIMM,
};
typedef struct GPIODevice {
nvdimm hotplug is enabled using GPIO(Pin 4) based ACPI event. Hot removal functionality is not yet supported. Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> --- hw/arm/virt-acpi-build.c | 17 +++++++++++++++++ hw/arm/virt.c | 29 ++++++++++++++++++----------- include/hw/arm/virt.h | 1 + 3 files changed, 36 insertions(+), 11 deletions(-)