diff mbox

[for-2.7,v3,07/15] spapr: Abstract CPU core device and type specific core devices

Message ID 20160608094241.GB8861@in.ibm.com
State New
Headers show

Commit Message

Bharata B Rao June 8, 2016, 9:42 a.m. UTC
On Fri, Jun 03, 2016 at 03:25:08PM +1000, David Gibson wrote:
> On Thu, May 12, 2016 at 09:18:17AM +0530, Bharata B Rao wrote:
> > Add sPAPR specific abastract CPU core device that is based on generic
> > CPU core device. Use this as base type to create sPAPR CPU specific core
> > devices.
> > 
> > TODO:
> > - Add core types for other remaining CPU types
> > - Handle CPU model alias correctly
> > 
> > Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
> 
> This is looking pretty cood, but there's some minor changes I'd like
> to see.
> 
> > ---
> >  hw/ppc/Makefile.objs            |   1 +
> >  hw/ppc/spapr.c                  |   3 +-
> >  hw/ppc/spapr_cpu_core.c         | 168 ++++++++++++++++++++++++++++++++++++++++
> >  include/hw/ppc/spapr.h          |   1 +
> >  include/hw/ppc/spapr_cpu_core.h |  28 +++++++
> >  5 files changed, 199 insertions(+), 2 deletions(-)
> >  create mode 100644 hw/ppc/spapr_cpu_core.c
> >  create mode 100644 include/hw/ppc/spapr_cpu_core.h
> > 
> > diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> > index c1ffc77..5cc6608 100644
> > --- a/hw/ppc/Makefile.objs
> > +++ b/hw/ppc/Makefile.objs
> > @@ -4,6 +4,7 @@ obj-y += ppc.o ppc_booke.o
> >  obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
> >  obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
> >  obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
> > +obj-$(CONFIG_PSERIES) += spapr_cpu_core.o
> >  ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
> >  obj-y += spapr_pci_vfio.o
> >  endif
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index b69995e..95db047 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -1605,8 +1605,7 @@ static void spapr_boot_set(void *opaque, const char *boot_device,
> >      machine->boot_order = g_strdup(boot_device);
> >  }
> >  
> > -static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
> > -                           Error **errp)
> > +void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp)
> 
> I think this function should actually move into spapr_cpu_core.c

Actually, this is a CPU thread specific routine and will be called from
spapr.c too. But I moved this to spapr_cpu_core.c as you suggest.

