Re: [Qemu-devel] [PATCH v2 11/15] ppc/pnv: POWER9 XSCOM quad support
On Thu, Mar 07, 2019 at 11:35:44PM +0100, Cédric Le Goater wrote: > The POWER9 processor does not support per-core frequency control. The > cores are arranged in groups of four, along with their respective L2 > and L3 caches, into a structure known as a Quad. The frequency must be > managed at the Quad level. > > Provide a basic Quad model to fake the settings done by the firmware > on the Non-Cacheable Unit (NCU). Each core pair (EX) needs a special > BAR setting for the TIMA area of XIVE because it resides on the same > address on all chips. > > Signed-off-by: Cédric Le Goater Applied, thanks. > --- > include/hw/ppc/pnv.h | 4 ++ > include/hw/ppc/pnv_core.h | 10 + > include/hw/ppc/pnv_xscom.h | 12 -- > hw/ppc/pnv.c | 38 - > hw/ppc/pnv_core.c | 87 ++ > 5 files changed, 146 insertions(+), 5 deletions(-) > > diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h > index 39888f9d52c1..e5b00d373ed2 100644 > --- a/include/hw/ppc/pnv.h > +++ b/include/hw/ppc/pnv.h > @@ -26,6 +26,7 @@ > #include "hw/ppc/pnv_psi.h" > #include "hw/ppc/pnv_occ.h" > #include "hw/ppc/pnv_xive.h" > +#include "hw/ppc/pnv_core.h" > > #define TYPE_PNV_CHIP "pnv-chip" > #define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP) > @@ -89,6 +90,9 @@ typedef struct Pnv9Chip { > Pnv9Psi psi; > PnvLpcController lpc; > PnvOCC occ; > + > +uint32_t nr_quads; > +PnvQuad *quads; > } Pnv9Chip; > > typedef struct PnvChipClass { > diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h > index cbe9ad36f32c..50cdb2b35838 100644 > --- a/include/hw/ppc/pnv_core.h > +++ b/include/hw/ppc/pnv_core.h > @@ -58,4 +58,14 @@ static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu) > return (PnvCPUState *)cpu->machine_data; > } > > +#define TYPE_PNV_QUAD "powernv-cpu-quad" > +#define PNV_QUAD(obj) \ > +OBJECT_CHECK(PnvQuad, (obj), TYPE_PNV_QUAD) > + > +typedef struct PnvQuad { > +DeviceState parent_obj; > + > +uint32_t id; > +MemoryRegion xscom_regs; > +} PnvQuad; > #endif /* _PPC_PNV_CORE_H */ > diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h > index 3292459fbb78..68dfae0dfe41 100644 > --- a/include/hw/ppc/pnv_xscom.h > +++ b/include/hw/ppc/pnv_xscom.h > @@ -60,10 +60,6 @@ typedef struct PnvXScomInterfaceClass { > (PNV_XSCOM_EX_CORE_BASE | ((uint64_t)(core) << 24)) > #define PNV_XSCOM_EX_SIZE 0x10 > > -#define PNV_XSCOM_P9_EC_BASE(core) \ > -((uint64_t)(((core) & 0x1F) + 0x20) << 24) > -#define PNV_XSCOM_P9_EC_SIZE 0x10 > - > #define PNV_XSCOM_LPC_BASE0xb0020 > #define PNV_XSCOM_LPC_SIZE0x4 > > @@ -73,6 +69,14 @@ typedef struct PnvXScomInterfaceClass { > #define PNV_XSCOM_OCC_BASE0x0066000 > #define PNV_XSCOM_OCC_SIZE0x6000 > > +#define PNV9_XSCOM_EC_BASE(core) \ > +((uint64_t)(((core) & 0x1F) + 0x20) << 24) > +#define PNV9_XSCOM_EC_SIZE0x10 > + > +#define PNV9_XSCOM_EQ_BASE(core) \ > +((uint64_t)(((core) & 0x1C) + 0x40) << 22) > +#define PNV9_XSCOM_EQ_SIZE0x10 > + > #define PNV9_XSCOM_OCC_BASE PNV_XSCOM_OCC_BASE > #define PNV9_XSCOM_OCC_SIZE 0x8000 > > diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c > index 1559a733235b..e68d419203e8 100644 > --- a/hw/ppc/pnv.c > +++ b/hw/ppc/pnv.c > @@ -963,6 +963,36 @@ static void pnv_chip_power9_instance_init(Object *obj) > OBJECT(>psi), _abort); > } > > +static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) > +{ > +PnvChip *chip = PNV_CHIP(chip9); > +const char *typename = pnv_chip_core_typename(chip); > +size_t typesize = object_type_get_instance_size(typename); > +int i; > + > +chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); > +chip9->quads = g_new0(PnvQuad, chip9->nr_quads); > + > +for (i = 0; i < chip9->nr_quads; i++) { > +char eq_name[32]; > +PnvQuad *eq = >quads[i]; > +PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize); > +int core_id = CPU_CORE(pnv_core)->core_id; > + > +object_initialize(eq, sizeof(*eq), TYPE_PNV_QUAD); > +snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); > + > +object_property_add_child(OBJECT(chip), eq_name, OBJECT(eq), > + _fatal); > +object_property_set_int(OBJECT(eq), core_id, "id", _fatal); > +object_property_set_bool(OBJECT(eq), true, "realized", _fatal); > +object_unref(OBJECT(eq)); > + > +pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), > +>xscom_regs); > +} > +} > + > static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) > { > PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); > @@ -977,6 +1007,12 @@ static void pnv_chip_power9_realize(DeviceState *dev, > Error **errp) >
[Qemu-devel] [PATCH v2 11/15] ppc/pnv: POWER9 XSCOM quad support
The POWER9 processor does not support per-core frequency control. The cores are arranged in groups of four, along with their respective L2 and L3 caches, into a structure known as a Quad. The frequency must be managed at the Quad level. Provide a basic Quad model to fake the settings done by the firmware on the Non-Cacheable Unit (NCU). Each core pair (EX) needs a special BAR setting for the TIMA area of XIVE because it resides on the same address on all chips. Signed-off-by: Cédric Le Goater --- include/hw/ppc/pnv.h | 4 ++ include/hw/ppc/pnv_core.h | 10 + include/hw/ppc/pnv_xscom.h | 12 -- hw/ppc/pnv.c | 38 - hw/ppc/pnv_core.c | 87 ++ 5 files changed, 146 insertions(+), 5 deletions(-) diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 39888f9d52c1..e5b00d373ed2 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -26,6 +26,7 @@ #include "hw/ppc/pnv_psi.h" #include "hw/ppc/pnv_occ.h" #include "hw/ppc/pnv_xive.h" +#include "hw/ppc/pnv_core.h" #define TYPE_PNV_CHIP "pnv-chip" #define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP) @@ -89,6 +90,9 @@ typedef struct Pnv9Chip { Pnv9Psi psi; PnvLpcController lpc; PnvOCC occ; + +uint32_t nr_quads; +PnvQuad *quads; } Pnv9Chip; typedef struct PnvChipClass { diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index cbe9ad36f32c..50cdb2b35838 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -58,4 +58,14 @@ static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu) return (PnvCPUState *)cpu->machine_data; } +#define TYPE_PNV_QUAD "powernv-cpu-quad" +#define PNV_QUAD(obj) \ +OBJECT_CHECK(PnvQuad, (obj), TYPE_PNV_QUAD) + +typedef struct PnvQuad { +DeviceState parent_obj; + +uint32_t id; +MemoryRegion xscom_regs; +} PnvQuad; #endif /* _PPC_PNV_CORE_H */ diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index 3292459fbb78..68dfae0dfe41 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -60,10 +60,6 @@ typedef struct PnvXScomInterfaceClass { (PNV_XSCOM_EX_CORE_BASE | ((uint64_t)(core) << 24)) #define PNV_XSCOM_EX_SIZE 0x10 -#define PNV_XSCOM_P9_EC_BASE(core) \ -((uint64_t)(((core) & 0x1F) + 0x20) << 24) -#define PNV_XSCOM_P9_EC_SIZE 0x10 - #define PNV_XSCOM_LPC_BASE0xb0020 #define PNV_XSCOM_LPC_SIZE0x4 @@ -73,6 +69,14 @@ typedef struct PnvXScomInterfaceClass { #define PNV_XSCOM_OCC_BASE0x0066000 #define PNV_XSCOM_OCC_SIZE0x6000 +#define PNV9_XSCOM_EC_BASE(core) \ +((uint64_t)(((core) & 0x1F) + 0x20) << 24) +#define PNV9_XSCOM_EC_SIZE0x10 + +#define PNV9_XSCOM_EQ_BASE(core) \ +((uint64_t)(((core) & 0x1C) + 0x40) << 22) +#define PNV9_XSCOM_EQ_SIZE0x10 + #define PNV9_XSCOM_OCC_BASE PNV_XSCOM_OCC_BASE #define PNV9_XSCOM_OCC_SIZE 0x8000 diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 1559a733235b..e68d419203e8 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -963,6 +963,36 @@ static void pnv_chip_power9_instance_init(Object *obj) OBJECT(>psi), _abort); } +static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) +{ +PnvChip *chip = PNV_CHIP(chip9); +const char *typename = pnv_chip_core_typename(chip); +size_t typesize = object_type_get_instance_size(typename); +int i; + +chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); +chip9->quads = g_new0(PnvQuad, chip9->nr_quads); + +for (i = 0; i < chip9->nr_quads; i++) { +char eq_name[32]; +PnvQuad *eq = >quads[i]; +PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize); +int core_id = CPU_CORE(pnv_core)->core_id; + +object_initialize(eq, sizeof(*eq), TYPE_PNV_QUAD); +snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); + +object_property_add_child(OBJECT(chip), eq_name, OBJECT(eq), + _fatal); +object_property_set_int(OBJECT(eq), core_id, "id", _fatal); +object_property_set_bool(OBJECT(eq), true, "realized", _fatal); +object_unref(OBJECT(eq)); + +pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), +>xscom_regs); +} +} + static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); @@ -977,6 +1007,12 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) return; } +pnv_chip_quad_realize(chip9, _err); +if (local_err) { +error_propagate(errp, local_err); +return; +} + /* XIVE interrupt controller (POWER9) */ object_property_set_int(OBJECT(>xive), PNV9_XIVE_IC_BASE(chip), "ic-bar", _fatal); @@ -1135,7 +1171,7 @@ static void