[PATCH] kernel panic during kernel module load (powerpc specific part)
roger blofeld
blofeldus at yahoo.com
Fri Jun 22 01:27:14 EST 2012
--- On Wed, 6/6/12, Steffen Rumler <steffen.rumler.ext at nsn.com> wrote:
> From: Steffen Rumler <steffen.rumler.ext at nsn.com>
> Subject: [PATCH] kernel panic during kernel module load (powerpc specific part)
> To: "ext Benjamin Herrenschmidt" <benh at kernel.crashing.org>, paulus at samba.org
> Cc: "Wrobel Heinz-R39252" <r39252 at freescale.com>, "Michael Ellerman" <michael at ellerman.id.au>, "linuxppc-dev at lists.ozlabs.org" <linuxppc-dev at lists.ozlabs.org>
> Date: Wednesday, June 6, 2012, 7:37 AM
> Hi,
>
> The patch below is intended to fix the following problem.
>
> According to the PowerPC EABI specification, the 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), the GPR r11 is also
> used
> to generate trampoline code.
>
> This combination crashes the kernel, in the following case:
>
> + The compiler has been generated the prologue and
> epilogue,
> which is part of the .text section.
> + The compiler has been generated the code for the
> module init entry point,
> part of the .init.text section (in the case it
> is marked with __init).
> + By returning from the module init entry point, the
> epilogue is called by doing
> a branch instruction.
> + If the epilogue is too far away, a relative branch
> instruction cannot be applied.
> Instead trampoline code is generated in
> do_plt_call(), in order to jump via register.
> Unfortunately the code generated by
> do_plt_call() destroys the content of GPR r11.
> + Because GPR r11 does not more keep the right stack
> frame pointer,
> the kernel crashes right after the epilogue.
>
> The fix just uses GPR r12 instead of GPR r11 for generating
> the trampoline code.
> According to the statements from Freescale, this is also
> save from EABI perspective.
>
> I've tested the fix for kernel 2.6.33 on MPC8541.
>
> Signed-off-by: Steffen Rumler <steffen.rumler.ext at nsn.com>
> ---
>
> --- orig/arch/powerpc/kernel/module_32.c
> 2012-06-06 16:04:28.956446788 +0200
> +++ new/arch/powerpc/kernel/module_32.c
> 2012-06-06 16:04:17.746290683 +0200
> @@ -187,8 +187,8 @@
>
> 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;
> }
> @@ -215,10 +215,9 @@
> entry++;
> }
>
> - /* Stolen from Paul Mackerras as well...
> */
> - entry->jump[0] =
> 0x3d600000+((val+0x8000)>>16); /*
> lis r11,sym at ha */
> - entry->jump[1] = 0x396b0000 +
> (val&0xffff); /* addi r11,r11,sym at l*/
> - entry->jump[2] =
> 0x7d6903a6;
> /* mtctr r11 */
> + entry->jump[0] =
> 0x3d800000+((val+0x8000)>>16); /* lis r12,sym at ha */
> + entry->jump[1] = 0x398c0000 +
> (val&0xffff); /* addi
> r12,r12,sym at l*/
> + entry->jump[2] = 0x7d8903a6;
>
> /* mtctr r12 */
> entry->jump[3] =
> 0x4e800420;
> /* bctr */
>
> DEBUGP("Initialized plt for 0x%x at
> %p\n", val, entry);
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
Hi,
Shouldn't the corresponding ftrace code be updated to match? Perhaps like the following (untested) patch:
Signed-off-by: Roger Blofeld <blofeldus at yahoo.com>
---
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -245,9 +245,9 @@ __ftrace_make_nop(struct module *mod,
/*
* On PPC32 the trampoline looks like:
- * 0x3d, 0x60, 0x00, 0x00 lis r11,sym at ha
- * 0x39, 0x6b, 0x00, 0x00 addi r11,r11,sym at l
- * 0x7d, 0x69, 0x03, 0xa6 mtctr r11
+ * 0x3d, 0x80, 0x00, 0x00 lis r12,sym at ha
+ * 0x39, 0x8c, 0x00, 0x00 addi r12,r12,sym at l
+ * 0x7d, 0x89, 0x03, 0xa6 mtctr r12
* 0x4e, 0x80, 0x04, 0x20 bctr
*/
@@ -262,9 +262,9 @@ __ftrace_make_nop(struct module *mod,
pr_devel(" %08x %08x ", jmp[0], jmp[1]);
/* verify that this is what we expect it to be */
- if (((jmp[0] & 0xffff0000) != 0x3d600000) ||
- ((jmp[1] & 0xffff0000) != 0x396b0000) ||
- (jmp[2] != 0x7d6903a6) ||
+ if (((jmp[0] & 0xffff0000) != 0x3d800000) ||
+ ((jmp[1] & 0xffff0000) != 0x398c0000) ||
+ (jmp[2] != 0x7d8903a6) ||
(jmp[3] != 0x4e800420)) {
printk(KERN_ERR "Not a trampoline\n");
return -EINVAL;
More information about the Linuxppc-dev
mailing list