From 37baa9731d0d07cfcc3201105e5c57a07ad91efc Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Tue, 8 Jan 2019 00:04:24 +1000 Subject: core/fast-reboot: fast reboot specific sreset patch 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 Signed-off-by: Stewart Smith --- 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 16ebf93..1659c1b 100644 --- a/asm/head.S +++ b/asm/head.S @@ -700,12 +700,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) @@ -742,13 +737,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 d3cc8cf..d841474 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 3f7dd14..e095507 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 fedd7b3..96caa27 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); -- cgit v1.1