> 
> >  {
> >      CPUPPCState *env = &cpu->env;
> >  
> > diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
> > new file mode 100644
> > index 0000000..af63ed9
> > --- /dev/null
> > +++ b/hw/ppc/spapr_cpu_core.c
> > @@ -0,0 +1,168 @@
> > +/*
> > + * sPAPR CPU core device, acts as container of CPU thread devices.
> > + *
> > + * Copyright (C) 2016 Bharata B Rao <bharata@linux.vnet.ibm.com>
> > + *
> > + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> > + * See the COPYING file in the top-level directory.
> > + */
> > +#include "hw/cpu/core.h"
> > +#include "hw/ppc/spapr_cpu_core.h"
> > +#include "hw/ppc/spapr.h"
> > +#include "hw/boards.h"
> > +#include "qapi/error.h"
> > +#include <sysemu/cpus.h>
> > +#include "target-ppc/kvm_ppc.h"
> > +
> > +static void spapr_cpu_core_create_threads(DeviceState *dev, int threads,
> > +                                          Error **errp)
> 
> This function could be folded into spapr_cpu_core_realize(), that's
> the only caller and they're both fairly short.

Ok done.

> 
> > +{
> > +    int i;
> > +    Error *local_err = NULL;
> > +    sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
> > +
> > +    for (i = 0; i < threads; i++) {
> > +        char id[32];
> > +
> > +        object_initialize(&core->threads[i], sizeof(core->threads[i]),
> > +                          object_class_get_name(core->cpu));
> 
> Given we have to go from the class pointer to the class name to
> actually use it here, maybe we would be better off storing the name
> rather than a class pointer.  Up to you, I'm happy either way.

I was doing typename initially and there were suggestions to move to
ObjectClass. May be I will leave it like this while I fix all the other
things and finally revisit this ?

> 
> > +        snprintf(id, sizeof(id), "thread[%d]", i);
> > +        object_property_add_child(OBJECT(core), id, OBJECT(&core->threads[i]),
> > +                                  &local_err);
> > +        if (local_err) {
> > +            goto err;
> > +        }
> > +    }
> > +    return;
> > +
> > +err:
> > +    while (--i) {
> > +        object_unparent(OBJECT(&core->threads[i]));
> 
> Is this safe if some of the threads haven't been initialized?

This is in the error path and only those threads which have been
initialized will be unparented.

> 
> > +    }
> > +    error_propagate(errp, local_err);
> > +}
> > +
> > +static int spapr_cpu_core_realize_child(Object *child, void *opaque)
> > +{
> > +    Error **errp = opaque;
> > +    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
> > +    CPUState *cs = CPU(child);
> > +    PowerPCCPU *cpu = POWERPC_CPU(cs);
> > +
> > +    object_property_set_bool(child, true, "realized", errp);
> > +    if (*errp) {
> > +        return 1;
> > +    }
> > +
> > +    spapr_cpu_init(spapr, cpu, errp);
> > +    if (*errp) {
> > +        return 1;
> > +    }
> > +    return 0;
> > +}
> > +
> > +static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
> > +{
> > +    sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
> > +    CPUCore *cc = CPU_CORE(OBJECT(dev));
> > +    Error *local_err = NULL;
> > +
> > +    sc->threads = g_new0(PowerPCCPU, cc->threads);
> 
> This isn't quite safe, because it assume the structure size for all
> the threads is that of PowerPCCPU.  That's true now, but cpu thread
> subtypes could in theory extend that structure with subtype specific
> fields.  I think we need to actually look up the class instance size
> here.

I couldn't find a way to obtain the instance_size of a type. I had to
introduce a QOM API like this:

sc->threads as PowerPCCPU pointer.

> 
> > +    spapr_cpu_core_create_threads(dev, cc->threads, &local_err);
> > +    if (local_err) {
> > +        goto out;
> > +    }
> > +    object_child_foreach(OBJECT(dev), spapr_cpu_core_realize_child, &local_err);
> > +
> > +out:
> > +    if (local_err) {
> > +        g_free(sc->threads);
> > +        error_propagate(errp, local_err);
> > +    }
> > +}
> > +
> > +static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(oc);
> > +    dc->realize = spapr_cpu_core_realize;
> > +}
> > +
> > +/*
> > + * instance_init routines from different flavours of sPAPR CPU cores.
> > + * TODO: Add support for 'host' core type.
> > + */
> > +#define SPAPR_CPU_CORE_INITFN(_type, _fname) \
> > +static void glue(glue(spapr_cpu_core_, _fname), _initfn(Object *obj)) \
> > +{ \
> > +    sPAPRCPUCore *core = SPAPR_CPU_CORE(obj); \
> > +    char *name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, stringify(_type)); \
> > +    ObjectClass *oc = object_class_by_name(name); \
> > +    g_assert(oc); \
> > +    g_free((void *)name); \
> > +    core->cpu = oc; \
> 
> This all looks like stuff which could be done at class_init time, but
> this is an instance_init function.

Essentially what we do here is to store the CPU thread ObjectClass within the
abstract sPAPRCPUCore object so that we can initialize the CPU threads
of right type from abstract sPAPRCPUCore object's realize routine. I am not
sure if core object is available in class_init routine to achieve this.

> 
> I'm also wondering if it might just be simpler to store _type in the
> subclass and do this in the base class.

Not sure if I really understand this suggestion correctly.

However, if you see, I am not yet defining a separate structures for the
subtypes of sPAPRCPUCore where _type can be stored, but instead using
sPAPRCPUCore as the instance_size for sub core types too.

