[Skiboot] [PATCH 12/16] core/fast-reboot: fast reboot specific sreset patch

Nicholas Piggin npiggin at gmail.com
Tue Jan 8 01:04:24 AEDT 2019


Provide an sreset handler specifically for fast reboots, which allows
FIXUP_ENDIAN to be removed from the normal sreset handler in the next
patch.

The save_1 == 0 condition is no longer required to signal a fast
reboot.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 asm/head.S         | 37 +++++++++++++++++++++++++------------
 core/fast-reboot.c | 19 ++++++++-----------
 core/init.c        | 13 ++++++++++++-
 include/skiboot.h  |  3 +++
 4 files changed, 48 insertions(+), 24 deletions(-)

diff --git a/asm/head.S b/asm/head.S
index f6475bcab..e9d9d9998 100644
--- a/asm/head.S
+++ b/asm/head.S
@@ -698,12 +698,7 @@ reset_wakeup:
 	GET_CPU()
 
 	/* Restore original stack pointer */
-	ld	%r3,CPUTHREAD_SAVE_R1(%r13)
-
-	/* If it's 0, we are doing a fast reboot */
-	cmpldi	%r3,0
-	beq	fast_reset_entry
-	mr	%r1,%r3
+	ld	%r1,CPUTHREAD_SAVE_R1(%r13)
 
 	/* Restore more stuff */
 	lwz	%r3,STACK_CR(%r1)
@@ -740,13 +735,31 @@ reset_wakeup:
 	mtlr	%r0
 	blr
 
-/* Fast reset code. We clean up the TLB and a few SPRs and
- * return to C code. All CPUs do that, the CPU triggering the
- * reset does it to itself last. The C code will sort out who
- * the master is. We come from the trampoline above with
- * r30 containing SKIBOOT_BASE
+.global reset_fast_reboot_patch_start
+reset_fast_reboot_patch_start:
+	FIXUP_ENDIAN	/* HILE bit may or may not be set */
+	smt_medium
+	LOAD_IMM64(%r30, SKIBOOT_BASE)
+	LOAD_IMM32(%r3, reset_fast_reboot_wakeup - __head)
+	add	%r3,%r30,%r3
+	mtctr	%r3
+	bctr
+.global reset_fast_reboot_patch_end
+reset_fast_reboot_patch_end:
+
+/* Fast reset code. We reset the stack, clean up the TLB and a few SPRs and
+ * jump to C code. All CPUs do that, the CPU triggering the reset does it to
+ * itself last. The C code will sort out who the master is. We come from the
+ * trampoline above with r30 containing SKIBOOT_BASE
  */
-fast_reset_entry:
+reset_fast_reboot_wakeup:
+	/* Get PIR */
+	mfspr	%r31,SPR_PIR
+
+	/* Get that CPU stack base and use it to restore r13 */
+	GET_STACK(%r1,%r31)
+	GET_CPU()
+
 	/* Clear out SLB */
 	li	%r6,0
 	slbmte	%r6,%r6
diff --git a/core/fast-reboot.c b/core/fast-reboot.c
index d3cc8cf5d..d841474d9 100644
--- a/core/fast-reboot.c
+++ b/core/fast-reboot.c
@@ -110,7 +110,6 @@ static bool fast_reboot_sanity_check(void)
 
 void fast_reboot(void)
 {
-	struct cpu_thread *cpu;
 	static int fast_reboot_count = 0;
 
 	if (!chip_quirk(QUIRK_MAMBO_CALLOUTS) &&
@@ -157,19 +156,15 @@ void fast_reboot(void)
 		return;
 	}
 
+	cpu_set_sreset_enable(false);
+	cpu_set_ipi_enable(false);
+
 	/*
 	 * There is no point clearing special wakeup or un-quiesce due to
 	 * failure after this point, because we will be going to full IPL.
 	 * Less cleanup work means less opportunity to fail.
 	 */
 
-	for_each_ungarded_cpu(cpu) {
-		/* Also make sure that saved_r1 is 0 ! That's what will
-		 * make our reset vector jump to fast_reboot_entry
-		 */
-		cpu->save_r1 = 0;
-	}
-
 	/*
 	 * Move SPRs and exception vectors back to OPAL-mode while all
 	 * others are quiesced. MSR[ME] is disabled while these are switched,
@@ -206,7 +201,7 @@ void fast_reboot(void)
 	 * sreset vector has a FIXUP_ENDIAN sequence at the start, so
 	 * secondaries can cope.
 	 */
-	copy_sreset_vector();
+	copy_sreset_vector_fast_reboot();
 
 	/* Send everyone else to 0x100 */
 	if (sreset_all_others() != OPAL_SUCCESS) {
@@ -374,9 +369,8 @@ void __noreturn fast_reboot_entry(void)
 	 */
 	cpu_state_wait_all_others(cpu_state_present, 0);
 
-	if (proc_gen == proc_gen_p9) {
+	if (proc_gen == proc_gen_p9)
 		xive_reset();
-	}
 
 	prlog(PR_INFO, "RESET: Releasing secondaries...\n");
 
@@ -405,6 +399,9 @@ void __noreturn fast_reboot_entry(void)
 	/* Let the CPU layer do some last minute global cleanups */
 	cpu_fast_reboot_complete();
 
+	/* Restore OPAL's sreset vector now that all CPUs have HILE clear */
+	copy_sreset_vector();
+
 	/* We can now do NAP mode */
 	cpu_set_sreset_enable(true);
 	cpu_set_ipi_enable(true);
diff --git a/core/init.c b/core/init.c
index 3f7dd14ee..e09550740 100644
--- a/core/init.c
+++ b/core/init.c
@@ -793,7 +793,18 @@ void copy_sreset_vector(void)
 	while(src < &reset_patch_end)
 		*(dst++) = *(src++);
 	sync_icache();
-	cpu_set_sreset_enable(true);
+}
+
+void copy_sreset_vector_fast_reboot(void)
+{
+	uint32_t *src, *dst;
+
+	/* Copy the reset code over the entry point. */
+	src = &reset_fast_reboot_patch_start;
+	dst = (uint32_t *)0x100;
+	while(src < &reset_fast_reboot_patch_end)
+		*(dst++) = *(src++);
+	sync_icache();
 }
 
 void copy_exception_vectors(void)
diff --git a/include/skiboot.h b/include/skiboot.h
index fedd7b345..96caa2714 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -200,6 +200,7 @@ extern void init_replicated_sprs(void);
 extern bool start_preload_kernel(void);
 extern void copy_exception_vectors(void);
 extern void copy_sreset_vector(void);
+extern void copy_sreset_vector_fast_reboot(void);
 
 /* Various probe routines, to replace with an initcall system */
 extern void probe_p7ioc(void);
@@ -292,6 +293,8 @@ extern void enter_p9_pm_state(uint64_t psscr);
 extern void enter_p9_pm_lite_state(uint64_t psscr);
 extern uint32_t reset_patch_start;
 extern uint32_t reset_patch_end;
+extern uint32_t reset_fast_reboot_patch_start;
+extern uint32_t reset_fast_reboot_patch_end;
 
 /* Fallback fake NVRAM */
 extern int fake_nvram_info(uint32_t *total_size);
-- 
2.18.0



More information about the Skiboot mailing list