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

powerpc/64s/exception: machine check move unrecoverable handling out of line



Similarly to the previous change, all callers of the unrecoverable
handler run relocated so can reach it with a direct branch. This makes
it easy to move out of line, which makes the "normal" path less
cluttered and easier to follow.

MSR[ME] manipulation still requires the rfi, so that is moved out of
line to its own function.

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/20190802105709.27696-15-npiggin@gmail.com
parent 296e753f
Loading
Loading
Loading
Loading
+44 −43
Original line number Diff line number Diff line
@@ -992,9 +992,9 @@ EXC_COMMON_BEGIN(machine_check_early_common)
	bne	1f
	/* First machine check entry */
	ld	r1,PACAMCEMERGSP(r13)	/* Use MC emergency stack */
1:	subi	r1,r1,INT_FRAME_SIZE	/* alloc stack frame */
	/* Limit nested MCE to level 4 to avoid stack overflow */
	bge	cr1,2f			/* Check if we hit limit of 4 */
1:	/* Limit nested MCE to level 4 to avoid stack overflow */
	bgt	cr1,unrecoverable_mce	/* Check if we hit limit of 4 */
	subi	r1,r1,INT_FRAME_SIZE	/* alloc stack frame */

	EXCEPTION_PROLOG_COMMON_1()
	/* We don't touch AMR here, we never go to virtual mode */
@@ -1013,21 +1013,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
	mtmsrd	r10,1
	b	machine_check_handle_early

2:
	/* Stack overflow. Stay on emergency stack and panic.
	 * Keep the ME bit off while panic-ing, so that if we hit
	 * another machine check we checkstop.
	 */
	addi	r1,r1,INT_FRAME_SIZE	/* go back to previous stack frame */
	ld	r11,PACAKMSR(r13)
	LOAD_HANDLER(r12, unrecover_mce)
	li	r10,MSR_ME
	andc	r11,r11,r10		/* Turn off MSR_ME */
	mtspr	SPRN_SRR0,r12
	mtspr	SPRN_SRR1,r11
	RFI_TO_KERNEL
	b	.	/* prevent speculative execution */

EXC_COMMON_BEGIN(machine_check_common)
	/*
	 * Machine check is different because we use a different
@@ -1141,32 +1126,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
	 * If yes, then stay on emergency stack and panic.
	 */
	andi.	r11,r12,MSR_RI
	bne	2f
1:	mfspr	r11,SPRN_SRR0
	LOAD_HANDLER(r10,unrecover_mce)
	mtspr	SPRN_SRR0,r10
	ld	r10,PACAKMSR(r13)
	/*
	 * We are going down. But there are chances that we might get hit by
	 * another MCE during panic path and we may run into unstable state
	 * with no way out. Hence, turn ME bit off while going down, so that
	 * when another MCE is hit during panic path, system will checkstop
	 * and hypervisor will get restarted cleanly by SP.
	 */
	li	r3,MSR_ME
	andc	r10,r10,r3		/* Turn off MSR_ME */
	mtspr	SPRN_SRR1,r10
	RFI_TO_KERNEL
	b	.
2:
	beq	unrecoverable_mce

	/*
	 * Check if we have successfully handled/recovered from error, if not
	 * then stay on emergency stack and panic.
	 */
	ld	r3,RESULT(r1)	/* Load result */
	cmpdi	r3,0		/* see if we handled MCE successfully */

	beq	1b		/* if !handled then panic */
	beq	unrecoverable_mce /* if !handled then panic */

	/*
	 * Return from MC interrupt.
@@ -1189,17 +1157,35 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
	EXCEPTION_PROLOG_1 EXC_STD, PACA_EXMC, 1, 0x200, 1, 1, 0
	EXCEPTION_PROLOG_2_REAL machine_check_common, EXC_STD, 0

EXC_COMMON_BEGIN(unrecover_mce)
EXC_COMMON_BEGIN(unrecoverable_mce)
	/*
	 * We are going down. But there are chances that we might get hit by
	 * another MCE during panic path and we may run into unstable state
	 * with no way out. Hence, turn ME bit off while going down, so that
	 * when another MCE is hit during panic path, system will checkstop
	 * and hypervisor will get restarted cleanly by SP.
	 */
BEGIN_FTR_SECTION
	li	r10,0 /* clear MSR_RI */
	mtmsrd	r10,1
	bl	disable_machine_check
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
	ld	r10,PACAKMSR(r13)
	li	r3,MSR_ME
	andc	r10,r10,r3
	mtmsrd	r10

	/* Invoke machine_check_exception to print MCE event and panic. */
	addi	r3,r1,STACK_FRAME_OVERHEAD
	bl	machine_check_exception

	/*
	 * We will not reach here. Even if we did, there is no way out. Call
	 * unrecoverable_exception and die.
	 * We will not reach here. Even if we did, there is no way out.
	 * Call unrecoverable_exception and die.
	 */
1:	addi	r3,r1,STACK_FRAME_OVERHEAD
	addi	r3,r1,STACK_FRAME_OVERHEAD
	bl	unrecoverable_exception
	b	1b
	b	.


EXC_REAL_BEGIN(data_access, 0x300, 0x80)
@@ -2282,6 +2268,21 @@ enable_machine_check:
1:	mtlr	r0
	blr

/* MSR[RI] should be clear because this uses SRR[01] */
disable_machine_check:
	mflr	r0
	bcl	20,31,$+4
0:	mflr	r3
	addi	r3,r3,(1f - 0b)
	mtspr	SPRN_SRR0,r3
	mfmsr	r3
	li	r4,MSR_ME
	andc	r3,r3,r4
	mtspr	SPRN_SRR1,r3
	RFI_TO_KERNEL
1:	mtlr	r0
	blr

/*
 * Hash table stuff
 */