aboutsummaryrefslogtreecommitdiff
path: root/core/cpu.c
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2019-01-08 00:04:26 +1000
committerStewart Smith <stewart@linux.ibm.com>2019-02-13 14:36:44 +1100
commit8a43bf86b7d4346521bd4ebc15eb3809d3d27adb (patch)
treed17ac162d4037ecff73d27477ffc61945a37ac4e /core/cpu.c
parent4ebb78cffda897c4175f6659e98e6722ea60703f (diff)
downloadskiboot-8a43bf86b7d4346521bd4ebc15eb3809d3d27adb.zip
skiboot-8a43bf86b7d4346521bd4ebc15eb3809d3d27adb.tar.gz
skiboot-8a43bf86b7d4346521bd4ebc15eb3809d3d27adb.tar.bz2
core/exceptions: implement an exception handler for non-powersave sresets
Detect non-powersave sresets and send them to the normal exception handler which prints registers and stack. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'core/cpu.c')
-rw-r--r--core/cpu.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/core/cpu.c b/core/cpu.c
index ad64b6e..50f399c 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -380,14 +380,15 @@ enum cpu_wake_cause {
cpu_wake_on_dec,
};
-static void cpu_idle_p8(enum cpu_wake_cause wake_on)
+static unsigned int cpu_idle_p8(enum cpu_wake_cause wake_on)
{
uint64_t lpcr = mfspr(SPR_LPCR) & ~SPR_LPCR_P8_PECE;
struct cpu_thread *cpu = this_cpu();
+ unsigned int vec = 0;
if (!pm_enabled) {
prlog_once(PR_DEBUG, "cpu_idle_p8 called pm disabled\n");
- return;
+ return vec;
}
/* Clean up ICP, be ready for IPIs */
@@ -426,6 +427,7 @@ static void cpu_idle_p8(enum cpu_wake_cause wake_on)
/* Enter nap */
enter_p8_pm_state(false);
+ vec = 0x100;
skip_sleep:
/* Restore */
@@ -433,17 +435,20 @@ skip_sleep:
cpu->in_idle = false;
cpu->in_sleep = false;
reset_cpu_icp();
+
+ return vec;
}
-static void cpu_idle_p9(enum cpu_wake_cause wake_on)
+static unsigned int cpu_idle_p9(enum cpu_wake_cause wake_on)
{
uint64_t lpcr = mfspr(SPR_LPCR) & ~SPR_LPCR_P9_PECE;
uint64_t psscr;
struct cpu_thread *cpu = this_cpu();
+ unsigned int vec = 0;
if (!pm_enabled) {
prlog_once(PR_DEBUG, "cpu_idle_p9 called pm disabled\n");
- return;
+ return vec;
}
/* Synchronize with wakers */
@@ -482,6 +487,7 @@ static void cpu_idle_p9(enum cpu_wake_cause wake_on)
psscr = PPC_BIT(42) | PPC_BIT(43) |
PPC_BITMASK(54, 55) | PPC_BIT(63);
enter_p9_pm_state(psscr);
+ vec = 0x100;
} else {
/* stop with EC=0 (resumes) which does not require sreset. */
/* PSSCR SD=0 ESL=0 EC=0 PSSL=0 TR=3 MTL=0 RL=1 */
@@ -497,21 +503,38 @@ static void cpu_idle_p9(enum cpu_wake_cause wake_on)
sync();
cpu->in_idle = false;
cpu->in_sleep = false;
+
+ return vec;
}
static void cpu_idle_pm(enum cpu_wake_cause wake_on)
{
+ unsigned int vec;
+
switch(proc_gen) {
case proc_gen_p8:
- cpu_idle_p8(wake_on);
+ vec = cpu_idle_p8(wake_on);
break;
case proc_gen_p9:
- cpu_idle_p9(wake_on);
+ vec = cpu_idle_p9(wake_on);
break;
default:
+ vec = 0;
prlog_once(PR_DEBUG, "cpu_idle_pm called with bad processor type\n");
break;
}
+
+ if (vec == 0x100) {
+ unsigned long srr1 = mfspr(SPR_SRR1);
+
+ switch (srr1 & SPR_SRR1_PM_WAKE_MASK) {
+ case SPR_SRR1_PM_WAKE_SRESET:
+ exception_entry_pm_sreset();
+ break;
+ default:
+ break;
+ }
+ }
}
void cpu_idle_job(void)