> 
> > +}
> > +
> > +SPAPR_CPU_CORE_INITFN(POWER7_v2.3, POWER7);
> > +SPAPR_CPU_CORE_INITFN(POWER7+_v2.1, POWER7plus);
> > +SPAPR_CPU_CORE_INITFN(POWER8_v2.0, POWER8);
> > +SPAPR_CPU_CORE_INITFN(POWER8E_v2.1, POWER8E);
> > +
> > +typedef struct SPAPRCoreInfo {
> > +    const char *name;
> > +    void (*initfn)(Object *obj);
> > +} SPAPRCoreInfo;
> > +
> > +static const SPAPRCoreInfo spapr_cores[] = {
> > +    /* POWER7 and aliases */
> > +    { .name = "POWER7_v2.3", .initfn = spapr_cpu_core_POWER7_initfn },
> > +    { .name = "POWER7", .initfn = spapr_cpu_core_POWER7_initfn },
> > +
> > +    /* POWER7+ and aliases */
> > +    { .name = "POWER7+_v2.1", .initfn = spapr_cpu_core_POWER7plus_initfn },
> > +    { .name = "POWER7+", .initfn = spapr_cpu_core_POWER7plus_initfn },
> > +
> > +    /* POWER8 and aliases */
> > +    { .name = "POWER8_v2.0", .initfn = spapr_cpu_core_POWER8_initfn },
> > +    { .name = "POWER8", .initfn = spapr_cpu_core_POWER8_initfn },
> > +    { .name = "power8", .initfn = spapr_cpu_core_POWER8_initfn },
> > +
> > +    /* POWER8E and aliases */
> > +    { .name = "POWER8E_v2.1", .initfn = spapr_cpu_core_POWER8E_initfn },
> > +    { .name = "POWER8E", .initfn = spapr_cpu_core_POWER8E_initfn },
> > +
> > +    { .name = NULL }
> > +};
> 
> > +
> > +static void spapr_cpu_core_register(const SPAPRCoreInfo *info)
> > +{
> > +    TypeInfo type_info = {
> > +        .parent = TYPE_SPAPR_CPU_CORE,
> > +        .instance_size = sizeof(sPAPRCPUCore),
> > +        .instance_init = info->initfn,
> > +    };
> > +
> > +    type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE, info->name);
> > +    type_register(&type_info);
> > +    g_free((void *)type_info.name);
> > +}
> 
> The way the above registration works is pretty clunky.  I'm not
> immediately sure how to make it nicer though, so I'm happy enough to
> merge it this way and hope we can clean up later.

There is a precedence for this in target-arm/cpu.c :)

