Commit 3b542549 authored by Bharata B Rao's avatar Bharata B Rao Committed by David Gibson
Browse files

spapr: Abstract CPU core device and type specific core devices



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: default avatarBharata B Rao <bharata@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent 3f97b53a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+1 −2
Original line number Diff line number Diff line
@@ -1623,8 +1623,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)
{
    CPUPPCState *env = &cpu->env;

+160 −0
Original line number Diff line number Diff line
/*
 * 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 "target-ppc/cpu.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 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));
    const char *typename = object_class_get_name(sc->cpu_class);
    size_t size = object_type_get_instance_size(typename);
    Error *local_err = NULL;
    Object *obj;
    int i;

    sc->threads = g_malloc0(size * cc->nr_threads);
    for (i = 0; i < cc->nr_threads; i++) {
        char id[32];
        void *obj = sc->threads + i * size;

        object_initialize(obj, size, typename);
        snprintf(id, sizeof(id), "thread[%d]", i);
        object_property_add_child(OBJECT(sc), id, obj, &local_err);
        if (local_err) {
            goto err;
        }
    }
    object_child_foreach(OBJECT(dev), spapr_cpu_core_realize_child, &local_err);
    if (local_err) {
        goto err;
    } else {
        return;
    }

err:
    while (i >= 0) {
        obj = sc->threads + i * size;
        object_unparent(obj);
        i--;
    }
    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_class = oc; \
}

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);
}

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)
+1 −0
Original line number Diff line number Diff line
@@ -582,6 +582,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 {
+29 −0
Original line number Diff line number Diff line
/*
 * 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"
#include "target-ppc/cpu-qom.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 >*/
    void *threads;
    ObjectClass *cpu_class;
} sPAPRCPUCore;

#endif
Loading