Skip to content

Commit dc398a0

Browse files
npigginmpe
authored andcommitted
powerpc/64s/interrupt: Perf NMI should not take normal exit path
NMI interrupts should exit with EXCEPTION_RESTORE_REGS not with interrupt_return_srr, which is what the perf NMI handler currently does. This breaks if a PMI hits after interrupt_exit_user_prepare_main() has switched the context tracking to user mode, then the CT_WARN_ON() in interrupt_exit_kernel_prepare() fires because it returns to kernel with context set to user. This could possibly be solved by soft-disabling PMIs in the exit path, but that reduces our ability to profile that code. The warning could be removed, but it's potentially useful. All other NMIs and soft-NMIs return using EXCEPTION_RESTORE_REGS, so this makes perf interrupts consistent with that and seems like the best fix. Signed-off-by: Nicholas Piggin <[email protected]> [mpe: Squash in fixups from Nick] Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent a073672 commit dc398a0

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

arch/powerpc/kernel/exceptions-64s.S

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2357,9 +2357,21 @@ EXC_VIRT_END(performance_monitor, 0x4f00, 0x20)
23572357
EXC_COMMON_BEGIN(performance_monitor_common)
23582358
GEN_COMMON performance_monitor
23592359
addi r3,r1,STACK_FRAME_OVERHEAD
2360-
bl performance_monitor_exception
2360+
lbz r4,PACAIRQSOFTMASK(r13)
2361+
cmpdi r4,IRQS_ENABLED
2362+
bne 1f
2363+
bl performance_monitor_exception_async
23612364
b interrupt_return_srr
2365+
1:
2366+
bl performance_monitor_exception_nmi
2367+
/* Clear MSR_RI before setting SRR0 and SRR1. */
2368+
li r9,0
2369+
mtmsrd r9,1
23622370

2371+
kuap_kernel_restore r9, r10
2372+
2373+
EXCEPTION_RESTORE_REGS hsrr=0
2374+
RFI_TO_KERNEL
23632375

23642376
/**
23652377
* Interrupt 0xf20 - Vector Unavailable Interrupt.

arch/powerpc/kernel/interrupt.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -377,13 +377,15 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
377377
* CT_WARN_ON comes here via program_check_exception, so avoid
378378
* recursion.
379379
*
380-
* Skip the assertion on PMIs to work around a problem caused by NMI
381-
* PMIs incorrectly taking this interrupt return path, it's possible
382-
* for this to hit after interrupt exit to user switches context to
383-
* user. See also the comment in the performance monitor handler in
384-
* exceptions-64e/s.S
380+
* Skip the assertion on PMIs on 64e to work around a problem caused
381+
* by NMI PMIs incorrectly taking this interrupt return path, it's
382+
* possible for this to hit after interrupt exit to user switches
383+
* context to user. See also the comment in the performance monitor
384+
* handler in exceptions-64e.S
385385
*/
386-
if (TRAP(regs) != INTERRUPT_PROGRAM && TRAP(regs) != INTERRUPT_PERFMON)
386+
if (!IS_ENABLED(CONFIG_PPC_BOOK3E_64) &&
387+
TRAP(regs) != INTERRUPT_PROGRAM &&
388+
TRAP(regs) != INTERRUPT_PERFMON)
387389
CT_WARN_ON(ct_state() == CONTEXT_USER);
388390

389391
kuap = kuap_get_and_assert_locked();

0 commit comments

Comments
 (0)