> 
> > +
> > +static const TypeInfo spapr_cpu_core_type_info = {
> > +    .name = TYPE_SPAPR_CPU_CORE,
> > +    .parent = TYPE_CPU_CORE,
> > +    .abstract = true,
> > +    .instance_size = sizeof(sPAPRCPUCore),
> > +    .class_init = spapr_cpu_core_class_init,
> > +};
> > +
> > +static void spapr_cpu_core_register_types(void)
> > +{
> > +    const SPAPRCoreInfo *info = spapr_cores;
> > +
> > +    type_register_static(&spapr_cpu_core_type_info);
> > +    while (info->name) {
> > +        spapr_cpu_core_register(info);
> > +        info++;
> > +    }
> > +}
> > +
> > +type_init(spapr_cpu_core_register_types)
> > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> > index 815d5ee..bcd9de6 100644
> > --- a/include/hw/ppc/spapr.h
> > +++ b/include/hw/ppc/spapr.h
> > @@ -580,6 +580,7 @@ void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type,
> >                                         uint32_t count);
> >  void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type,
> >                                            uint32_t count);
> > +void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp);
> >  
> >  /* rtas-configure-connector state */
> >  struct sPAPRConfigureConnectorState {
> > diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h
> > new file mode 100644
> > index 0000000..b6aa39e
> > --- /dev/null
> > +++ b/include/hw/ppc/spapr_cpu_core.h
> > @@ -0,0 +1,28 @@
> > +/*
> > + * sPAPR CPU core device.
> > + *
> > + * Copyright (C) 2016 Bharata B Rao <bharata@linux.vnet.ibm.com>
> > + *
> > + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> > + * See the COPYING file in the top-level directory.
> > + */
> > +#ifndef HW_SPAPR_CPU_CORE_H
> > +#define HW_SPAPR_CPU_CORE_H
> > +
> > +#include "hw/qdev.h"
> > +#include "hw/cpu/core.h"
> > +
> > +#define TYPE_SPAPR_CPU_CORE "spapr-cpu-core"
> > +#define SPAPR_CPU_CORE(obj) \
> > +    OBJECT_CHECK(sPAPRCPUCore, (obj), TYPE_SPAPR_CPU_CORE)
> > +
> > +typedef struct sPAPRCPUCore {
> > +    /*< private >*/
> > +    CPUCore parent_obj;
> > +
> > +    /*< public >*/
> > +    PowerPCCPU *threads;
> > +    ObjectClass *cpu;
> 
> I'd prefer to see this called 'cpu_class' or something - seeing 'cpu'
> makes me think an instance rather than a class.

Changed to cpu_class.

Regards,
Bharata.

Comments

David Gibson June 9, 2016, 12:45 a.m. UTC | #1
On Wed, Jun 08, 2016 at 03:12:42PM +0530, Bharata B Rao wrote:
> On Fri, Jun 03, 2016 at 03:25:08PM +1000, David Gibson wrote:
> > On Thu, May 12, 2016 at 09:18:17AM +0530, Bharata B Rao wrote:
> > > Add sPAPR specific abastract CPU core device that is based on generic
> > > CPU core device. Use this as base type to create sPAPR CPU specific core
> > > devices.
> > > 
> > > TODO:
> > > - Add core types for other remaining CPU types
> > > - Handle CPU model alias correctly
> > > 
> > > Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
> > 
> > This is looking pretty cood, but there's some minor changes I'd like
> > to see.
> > 
> > > ---
> > >  hw/ppc/Makefile.objs            |   1 +
> > >  hw/ppc/spapr.c                  |   3 +-
> > >  hw/ppc/spapr_cpu_core.c         | 168 ++++++++++++++++++++++++++++++++++++++++
> > >  include/hw/ppc/spapr.h          |   1 +
> > >  include/hw/ppc/spapr_cpu_core.h |  28 +++++++
> > >  5 files changed, 199 insertions(+), 2 deletions(-)
> > >  create mode 100644 hw/ppc/spapr_cpu_core.c
> > >  create mode 100644 include/hw/ppc/spapr_cpu_core.h
> > > 
> > > diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
> > > index c1ffc77..5cc6608 100644
> > > --- a/hw/ppc/Makefile.objs
> > > +++ b/hw/ppc/Makefile.objs
> > > @@ -4,6 +4,7 @@ obj-y += ppc.o ppc_booke.o
> > >  obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
> > >  obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
> > >  obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
> > > +obj-$(CONFIG_PSERIES) += spapr_cpu_core.o
> > >  ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
> > >  obj-y += spapr_pci_vfio.o
> > >  endif
> > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > > index b69995e..95db047 100644
> > > --- a/hw/ppc/spapr.c
> > > +++ b/hw/ppc/spapr.c
> > > @@ -1605,8 +1605,7 @@ static void spapr_boot_set(void *opaque, const char *boot_device,
> > >      machine->boot_order = g_strdup(boot_device);
> > >  }
> > >  
> > > -static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
> > > -                           Error **errp)
> > > +void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp)
> > 
> > I think this function should actually move into spapr_cpu_core.c
> 
> Actually, this is a CPU thread specific routine and will be called from
> spapr.c too. But I moved this to spapr_cpu_core.c as you suggest.

Yes, I realize it will be called from spapr.c as well.  The idea is to
make the core based initialization the clean path, even if the
thread-based initialization needed for backwards compat needs some
awkward cross-module calls and exports.

