forked from Minki/linux
powerpc: Fix kernel panic during kernel module load
This fixes a problem which can causes kernel oopses while loading a kernel module. According to the PowerPC EABI specification, GPR r11 is assigned the dedicated function to point to the previous stack frame. In the powerpc-specific kernel module loader, do_plt_call() (in arch/powerpc/kernel/module_32.c), GPR r11 is also used to generate trampoline code. This combination crashes the kernel, in the case where the compiler chooses to use a helper function for saving GPRs on entry, and the module loader has placed the .init.text section far away from the .text section, meaning that it has to generate a trampoline for functions in the .init.text section to call the GPR save helper. Because the trampoline trashes r11, references to the stack frame using r11 can cause an oops. The fix just uses GPR r12 instead of GPR r11 for generating the trampoline code. According to the statements from Freescale, this is safe from an EABI perspective. I've tested the fix for kernel 2.6.33 on MPC8541. Cc: stable@vger.kernel.org Signed-off-by: Steffen Rumler <steffen.rumler.ext@nsn.com> [paulus@samba.org: reworded the description] Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
860aed25a1
commit
3c75296562
@ -176,8 +176,8 @@ int module_frob_arch_sections(Elf32_Ehdr *hdr,
|
||||
|
||||
static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
|
||||
{
|
||||
if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16)
|
||||
&& entry->jump[1] == 0x396b0000 + (val & 0xffff))
|
||||
if (entry->jump[0] == 0x3d800000 + ((val + 0x8000) >> 16)
|
||||
&& entry->jump[1] == 0x398c0000 + (val & 0xffff))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@ -204,10 +204,9 @@ static uint32_t do_plt_call(void *location,
|
||||
entry++;
|
||||
}
|
||||
|
||||
/* Stolen from Paul Mackerras as well... */
|
||||
entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */
|
||||
entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/
|
||||
entry->jump[2] = 0x7d6903a6; /* mtctr r11 */
|
||||
entry->jump[0] = 0x3d800000+((val+0x8000)>>16); /* lis r12,sym@ha */
|
||||
entry->jump[1] = 0x398c0000 + (val&0xffff); /* addi r12,r12,sym@l*/
|
||||
entry->jump[2] = 0x7d8903a6; /* mtctr r12 */
|
||||
entry->jump[3] = 0x4e800420; /* bctr */
|
||||
|
||||
DEBUGP("Initialized plt for 0x%x at %p\n", val, entry);
|
||||
|
Loading…
Reference in New Issue
Block a user