Skip to content

Commit a6e2c22

Browse files
kvaneeshmpe
authored andcommitted
powerpc: Fix kernel crash in show_instructions() w/DEBUG_VIRTUAL
With CONFIG_DEBUG_VIRTUAL=y, we can hit a BUG() if we take a hard lockup watchdog interrupt when in OPAL mode. This happens in show_instructions() if the kernel takes the watchdog NMI IPI, or any other interrupt, with MSR_IR == 0. show_instructions() updates the variable pc in the loop and the second iteration will result in BUG(). We hit the BUG_ON due the below check in __va() #define __va(x) ({ VIRTUAL_BUG_ON((unsigned long)(x) >= PAGE_OFFSET); (void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET); }) Fix it by moving the check out of the loop. Also update nip so that the nip == pc check still matches. Fixes: 4dd7554 ("powerpc/64: Add VIRTUAL_BUG_ON checks for __va and __pa addresses") Signed-off-by: Aneesh Kumar K.V <[email protected]> [mpe: Use IS_ENABLED(), massage change log] Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent b3a9e3b commit a6e2c22

File tree

1 file changed

+11
-9
lines changed

1 file changed

+11
-9
lines changed

arch/powerpc/kernel/process.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,29 +1252,31 @@ struct task_struct *__switch_to(struct task_struct *prev,
12521252
static void show_instructions(struct pt_regs *regs)
12531253
{
12541254
int i;
1255+
unsigned long nip = regs->nip;
12551256
unsigned long pc = regs->nip - (NR_INSN_TO_PRINT * 3 / 4 * sizeof(int));
12561257

12571258
printk("Instruction dump:");
12581259

1260+
/*
1261+
* If we were executing with the MMU off for instructions, adjust pc
1262+
* rather than printing XXXXXXXX.
1263+
*/
1264+
if (!IS_ENABLED(CONFIG_BOOKE) && !(regs->msr & MSR_IR)) {
1265+
pc = (unsigned long)phys_to_virt(pc);
1266+
nip = (unsigned long)phys_to_virt(regs->nip);
1267+
}
1268+
12591269
for (i = 0; i < NR_INSN_TO_PRINT; i++) {
12601270
int instr;
12611271

12621272
if (!(i % 8))
12631273
pr_cont("\n");
12641274

1265-
#if !defined(CONFIG_BOOKE)
1266-
/* If executing with the IMMU off, adjust pc rather
1267-
* than print XXXXXXXX.
1268-
*/
1269-
if (!(regs->msr & MSR_IR))
1270-
pc = (unsigned long)phys_to_virt(pc);
1271-
#endif
1272-
12731275
if (!__kernel_text_address(pc) ||
12741276
probe_kernel_address((const void *)pc, instr)) {
12751277
pr_cont("XXXXXXXX ");
12761278
} else {
1277-
if (regs->nip == pc)
1279+
if (nip == pc)
12781280
pr_cont("<%08x> ", instr);
12791281
else
12801282
pr_cont("%08x ", instr);

0 commit comments

Comments
 (0)