diff mbox

[PULL,016/103] pc: add memory hotplug handler to PC_MACHINE

Message ID 1403021756-15960-17-git-send-email-mst@redhat.com
State New
Headers show

Commit Message

Michael S. Tsirkin June 17, 2014, 5:37 p.m. UTC
From: Igor Mammedov <imammedo@redhat.com>

that will perform mapping of PC_DIMM device into guest's RAM address space

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 include/hw/i386/pc.h |  8 +++++++
 hw/i386/pc.c         | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)
diff mbox

Patch

diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 501d9a0..c3ed858 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -31,9 +31,17 @@  struct PCMachineState {
     MemoryRegion hotplug_memory;
 };
 
+/**
+ * PCMachineClass:
+ * @get_hotplug_handler: pointer to parent class callback @get_hotplug_handler
+ */
 struct PCMachineClass {
     /*< private >*/
     MachineClass parent_class;
+
+    /*< public >*/
+    HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
+                                           DeviceState *dev);
 };
 
 typedef struct PCMachineState PCMachineState;
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index de5f259..e3b81db 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -58,6 +58,7 @@ 
 #include "hw/boards.h"
 #include "hw/pci/pci_host.h"
 #include "acpi-build.h"
+#include "hw/mem/pc-dimm.h"
 
 /* debug PC/ISA interrupts */
 //#define DEBUG_IRQ
@@ -1547,12 +1548,70 @@  void qemu_register_pc_machine(QEMUMachine *m)
     g_free(name);
 }
 
+static void pc_dimm_plug(HotplugHandler *hotplug_dev,
+                         DeviceState *dev, Error **errp)
+{
+    Error *local_err = NULL;
+    PCMachineState *pcms = PC_MACHINE(hotplug_dev);
+    PCDIMMDevice *dimm = PC_DIMM(dev);
+    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
+    MemoryRegion *mr = ddc->get_memory_region(dimm);
+    uint64_t addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP,
+                                            &local_err);
+    if (local_err) {
+        goto out;
+    }
+
+    memory_region_add_subregion(&pcms->hotplug_memory,
+                                addr - pcms->hotplug_memory_base, mr);
+    vmstate_register_ram(mr, dev);
+out:
+    error_propagate(errp, local_err);
+}
+
+static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
+                                      DeviceState *dev, Error **errp)
+{
+    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        pc_dimm_plug(hotplug_dev, dev, errp);
+    }
+}
+
+static HotplugHandler *pc_get_hotpug_handler(MachineState *machine,
+                                             DeviceState *dev)
+{
+    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine);
+
+    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        return HOTPLUG_HANDLER(machine);
+    }
+
+    return pcmc->get_hotplug_handler ?
+        pcmc->get_hotplug_handler(machine, dev) : NULL;
+}
+
+static void pc_machine_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+    PCMachineClass *pcmc = PC_MACHINE_CLASS(oc);
+    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
+
+    pcmc->get_hotplug_handler = mc->get_hotplug_handler;
+    mc->get_hotplug_handler = pc_get_hotpug_handler;
+    hc->plug = pc_machine_device_plug_cb;
+}
+
 static const TypeInfo pc_machine_info = {
     .name = TYPE_PC_MACHINE,
     .parent = TYPE_MACHINE,
     .abstract = true,
     .instance_size = sizeof(PCMachineState),
     .class_size = sizeof(PCMachineClass),
+    .class_init = pc_machine_class_init,
+    .interfaces = (InterfaceInfo[]) {
+         { TYPE_HOTPLUG_HANDLER },
+         { }
+    },
 };
 
 static void pc_machine_register_types(void)