> > >  {
> > >      CPUPPCState *env = &cpu->env;
> > >  
> > > diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
> > > new file mode 100644
> > > index 0000000..af63ed9
> > > --- /dev/null
> > > +++ b/hw/ppc/spapr_cpu_core.c
> > > @@ -0,0 +1,168 @@
> > > +/*
> > > + * sPAPR CPU core device, acts as container of CPU thread devices.
> > > + *
> > > + * Copyright (C) 2016 Bharata B Rao <bharata@linux.vnet.ibm.com>
> > > + *
> > > + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> > > + * See the COPYING file in the top-level directory.
> > > + */
> > > +#include "hw/cpu/core.h"
> > > +#include "hw/ppc/spapr_cpu_core.h"
> > > +#include "hw/ppc/spapr.h"
> > > +#include "hw/boards.h"
> > > +#include "qapi/error.h"
> > > +#include <sysemu/cpus.h>
> > > +#include "target-ppc/kvm_ppc.h"
> > > +
> > > +static void spapr_cpu_core_create_threads(DeviceState *dev, int threads,
> > > +                                          Error **errp)
> > 
> > This function could be folded into spapr_cpu_core_realize(), that's
> > the only caller and they're both fairly short.
> 
> Ok done.
> 
> > 
> > > +{
> > > +    int i;
> > > +    Error *local_err = NULL;
> > > +    sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
> > > +
> > > +    for (i = 0; i < threads; i++) {
> > > +        char id[32];
> > > +
> > > +        object_initialize(&core->threads[i], sizeof(core->threads[i]),
> > > +                          object_class_get_name(core->cpu));
> > 
> > Given we have to go from the class pointer to the class name to
> > actually use it here, maybe we would be better off storing the name
> > rather than a class pointer.  Up to you, I'm happy either way.
> 
> I was doing typename initially and there were suggestions to move to
> ObjectClass. May be I will leave it like this while I fix all the other
> things and finally revisit this ?

Yes, that makes sense.  As I say it's not really a big deal either
way.

Could you use object_initialize_with_type() to avoid going via the
type name?

> > > +        snprintf(id, sizeof(id), "thread[%d]", i);
> > > +        object_property_add_child(OBJECT(core), id, OBJECT(&core->threads[i]),
> > > +                                  &local_err);
> > > +        if (local_err) {
> > > +            goto err;
> > > +        }
> > > +    }
> > > +    return;
> > > +
> > > +err:
> > > +    while (--i) {
> > > +        object_unparent(OBJECT(&core->threads[i]));
> > 
> > Is this safe if some of the threads haven't been initialized?
> 
> This is in the error path and only those threads which have been
> initialized will be unparented.

Ah, I misread the loop condition.  Except... there are other problems
with that loop condition.

First, (--i) means i will be decremented before you do anything, so
you won't clean up the cpu which actually triggered the error in the
first place.  And the if condition also means the loop body will never
be called with (i == 0).  So both the first and last threads
initialized won't actually be cleaned up.

> > > +    }
> > > +    error_propagate(errp, local_err);
> > > +}
> > > +
> > > +static int spapr_cpu_core_realize_child(Object *child, void *opaque)
> > > +{
> > > +    Error **errp = opaque;
> > > +    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
> > > +    CPUState *cs = CPU(child);
> > > +    PowerPCCPU *cpu = POWERPC_CPU(cs);
> > > +
> > > +    object_property_set_bool(child, true, "realized", errp);
> > > +    if (*errp) {
> > > +        return 1;
> > > +    }
> > > +
> > > +    spapr_cpu_init(spapr, cpu, errp);
> > > +    if (*errp) {
> > > +        return 1;
> > > +    }
> > > +    return 0;
> > > +}
> > > +
> > > +static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
> > > +{
> > > +    sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
> > > +    CPUCore *cc = CPU_CORE(OBJECT(dev));
> > > +    Error *local_err = NULL;
> > > +
> > > +    sc->threads = g_new0(PowerPCCPU, cc->threads);
> > 
> > This isn't quite safe, because it assume the structure size for all
> > the threads is that of PowerPCCPU.  That's true now, but cpu thread
> > subtypes could in theory extend that structure with subtype specific
> > fields.  I think we need to actually look up the class instance size
> > here.
> 
> I couldn't find a way to obtain the instance_size of a type. I had to
> introduce a QOM API like this:
> 
> diff --git a/qom/object.c b/qom/object.c
> index 3bc8a00..0e75877 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -202,6 +202,14 @@ static size_t type_object_get_size(TypeImpl *ti)
>      return 0;
>  }
>  
> +size_t object_type_get_size(const char *typename)
> +{
> +    TypeImpl *type = type_get_by_name(typename);
> +
> +    g_assert(type != NULL);
> +    return type_object_get_size(type);
> +}
> +
> 
> With the above I can obtain the size and use the same with
> object_initialize(). With this we don't have to make
> sc->threads as PowerPCCPU pointer.
> 
> > 
> > > +    spapr_cpu_core_create_threads(dev, cc->threads, &local_err);
> > > +    if (local_err) {
> > > +        goto out;
> > > +    }
> > > +    object_child_foreach(OBJECT(dev), spapr_cpu_core_realize_child, &local_err);
> > > +
> > > +out:
> > > +    if (local_err) {
> > > +        g_free(sc->threads);
> > > +        error_propagate(errp, local_err);
> > > +    }
> > > +}
> > > +
> > > +static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
> > > +{
> > > +    DeviceClass *dc = DEVICE_CLASS(oc);
> > > +    dc->realize = spapr_cpu_core_realize;
> > > +}
> > > +
> > > +/*
> > > + * instance_init routines from different flavours of sPAPR CPU cores.
> > > + * TODO: Add support for 'host' core type.
> > > + */
> > > +#define SPAPR_CPU_CORE_INITFN(_type, _fname) \
> > > +static void glue(glue(spapr_cpu_core_, _fname), _initfn(Object *obj)) \
> > > +{ \
> > > +    sPAPRCPUCore *core = SPAPR_CPU_CORE(obj); \
> > > +    char *name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, stringify(_type)); \
> > > +    ObjectClass *oc = object_class_by_name(name); \
> > > +    g_assert(oc); \
> > > +    g_free((void *)name); \
> > > +    core->cpu = oc; \
> > 
> > This all looks like stuff which could be done at class_init time, but
> > this is an instance_init function.
> 
> Essentially what we do here is to store the CPU thread ObjectClass within the
> abstract sPAPRCPUCore object so that we can initialize the CPU threads
> of right type from abstract sPAPRCPUCore object's realize routine. I am not
> sure if core object is available in class_init routine to achieve this.

