Commit 6ecbb582 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman
Browse files

powerpc/64s: move NMI soft-mask handling to C



Saving and restoring soft-mask state can now be done in C using the
interrupt handler wrapper functions.

Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210130130852.2952424-41-npiggin@gmail.com
parent 118178e6
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -95,6 +95,10 @@ static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct int

struct interrupt_nmi_state {
#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC_BOOK3S_64
	u8 irq_soft_mask;
	u8 irq_happened;
#endif
	u8 ftrace_enabled;
#endif
};
@@ -102,6 +106,20 @@ struct interrupt_nmi_state {
static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)
{
#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC_BOOK3S_64
	state->irq_soft_mask = local_paca->irq_soft_mask;
	state->irq_happened = local_paca->irq_happened;

	/*
	 * Set IRQS_ALL_DISABLED unconditionally so irqs_disabled() does
	 * the right thing, and set IRQ_HARD_DIS. We do not want to reconcile
	 * because that goes through irq tracing which we don't want in NMI.
	 */
	local_paca->irq_soft_mask = IRQS_ALL_DISABLED;
	local_paca->irq_happened |= PACA_IRQ_HARD_DIS;

	/* Don't do any per-CPU operations until interrupt state is fixed */
#endif
	/* Allow DEC and PMI to be traced when they are soft-NMI */
	if (TRAP(regs) != 0x900 && TRAP(regs) != 0xf00 && TRAP(regs) != 0x260) {
		state->ftrace_enabled = this_cpu_get_ftrace_enabled();
@@ -129,6 +147,13 @@ static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct inter
#ifdef CONFIG_PPC64
	if (TRAP(regs) != 0x900 && TRAP(regs) != 0xf00 && TRAP(regs) != 0x260)
		this_cpu_set_ftrace_enabled(state->ftrace_enabled);

#ifdef CONFIG_PPC_BOOK3S_64
	/* Check we didn't change the pending interrupt mask. */
	WARN_ON_ONCE((state->irq_happened | PACA_IRQ_HARD_DIS) != local_paca->irq_happened);
	local_paca->irq_happened = state->irq_happened;
	local_paca->irq_soft_mask = state->irq_soft_mask;
#endif
#endif
}

+0 −60
Original line number Diff line number Diff line
@@ -1008,20 +1008,6 @@ EXC_COMMON_BEGIN(system_reset_common)
	ld	r1,PACA_NMI_EMERG_SP(r13)
	subi	r1,r1,INT_FRAME_SIZE
	__GEN_COMMON_BODY system_reset
	/*
	 * Set IRQS_ALL_DISABLED unconditionally so irqs_disabled() does
	 * the right thing. We do not want to reconcile because that goes
	 * through irq tracing which we don't want in NMI.
	 *
	 * Save PACAIRQHAPPENED to RESULT (otherwise unused), and set HARD_DIS
	 * as we are running with MSR[EE]=0.
	 */
	li	r10,IRQS_ALL_DISABLED
	stb	r10,PACAIRQSOFTMASK(r13)
	lbz	r10,PACAIRQHAPPENED(r13)
	std	r10,RESULT(r1)
	ori	r10,r10,PACA_IRQ_HARD_DIS
	stb	r10,PACAIRQHAPPENED(r13)

	addi	r3,r1,STACK_FRAME_OVERHEAD
	bl	system_reset_exception
@@ -1037,14 +1023,6 @@ EXC_COMMON_BEGIN(system_reset_common)
	subi	r10,r10,1
	sth	r10,PACA_IN_NMI(r13)

	/*
	 * Restore soft mask settings.
	 */
	ld	r10,RESULT(r1)
	stb	r10,PACAIRQHAPPENED(r13)
	ld	r10,SOFTE(r1)
	stb	r10,PACAIRQSOFTMASK(r13)

	kuap_kernel_restore r9, r10
	EXCEPTION_RESTORE_REGS
	RFI_TO_USER_OR_KERNEL
@@ -1190,30 +1168,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
	li	r10,MSR_RI
	mtmsrd	r10,1

	/*
	 * Set IRQS_ALL_DISABLED and save PACAIRQHAPPENED (see
	 * system_reset_common)
	 */
	li	r10,IRQS_ALL_DISABLED
	stb	r10,PACAIRQSOFTMASK(r13)
	lbz	r10,PACAIRQHAPPENED(r13)
	std	r10,RESULT(r1)
	ori	r10,r10,PACA_IRQ_HARD_DIS
	stb	r10,PACAIRQHAPPENED(r13)

	addi	r3,r1,STACK_FRAME_OVERHEAD
	bl	machine_check_early
	std	r3,RESULT(r1)	/* Save result */
	ld	r12,_MSR(r1)

	/*
	 * Restore soft mask settings.
	 */
	ld	r10,RESULT(r1)
	stb	r10,PACAIRQHAPPENED(r13)
	ld	r10,SOFTE(r1)
	stb	r10,PACAIRQSOFTMASK(r13)

#ifdef CONFIG_PPC_P7_NAP
	/*
	 * Check if thread was in power saving mode. We come here when any
@@ -2818,17 +2777,6 @@ EXC_COMMON_BEGIN(soft_nmi_common)
	subi	r1,r1,INT_FRAME_SIZE
	__GEN_COMMON_BODY soft_nmi

	/*
	 * Set IRQS_ALL_DISABLED and save PACAIRQHAPPENED (see
	 * system_reset_common)
	 */
	li	r10,IRQS_ALL_DISABLED
	stb	r10,PACAIRQSOFTMASK(r13)
	lbz	r10,PACAIRQHAPPENED(r13)
	std	r10,RESULT(r1)
	ori	r10,r10,PACA_IRQ_HARD_DIS
	stb	r10,PACAIRQHAPPENED(r13)

	addi	r3,r1,STACK_FRAME_OVERHEAD
	bl	soft_nmi_interrupt

@@ -2836,14 +2784,6 @@ EXC_COMMON_BEGIN(soft_nmi_common)
	li	r9,0
	mtmsrd	r9,1

	/*
	 * Restore soft mask settings.
	 */
	ld	r10,RESULT(r1)
	stb	r10,PACAIRQHAPPENED(r13)
	ld	r10,SOFTE(r1)
	stb	r10,PACAIRQSOFTMASK(r13)

	kuap_kernel_restore r9, r10
	EXCEPTION_RESTORE_REGS hsrr=0
	RFI_TO_KERNEL