powerpc/64s: Use emergency stack for 0x100 system reset interrupt
Nicholas Piggin
reviewerRFC PATCH 1/1 powerpc/64s: Use emergency stack for 0x100 system reset interrupt
Also use EX_NMI save space. This should give cleaner debug data in case kernel stacks have become corrupted.
MSR_RI is kept clear for the 0x100 handler, because we can't mask it, and can't tolerate a reentrant NMI. Technically the 0x100 is not really recoverable yet, because it could trample on another emergency stack user. This will require a bit more work to safely implement, but for now we don't need to recover after a 0x100.
A little bit of the emergency stack / MSR_RI handling differences seem like they can be consolidated with some other handlers. I'll split those into a couple more patches before submitting.
I moved the MC save area in the paca out from between the general and slb save areas, and put it with the nmi area because it shouldn't be used much.
Thanks,
Nick
--- arch/powerpc/include/asm/exception-64s.h | 61 ++++++++++++++++++++++++++++---- arch/powerpc/include/asm/paca.h | 6 +++- arch/powerpc/kernel/asm-offsets.c | 3 +- arch/powerpc/kernel/exceptions-64s.S | 43 ++++++++-------------- 4 files changed, 77 insertions(+), 36 deletions(-)
arch/powerpc/include/asm/exception-64s.h +55 -6
@@ -191,11 +191,32 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)#define EXCEPTION_PROLOG_PSERIES_1 (label, h) \ __EXCEPTION_PROLOG_PSERIES_1(label, h) +/* _NORI variant keeps MSR_RI clear */ +#define __EXCEPTION_PROLOG_PSERIES_1_NORI (label, h) \ + ld r12,PACAKBASE(r13);/* get high part of &label */ \ +ld r10,PACAKMSR (r13 );/* get MSR value for kernel */ \ +xori r10,r10,MSR_RI ;/* Clear MSR_RI */ \ + mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ + LOAD_HANDLER(r12,label) \ + mtspr SPRN_##h##SRR0,r12; \ + mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ + mtspr SPRN_##h##SRR1,r10; \ + h##rfid; \ + b ./* prevent speculative execution */ + +#define EXCEPTION_PROLOG_PSERIES_1_NORI (label, h) \ + __EXCEPTION_PROLOG_PSERIES_1_NORI(label, h) +#define EXCEPTION_PROLOG_PSERIES (area, label, h, extra, vec) \ EXCEPTION_PROLOG_0(area); \ EXCEPTION_PROLOG_1(area, extra, vec); \ EXCEPTION_PROLOG_PSERIES_1(label, h); +#define EXCEPTION_PROLOG_PSERIES_NORI (area, label, h, extra, vec) \ + EXCEPTION_PROLOG_0(area); \ + EXCEPTION_PROLOG_1(area, extra, vec); \ + EXCEPTION_PROLOG_PSERIES_1_NORI(label, h); +#define __KVMTEST (h, n) \ lbz r10,HSTATE_IN_GUEST(r13); \ cmpwi r10,0; \
@@ -273,6 +294,19 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)#define NOTEST (n) +#define EXCEPTION_PROLOG_COMMON_EMSTACK (n, area) \ + mr r10,r1;/* Save r1 */ \ +ld r1,PACAEMERGSP (r13 );/* Use emergency kernel stack */ \ +subi r1,r1,INT_FRAME_SIZE ;/* alloc stack frame */ \ +std r9,_CCR (r1 );/* save CR in stackframe */ \ +std r11,_NIP (r1 );/* save SRR0 in stackframe */ \ +std r12,_MSR (r1 );/* save SRR1 in stackframe */ \ + std r10,0(r1); /* make stack chain pointer */ \ +std r0,GPR0 (r1 );/* save r0 in stackframe */ \ +std r10,GPR1 (r1 );/* save r1 in stackframe */ \ +EXCEPTION_PROLOG_COMMON_2 (area) \ +EXCEPTION_PROLOG_COMMON_3 (n) +/* * The common exception prolog is used for all except a few exceptions * such as a segment miss on a kernel address. We have to be prepared
@@ -495,8 +529,16 @@ BEGIN_FTR_SECTION \beql ppc64_runlatch_on_trampoline; \ END_FTR_SECTION_IFSET(CPU_FTR_CTRL) -#define EXCEPTION_COMMON (trap, label, hdlr, ret, additions) \ - EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ +#define EXCEPTION_COMMON (area, trap, label, hdlr, ret, additions) \ + EXCEPTION_PROLOG_COMMON(trap, area); \ +/* Volatile regs are potentially clobbered here */ \ + additions; \ +addi r3,r1,STACK_FRAME_OVERHEAD ; \ +bl hdlr; \ + b ret + +#define EXCEPTION_COMMON_EMSTACK (area, trap, label, hdlr, ret, additions) \ + EXCEPTION_PROLOG_COMMON_EMSTACK(trap, area); \/* Volatile regs are potentially clobbered here */ \ additions; \addi r3,r1,STACK_FRAME_OVERHEAD ; \
@@ -504,7 +546,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CTRL) b ret#define STD_EXCEPTION_COMMON (trap, label, hdlr) \ - EXCEPTION_COMMON(trap, label, hdlr, ret_from_except, \ + EXCEPTION_COMMON(PACA_EXGEN, trap, label, hdlr, ret_from_except, \ ADD_NVGPRS;ADD_RECONCILE)/*
@@ -512,9 +554,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_CTRL)* in the idle task and therefore need the special idle handling * (finish nap and runlatch) */ -#define STD_EXCEPTION_COMMON_ASYNC (trap, label, hdlr) \ - EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \ - FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON) +#define STD_EXCEPTION_COMMON_ASYNC (trap, label, hdlr) \ + EXCEPTION_COMMON(PACA_EXGEN, trap, label, hdlr, \ + ret_from_except_lite, FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON) + +/* +* Like STD_EXCEPTION_COMMON, but for "NMI" exceptions. +*/ +#define NMI_EXCEPTION_COMMON_ASYNC (trap, label, hdlr) \ + EXCEPTION_COMMON_EMSTACK(PACA_EXNMI, trap, label, hdlr, \ + ret_from_except_lite, FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON)/* * When the idle code in power4_idle puts the CPU into NAP mode,
arch/powerpc/include/asm/paca.h +5 -1
@@ -99,7 +99,6 @@ struct paca_struct {*/ /* used for most interrupts/exceptions */ u64 exgen[13] __attribute__((aligned(0x80))); -u64 exmc[13 ];/* used for machine checks */ u64 exslb[13 ];/* used for SLB/segment table misses * on the linear mapping */ /* SLB related definitions */
@@ -174,6 +173,11 @@ struct paca_struct {u8 subcore_sibling_mask;#endif +#ifdef CONFIG_PPC_STD_MMU_64 +/* Non-maskable exceptions that are not performance critical */ +u64 exnmi[13 ];/* used for system reset (nmi) */ +u64 exmc[13 ];/* used for machine checks */ +#endif #ifdef CONFIG_PPC_BOOK3S_64 /* Exclusive emergency stack pointer for machine check exception. */ void *mc_emergency_sp;
arch/powerpc/kernel/asm-offsets.c +2 -1
@@ -222,8 +222,9 @@ int main(void)DEFINE (PACACONTEXTSLLP , offsetof(struct paca_struct , mm_ctx_sllp));#endif /* CONFIG_PPC_MM_SLICES */ DEFINE (PACA_EXGEN , offsetof(struct paca_struct , exgen)); -DEFINE (PACA_EXMC , offsetof(struct paca_struct , exmc));DEFINE (PACA_EXSLB , offsetof(struct paca_struct , exslb)); +DEFINE (PACA_EXNMI , offsetof(struct paca_struct , exnmi)); +DEFINE (PACA_EXMC , offsetof(struct paca_struct , exmc));DEFINE (PACALPPACAPTR , offsetof(struct paca_struct , lppaca_ptr));DEFINE (PACA_SLBSHADOWPTR , offsetof(struct paca_struct , slb_shadow_ptr)); DEFINE(SLBSHADOW_STACKVSID,
arch/powerpc/kernel/exceptions-64s.S +15 -28
75 lines not on this page · raw message
Signature · 1 line
2.9.3
Quoted 9 lines · Nicholas Piggin
Also use
EX_NMIsave space. This should give cleaner debug data in case kernel stacks have become corrupted.
MSR_RIis kept clear for the0x100handler, because we can't mask it, and can't tolerate a reentrant NMI. Technically the0x100is not really recoverable yet, because it could trample on another emergency stack user. This will require a bit more work to safely implement, but for now we don't need to recover after a0x100.
Quoted 7 lines
A little bit of the emergency stack /
MSR_RIhandling differences seem like they can be consolidated with some other handlers. I'll split those into a couple more patches before submitting.I moved the MC save area in the paca out from between the general and slb save areas, and put it with the nmi area because it shouldn't be used much.
I think we should document the limitations as discussed
One of them is that sequential system resets have unpredictable behaviour when done in quick successions. I also don't like some of the naming like NORI, I would rather prefer NOT_RI, but thats just nit picking
Balbir Singh.