diff options
Diffstat (limited to 'hw/ppc/spapr.c')
-rw-r--r-- | hw/ppc/spapr.c | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 2375cbee12..f59999daac 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3136,7 +3136,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, } static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - uint32_t node, Error **errp) + Error **errp) { Error *local_err = NULL; sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); @@ -3144,6 +3144,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); MemoryRegion *mr; uint64_t align, size, addr; + uint32_t node; mr = ddc->get_memory_region(dimm, &local_err); if (local_err) { @@ -3163,6 +3164,8 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, goto out_unplug; } + node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP, + &error_abort); spapr_add_lmbs(dev, addr, size, node, spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), &local_err); @@ -3181,12 +3184,18 @@ out: static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + const sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev); PCDIMMDevice *dimm = PC_DIMM(dev); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); MemoryRegion *mr; uint64_t size; char *mem_dev; + if (!smc->dr_lmb_enabled) { + error_setg(errp, "Memory hotplug not supported for this machine"); + return; + } + mr = ddc->get_memory_region(dimm, errp); if (!mr) { return; @@ -3290,7 +3299,8 @@ static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms, /* Callback to be called during DRC release. */ void spapr_lmb_release(DeviceState *dev) { - sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_hotplug_handler(dev)); + HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); + sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl); sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); /* This information will get lost if a migration occurs @@ -3308,9 +3318,17 @@ void spapr_lmb_release(DeviceState *dev) /* * Now that all the LMBs have been removed by the guest, call the - * pc-dimm unplug handler to cleanup up the pc-dimm device. + * unplug handler chain. This can never fail. */ - pc_dimm_memory_unplug(dev, MACHINE(spapr)); + hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); +} + +static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) +{ + sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev); + sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev)); + + pc_dimm_memory_unplug(dev, MACHINE(hotplug_dev)); object_unparent(OBJECT(dev)); spapr_pending_dimm_unplugs_remove(spapr, ds); } @@ -3398,7 +3416,15 @@ static void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, /* Callback to be called during DRC release. */ void spapr_core_release(DeviceState *dev) { - MachineState *ms = MACHINE(qdev_get_hotplug_handler(dev)); + HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); + + /* Call the unplug handler chain. This can never fail. */ + hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); +} + +static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) +{ + MachineState *ms = MACHINE(hotplug_dev); sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); CPUCore *cc = CPU_CORE(dev); CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); @@ -3568,31 +3594,23 @@ out: static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - MachineState *ms = MACHINE(hotplug_dev); - sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms); - if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { - int node; - - if (!smc->dr_lmb_enabled) { - error_setg(errp, "Memory hotplug not supported for this machine"); - return; - } - node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP, errp); - if (*errp) { - return; - } - if (node < 0 || node >= MAX_NODES) { - error_setg(errp, "Invaild node %d", node); - return; - } - - spapr_memory_plug(hotplug_dev, dev, node, errp); + spapr_memory_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { spapr_core_plug(hotplug_dev, dev, errp); } } +static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + spapr_memory_unplug(hotplug_dev, dev); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { + spapr_core_unplug(hotplug_dev, dev); + } +} + static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -3987,6 +4005,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->get_default_cpu_node_id = spapr_get_default_cpu_node_id; mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; hc->unplug_request = spapr_machine_device_unplug_request; + hc->unplug = spapr_machine_device_unplug; smc->dr_lmb_enabled = true; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); |