Skip to content

Commit 2f5182c

Browse files
npigginmpe
authored andcommitted
powerpc/64s: early boot machine check handler
Use the early boot interrupt fixup in the machine check handler to allow the machine check handler to run before interrupt endian is set up. Branch to an early boot handler that just does a basic crash, which allows it to run before ppc_md is set up. MSR[ME] is enabled on the boot CPU earlier, and the machine check stack is temporarily set to the middle of the init task stack. This allows machine checks (e.g., due to invalid data access in real mode) to print something useful earlier in boot (as soon as udbg is set up, if CONFIG_PPC_EARLY_DEBUG=y). Signed-off-by: Nicholas Piggin <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent bf75a32 commit 2f5182c

File tree

4 files changed

+34
-1
lines changed

4 files changed

+34
-1
lines changed

arch/powerpc/include/asm/asm-prototypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ int64_t __opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
3636
int64_t opcode, uint64_t msr);
3737

3838
/* misc runtime */
39+
void enable_machine_check(void);
3940
extern u64 __bswapdi2(u64);
4041
extern s64 __lshrdi3(s64, int);
4142
extern s64 __ashldi3(s64, int);

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,7 @@ INT_DEFINE_BEGIN(machine_check)
11341134
INT_DEFINE_END(machine_check)
11351135

11361136
EXC_REAL_BEGIN(machine_check, 0x200, 0x100)
1137+
EARLY_BOOT_FIXUP
11371138
GEN_INT_ENTRY machine_check_early, virt=0
11381139
EXC_REAL_END(machine_check, 0x200, 0x100)
11391140
EXC_VIRT_NONE(0x4200, 0x100)
@@ -1198,6 +1199,9 @@ BEGIN_FTR_SECTION
11981199
bl enable_machine_check
11991200
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
12001201
addi r3,r1,STACK_FRAME_OVERHEAD
1202+
BEGIN_FTR_SECTION
1203+
bl machine_check_early_boot
1204+
END_FTR_SECTION(0, 1) // nop out after boot
12011205
bl machine_check_early
12021206
std r3,RESULT(r1) /* Save result */
12031207
ld r12,_MSR(r1)
@@ -3096,7 +3100,7 @@ CLOSE_FIXED_SECTION(virt_trampolines);
30963100
USE_TEXT_SECTION()
30973101

30983102
/* MSR[RI] should be clear because this uses SRR[01] */
3099-
enable_machine_check:
3103+
_GLOBAL(enable_machine_check)
31003104
mflr r0
31013105
bcl 20,31,$+4
31023106
0: mflr r3

arch/powerpc/kernel/setup_64.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/of.h>
3535
#include <linux/of_fdt.h>
3636

37+
#include <asm/asm-prototypes.h>
3738
#include <asm/kvm_guest.h>
3839
#include <asm/io.h>
3940
#include <asm/kdump.h>
@@ -180,6 +181,16 @@ static void __init fixup_boot_paca(void)
180181
{
181182
/* The boot cpu is started */
182183
get_paca()->cpu_start = 1;
184+
#ifdef CONFIG_PPC_BOOK3S_64
185+
/*
186+
* Give the early boot machine check stack somewhere to use, use
187+
* half of the init stack. This is a bit hacky but there should not be
188+
* deep stack usage in early init so shouldn't overflow it or overwrite
189+
* things.
190+
*/
191+
get_paca()->mc_emergency_sp = (void *)&init_thread_union +
192+
(THREAD_SIZE/2);
193+
#endif
183194
/* Allow percpu accesses to work until we setup percpu data */
184195
get_paca()->data_offset = 0;
185196
/* Mark interrupts soft and hard disabled in PACA */
@@ -357,6 +368,9 @@ void __init early_setup(unsigned long dt_ptr)
357368

358369
/* -------- printk is now safe to use ------- */
359370

371+
if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && (mfmsr() & MSR_HV))
372+
enable_machine_check();
373+
360374
/* Try new device tree based feature discovery ... */
361375
if (!dt_cpu_ftrs_init(__va(dt_ptr)))
362376
/* Otherwise use the old style CPU table */

arch/powerpc/kernel/traps.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#include <asm/stacktrace.h>
6969
#include <asm/nmi.h>
7070
#include <asm/disassemble.h>
71+
#include <asm/udbg.h>
7172

7273
#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC_CORE)
7374
int (*__debugger)(struct pt_regs *regs) __read_mostly;
@@ -850,6 +851,19 @@ static void __machine_check_exception(struct pt_regs *regs)
850851
}
851852

852853
#ifdef CONFIG_PPC_BOOK3S_64
854+
DEFINE_INTERRUPT_HANDLER_RAW(machine_check_early_boot)
855+
{
856+
udbg_printf("Machine check (early boot)\n");
857+
udbg_printf("SRR0=0x%016lx SRR1=0x%016lx\n", regs->nip, regs->msr);
858+
udbg_printf(" DAR=0x%016lx DSISR=0x%08lx\n", regs->dar, regs->dsisr);
859+
udbg_printf(" LR=0x%016lx R1=0x%08lx\n", regs->link, regs->gpr[1]);
860+
udbg_printf("------\n");
861+
die("Machine check (early boot)", regs, SIGBUS);
862+
for (;;)
863+
;
864+
return 0;
865+
}
866+
853867
DEFINE_INTERRUPT_HANDLER_ASYNC(machine_check_exception_async)
854868
{
855869
__machine_check_exception(regs);

0 commit comments

Comments
 (0)