Commit b097cc52 authored by Xiao Guangrong's avatar Xiao Guangrong Committed by Michael S. Tsirkin
Browse files

pc: memhp: enable nvdimm device hotplug



_GPE.E04 is dedicated for nvdimm device hotplug

Signed-off-by: default avatarXiao Guangrong <guangrong.xiao@linux.intel.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 806864d9
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -4,6 +4,9 @@ QEMU<->ACPI BIOS memory hotplug interface
ACPI BIOS GPE.3 handler is dedicated for notifying OS about memory hot-add
and hot-remove events.

ACPI BIOS GPE.4 handler is dedicated for notifying OS about nvdimm device
hot-add and hot-remove events.

Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access):
---------------------------------------------------------------
0xa00:
+23 −8
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
#include "hw/acpi/memory_hotplug.h"
#include "hw/acpi/pc-hotplug.h"
#include "hw/mem/pc-dimm.h"
#include "hw/mem/nvdimm.h"
#include "hw/boards.h"
#include "hw/qdev-core.h"
#include "trace.h"
@@ -232,11 +233,8 @@ void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
                         DeviceState *dev, Error **errp)
{
    MemStatus *mdev;
    DeviceClass *dc = DEVICE_GET_CLASS(dev);

    if (!dc->hotpluggable) {
        return;
    }
    AcpiEventStatusBits event;
    bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);

    mdev = acpi_memory_slot_status(mem_st, dev, errp);
    if (!mdev) {
@@ -244,10 +242,23 @@ void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
    }

    mdev->dimm = dev;

    /*
     * do not set is_enabled and is_inserting if the slot is plugged with
     * a nvdimm device to stop OSPM inquires memory region from the slot.
     */
    if (is_nvdimm) {
        event = ACPI_NVDIMM_HOTPLUG_STATUS;
    } else {
        mdev->is_enabled = true;
        event = ACPI_MEMORY_HOTPLUG_STATUS;
    }

    if (dev->hotplugged) {
        if (!is_nvdimm) {
            mdev->is_inserting = true;
        acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
        }
        acpi_send_event(DEVICE(hotplug_dev), event);
    }
}

@@ -262,6 +273,8 @@ void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
        return;
    }

    /* nvdimm device hot unplug is not supported yet. */
    assert(!object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM));
    mdev->is_removing = true;
    acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
}
@@ -276,6 +289,8 @@ void acpi_memory_unplug_cb(MemHotplugState *mem_st,
        return;
    }

    /* nvdimm device hot unplug is not supported yet. */
    assert(!object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM));
    mdev->is_enabled = false;
    mdev->dimm = NULL;
}
+7 −0
Original line number Diff line number Diff line
@@ -2069,6 +2069,13 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
        method = aml_method("_E03", 0, AML_NOTSERIALIZED);
        aml_append(method, aml_call0(MEMORY_HOTPLUG_HANDLER_PATH));
        aml_append(scope, method);

        if (pcms->acpi_nvdimm_state.is_enabled) {
            method = aml_method("_E04", 0, AML_NOTSERIALIZED);
            aml_append(method, aml_notify(aml_name("\\_SB.NVDR"),
                                          aml_int(0x80)));
            aml_append(scope, method);
        }
    }
    aml_append(dsdt, scope);

+12 −0
Original line number Diff line number Diff line
@@ -1744,6 +1744,12 @@ static void pc_dimm_unplug_request(HotplugHandler *hotplug_dev,
        goto out;
    }

    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
        error_setg(&local_err,
                   "nvdimm device hot unplug is not supported yet.");
        goto out;
    }

    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
    hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);

@@ -1761,6 +1767,12 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
    HotplugHandlerClass *hhc;
    Error *local_err = NULL;

    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
        error_setg(&local_err,
                   "nvdimm device hot unplug is not supported yet.");
        goto out;
    }

    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);

+0 −4
Original line number Diff line number Diff line
@@ -148,13 +148,9 @@ static MemoryRegion *nvdimm_get_vmstate_memory_region(PCDIMMDevice *dimm)

static void nvdimm_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);
    PCDIMMDeviceClass *ddc = PC_DIMM_CLASS(oc);
    NVDIMMClass *nvc = NVDIMM_CLASS(oc);

    /* nvdimm hotplug has not been supported yet. */
    dc->hotpluggable = false;

    ddc->realize = nvdimm_realize;
    ddc->get_memory_region = nvdimm_get_memory_region;
    ddc->get_vmstate_memory_region = nvdimm_get_vmstate_memory_region;
Loading