[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCH v4 05/20] ppc/pnv: add a PnvCore object
From: |
Cédric Le Goater |
Subject: |
Re: [Qemu-ppc] [PATCH v4 05/20] ppc/pnv: add a PnvCore object |
Date: |
Mon, 10 Oct 2016 10:07:29 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0 |
On 10/07/2016 06:52 AM, David Gibson wrote:
> On Mon, Oct 03, 2016 at 09:24:41AM +0200, Cédric Le Goater wrote:
>> This is largy inspired by sPAPRCPUCore with some simplification, no
>> hotplug for instance. But the differences are small and the objects
>> could possibly be merged.
>>
>> A set of PnvCore objects is added to the PnvChip and the device
>> tree is populated looping on these cores.
>>
>> Real HW cpu ids are now generated depending on the chip cpu model, the
>> chip id and a core mask.
>>
>> Signed-off-by: Cédric Le Goater <address@hidden>
>> ---
>>
>> I did not introduce a single table to construct both the chip types
>> and the corresponding core types yet. Keeping the idea for later as
>> there might be other types to construct with P9 support.
>>
>> Changes since v3:
>>
>> - removed the usage of cpu_index
>> - removed the setting of the msr_mask
>>
>> Changes since v2:
>>
>> - added P9 support
>> - used error_fatal instead of error_abort when setting the chip
>> properties
>> - replaced num_cores by nr_cores
>> - removed gservers properties that were unused on powernv.
>> - used a 'void *' instead of a 'PnvCore *' to hold core Objects of
>> potentially different size.
>> - qom: linked the core Objects to the chip
>> - moved device tree creation under powernv_populate_chip()
>> - added a 'pir' property' for ease of use
>>
>> Changes since v1:
>>
>> - changed name to PnvCore
>> - changed PnvChip core array type to a 'PnvCore *cores'
>> - introduced real cpu hw ids using a core mask from the chip
>> - reworked powernv_create_core_node() which populates the device tree
>> - added missing "ibm,pa-features" property
>> - smp_cpus representing threads, used smp_cores instead to create the
>> cores in the chip.
>> - removed the use of ppc_get_vcpu_dt_id()
>> - added "POWER8E" and "POWER8NVL" cpu models to exercice the
>> PnvChipClass
>>
>> hw/ppc/Makefile.objs | 2 +-
>> hw/ppc/pnv.c | 187
>> ++++++++++++++++++++++++++++++++++++++++++++++
>> hw/ppc/pnv_core.c | 186
>> +++++++++++++++++++++++++++++++++++++++++++++
>> include/hw/ppc/pnv.h | 3 +
>> include/hw/ppc/pnv_core.h | 48 ++++++++++++
>> 5 files changed, 425 insertions(+), 1 deletion(-)
>> create mode 100644 hw/ppc/pnv_core.c
>> create mode 100644 include/hw/ppc/pnv_core.h
>>
>> diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
>> index 8105db7d5600..f8c7d1db9ade 100644
>> --- a/hw/ppc/Makefile.objs
>> +++ b/hw/ppc/Makefile.objs
>> @@ -6,7 +6,7 @@ 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
>> # IBM PowerNV
>> -obj-$(CONFIG_POWERNV) += pnv.o
>> +obj-$(CONFIG_POWERNV) += pnv.o pnv_core.o
>> ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
>> obj-y += spapr_pci_vfio.o
>> endif
>> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
>> index 758c849702a0..2376bb222918 100644
>> --- a/hw/ppc/pnv.c
>> +++ b/hw/ppc/pnv.c
>> @@ -27,6 +27,7 @@
>> #include "hw/ppc/fdt.h"
>> #include "hw/ppc/ppc.h"
>> #include "hw/ppc/pnv.h"
>> +#include "hw/ppc/pnv_core.h"
>> #include "hw/loader.h"
>> #include "exec/address-spaces.h"
>> #include "qemu/cutils.h"
>> @@ -74,14 +75,162 @@ static void powernv_populate_memory_node(void *fdt, int
>> chip_id, hwaddr start,
>> _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
>> }
>>
>> +static int get_cpus_node(void *fdt)
>> +{
>> + int cpus_offset = fdt_path_offset(fdt, "/cpus");
>> +
>> + if (cpus_offset < 0) {
>> + cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
>> + "cpus");
>> + if (cpus_offset) {
>> + _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells",
>> 0x1)));
>> + _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
>> + }
>> + }
>> + _FDT(cpus_offset);
>> + return cpus_offset;
>> +}
>> +
>> +/*
>> + * The PowerNV cores (and threads) need to use real HW ids and not an
>> + * incremental index like it has been done on other platforms. This HW
>> + * id is stored in the CPU PIR, it is used to create cpu nodes in the
>> + * device tree, used in XSCOM to address cores and in interrupt
>> + * servers.
>> + */
>> +static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt)
>> +{
>> + CPUState *cs = CPU(DEVICE(pc->threads));
>> + DeviceClass *dc = DEVICE_GET_CLASS(cs);
>> + PowerPCCPU *cpu = POWERPC_CPU(cs);
>> + int smt_threads = ppc_get_compat_smt_threads(cpu);
>> + CPUPPCState *env = &cpu->env;
>> + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
>> + uint32_t servers_prop[smt_threads];
>> + int i;
>> + uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
>> + 0xffffffff, 0xffffffff};
>> + uint32_t tbfreq = PNV_TIMEBASE_FREQ;
>> + uint32_t cpufreq = 1000000000;
>> + uint32_t page_sizes_prop[64];
>> + size_t page_sizes_prop_size;
>> + const uint8_t pa_features[] = { 24, 0,
>> + 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
>> + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
>> + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
>> + 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
>> + int offset;
>> + char *nodename;
>> + int cpus_offset = get_cpus_node(fdt);
>> +
>> + nodename = g_strdup_printf("address@hidden", dc->fw_name, pc->pir);
>> + offset = fdt_add_subnode(fdt, cpus_offset, nodename);
>> + _FDT(offset);
>> + g_free(nodename);
>> +
>> + _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
>> +
>> + _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
>> + _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
>> + _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
>> +
>> + _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
>> + _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
>> + env->dcache_line_size)));
>> + _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
>> + env->dcache_line_size)));
>> + _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
>> + env->icache_line_size)));
>> + _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
>> + env->icache_line_size)));
>> +
>> + if (pcc->l1_dcache_size) {
>> + _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
>> + pcc->l1_dcache_size)));
>> + } else {
>> + error_report("Warning: Unknown L1 dcache size for cpu");
>> + }
>> + if (pcc->l1_icache_size) {
>> + _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
>> + pcc->l1_icache_size)));
>> + } else {
>> + error_report("Warning: Unknown L1 icache size for cpu");
>> + }
>> +
>> + _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
>> + _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
>> + _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr)));
>> + _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
>> + _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
>> +
>> + if (env->spr_cb[SPR_PURR].oea_read) {
>> + _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
>> + }
>> +
>> + if (env->mmu_model & POWERPC_MMU_1TSEG) {
>> + _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
>> + segs, sizeof(segs))));
>> + }
>> +
>> + /* Advertise VMX/VSX (vector extensions) if available
>> + * 0 / no property == no vector extensions
>> + * 1 == VMX / Altivec available
>> + * 2 == VSX available */
>> + if (env->insns_flags & PPC_ALTIVEC) {
>> + uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
>> +
>> + _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
>> + }
>> +
>> + /* Advertise DFP (Decimal Floating Point) if available
>> + * 0 / no property == no DFP
>> + * 1 == DFP available */
>> + if (env->insns_flags2 & PPC2_DFP) {
>> + _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
>> + }
>> +
>> + page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop,
>> + sizeof(page_sizes_prop));
>> + if (page_sizes_prop_size) {
>> + _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
>> + page_sizes_prop, page_sizes_prop_size)));
>> + }
>> +
>> + _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
>> + pa_features, sizeof(pa_features))));
>> +
>> + if (cpu->cpu_version) {
>> + _FDT((fdt_setprop_cell(fdt, offset, "cpu-version",
>> cpu->cpu_version)));
>> + }
>> +
>> + /* Build interrupt servers properties */
>> + for (i = 0; i < smt_threads; i++) {
>> + servers_prop[i] = cpu_to_be32(pc->pir + i);
>> + }
>> + _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
>> + servers_prop, sizeof(servers_prop))));
>> +}
>> +
>> static void powernv_populate_chip(PnvChip *chip, void *fdt)
>> {
>> + PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
>> + char *typename = pnv_core_typename(pcc->cpu_model);
>> + size_t typesize = object_type_get_instance_size(typename);
>> + int i;
>> +
>> + for (i = 0; i < chip->nr_cores; i++) {
>> + PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
>> +
>> + powernv_create_core_node(chip, pnv_core, fdt);
>> + }
>> +
>> /* Put all the memory in one node on chip 0 until we find a way to
>> * specify different ranges for each chip
>> */
>> if (chip->chip_id == 0) {
>> powernv_populate_memory_node(fdt, chip->chip_id, 0, ram_size);
>> }
>> + g_free(typename);
>> }
>>
>> static void *powernv_create_fdt(PnvMachineState *pnv,
>> @@ -404,6 +553,15 @@ static void pnv_chip_realize(DeviceState *dev, Error
>> **errp)
>> {
>> PnvChip *chip = PNV_CHIP(dev);
>> Error *error = NULL;
>> + PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
>> + char *typename = pnv_core_typename(pcc->cpu_model);
>> + size_t typesize = object_type_get_instance_size(typename);
>> + int i, core_hwid;
>> +
>> + if (!object_class_by_name(typename)) {
>> + error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
>> + return;
>> + }
>>
>> /* Early checks on the core settings */
>> pnv_chip_core_sanitize(chip, &error);
>> @@ -411,6 +569,35 @@ static void pnv_chip_realize(DeviceState *dev, Error
>> **errp)
>> error_propagate(errp, error);
>> return;
>> }
>> +
>> + chip->cores = g_malloc0(typesize * chip->nr_cores);
>> +
>> + for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
>> + && (i < chip->nr_cores); core_hwid++) {
>> + char core_name[32];
>> + void *pnv_core = chip->cores + i * typesize;
>> +
>> + if (!(chip->cores_mask & (1ull << core_hwid))) {
>> + continue;
>> + }
>> +
>> + object_initialize(pnv_core, typesize, typename);
>> + snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
>> + object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
>> + &error_fatal);
>> + object_property_set_int(OBJECT(pnv_core), smp_threads, "nr-threads",
>> + &error_fatal);
>> + object_property_set_int(OBJECT(pnv_core), core_hwid,
>> + CPU_CORE_PROP_CORE_ID, &error_fatal);
>> + object_property_set_int(OBJECT(pnv_core),
>> + pcc->core_pir(chip, core_hwid),
>> + "pir", &error_fatal);
>> + object_property_set_bool(OBJECT(pnv_core), true, "realized",
>> + &error_fatal);
>> + object_unref(OBJECT(pnv_core));
>> + i++;
>> + }
>> + g_free(typename);
>> }
>>
>> static Property pnv_chip_properties[] = {
>> diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
>> new file mode 100644
>> index 000000000000..d37788f142f4
>> --- /dev/null
>> +++ b/hw/ppc/pnv_core.c
>> @@ -0,0 +1,186 @@
>> +/*
>> + * QEMU PowerPC PowerNV CPU Core model
>> + *
>> + * Copyright (c) 2016, IBM Corporation.
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public License
>> + * as published by the Free Software Foundation; either version 2 of
>> + * the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful, but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see
>> <http://www.gnu.org/licenses/>.
>> + */
>> +#include "qemu/osdep.h"
>> +#include "sysemu/sysemu.h"
>> +#include "qapi/error.h"
>> +#include "target-ppc/cpu.h"
>> +#include "hw/ppc/ppc.h"
>> +#include "hw/ppc/pnv.h"
>> +#include "hw/ppc/pnv_core.h"
>> +
>> +static void powernv_cpu_reset(void *opaque)
>> +{
>> + PowerPCCPU *cpu = opaque;
>> + CPUState *cs = CPU(cpu);
>> + CPUPPCState *env = &cpu->env;
>> + int core_pir;
>> + int thread_index = 0; /* TODO: TCG supports only one thread */
>> +
>> + cpu_reset(cs);
>> +
>> + core_pir = object_property_get_int(OBJECT(cpu), "core-pir",
>> &error_abort);
>
> Took me a while to figure out how this core-pir alias thing works, but
> once I did, it looks ok. I do wonder if you'll need to change to a
> link back to the core object at some point if there's more than just
> the pir you need to look up from the core.
yes. That is how I handled it in a first version, with a back link to the
core, but the current patchset does not need it at runtime. so I just used
a property.
>> + /*
>> + * The PIR of a thread is the core PIR + the thread index. We will
>> + * need to find a way to get the thread index when TCG supports
>> + * more than 1. We could use the object name ?
>> + */
>> + env->spr[SPR_PIR] = core_pir + thread_index;
>
> The PIR is read-only, so could it be initialized directly in _init()
> rather than in the _reset() handler?
yes. I found now how it should be set in init :
env->spr_cb[SPR_PIR]->default_value
>
>> + env->spr[SPR_HIOR] = 0;
HIOR is for 970. I will remove that also from reset.
>> + /*
>> + * the skiboot firmware elects a primary thread to initialize the
>> + * system and it can be any.
>> + */
>> + env->gpr[3] = POWERNV_FDT_ADDR;
>> + env->nip = 0x10;
>> + env->msr |= MSR_HVB; /* Hypervisor mode */
>> +}
>> +
>> +static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
>> +{
>> + CPUPPCState *env = &cpu->env;
>> +
>> + /* Set time-base frequency to 512 MHz */
>> + cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
>> +
>> + qemu_register_reset(powernv_cpu_reset, cpu);
>> + powernv_cpu_reset(cpu);
>
> I don't think you need this explicit call to the reset function - all
> the registered reset functions should get called after this point, but
> before qemu tries to start the guest.
I think you are right. This is just adding an extra superfluous call.
>
>> +}
>> +
>> +static void pnv_core_realize_child(Object *child, Error **errp)
>> +{
>> + Error *local_err = NULL;
>> + CPUState *cs = CPU(child);
>> + PowerPCCPU *cpu = POWERPC_CPU(cs);
>> +
>> + object_property_set_bool(child, true, "realized", &local_err);
>> + if (local_err) {
>> + error_propagate(errp, local_err);
>> + return;
>> + }
>> +
>> + powernv_cpu_init(cpu, &local_err);
>> + if (local_err) {
>> + error_propagate(errp, local_err);
>> + return;
>> + }
>> +}
>> +
>> +static void pnv_core_realize(DeviceState *dev, Error **errp)
>> +{
>> + PnvCore *pc = PNV_CORE(OBJECT(dev));
>> + CPUCore *cc = CPU_CORE(OBJECT(dev));
>> + PnvCoreClass *pcc = PNV_CORE_GET_CLASS(OBJECT(dev));
>> + const char *typename = object_class_get_name(pcc->cpu_oc);
>> + size_t size = object_type_get_instance_size(typename);
>> + Error *local_err = NULL;
>> + void *obj;
>> + int i, j;
>> + char name[32];
>> +
>> + pc->threads = g_malloc0(size * cc->nr_threads);
>> + for (i = 0; i < cc->nr_threads; i++) {
>> + obj = pc->threads + i * size;
>> +
>> + object_initialize(obj, size, typename);
>> +
>> + snprintf(name, sizeof(name), "thread[%d]", i);
>> + object_property_add_child(OBJECT(pc), name, obj, &local_err);
>> + object_property_add_alias(obj, "core-pir", OBJECT(pc),
>> + "pir", &local_err);
>> + if (local_err) {
>> + goto err;
>> + }
>> + object_unref(obj);
>> + }
>> +
>> + for (j = 0; j < cc->nr_threads; j++) {
>> + obj = pc->threads + j * size;
>> +
>> + pnv_core_realize_child(obj, &local_err);
>> + if (local_err) {
>> + goto err;
>> + }
>> + }
>> + return;
>> +
>> +err:
>> + while (--i >= 0) {
>> + obj = pc->threads + i * size;
>> + object_unparent(obj);
>> + }
>> + g_free(pc->threads);
>> + error_propagate(errp, local_err);
>> +}
>> +
>> +static Property pnv_core_properties[] = {
>> + DEFINE_PROP_UINT32("pir", PnvCore, pir, 0),
>> + DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>> +static void pnv_core_class_init(ObjectClass *oc, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(oc);
>> + PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
>> +
>> + dc->realize = pnv_core_realize;
>> + dc->props = pnv_core_properties;
>> + pcc->cpu_oc = cpu_class_by_name(TYPE_POWERPC_CPU, data);
>> +}
>> +
>> +static const TypeInfo pnv_core_info = {
>> + .name = TYPE_PNV_CORE,
>> + .parent = TYPE_CPU_CORE,
>> + .instance_size = sizeof(PnvCore),
>> + .class_size = sizeof(PnvCoreClass),
>> + .abstract = true,
>> +};
>> +
>> +/*
>> + * Grow this list or merge with SPAPRCoreInfo which is very similar
>
> I don't think combining this with the spapr one makes sense. If
> nothing else I don't think we want to bind what CPU models are
> supported for pnv to what models are supported for PAPR.
ok.
Thanks,
C.
>
>> + */
>> +static const char *pnv_core_models[] = {
>> + "POWER8E", "POWER8", "POWER8NVL", "POWER9"
>> +};
>> +
>> +static void pnv_core_register_types(void)
>> +{
>> + int i ;
>> +
>> + type_register_static(&pnv_core_info);
>> + for (i = 0; i < ARRAY_SIZE(pnv_core_models); ++i) {
>> + TypeInfo ti = {
>> + .parent = TYPE_PNV_CORE,
>> + .instance_size = sizeof(PnvCore),
>> + .class_init = pnv_core_class_init,
>> + .class_data = (void *) pnv_core_models[i],
>> + };
>> + ti.name = pnv_core_typename(pnv_core_models[i]);
>> + type_register(&ti);
>> + g_free((void *)ti.name);
>> + }
>> +}
>> +
>> +type_init(pnv_core_register_types)
>> +
>> +char *pnv_core_typename(const char *model)
>> +{
>> + return g_strdup_printf(TYPE_PNV_CORE "-%s", model);
>> +}
>> diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
>> index c676f800e28e..ed4a360cde3b 100644
>> --- a/include/hw/ppc/pnv.h
>> +++ b/include/hw/ppc/pnv.h
>> @@ -45,6 +45,7 @@ typedef struct PnvChip {
>>
>> uint32_t nr_cores;
>> uint64_t cores_mask;
>> + void *cores;
>> } PnvChip;
>>
>> typedef struct PnvChipClass {
>> @@ -102,4 +103,6 @@ typedef struct PnvMachineState {
>>
>> #define POWERNV_FDT_ADDR 0x01000000
>>
>> +#define PNV_TIMEBASE_FREQ 512000000ULL
>> +
>> #endif /* _PPC_PNV_H */
>> diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
>> new file mode 100644
>> index 000000000000..a151e281c017
>> --- /dev/null
>> +++ b/include/hw/ppc/pnv_core.h
>> @@ -0,0 +1,48 @@
>> +/*
>> + * QEMU PowerPC PowerNV CPU Core model
>> + *
>> + * Copyright (c) 2016, IBM Corporation.
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public License
>> + * as published by the Free Software Foundation; either version 2 of
>> + * the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful, but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see
>> <http://www.gnu.org/licenses/>.
>> + */
>> +#ifndef _PPC_PNV_CORE_H
>> +#define _PPC_PNV_CORE_H
>> +
>> +#include "hw/cpu/core.h"
>> +
>> +#define TYPE_PNV_CORE "powernv-cpu-core"
>> +#define PNV_CORE(obj) \
>> + OBJECT_CHECK(PnvCore, (obj), TYPE_PNV_CORE)
>> +#define PNV_CORE_CLASS(klass) \
>> + OBJECT_CLASS_CHECK(PnvCoreClass, (klass), TYPE_PNV_CORE)
>> +#define PNV_CORE_GET_CLASS(obj) \
>> + OBJECT_GET_CLASS(PnvCoreClass, (obj), TYPE_PNV_CORE)
>> +
>> +typedef struct PnvCore {
>> + /*< private >*/
>> + CPUCore parent_obj;
>> +
>> + /*< public >*/
>> + void *threads;
>> + uint32_t pir;
>> +} PnvCore;
>> +
>> +typedef struct PnvCoreClass {
>> + DeviceClass parent_class;
>> + ObjectClass *cpu_oc;
>> +} PnvCoreClass;
>> +
>> +extern char *pnv_core_typename(const char *model);
>> +
>> +#endif /* _PPC_PNV_CORE_H */
>
- Re: [Qemu-ppc] [PATCH v4 03/20] ppc/pnv: add a core mask to PnvChip, (continued)
- Re: [Qemu-ppc] [PATCH v4 03/20] ppc/pnv: add a core mask to PnvChip, Cédric Le Goater, 2016/10/07
- Re: [Qemu-ppc] [PATCH v4 03/20] ppc/pnv: add a core mask to PnvChip, Cédric Le Goater, 2016/10/10
- Re: [Qemu-ppc] [PATCH v4 03/20] ppc/pnv: add a core mask to PnvChip, David Gibson, 2016/10/11
- Re: [Qemu-ppc] [PATCH v4 03/20] ppc/pnv: add a core mask to PnvChip, Cédric Le Goater, 2016/10/12
- Re: [Qemu-ppc] [PATCH v4 03/20] ppc/pnv: add a core mask to PnvChip, David Gibson, 2016/10/13
[Qemu-ppc] [PATCH v4 04/20] ppc/pnv: add a PIR handler to PnvChip, Cédric Le Goater, 2016/10/03
[Qemu-ppc] [PATCH v4 05/20] ppc/pnv: add a PnvCore object, Cédric Le Goater, 2016/10/03
[Qemu-ppc] [PATCH v4 06/20] ppc/pnv: add XSCOM infrastructure, Cédric Le Goater, 2016/10/03
[Qemu-ppc] [PATCH v4 07/20] ppc/pnv: add XSCOM handlers to PnvCore, Cédric Le Goater, 2016/10/03
[Qemu-ppc] [PATCH v4 08/20] ppc/pnv: add a LPC controller, Cédric Le Goater, 2016/10/03