Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

powerpc/64: Fix HMI exception on LE with CONFIG_RELOCATABLE=y

Prior to commit 2337d207288f ("powerpc/64: CONFIG_RELOCATABLE support for hmi
interrupts"), the branch from hmi_exception_early() to hmi_exception_realmode()
was just a bl hmi_exception_realmode, which the linker would turn into a bl to
the local entry point of hmi_exception_realmode. This was broken when
CONFIG_RELOCATABLE=y because hmi_exception_realmode() is not in the low part of
the kernel text that is copied down to 0x0.

But in fixing that, we added a new bug on little endian kernels. Because the
branch is now a bctrl when CONFIG_RELOCATABLE=y, we branch to the global entry
point of hmi_exception_realmode(). The global entry point must be called with
r12 containing the address of hmi_exception_realmode(), because it uses that
value to calculate the TOC value (r2).

This may manifest as a checkstop, because we take a junk value from r12 which
came from HSRR1, add a small constant to it and then use that as the TOC
pointer. The HSRR1 value will have 0x9 as the top nibble, which puts it above
RAM and somewhere in MMIO space.

Fix it by changing the BRANCH_LINK_TO_FAR() macro to always use r12 to load the
label we're branching to. This means r12 will be setup correctly on LE, fixing
this bug, and r12 is also volatile across function calls on BE so it's a good
choice anyway.

Fixes: 2337d207288f ("powerpc/64: CONFIG_RELOCATABLE support for hmi interrupts")
Reported-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Acked-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

+5 -5
+4 -4
arch/powerpc/include/asm/exception-64s.h
··· 236 236 mtctr reg; \ 237 237 bctr 238 238 239 - #define BRANCH_LINK_TO_FAR(reg, label) \ 240 - __LOAD_FAR_HANDLER(reg, label); \ 241 - mtctr reg; \ 239 + #define BRANCH_LINK_TO_FAR(label) \ 240 + __LOAD_FAR_HANDLER(r12, label); \ 241 + mtctr r12; \ 242 242 bctrl 243 243 244 244 /* ··· 265 265 #define BRANCH_TO_COMMON(reg, label) \ 266 266 b label 267 267 268 - #define BRANCH_LINK_TO_FAR(reg, label) \ 268 + #define BRANCH_LINK_TO_FAR(label) \ 269 269 bl label 270 270 271 271 #define BRANCH_TO_KVM(reg, label) \
+1 -1
arch/powerpc/kernel/exceptions-64s.S
··· 982 982 EXCEPTION_PROLOG_COMMON_2(PACA_EXGEN) 983 983 EXCEPTION_PROLOG_COMMON_3(0xe60) 984 984 addi r3,r1,STACK_FRAME_OVERHEAD 985 - BRANCH_LINK_TO_FAR(r4, hmi_exception_realmode) 985 + BRANCH_LINK_TO_FAR(hmi_exception_realmode) /* Function call ABI */ 986 986 /* Windup the stack. */ 987 987 /* Move original HSRR0 and HSRR1 into the respective regs */ 988 988 ld r9,_MSR(r1)