Skip to content

Commit 118178e

Browse files
npigginmpe
authored andcommitted
powerpc: move NMI entry/exit code into wrapper
This moves the common NMI entry and exit code into the interrupt handler wrappers. This changes the behaviour of soft-NMI (watchdog) and HMI interrupts, and also MCE interrupts on 64e, by adding missing parts of the NMI entry to them. Signed-off-by: Nicholas Piggin <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 74c3354 commit 118178e

File tree

4 files changed

+38
-46
lines changed

4 files changed

+38
-46
lines changed

arch/powerpc/include/asm/interrupt.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,42 @@ static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct int
9494
}
9595

9696
struct interrupt_nmi_state {
97+
#ifdef CONFIG_PPC64
98+
u8 ftrace_enabled;
99+
#endif
97100
};
98101

99102
static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)
100103
{
104+
#ifdef CONFIG_PPC64
105+
/* Allow DEC and PMI to be traced when they are soft-NMI */
106+
if (TRAP(regs) != 0x900 && TRAP(regs) != 0xf00 && TRAP(regs) != 0x260) {
107+
state->ftrace_enabled = this_cpu_get_ftrace_enabled();
108+
this_cpu_set_ftrace_enabled(0);
109+
}
110+
#endif
111+
112+
/*
113+
* Do not use nmi_enter() for pseries hash guest taking a real-mode
114+
* NMI because not everything it touches is within the RMA limit.
115+
*/
116+
if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
117+
!firmware_has_feature(FW_FEATURE_LPAR) ||
118+
radix_enabled() || (mfmsr() & MSR_DR))
119+
nmi_enter();
101120
}
102121

103122
static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)
104123
{
124+
if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) ||
125+
!firmware_has_feature(FW_FEATURE_LPAR) ||
126+
radix_enabled() || (mfmsr() & MSR_DR))
127+
nmi_exit();
128+
129+
#ifdef CONFIG_PPC64
130+
if (TRAP(regs) != 0x900 && TRAP(regs) != 0xf00 && TRAP(regs) != 0x260)
131+
this_cpu_set_ftrace_enabled(state->ftrace_enabled);
132+
#endif
105133
}
106134

107135
/**

arch/powerpc/kernel/mce.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -587,12 +587,6 @@ EXPORT_SYMBOL_GPL(machine_check_print_event_info);
587587
DEFINE_INTERRUPT_HANDLER_NMI(machine_check_early)
588588
{
589589
long handled = 0;
590-
u8 ftrace_enabled = this_cpu_get_ftrace_enabled();
591-
592-
this_cpu_set_ftrace_enabled(0);
593-
/* Do not use nmi_enter/exit for pseries hpte guest */
594-
if (radix_enabled() || !firmware_has_feature(FW_FEATURE_LPAR))
595-
nmi_enter();
596590

597591
hv_nmi_check_nonrecoverable(regs);
598592

@@ -602,11 +596,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(machine_check_early)
602596
if (ppc_md.machine_check_early)
603597
handled = ppc_md.machine_check_early(regs);
604598

605-
if (radix_enabled() || !firmware_has_feature(FW_FEATURE_LPAR))
606-
nmi_exit();
607-
608-
this_cpu_set_ftrace_enabled(ftrace_enabled);
609-
610599
return handled;
611600
}
612601

arch/powerpc/kernel/traps.c

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -435,11 +435,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(system_reset_exception)
435435
{
436436
unsigned long hsrr0, hsrr1;
437437
bool saved_hsrrs = false;
438-
u8 ftrace_enabled = this_cpu_get_ftrace_enabled();
439-
440-
this_cpu_set_ftrace_enabled(0);
441-
442-
nmi_enter();
443438

444439
/*
445440
* System reset can interrupt code where HSRRs are live and MSR[RI]=1.
@@ -514,10 +509,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(system_reset_exception)
514509
mtspr(SPRN_HSRR1, hsrr1);
515510
}
516511

517-
nmi_exit();
518-
519-
this_cpu_set_ftrace_enabled(ftrace_enabled);
520-
521512
/* What should we do here? We could issue a shutdown or hard reset. */
522513

523514
return 0;
@@ -809,6 +800,12 @@ void die_mce(const char *str, struct pt_regs *regs, long err)
809800
}
810801
NOKPROBE_SYMBOL(die_mce);
811802

