Message ID | 1492491886-29233-1-git-send-email-mpe@ellerman.id.au (mailing list archive) |
---|---|
State | Accepted |
Commit | be5c5e843c4afa1c8397cb740b6032bd4142f32d |
Headers | show |
On Tue, 2017-04-18 at 05:04:46 UTC, Michael Ellerman wrote: > 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> Applied to powerpc fixes. https://git.kernel.org/powerpc/c/be5c5e843c4afa1c8397cb740b6032 cheers
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 14752eee3d0c..ed3beadd2cc5 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -236,9 +236,9 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) mtctr reg; \ bctr -#define BRANCH_LINK_TO_FAR(reg, label) \ - __LOAD_FAR_HANDLER(reg, label); \ - mtctr reg; \ +#define BRANCH_LINK_TO_FAR(label) \ + __LOAD_FAR_HANDLER(r12, label); \ + mtctr r12; \ bctrl /* @@ -265,7 +265,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) #define BRANCH_TO_COMMON(reg, label) \ b label -#define BRANCH_LINK_TO_FAR(reg, label) \ +#define BRANCH_LINK_TO_FAR(label) \ bl label #define BRANCH_TO_KVM(reg, label) \ diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 857bf7c5b946..6353019966e6 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -982,7 +982,7 @@ TRAMP_REAL_BEGIN(hmi_exception_early) EXCEPTION_PROLOG_COMMON_2(PACA_EXGEN) EXCEPTION_PROLOG_COMMON_3(0xe60) addi r3,r1,STACK_FRAME_OVERHEAD - BRANCH_LINK_TO_FAR(r4, hmi_exception_realmode) + BRANCH_LINK_TO_FAR(hmi_exception_realmode) /* Function call ABI */ /* Windup the stack. */ /* Move original HSRR0 and HSRR1 into the respective regs */ ld r9,_MSR(r1)