Permalink
Browse files

Fast reboot for P8

This is an experimental patch that implements "Fast reboot" on P8
machines.

The basic idea is that when the OS calls OPAL reboot, we gather all
the threads in the system using a combination of patching the reset
vector and soft-resetting them, then cleanup a few bits of hardware
(we do re-probe PCIe for example), and reload & restart the bootloader.

For Trusted Boot, this means we *add* measurements to the TPM, so you
will get *different* PCR values as compared to a full IPL. This makes
sense as if you want to be sure you are running something known then,
well, do a full IPL as soft reset should never be trusted to clear any
malicious code.

This is very experimental and needs a lot of testing and also auditing
code for other bits of HW that might need to be cleaned up.

BenH TODO: I also need to check if we are properly PERST'ing PCI devices.

This is partially based on old code I had to do that on P7. I only
support it on P8 though as there are issues with the PSI interrupts
on P7 that cannot be reliably solved.

Even though this should be considered somewhat experimental, we've had
a lot of success on a variety of machines. Dozens/hundreds of reboots
across Tuleta, Garrison and Habanero.

Currently, we've hidden it behind a NVRAM config option, which *is*
liable to change in the future (to ensure that only those who know
what they're doing enable it)

You can enable the experimental support via nvram option:
 nvram -p ibm,skiboot --update-config experimental-fast-reset=feeling-lucky

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
[stewart@linux.vnet.ibm.com: hide behind nvram option, include Mambo fixes
from Mikey]
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
  • Loading branch information...
ozbenh authored and stewart-ibm committed Jul 23, 2016
1 parent 8110b05 commit 0279d8951ead549fdebce93130a2f6c673081862
Showing with 527 additions and 312 deletions.
  1. +61 −61 asm/head.S
  2. +361 −177 core/fast-reboot.c
  3. +6 −2 core/init.c
  4. +3 −0 core/lock.c
  5. +10 −2 core/pci.c
  6. +5 −4 core/platform.c
  7. +5 −0 hw/fsp/fsp-console.c
  8. +3 −0 hw/fsp/fsp-leds.c
  9. +5 −0 hw/occ.c
  10. +43 −60 hw/psi.c
  11. +5 −2 hw/slw.c
  12. +0 −3 include/config.h
  13. +1 −0 include/cpu.h
  14. +1 −0 include/processor.h
  15. +8 −1 include/skiboot.h
  16. +10 −0 platforms/mambo/mambo.c
View
@@ -458,64 +458,6 @@ call_relocate:
1: /* Fatal relocate failure */
attn
/* This is a little piece of code that is copied down to
* 0x100 when doing a "fast reset"
*/
.global fast_reset_patch_start
fast_reset_patch_start:
smt_medium
LOAD_IMM64(%r30, SKIBOOT_BASE)
LOAD_IMM32(%r3, fast_reset_entry - __head)
add %r3,%r30,%r3
mtctr %r3
bctr
.global fast_reset_patch_end
fast_reset_patch_end:
/* 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
*/
fast_reset_entry:
/* Clear out SLB */
li %r6,0
slbmte %r6,%r6
slbia
ptesync
/* Get PIR */
mfspr %r31,SPR_PIR
/* Get a stack and restore r13 */
GET_STACK(%r1,%r31)
li %r3,0
std %r3,0(%r1)
std %r3,8(%r1)
std %r3,16(%r1)
GET_CPU()
/* Get our TOC */
addis %r2,%r30,(__toc_start - __head)@ha
addi %r2,%r2,(__toc_start - __head)@l
/* Go to C ! */
bl fast_reboot
b .
.global cleanup_tlb
cleanup_tlb:
/* Clean the TLB */
li %r3,128
mtctr %r3
li %r4,0x800 /* IS field = 0b10 */
ptesync
1: tlbiel %r4
addi %r4,%r4,0x1000
bdnz 1b
ptesync
#define FIXUP_ENDIAN \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
b $+36; /* Skip trampoline if endian is good */ \
@@ -624,7 +566,12 @@ reset_wakeup:
GET_CPU()
/* Restore original stack pointer */
ld %r1,CPUTHREAD_SAVE_R1(%r13)
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
/* Restore more stuff */
lwz %r3,STACK_CR(%r1)
@@ -661,6 +608,46 @@ 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
*/
fast_reset_entry:
/* Clear out SLB */
li %r6,0
slbmte %r6,%r6
slbia
ptesync
/* Dummy stack frame */
li %r3,0
std %r3,0(%r1)
std %r3,8(%r1)
std %r3,16(%r1)
/* Get our TOC */
addis %r2,%r30,(__toc_start - __head)@ha
addi %r2,%r2,(__toc_start - __head)@l
/* Go to C ! */
bl fast_reboot_entry
b .
.global cleanup_tlb
cleanup_tlb:
/* Clean the TLB */
li %r3,512
mtctr %r3
li %r4,0xc00 /* IS field = 0b11 */
ptesync
1: tlbiel %r4
addi %r4,%r4,0x1000
bdnz 1b
ptesync
blr
/* Functions to initialize replicated and shared SPRs to sane
* values. This is called at boot and on soft-reset
*/
@@ -708,10 +695,14 @@ init_shared_sprs:
mtspr SPR_LPCR,%r3
sync
isync
/* HID0: Clear bit 13 (enable core recovery) */
/* HID0: Clear bit 13 (enable core recovery)
* Clear bit 19 (HILE)
*/
mfspr %r3,SPR_HID0
li %r0,1
sldi %r0,%r0,(63-13)
sldi %r4,%r0,(63-13)
sldi %r5,%r0,(63-19)
or %r0,%r4,%r5,
andc %r3,%r3,%r0
sync
mtspr SPR_HID0,%r3
@@ -743,6 +734,15 @@ init_replicated_sprs:
/* XXX TODO: Add more */
blr
.global enter_nap
enter_nap:
std %r0,0(%r1)
ptesync
ld %r0,0(%r1)
1: cmp %cr0,%r0,%r0
bne 1b
nap
b .
/*
*
* NACA structure, accessed by the FPS to find the SPIRA
Oops, something went wrong.

0 comments on commit 0279d89

Please sign in to comment.