803+
/*
804+
* BOOK3S_64 does not call this handler as a non-maskable interrupt
805+
* (it uses its own early real-mode handler to handle the MCE proper
806+
* and then raises irq_work to call this handler when interrupts are
807+
* enabled).
808+
*/
812809
#ifdef CONFIG_PPC_BOOK3S_64
813810
DEFINE_INTERRUPT_HANDLER_ASYNC(machine_check_exception)
814811
#else
@@ -817,20 +814,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(machine_check_exception)
817814
{
818815
int recover = 0;
819816

820-
/*
821-
* BOOK3S_64 does not call this handler as a non-maskable interrupt
822-
* (it uses its own early real-mode handler to handle the MCE proper
823-
* and then raises irq_work to call this handler when interrupts are
824-
* enabled).
825-
*
826-
* This is silly. The BOOK3S_64 should just call a different function
827-
* rather than expecting semantics to magically change. Something
828-
* like 'non_nmi_machine_check_exception()', perhaps?
829-
*/
830-
const bool nmi = !IS_ENABLED(CONFIG_PPC_BOOK3S_64);
831-
832-
if (nmi) nmi_enter();
833-
834817
__this_cpu_inc(irq_stat.mce_exceptions);
835818

836819
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
@@ -862,8 +845,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(machine_check_exception)
862845
if (!(regs->msr & MSR_RI))
863846
die_mce("Unrecoverable Machine check", regs, SIGBUS);
864847

865-
if (nmi) nmi_exit();
866-
867848
#ifdef CONFIG_PPC_BOOK3S_64
868849
return;
869850
#else
@@ -1892,14 +1873,10 @@ DEFINE_INTERRUPT_HANDLER(vsx_unavailable_tm)
18921873
DECLARE_INTERRUPT_HANDLER_NMI(performance_monitor_exception_nmi);
18931874
DEFINE_INTERRUPT_HANDLER_NMI(performance_monitor_exception_nmi)
18941875
{
1895-
nmi_enter();
1896-
18971876
__this_cpu_inc(irq_stat.pmu_irqs);
18981877

18991878
perf_irq(regs);
19001879

1901-
nmi_exit();
1902-
19031880
return 0;
19041881
}
19051882
#endif

arch/powerpc/kernel/watchdog.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,19 +255,20 @@ DEFINE_INTERRUPT_HANDLER_NMI(soft_nmi_interrupt)
255255
int cpu = raw_smp_processor_id();
256256
u64 tb;
257257

258+
/* should only arrive from kernel, with irqs disabled */
259+
WARN_ON_ONCE(!arch_irq_disabled_regs(regs));
260+
258261
if (!cpumask_test_cpu(cpu, &wd_cpus_enabled))
259262
return 0;
260263

261-
nmi_enter();
262-
263264
__this_cpu_inc(irq_stat.soft_nmi_irqs);
264265

265266
tb = get_tb();
266267
if (tb - per_cpu(wd_timer_tb, cpu) >= wd_panic_timeout_tb) {
267268
wd_smp_lock(&flags);
268269
if (cpumask_test_cpu(cpu, &wd_smp_cpus_stuck)) {
269270
wd_smp_unlock(&flags);
270-
goto out;
271+
return 0;
271272
}
272273
set_cpu_stuck(cpu, tb);
273274

@@ -291,9 +292,6 @@ DEFINE_INTERRUPT_HANDLER_NMI(soft_nmi_interrupt)
291292
if (wd_panic_timeout_tb < 0x7fffffff)
292293
mtspr(SPRN_DEC, wd_panic_timeout_tb);
293294

294-
out:
295-
nmi_exit();
296-
297295
return 0;
298296
}
299297

0 commit comments

Comments
 (0)