ppc/pnv: Improve pervasive topology calculation for big-core
Big (SMT8) cores have a complicated function to map the core, thread ID to pervasive topology (PIR). Fix this for power8, power9, and power10. Reviewed-by: Cédric Le Goater <clg@kaod.org> Signed-off-by: Caleb Schlossin <calebs@linux.vnet.ibm.com> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
This commit is contained in:
parent
0b8893236e
commit
9940412ae4
71
hw/ppc/pnv.c
71
hw/ppc/pnv.c
@ -141,8 +141,10 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
|
||||
int smt_threads = CPU_CORE(pc)->nr_threads;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
|
||||
PnvChipClass *pnv_cc = PNV_CHIP_GET_CLASS(chip);
|
||||
g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads);
|
||||
int i;
|
||||
uint32_t pir;
|
||||
uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
|
||||
0xffffffff, 0xffffffff};
|
||||
uint32_t tbfreq = PNV_TIMEBASE_FREQ;
|
||||
@ -153,15 +155,17 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
|
||||
char *nodename;
|
||||
int cpus_offset = get_cpus_node(fdt);
|
||||
|
||||
nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
|
||||
pir = pnv_cc->chip_pir(chip, pc->hwid, 0);
|
||||
|
||||
nodename = g_strdup_printf("%s@%x", dc->fw_name, 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_cell(fdt, offset, "reg", pir)));
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pir)));
|
||||
_FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
|
||||
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
|
||||
@ -233,7 +237,7 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
|
||||
|
||||
/* Build interrupt servers properties */
|
||||
for (i = 0; i < smt_threads; i++) {
|
||||
servers_prop[i] = cpu_to_be32(pc->pir + i);
|
||||
servers_prop[i] = cpu_to_be32(pnv_cc->chip_pir(chip, pc->hwid, i));
|
||||
}
|
||||
_FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
|
||||
servers_prop, sizeof(*servers_prop) * smt_threads)));
|
||||
@ -241,9 +245,11 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
|
||||
static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t hwid,
|
||||
uint32_t nr_threads)
|
||||
{
|
||||
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
|
||||
uint32_t pir = pcc->chip_pir(chip, hwid, 0);
|
||||
uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
|
||||
char *name;
|
||||
const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
|
||||
@ -257,6 +263,7 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
|
||||
rsize = sizeof(uint64_t) * 2 * nr_threads;
|
||||
reg = g_malloc(rsize);
|
||||
for (i = 0; i < nr_threads; i++) {
|
||||
/* We know P8 PIR is linear with thread id */
|
||||
reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
|
||||
reg[i * 2 + 1] = cpu_to_be64(0x1000);
|
||||
}
|
||||
@ -324,7 +331,7 @@ static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
|
||||
pa_features_207, sizeof(pa_features_207))));
|
||||
|
||||
/* Interrupt Control Presenters (ICP). One per core. */
|
||||
pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
|
||||
pnv_dt_icp(chip, fdt, pnv_core->hwid, CPU_CORE(pnv_core)->nr_threads);
|
||||
}
|
||||
|
||||
if (chip->ram_size) {
|
||||
@ -1075,9 +1082,10 @@ static void pnv_init(MachineState *machine)
|
||||
* 25:28 Core number
|
||||
* 29:31 Thread ID
|
||||
*/
|
||||
static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
|
||||
static uint32_t pnv_chip_pir_p8(PnvChip *chip, uint32_t core_id,
|
||||
uint32_t thread_id)
|
||||
{
|
||||
return (chip->chip_id << 7) | (core_id << 3);
|
||||
return (chip->chip_id << 7) | (core_id << 3) | thread_id;
|
||||
}
|
||||
|
||||
static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
|
||||
@ -1129,14 +1137,37 @@ static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
|
||||
*
|
||||
* We only care about the lower bits. uint32_t is fine for the moment.
|
||||
*/
|
||||
static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
|
||||
static uint32_t pnv_chip_pir_p9(PnvChip *chip, uint32_t core_id,
|
||||
uint32_t thread_id)
|
||||
{
|
||||
return (chip->chip_id << 8) | (core_id << 2);
|
||||
if (chip->nr_threads == 8) {
|
||||
return (chip->chip_id << 8) | ((thread_id & 1) << 2) | (core_id << 3) |
|
||||
(thread_id >> 1);
|
||||
} else {
|
||||
return (chip->chip_id << 8) | (core_id << 2) | thread_id;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
|
||||
/*
|
||||
* 0:48 Reserved - Read as zeroes
|
||||
* 49:52 Node ID
|
||||
* 53:55 Chip ID
|
||||
* 56 Reserved - Read as zero
|
||||
* 57:59 Quad ID
|
||||
* 60 Core Chiplet Pair ID
|
||||
* 61:63 Thread/Core Chiplet ID t0-t2
|
||||
*
|
||||
* We only care about the lower bits. uint32_t is fine for the moment.
|
||||
*/
|
||||
static uint32_t pnv_chip_pir_p10(PnvChip *chip, uint32_t core_id,
|
||||
uint32_t thread_id)
|
||||
{
|
||||
return (chip->chip_id << 8) | (core_id << 2);
|
||||
if (chip->nr_threads == 8) {
|
||||
return (chip->chip_id << 8) | ((core_id / 4) << 4) |
|
||||
((core_id % 2) << 3) | thread_id;
|
||||
} else {
|
||||
return (chip->chip_id << 8) | (core_id << 2) | thread_id;
|
||||
}
|
||||
}
|
||||
|
||||
static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
|
||||
@ -1315,7 +1346,7 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
|
||||
int core_hwid = CPU_CORE(pnv_core)->core_id;
|
||||
|
||||
for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
|
||||
uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
|
||||
uint32_t pir = pcc->chip_pir(chip, core_hwid, j);
|
||||
PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
|
||||
|
||||
memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
|
||||
@ -1428,7 +1459,7 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
|
||||
k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */
|
||||
k->cores_mask = POWER8E_CORE_MASK;
|
||||
k->num_phbs = 3;
|
||||
k->core_pir = pnv_chip_core_pir_p8;
|
||||
k->chip_pir = pnv_chip_pir_p8;
|
||||
k->intc_create = pnv_chip_power8_intc_create;
|
||||
k->intc_reset = pnv_chip_power8_intc_reset;
|
||||
k->intc_destroy = pnv_chip_power8_intc_destroy;
|
||||
@ -1452,7 +1483,7 @@ static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
|
||||
k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
|
||||
k->cores_mask = POWER8_CORE_MASK;
|
||||
k->num_phbs = 3;
|
||||
k->core_pir = pnv_chip_core_pir_p8;
|
||||
k->chip_pir = pnv_chip_pir_p8;
|
||||
k->intc_create = pnv_chip_power8_intc_create;
|
||||
k->intc_reset = pnv_chip_power8_intc_reset;
|
||||
k->intc_destroy = pnv_chip_power8_intc_destroy;
|
||||
@ -1476,7 +1507,7 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
|
||||
k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */
|
||||
k->cores_mask = POWER8_CORE_MASK;
|
||||
k->num_phbs = 4;
|
||||
k->core_pir = pnv_chip_core_pir_p8;
|
||||
k->chip_pir = pnv_chip_pir_p8;
|
||||
k->intc_create = pnv_chip_power8_intc_create;
|
||||
k->intc_reset = pnv_chip_power8_intc_reset;
|
||||
k->intc_destroy = pnv_chip_power8_intc_destroy;
|
||||
@ -1749,7 +1780,7 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
|
||||
k->cores_mask = POWER9_CORE_MASK;
|
||||
k->core_pir = pnv_chip_core_pir_p9;
|
||||
k->chip_pir = pnv_chip_pir_p9;
|
||||
k->intc_create = pnv_chip_power9_intc_create;
|
||||
k->intc_reset = pnv_chip_power9_intc_reset;
|
||||
k->intc_destroy = pnv_chip_power9_intc_destroy;
|
||||
@ -2061,7 +2092,7 @@ static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
|
||||
k->cores_mask = POWER10_CORE_MASK;
|
||||
k->core_pir = pnv_chip_core_pir_p10;
|
||||
k->chip_pir = pnv_chip_pir_p10;
|
||||
k->intc_create = pnv_chip_power10_intc_create;
|
||||
k->intc_reset = pnv_chip_power10_intc_reset;
|
||||
k->intc_destroy = pnv_chip_power10_intc_destroy;
|
||||
@ -2151,8 +2182,8 @@ static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
|
||||
chip->nr_threads, &error_fatal);
|
||||
object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
|
||||
core_hwid, &error_fatal);
|
||||
object_property_set_int(OBJECT(pnv_core), "pir",
|
||||
pcc->core_pir(chip, core_hwid), &error_fatal);
|
||||
object_property_set_int(OBJECT(pnv_core), "hwid", core_hwid,
|
||||
&error_fatal);
|
||||
object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
|
||||
&error_fatal);
|
||||
object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
|
||||
|
@ -226,7 +226,7 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
|
||||
int thread_index)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
int core_pir;
|
||||
int core_hwid;
|
||||
ppc_spr_t *pir = &env->spr_cb[SPR_PIR];
|
||||
ppc_spr_t *tir = &env->spr_cb[SPR_TIR];
|
||||
Error *local_err = NULL;
|
||||
@ -242,10 +242,10 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
|
||||
return;
|
||||
}
|
||||
|
||||
core_pir = object_property_get_uint(OBJECT(pc), "pir", &error_abort);
|
||||
core_hwid = object_property_get_uint(OBJECT(pc), "hwid", &error_abort);
|
||||
|
||||
tir->default_value = thread_index;
|
||||
pir->default_value = core_pir + thread_index;
|
||||
pir->default_value = pcc->chip_pir(pc->chip, core_hwid, thread_index);
|
||||
|
||||
/* Set time-base frequency to 512 MHz */
|
||||
cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
|
||||
@ -342,7 +342,7 @@ static void pnv_core_unrealize(DeviceState *dev)
|
||||
}
|
||||
|
||||
static Property pnv_core_properties[] = {
|
||||
DEFINE_PROP_UINT32("pir", PnvCore, pir, 0),
|
||||
DEFINE_PROP_UINT32("hwid", PnvCore, hwid, 0),
|
||||
DEFINE_PROP_UINT64("hrmor", PnvCore, hrmor, 0),
|
||||
DEFINE_PROP_LINK("chip", PnvCore, chip, TYPE_PNV_CHIP, PnvChip *),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
|
@ -147,7 +147,7 @@ struct PnvChipClass {
|
||||
|
||||
DeviceRealize parent_realize;
|
||||
|
||||
uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);
|
||||
uint32_t (*chip_pir)(PnvChip *chip, uint32_t core_id, uint32_t thread_id);
|
||||
void (*intc_create)(PnvChip *chip, PowerPCCPU *cpu, Error **errp);
|
||||
void (*intc_reset)(PnvChip *chip, PowerPCCPU *cpu);
|
||||
void (*intc_destroy)(PnvChip *chip, PowerPCCPU *cpu);
|
||||
|
@ -36,6 +36,7 @@ struct PnvCore {
|
||||
/*< public >*/
|
||||
PowerPCCPU **threads;
|
||||
uint32_t pir;
|
||||
uint32_t hwid;
|
||||
uint64_t hrmor;
|
||||
PnvChip *chip;
|
||||
|
||||
|
@ -49,9 +49,6 @@ void helper_spr_core_write_generic(CPUPPCState *env, uint32_t sprn,
|
||||
CPUState *cs = env_cpu(env);
|
||||
CPUState *ccs;
|
||||
uint32_t nr_threads = cs->nr_threads;
|
||||
uint32_t core_id = env->spr[SPR_PIR] & ~(nr_threads - 1);
|
||||
|
||||
assert(core_id == env->spr[SPR_PIR] - env->spr[SPR_TIR]);
|
||||
|
||||
if (nr_threads == 1) {
|
||||
env->spr[sprn] = val;
|
||||
|
Loading…
Reference in New Issue
Block a user