qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 11/11] spapr: Memory hot-unplug support


From: Bharata B Rao
Subject: Re: [Qemu-devel] [PATCH 11/11] spapr: Memory hot-unplug support
Date: Fri, 14 Oct 2016 12:35:39 +0530
User-agent: Mutt/1.6.1 (2016-04-27)

On Wed, Oct 12, 2016 at 06:13:59PM -0500, Michael Roth wrote:
> From: Bharata B Rao <address@hidden>
> 
> Add support to hot remove pc-dimm memory devices.
> 
> Signed-off-by: Bharata B Rao <address@hidden>
> * add hooks to CAS/cmdline enablement of hotplug ACR support
> Signed-off-by: Michael Roth <address@hidden>
> ---
>  hw/ppc/spapr.c     | 106 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  hw/ppc/spapr_drc.c |  17 +++++++++
>  2 files changed, 122 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 9af4268..180fa3d 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -2310,6 +2310,90 @@ out:
>      error_propagate(errp, local_err);
>  }
> 
> +typedef struct sPAPRDIMMState {
> +    uint32_t nr_lmbs;
> +} sPAPRDIMMState;
> +
> +static void spapr_lmb_release(DeviceState *dev, void *opaque)
> +{
> +    sPAPRDIMMState *ds = (sPAPRDIMMState *)opaque;
> +    HotplugHandler *hotplug_ctrl = NULL;
> +
> +    if (--ds->nr_lmbs) {
> +        return;
> +    }
> +
> +    g_free(ds);
> +
> +    /*
> +     * Now that all the LMBs have been removed by the guest, call the
> +     * pc-dimm unplug handler to cleanup up the pc-dimm device.
> +     */
> +    hotplug_ctrl = qdev_get_hotplug_handler(dev);
> +    hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
> +}
> +
> +static void spapr_del_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t 
> size,
> +                           Error **errp)
> +{
> +    sPAPRDRConnector *drc;
> +    sPAPRDRConnectorClass *drck;
> +    uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
> +    int i;
> +    sPAPRDIMMState *ds = g_malloc0(sizeof(sPAPRDIMMState));
> +    uint64_t addr = addr_start;
> +
> +    ds->nr_lmbs = nr_lmbs;
> +    for (i = 0; i < nr_lmbs; i++) {
> +        drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
> +                addr / SPAPR_MEMORY_BLOCK_SIZE);
> +        g_assert(drc);
> +
> +        drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> +        drck->detach(drc, dev, spapr_lmb_release, ds, errp);
> +        addr += SPAPR_MEMORY_BLOCK_SIZE;
> +    }
> +
> +    drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
> +                                   addr_start / SPAPR_MEMORY_BLOCK_SIZE);
> +    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> +    spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
> +                                              nr_lmbs,
> +                                              drck->get_index(drc));
> +}
> +
> +static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState 
> *dev,
> +                                Error **errp)
> +{
> +    sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
> +    PCDIMMDevice *dimm = PC_DIMM(dev);
> +    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
> +    MemoryRegion *mr = ddc->get_memory_region(dimm);
> +
> +    pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
> +    object_unparent(OBJECT(dev));
> +}
> +
> +static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
> +                                        DeviceState *dev, Error **errp)
> +{
> +    Error *local_err = NULL;
> +    PCDIMMDevice *dimm = PC_DIMM(dev);
> +    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
> +    MemoryRegion *mr = ddc->get_memory_region(dimm);
> +    uint64_t size = memory_region_size(mr);
> +    uint64_t addr;
> +
> +    addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, 
> &local_err);
> +    if (local_err) {
> +        goto out;
> +    }
> +
> +    spapr_del_lmbs(dev, addr, size, &error_abort);
> +out:
> +    error_propagate(errp, local_err);
> +}
> +
>  void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset,
>                                      sPAPRMachineState *spapr)
>  {
> @@ -2383,10 +2467,21 @@ static void spapr_machine_device_plug(HotplugHandler 
> *hotplug_dev,
>  static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
>                                        DeviceState *dev, Error **errp)
>  {
> +    sPAPRMachineState *sms = SPAPR_MACHINE(qdev_get_machine());
>      MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
> 
>      if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
> -        error_setg(errp, "Memory hot unplug not supported by sPAPR");
> +        if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
> +            spapr_memory_unplug(hotplug_dev, dev, errp);
> +        } else {
> +            /* NOTE: this means there is a window after guest reset, prior to
> +             * CAS negotiation, where unplug requests will fail due to the
> +             * capability not being detected yet. This is a bit different 
> than
> +             * the case with PCI unplug, where the events will be queued and
> +             * eventually handled by the guest after boot
> +             */
> +            error_setg(errp, "Memory hot unplug not supported for this 
> guest");
> +        }
>      } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
>          if (!mc->query_hotpluggable_cpus) {
>              error_setg(errp, "CPU hot unplug not supported on this machine");
> @@ -2396,6 +2491,14 @@ static void spapr_machine_device_unplug(HotplugHandler 
> *hotplug_dev,
>      }
>  }
> 
> +static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
> +                                                DeviceState *dev, Error 
> **errp)
> +{
> +    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
> +        spapr_memory_unplug_request(hotplug_dev, dev, errp);
> +    }
> +}
> +
>  static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev,
>                                            DeviceState *dev, Error **errp)
>  {
> @@ -2482,6 +2585,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
> void *data)
>      hc->plug = spapr_machine_device_plug;
>      hc->unplug = spapr_machine_device_unplug;
>      mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id;
> +    hc->unplug_request = spapr_machine_device_unplug_request;

After this, spapr_core_unplug() call needs to be moved to
->unplug_request() as ->unplug() won't be called if ->unplug_request()
is present.

However I am not able to get CPU hotplug working with your patchset.
Looks like RTAS event is getting missed or not getting generated. Will
get back after further debugging.

Regards,
Bharata.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]