It's not, but my point is you can move the ObjectClass * field from
the instance to the class structure, and initialize it from class_init
instead of instance_init.

> > I'm also wondering if it might just be simpler to store _type in the
> > subclass and do this in the base class.
> 
> Not sure if I really understand this suggestion correctly.
> 
> However, if you see, I am not yet defining a separate structures for the
> subtypes of sPAPRCPUCore where _type can be stored, but instead using
> sPAPRCPUCore as the instance_size for sub core types too.

Uh.. not relevant to the point I'm making.

> > > +}
> > > +
> > > +SPAPR_CPU_CORE_INITFN(POWER7_v2.3, POWER7);
> > > +SPAPR_CPU_CORE_INITFN(POWER7+_v2.1, POWER7plus);
> > > +SPAPR_CPU_CORE_INITFN(POWER8_v2.0, POWER8);
> > > +SPAPR_CPU_CORE_INITFN(POWER8E_v2.1, POWER8E);
> > > +
> > > +typedef struct SPAPRCoreInfo {
> > > +    const char *name;
> > > +    void (*initfn)(Object *obj);
> > > +} SPAPRCoreInfo;
> > > +
> > > +static const SPAPRCoreInfo spapr_cores[] = {
> > > +    /* POWER7 and aliases */
> > > +    { .name = "POWER7_v2.3", .initfn = spapr_cpu_core_POWER7_initfn },
> > > +    { .name = "POWER7", .initfn = spapr_cpu_core_POWER7_initfn },
> > > +
> > > +    /* POWER7+ and aliases */
> > > +    { .name = "POWER7+_v2.1", .initfn = spapr_cpu_core_POWER7plus_initfn },
> > > +    { .name = "POWER7+", .initfn = spapr_cpu_core_POWER7plus_initfn },
> > > +
> > > +    /* POWER8 and aliases */
> > > +    { .name = "POWER8_v2.0", .initfn = spapr_cpu_core_POWER8_initfn },
> > > +    { .name = "POWER8", .initfn = spapr_cpu_core_POWER8_initfn },
> > > +    { .name = "power8", .initfn = spapr_cpu_core_POWER8_initfn },
> > > +
> > > +    /* POWER8E and aliases */
> > > +    { .name = "POWER8E_v2.1", .initfn = spapr_cpu_core_POWER8E_initfn },
> > > +    { .name = "POWER8E", .initfn = spapr_cpu_core_POWER8E_initfn },
> > > +
> > > +    { .name = NULL }
> > > +};
> > 
> > > +
> > > +static void spapr_cpu_core_register(const SPAPRCoreInfo *info)
> > > +{
> > > +    TypeInfo type_info = {
> > > +        .parent = TYPE_SPAPR_CPU_CORE,
> > > +        .instance_size = sizeof(sPAPRCPUCore),
> > > +        .instance_init = info->initfn,
> > > +    };
> > > +
> > > +    type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE, info->name);
> > > +    type_register(&type_info);
> > > +    g_free((void *)type_info.name);
> > > +}
> > 
> > The way the above registration works is pretty clunky.  I'm not
> > immediately sure how to make it nicer though, so I'm happy enough to
> > merge it this way and hope we can clean up later.
> 
> There is a precedence for this in target-arm/cpu.c :)

