summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/module_64.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2014-03-18 10:43:03 +0100
committerAnton Blanchard <anton@samba.org>2014-04-23 02:05:31 +0200
commit5c729a115e4727fd71308e4d68846f64fa460ead (patch)
treeb99b125e90a2600c47a08f48515da2b80641f913 /arch/powerpc/kernel/module_64.c
parentpowerpc: modules: use r12 for stub jump address. (diff)
downloadlinux-5c729a115e4727fd71308e4d68846f64fa460ead.tar.xz
linux-5c729a115e4727fd71308e4d68846f64fa460ead.zip
powerpc: modules: skip r2 setup for ELFv2
ELFv2 doesn't need to set up r2 when calling a function. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'arch/powerpc/kernel/module_64.c')
-rw-r--r--arch/powerpc/kernel/module_64.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index f8b6d28784ef..d7222495e24c 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -59,12 +59,19 @@ struct ppc64_stub_entry
struct ppc64_opd_entry opd;
};
-/* We use a stub to fix up r2 (TOC ptr) and to jump to the (external)
- function which may be more than 24-bits away. We could simply
- patch the new r2 value and function pointer into the stub, but it's
- significantly shorter to put these values at the end of the stub
- code, and patch the stub address (32-bits relative to the TOC ptr,
- r2) into the stub. */
+/*
+ * PPC64 uses 24 bit jumps, but we need to jump into other modules or
+ * the kernel which may be further. So we jump to a stub.
+ *
+ * For ELFv1 we need to use this to set up the new r2 value (aka TOC
+ * pointer). For ELFv2 it's the callee's responsibility to set up the
+ * new r2, but for both we need to save the old r2.
+ *
+ * We could simply patch the new r2 value and function pointer into
+ * the stub, but it's significantly shorter to put these values at the
+ * end of the stub code, and patch the stub address (32-bits relative
+ * to the TOC ptr, r2) into the stub.
+ */
static struct ppc64_stub_entry ppc64_stub =
{ .jump = {
0x3d620000, /* addis r11,r2, <high> */
@@ -72,7 +79,10 @@ static struct ppc64_stub_entry ppc64_stub =
/* Save current r2 value in magic place on the stack. */
0xf8410000|R2_STACK_OFFSET, /* std r2,R2_STACK_OFFSET(r1) */
0xe98b0020, /* ld r12,32(r11) */
+#if !defined(_CALL_ELF) || _CALL_ELF != 2
+ /* Set up new r2 from function descriptor */
0xe84b0026, /* ld r2,40(r11) */
+#endif
0x7d8903a6, /* mtctr r12 */
0x4e800420 /* bctr */
} };