powerpc/64s: Disallow system reset vs system reset reentrancy
In preparation for using a dedicated stack for system reset interrupts, prevent a nested system reset from recovering, in order to simplify code that is called in crash/debug path. This allows a system reset interrupt to just use the base stack pointer. Keep an in_nmi nesting counter similarly to the in_mce counter. Consider the interrrupt non-recoverable if it is taken inside another system reset. Interrupt nesting could be allowed similarly to MCE, but system reset is a special case that's not for normal operation, so simplicity wins until there is requirement for nested system reset interrupts. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:

committed by
Michael Ellerman

parent
a3d96f70c1
commit
c4f3b52ce7
@@ -116,7 +116,11 @@ EXC_VIRT_NONE(0x4000, 0x100)
|
||||
|
||||
EXC_REAL_BEGIN(system_reset, 0x100, 0x100)
|
||||
SET_SCRATCH0(r13)
|
||||
EXCEPTION_PROLOG_PSERIES(PACA_EXNMI, system_reset_common, EXC_STD,
|
||||
/*
|
||||
* MSR_RI is not enabled, because PACA_EXNMI and nmi stack is
|
||||
* being used, so a nested NMI exception would corrupt it.
|
||||
*/
|
||||
EXCEPTION_PROLOG_PSERIES_NORI(PACA_EXNMI, system_reset_common, EXC_STD,
|
||||
IDLETEST, 0x100)
|
||||
|
||||
EXC_REAL_END(system_reset, 0x100, 0x100)
|
||||
@@ -128,9 +132,31 @@ EXC_COMMON_BEGIN(system_reset_idle_common)
|
||||
#endif
|
||||
|
||||
EXC_COMMON_BEGIN(system_reset_common)
|
||||
/*
|
||||
* Increment paca->in_nmi then enable MSR_RI. SLB or MCE will be able
|
||||
* to recover, but nested NMI will notice in_nmi and not recover
|
||||
* because of the use of the NMI stack. in_nmi reentrancy is tested in
|
||||
* system_reset_exception.
|
||||
*/
|
||||
lhz r10,PACA_IN_NMI(r13)
|
||||
addi r10,r10,1
|
||||
sth r10,PACA_IN_NMI(r13)
|
||||
li r10,MSR_RI
|
||||
mtmsrd r10,1
|
||||
|
||||
EXCEPTION_COMMON(PACA_EXNMI, 0x100,
|
||||
system_reset, system_reset_exception,
|
||||
ret_from_except, ADD_NVGPRS;ADD_RECONCILE)
|
||||
system_reset, system_reset_exception, 1f,
|
||||
ADD_NVGPRS;ADD_RECONCILE)
|
||||
1: /* EXCEPTION_COMMON continues here */
|
||||
|
||||
/*
|
||||
* The stack is no longer in use, decrement in_nmi.
|
||||
*/
|
||||
lhz r10,PACA_IN_NMI(r13)
|
||||
subi r10,r10,1
|
||||
sth r10,PACA_IN_NMI(r13)
|
||||
|
||||
b ret_from_except
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
/*
|
||||
@@ -138,8 +164,9 @@ EXC_COMMON_BEGIN(system_reset_common)
|
||||
*/
|
||||
TRAMP_REAL_BEGIN(system_reset_fwnmi)
|
||||
SET_SCRATCH0(r13) /* save r13 */
|
||||
EXCEPTION_PROLOG_PSERIES(PACA_EXNMI, system_reset_common, EXC_STD,
|
||||
NOTEST, 0x100)
|
||||
/* See comment at system_reset exception */
|
||||
EXCEPTION_PROLOG_PSERIES_NORI(PACA_EXNMI, system_reset_common,
|
||||
EXC_STD, NOTEST, 0x100)
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user