aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorRyan Grimm <grimm@linux.vnet.ibm.com>2020-08-04 23:02:13 +0530
committerOliver O'Halloran <oohall@gmail.com>2020-08-07 16:00:20 +1000
commit2d065e249f78e11ddeca0c84920b28a7ca4f8ee1 (patch)
tree0dcbaee1a6b13760e63b911cb58e61061d47e440 /core
parent043725d49d3b2c0b6ea3c37395aa5d6e38d5e73a (diff)
downloadskiboot-2d065e249f78e11ddeca0c84920b28a7ca4f8ee1.zip
skiboot-2d065e249f78e11ddeca0c84920b28a7ca4f8ee1.tar.gz
skiboot-2d065e249f78e11ddeca0c84920b28a7ca4f8ee1.tar.bz2
Add basic P9 fused core support
P9 cores can be configured into fused core mode where two core chiplets function as an 8-threaded, single core. So, bump four to eight in boot_entry when in fused core mode and cpu_thread_count in init_boot_cpu. The HID, AMOR, TSCR, RPR require the first active thread on that core chiplet to load the copy for that core chiplet. So, send thread 1 of a fused core to init_shared_sprs in boot_entry. The code checks for fused core mode in the core thead state register and puts a field in struct cpu_thread. This flag is checked when updating the HID and in XIVE code when setting the special bar. For XSCOM, the core ID is the non-fused EX. So, create macros to arrange the bits. It's fairly verbose but somewhat readable. This was tested on a P9 ZZ with 16 fused cores and ran HTX for over 24 hours. Signed-off-by: Ryan Grimm <grimm@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.ibm.com> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Diffstat (limited to 'core')
-rw-r--r--core/chip.c19
-rw-r--r--core/cpu.c31
2 files changed, 39 insertions, 11 deletions
diff --git a/core/chip.c b/core/chip.c
index 191432d..5c3276a 100644
--- a/core/chip.c
+++ b/core/chip.c
@@ -6,6 +6,7 @@
#include <console.h>
#include <device.h>
#include <timebase.h>
+#include <cpu.h>
static struct proc_chip *chips[MAX_CHIPS];
enum proc_chip_quirks proc_chip_quirks;
@@ -22,9 +23,12 @@ uint32_t pir_to_chip_id(uint32_t pir)
uint32_t pir_to_core_id(uint32_t pir)
{
- if (proc_gen == proc_gen_p9)
- return P9_PIR2COREID(pir);
- else if (proc_gen == proc_gen_p8)
+ if (proc_gen == proc_gen_p9) {
+ if (this_cpu()->is_fused_core)
+ return P9_PIRFUSED2NORMALCOREID(pir);
+ else
+ return P9_PIR2COREID(pir);
+ } else if (proc_gen == proc_gen_p8)
return P8_PIR2COREID(pir);
else
assert(false);
@@ -32,9 +36,12 @@ uint32_t pir_to_core_id(uint32_t pir)
uint32_t pir_to_thread_id(uint32_t pir)
{
- if (proc_gen == proc_gen_p9)
- return P9_PIR2THREADID(pir);
- else if (proc_gen == proc_gen_p8)
+ if (proc_gen == proc_gen_p9) {
+ if (this_cpu()->is_fused_core)
+ return P9_PIR2FUSEDTHREADID(pir);
+ else
+ return P9_PIR2THREADID(pir);
+ } else if (proc_gen == proc_gen_p8)
return P8_PIR2THREADID(pir);
else
assert(false);
diff --git a/core/cpu.c b/core/cpu.c
index 73777dd..158f73e 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -932,6 +932,7 @@ static void init_cpu_thread(struct cpu_thread *t,
#ifdef STACK_CHECK_ENABLED
t->stack_bot_mark = LONG_MAX;
#endif
+ t->is_fused_core = is_fused_core(mfspr(SPR_PVR));
assert(pir == container_of(t, struct cpu_stack, cpu) - cpu_stacks);
}
@@ -1016,14 +1017,16 @@ void init_boot_cpu(void)
" (max %d threads/core)\n", cpu_thread_count);
break;
case proc_gen_p9:
- cpu_thread_count = 4;
+ if (is_fused_core(pvr))
+ cpu_thread_count = 8;
+ else
+ cpu_thread_count = 4;
prlog(PR_INFO, "CPU: P9 generation processor"
" (max %d threads/core)\n", cpu_thread_count);
break;
default:
prerror("CPU: Unknown PVR, assuming 1 thread\n");
cpu_thread_count = 1;
- cpu_max_pir = mfspr(SPR_PIR);
}
if (is_power9n(pvr) && (PVR_VERS_MAJ(pvr) == 1)) {
@@ -1151,7 +1154,7 @@ void init_all_cpus(void)
/* Iterate all CPUs in the device-tree */
dt_for_each_child(cpus, cpu) {
- unsigned int pir, server_no, chip_id;
+ unsigned int pir, server_no, chip_id, threads;
enum cpu_thread_state state;
const struct dt_property *p;
struct cpu_thread *t, *pt;
@@ -1181,6 +1184,14 @@ void init_all_cpus(void)
prlog(PR_INFO, "CPU: CPU from DT PIR=0x%04x Server#=0x%x"
" State=%d\n", pir, server_no, state);
+ /* Check max PIR */
+ if (cpu_max_pir < (pir + cpu_thread_count - 1)) {
+ prlog(PR_WARNING, "CPU: CPU potentially out of range"
+ "PIR=0x%04x MAX=0x%04x !\n",
+ pir, cpu_max_pir);
+ continue;
+ }
+
/* Setup thread 0 */
assert(pir <= cpu_max_pir);
t = pt = &cpu_stacks[pir].cpu;
@@ -1206,11 +1217,21 @@ void init_all_cpus(void)
/* Add the decrementer width property */
dt_add_property_cells(cpu, "ibm,dec-bits", dec_bits);
+ if (t->is_fused_core)
+ dt_add_property(t->node, "ibm,fused-core", NULL, 0);
+
/* Iterate threads */
p = dt_find_property(cpu, "ibm,ppc-interrupt-server#s");
if (!p)
continue;
- for (thread = 1; thread < (p->len / 4); thread++) {
+ threads = p->len / 4;
+ if (threads > cpu_thread_count) {
+ prlog(PR_WARNING, "CPU: Threads out of range for PIR 0x%04x"
+ " threads=%d max=%d\n",
+ pir, threads, cpu_thread_count);
+ threads = cpu_thread_count;
+ }
+ for (thread = 1; thread < threads; thread++) {
prlog(PR_TRACE, "CPU: secondary thread %d found\n",
thread);
t = &cpu_stacks[pir + thread].cpu;
@@ -1396,7 +1417,7 @@ static int64_t cpu_change_all_hid0(struct hid0_change_req *req)
assert(jobs);
for_each_available_cpu(cpu) {
- if (!cpu_is_thread0(cpu))
+ if (!cpu_is_thread0(cpu) && !cpu_is_core_chiplet_primary(cpu))
continue;
if (cpu == this_cpu())
continue;