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;
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])));
/* 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)));
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";
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);
}
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) {
* 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,
*
* 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,
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,
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;
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;
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;
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;
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;
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),