On Tue, Jan 12, 2016 at 05:06:34PM +1100, David Gibson wrote:
> On Fri, Jan 08, 2016 at 12:25:19PM +0530, Bharata B Rao wrote:
> > Remove the CPU core device by removing the underlying CPU thread devices.
> > Support hot removal of CPU for sPAPR guests by sending the hot unplug
> > notification to the guest via EPOW interrupt. Release the vCPU object
> > after CPU hot unplug so that vCPU fd can be parked and reused.
> > 
> > Signed-off-by: Bharata B Rao <bhar...@linux.vnet.ibm.com>
> > ---
> >  hw/ppc/spapr.c         | 113 
> > +++++++++++++++++++++++++++++++++++++++++++++++++
> >  include/hw/ppc/spapr.h |   6 +++
> >  2 files changed, 119 insertions(+)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index c2af9ca..43cb726 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -93,6 +93,9 @@
> >  
> >  #define HTAB_SIZE(spapr)        (1ULL << ((spapr)->htab_shift))
> >  
> > +static QLIST_HEAD(cpu_unplug_list, sPAPRCPUUnplug) cpu_unplug_list
> > +                  = QLIST_HEAD_INITIALIZER(cpu_unplug_list);
> > +
> >  static XICSState *try_create_xics(const char *type, int nr_servers,
> >                                    int nr_irqs, Error **errp)
> >  {
> > @@ -2432,11 +2435,121 @@ static void 
> > spapr_machine_device_plug(HotplugHandler *hotplug_dev,
> >      }
> >  }
> >  
> > +static void spapr_cpu_destroy(PowerPCCPU *cpu)
> > +{
> > +    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
> > +
> > +    xics_cpu_destroy(spapr->icp, cpu);
> > +    qemu_unregister_reset(spapr_cpu_reset, cpu);
> > +}
> > +
> > +static void spapr_cpu_core_cleanup(void)
> > +{
> > +    sPAPRCPUUnplug *unplug, *next;
> > +    Object *cpu;
> > +
> > +    QLIST_FOREACH_SAFE(unplug, &cpu_unplug_list, node, next) {
> > +        cpu = unplug->cpu;
> > +        object_unparent(cpu);
> > +        QLIST_REMOVE(unplug, node);
> > +        g_free(unplug);
> > +    }
> > +}
> > +
> > +static void spapr_add_cpu_to_unplug_list(Object *cpu)
> > +{
> > +    sPAPRCPUUnplug *unplug = g_malloc(sizeof(*unplug));
> > +
> > +    unplug->cpu = cpu;
> > +    QLIST_INSERT_HEAD(&cpu_unplug_list, unplug, node);
> > +}
> > +
> > +static int spapr_cpu_release(Object *obj, void *opaque)
> > +{
> > +    DeviceState *dev = DEVICE(obj);
> > +    CPUState *cs = CPU(dev);
> > +    PowerPCCPU *cpu = POWERPC_CPU(cs);
> > +
> > +    spapr_cpu_destroy(cpu);
> > +    cpu_remove_sync(cs);
> > +
> > +    /*
> > +     * We are still walking the core object's children list, and
> > +     * hence can't cleanup this CPU thread object just yet. Put
> > +     * it on a list for later removal.
> > +     */
> > +    spapr_add_cpu_to_unplug_list(obj);
> > +    return 0;
> > +}
> > +
> > +static void spapr_core_release(DeviceState *dev, void *opaque)
> > +{
> > +    object_child_foreach(OBJECT(dev), spapr_cpu_release, opaque);
> > +    spapr_cpu_core_cleanup();
> > +    object_unparent(OBJECT(dev));
> 
> I'd prefer to see the unplug_list as a local to this function (passed
> to spapr_cpu_release via opaque) rather than using a new global.

Will try that in the next iteration.

> 
> > +}
> > +
> > +static int spapr_core_detach(Object *obj, void *opaque)
> > +{
> > +    sPAPRCoreState *core = opaque;
> > +    DeviceState *dev = DEVICE(obj);
> > +    CPUState *cs = CPU(dev);
> > +    PowerPCCPU *cpu = POWERPC_CPU(cs);
> > +    int id = ppc_get_vcpu_dt_id(cpu);
> > +    int smt = kvmppc_smt_threads();
> > +    sPAPRDRConnector *drc =
> > +        spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, id);
> > +    sPAPRDRConnectorClass *drck;
> > +    Error *local_err = NULL;
> > +
> > +    /*
> > +     * SMT threads return from here, only main thread (thread 0) will
> > +     * continue and signal hot unplug event to the guest.
> > +     */
> 
> This seems silly.  spapr_core_unplug() iterates through all the
> children only to have all of them except thread 0 ignore the call..
> 
> Can't you just grab the first thread and do this logic directly from
> spapr_core_unplug()?

If I purely rely on the children list of the core object like I am doing
here, I don't see how to grab the first thread object from the list w/o
doing what I am doing here. However I can store the first thread object
in the core object during the core object's instance_init and use it here.
Will give it a try in the next iteration.

Regards,
Bharata.


Reply via email to