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:
parent
3f97b53a68
commit
3b54254966
@ -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
|
||||||
|
@ -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
160
hw/ppc/spapr_cpu_core.c
Normal 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)
|
@ -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 {
|
||||||
|
29
include/hw/ppc/spapr_cpu_core.h
Normal file
29
include/hw/ppc/spapr_cpu_core.h
Normal 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
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user