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: Bharata B Rao <bharata@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
Bharata B Rao 2016-06-10 06:29:01 +05:30 committed by David Gibson
parent 3f97b53a68
commit 3b54254966
6 changed files with 220 additions and 2 deletions

View File

@ -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.o spapr_vio.o spapr_events.o
obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.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_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) ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
obj-y += spapr_pci_vfio.o obj-y += spapr_pci_vfio.o
endif endif

View File

@ -1623,8 +1623,7 @@ static void spapr_boot_set(void *opaque, const char *boot_device,
machine->boot_order = g_strdup(boot_device); machine->boot_order = g_strdup(boot_device);
} }
static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp)
Error **errp)
{ {
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;

160
hw/ppc/spapr_cpu_core.c Normal file
View File

@ -0,0 +1,160 @@
/*
* 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)

View File

@ -582,6 +582,7 @@ void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type,
uint32_t count); uint32_t count);
void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type, void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type,
uint32_t count); uint32_t count);
void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp);
/* rtas-configure-connector state */ /* rtas-configure-connector state */
struct sPAPRConfigureConnectorState { struct sPAPRConfigureConnectorState {

View File

@ -0,0 +1,29 @@
/*
* 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

View File

@ -42,6 +42,9 @@
#include "exec/memattrs.h" #include "exec/memattrs.h"
#include "sysemu/hostmem.h" #include "sysemu/hostmem.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#if defined(TARGET_PPC64)
#include "hw/ppc/spapr_cpu_core.h"
#endif
//#define DEBUG_KVM //#define DEBUG_KVM
@ -2341,6 +2344,19 @@ PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
return pvr_pcc; return pvr_pcc;
} }
#if defined(TARGET_PPC64)
static void spapr_cpu_core_host_initfn(Object *obj)
{
sPAPRCPUCore *core = SPAPR_CPU_CORE(obj);
char *name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, "host");
ObjectClass *oc = object_class_by_name(name);
g_assert(oc);
g_free((void *)name);
core->cpu_class = oc;
}
#endif
static int kvm_ppc_register_host_cpu_type(void) static int kvm_ppc_register_host_cpu_type(void)
{ {
TypeInfo type_info = { TypeInfo type_info = {
@ -2358,6 +2374,18 @@ static int kvm_ppc_register_host_cpu_type(void)
type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc));
type_register(&type_info); type_register(&type_info);
#if defined(TARGET_PPC64)
type_info.name = g_strdup_printf("%s-"TYPE_SPAPR_CPU_CORE, "host");
type_info.parent = TYPE_SPAPR_CPU_CORE,
type_info.instance_size = sizeof(sPAPRCPUCore),
type_info.instance_init = spapr_cpu_core_host_initfn,
type_info.class_init = NULL;
type_register(&type_info);
g_free((void *)type_info.name);
type_info.instance_size = 0;
type_info.instance_init = NULL;
#endif
/* Register generic family CPU class for a family */ /* Register generic family CPU class for a family */
pvr_pcc = ppc_cpu_get_family_class(pvr_pcc); pvr_pcc = ppc_cpu_get_family_class(pvr_pcc);
dc = DEVICE_CLASS(pvr_pcc); dc = DEVICE_CLASS(pvr_pcc);