aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.ibm.com>2021-06-25 11:49:34 +0530
committerVasant Hegde <hegdevasant@linux.vnet.ibm.com>2021-06-30 15:05:55 +0530
commit2c43e32c837b72bea12be08315d69f0a0f2360ba (patch)
tree9c3741ee794500eed28462af66e9cee78c446865
parent1178a47ab079297cc693421ce0215efadb271a41 (diff)
downloadskiboot-2c43e32c837b72bea12be08315d69f0a0f2360ba.zip
skiboot-2c43e32c837b72bea12be08315d69f0a0f2360ba.tar.gz
skiboot-2c43e32c837b72bea12be08315d69f0a0f2360ba.tar.bz2
core/cpu: Initialize all cpu thread areas to avoid invalid memory access.
Starting from p10 hostboot will no longer clear all the system memory except its own space. OPAL uses the memory at SKIBOOT_BASE + SKIBOOT_SIZE for cpu stack with pir as index. With hostboot no longer clearing memory this region may hold junk contents. Currently opal initialize cpu stack memory only for cpu pir that is found on the device-tree. For the rest, the cpu thread contents are uninitialized. This sometime causes for_each_cpu* macros to return cpu thread for pir/cpu which isn't present on the system. The for_each_cpu* macros iterate over cpu stacks using pir as index and returns cpu thread pointer if state != cpu_state_no_cpu. For cpus that are not found on device-tree the state may hold junk value leading OPAL to access invalid cpu thread area. This further leads to accessing pointers with junk values causing machine check (MCE) during OPAL init code. Fix this by Initializing all the cpu thread areas upto cpu_max_pir. [ 182.049714372,3] *********************************************** [ 182.049878580,3] Fatal MCE at 0000000030039738 .init_trace_buffers+0x21c MSR 9000000000201002 [ 182.049943811,3] Cause: load real address error [ 182.049968681,3] Effective address: 0x480113a4791c4a50 [ 182.050000736,3] CFAR : 00000000300395b8 MSR : 9000000000201002 [ 182.050035376,3] SRR0 : 0000000030039738 SRR1 : 9000000000201002 [ 182.050072878,3] HSRR0: 0000000030020024 HSRR1: 9000000000001000 [ 182.050117303,3] DSISR: 00000040 DAR : 480113a4791c4a50 [ 182.050149054,3] LR : 0000000030039744 CTR : 0000000000000000 [ 182.050182991,3] CR : 42000224 XER : 00000000 [ 182.050217262,3] GPR00: 000000003003962c GPR16: 0000000032d50000 [ 182.050255746,3] GPR01: 0000000032d53a50 GPR17: 0000000030003198 [ 182.050288081,3] GPR02: 000000003014cb00 GPR18: 0000000000000000 [ 182.050331474,3] GPR03: 0000000031c50000 GPR19: 0000000000000000 [ 182.050371934,3] GPR04: 0000000000000000 GPR20: 0000000000000000 [ 182.050416212,3] GPR05: ffffffffffffffff GPR21: 0000000000000001 [ 182.050454130,3] GPR06: 0000000000000005 GPR22: 00000000300f74eb [ 182.050488053,3] GPR07: 0000000000000028 GPR23: 00000000000fffd8 [ 182.050522774,3] GPR08: 000000000000067f GPR24: 00000000000fff40 [ 182.050566878,3] GPR09: 480113a4791c4a18 GPR25: 0000000000000070 [ 182.050601524,3] GPR10: 00000000078b0353 GPR26: 00000000300f7527 [ 182.050640345,3] GPR11: 0000000000000000 GPR27: 00000000300f7516 [ 182.050680816,3] GPR12: 0000000042000222 GPR28: 000000003acd0000 [ 182.050724099,3] GPR13: 000000000025a908 GPR29: 000000003acd0000 [ 182.050759728,3] GPR14: 0000000000000000 GPR30: 0000000000000000 [ 182.050790430,3] GPR15: 0000000000000000 GPR31: 00000000301f0038 CPU 0228 Backtrace: S: 0000000032d53d60 R: 000000003003962c .init_trace_buffers+0x110 S: 0000000032d53e30 R: 0000000030022f84 .main_cpu_entry+0x550 S: 0000000032d53f00 R: 00000000300031f8 not_fused+0x11c Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com> Signed-off-by: Nicholas Piggin <npiggin@gmail.com> [Folded Nick's patch to that added mark_all_secondary_cpus_absent() - Vasant] Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
-rw-r--r--core/cpu.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/core/cpu.c b/core/cpu.c
index f2b5bbc..dbc1ff4 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -1150,10 +1150,30 @@ void init_cpu_max_pir(void)
prlog(PR_DEBUG, "CPU: New max PIR set to 0x%x\n", cpu_max_pir);
}
+/*
+ * Set cpu->state to cpu_state_no_cpu for all secondaries, before the dt is
+ * parsed and they will be flipped to present as populated CPUs are found.
+ *
+ * Some configurations (e.g., with memory encryption) will not zero system
+ * memory at boot, so can't rely on cpu->state to be zero (== cpu_state_no_cpu).
+ */
+static void mark_all_secondary_cpus_absent(void)
+{
+ unsigned int pir;
+ struct cpu_thread *cpu;
+
+ for (pir = 0; pir <= cpu_max_pir; pir++) {
+ cpu = &cpu_stacks[pir].cpu;
+ if (cpu == boot_cpu)
+ continue;
+ cpu->state = cpu_state_no_cpu;
+ }
+}
+
void init_all_cpus(void)
{
struct dt_node *cpus, *cpu;
- unsigned int thread;
+ unsigned int pir, thread;
int dec_bits = find_dec_bits();
cpus = dt_find_by_path(dt_root, "/cpus");
@@ -1161,9 +1181,11 @@ void init_all_cpus(void)
init_tm_suspend_mode_property();
+ mark_all_secondary_cpus_absent();
+
/* Iterate all CPUs in the device-tree */
dt_for_each_child(cpus, cpu) {
- unsigned int pir, server_no, chip_id, threads;
+ unsigned int server_no, chip_id, threads;
enum cpu_thread_state state;
const struct dt_property *p;
struct cpu_thread *t, *pt0, *pt1;