Ok, fair enough.

> > > +
> > > +static const TypeInfo spapr_cpu_core_type_info = {
> > > +    .name = TYPE_SPAPR_CPU_CORE,
> > > +    .parent = TYPE_CPU_CORE,
> > > +    .abstract = true,
> > > +    .instance_size = sizeof(sPAPRCPUCore),
> > > +    .class_init = spapr_cpu_core_class_init,
> > > +};
> > > +
> > > +static void spapr_cpu_core_register_types(void)
> > > +{
> > > +    const SPAPRCoreInfo *info = spapr_cores;
> > > +
> > > +    type_register_static(&spapr_cpu_core_type_info);
> > > +    while (info->name) {
> > > +        spapr_cpu_core_register(info);
> > > +        info++;
> > > +    }
> > > +}
> > > +
> > > +type_init(spapr_cpu_core_register_types)
> > > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> > > index 815d5ee..bcd9de6 100644
> > > --- a/include/hw/ppc/spapr.h
> > > +++ b/include/hw/ppc/spapr.h
> > > @@ -580,6 +580,7 @@ void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type,
> > >                                         uint32_t count);
> > >  void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type,
> > >                                            uint32_t count);
> > > +void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp);
> > >  
> > >  /* rtas-configure-connector state */
> > >  struct sPAPRConfigureConnectorState {
> > > diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h
> > > new file mode 100644
> > > index 0000000..b6aa39e
> > > --- /dev/null
> > > +++ b/include/hw/ppc/spapr_cpu_core.h
> > > @@ -0,0 +1,28 @@
> > > +/*
> > > + * sPAPR CPU core device.
> > > + *
> > > + * Copyright (C) 2016 Bharata B Rao <bharata@linux.vnet.ibm.com>
> > > + *
> > > + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> > > + * See the COPYING file in the top-level directory.
> > > + */
> > > +#ifndef HW_SPAPR_CPU_CORE_H
> > > +#define HW_SPAPR_CPU_CORE_H
> > > +
> > > +#include "hw/qdev.h"
> > > +#include "hw/cpu/core.h"
> > > +
> > > +#define TYPE_SPAPR_CPU_CORE "spapr-cpu-core"
> > > +#define SPAPR_CPU_CORE(obj) \
> > > +    OBJECT_CHECK(sPAPRCPUCore, (obj), TYPE_SPAPR_CPU_CORE)
> > > +
> > > +typedef struct sPAPRCPUCore {
> > > +    /*< private >*/
> > > +    CPUCore parent_obj;
> > > +
> > > +    /*< public >*/
> > > +    PowerPCCPU *threads;
> > > +    ObjectClass *cpu;
> > 
> > I'd prefer to see this called 'cpu_class' or something - seeing 'cpu'
> > makes me think an instance rather than a class.
> 
> Changed to cpu_class.

Thanks.
diff mbox

Patch

diff --git a/qom/object.c b/qom/object.c
index 3bc8a00..0e75877 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -202,6 +202,14 @@  static size_t type_object_get_size(TypeImpl *ti)
     return 0;
 }
 
+size_t object_type_get_size(const char *typename)
+{
+    TypeImpl *type = type_get_by_name(typename);
+
+    g_assert(type != NULL);
+    return type_object_get_size(type);
+}
+

With the above I can obtain the size and use the same with
object_initialize(). With this we don't have to make