提交 c4f3b52c 编写于 作者: N Nicholas Piggin 提交者: Michael Ellerman

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: NNicholas Piggin <npiggin@gmail.com>
Signed-off-by: NMichael Ellerman <mpe@ellerman.id.au>
上级 a3d96f70
...@@ -275,6 +275,12 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) ...@@ -275,6 +275,12 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
#endif #endif
/* Do not enable RI */
#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 __KVM_HANDLER(area, h, n) \ #define __KVM_HANDLER(area, h, n) \
BEGIN_FTR_SECTION_NESTED(947) \ BEGIN_FTR_SECTION_NESTED(947) \
......
...@@ -187,12 +187,15 @@ struct paca_struct { ...@@ -187,12 +187,15 @@ struct paca_struct {
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
/* Exclusive emergency stack pointer for machine check exception. */ /* Exclusive emergency stack pointer for machine check exception. */
void *mc_emergency_sp; void *mc_emergency_sp;
u16 in_nmi; /* In nmi handler */
/* /*
* Flag to check whether we are in machine check early handler * Flag to check whether we are in machine check early handler
* and already using emergency stack. * and already using emergency stack.
*/ */
u16 in_mce; u16 in_mce;
u8 hmi_event_available; /* HMI event is available */ u8 hmi_event_available; /* HMI event is available */
#endif #endif
/* Stuff for accurate time accounting */ /* Stuff for accurate time accounting */
......
...@@ -235,6 +235,7 @@ int main(void) ...@@ -235,6 +235,7 @@ int main(void)
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
OFFSET(PACAMCEMERGSP, paca_struct, mc_emergency_sp); OFFSET(PACAMCEMERGSP, paca_struct, mc_emergency_sp);
OFFSET(PACA_IN_MCE, paca_struct, in_mce); OFFSET(PACA_IN_MCE, paca_struct, in_mce);
OFFSET(PACA_IN_NMI, paca_struct, in_nmi);
#endif #endif
OFFSET(PACAHWCPUID, paca_struct, hw_cpu_id); OFFSET(PACAHWCPUID, paca_struct, hw_cpu_id);
OFFSET(PACAKEXECSTATE, paca_struct, kexec_state); OFFSET(PACAKEXECSTATE, paca_struct, kexec_state);
......
...@@ -116,7 +116,11 @@ EXC_VIRT_NONE(0x4000, 0x100) ...@@ -116,7 +116,11 @@ EXC_VIRT_NONE(0x4000, 0x100)
EXC_REAL_BEGIN(system_reset, 0x100, 0x100) EXC_REAL_BEGIN(system_reset, 0x100, 0x100)
SET_SCRATCH0(r13) 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) IDLETEST, 0x100)
EXC_REAL_END(system_reset, 0x100, 0x100) EXC_REAL_END(system_reset, 0x100, 0x100)
...@@ -128,9 +132,31 @@ EXC_COMMON_BEGIN(system_reset_idle_common) ...@@ -128,9 +132,31 @@ EXC_COMMON_BEGIN(system_reset_idle_common)
#endif #endif
EXC_COMMON_BEGIN(system_reset_common) 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, EXCEPTION_COMMON(PACA_EXNMI, 0x100,
system_reset, system_reset_exception, system_reset, system_reset_exception, 1f,
ret_from_except, ADD_NVGPRS;ADD_RECONCILE) 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 #ifdef CONFIG_PPC_PSERIES
/* /*
...@@ -138,8 +164,9 @@ EXC_COMMON_BEGIN(system_reset_common) ...@@ -138,8 +164,9 @@ EXC_COMMON_BEGIN(system_reset_common)
*/ */
TRAMP_REAL_BEGIN(system_reset_fwnmi) TRAMP_REAL_BEGIN(system_reset_fwnmi)
SET_SCRATCH0(r13) /* save r13 */ SET_SCRATCH0(r13) /* save r13 */
EXCEPTION_PROLOG_PSERIES(PACA_EXNMI, system_reset_common, EXC_STD, /* See comment at system_reset exception */
NOTEST, 0x100) EXCEPTION_PROLOG_PSERIES_NORI(PACA_EXNMI, system_reset_common,
EXC_STD, NOTEST, 0x100)
#endif /* CONFIG_PPC_PSERIES */ #endif /* CONFIG_PPC_PSERIES */
......
...@@ -282,11 +282,17 @@ void system_reset_exception(struct pt_regs *regs) ...@@ -282,11 +282,17 @@ void system_reset_exception(struct pt_regs *regs)
/* See if any machine dependent calls */ /* See if any machine dependent calls */
if (ppc_md.system_reset_exception) { if (ppc_md.system_reset_exception) {
if (ppc_md.system_reset_exception(regs)) if (ppc_md.system_reset_exception(regs))
return; goto out;
} }
die("System Reset", regs, SIGABRT); die("System Reset", regs, SIGABRT);
out:
#ifdef CONFIG_PPC_BOOK3S_64
BUG_ON(get_paca()->in_nmi == 0);
if (get_paca()->in_nmi > 1)
panic("Unrecoverable nested System Reset");
#endif
/* Must die if the interrupt is not recoverable */ /* Must die if the interrupt is not recoverable */
if (!(regs->msr & MSR_RI)) if (!(regs->msr & MSR_RI))
panic("Unrecoverable System Reset"); panic("Unrecoverable System Reset");
......
...@@ -2236,6 +2236,7 @@ static void dump_one_paca(int cpu) ...@@ -2236,6 +2236,7 @@ static void dump_one_paca(int cpu)
DUMP(p, emergency_sp, "p"); DUMP(p, emergency_sp, "p");
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
DUMP(p, mc_emergency_sp, "p"); DUMP(p, mc_emergency_sp, "p");
DUMP(p, in_nmi, "x");
DUMP(p, in_mce, "x"); DUMP(p, in_mce, "x");
DUMP(p, hmi_event_available, "x"); DUMP(p, hmi_event_available, "x");
#endif #endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册