diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2013-11-20 06:15:02 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-11-20 17:19:19 -0500 |
commit | 94af3abf995b17f6a008b00152c94841242ec6c7 (patch) | |
tree | 97f860cd9c2957d3c51cccfaa927ae94b3b898e4 | |
parent | 918d03552e031dcbdaa2a22da3c2abff5952c38a (diff) |
powerpc: ELF2 binaries launched directly.
No function descriptor, but we set r12 up and set TIF_RESTOREALL as it
normally isn't restored on return from syscall.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/kernel/process.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 75c2d1009985..0650e18169f8 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -1086,25 +1086,45 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) | |||
1086 | regs->msr = MSR_USER; | 1086 | regs->msr = MSR_USER; |
1087 | #else | 1087 | #else |
1088 | if (!is_32bit_task()) { | 1088 | if (!is_32bit_task()) { |
1089 | unsigned long entry, toc; | 1089 | unsigned long entry; |
1090 | 1090 | ||
1091 | /* start is a relocated pointer to the function descriptor for | 1091 | if (is_elf2_task()) { |
1092 | * the elf _start routine. The first entry in the function | 1092 | /* Look ma, no function descriptors! */ |
1093 | * descriptor is the entry address of _start and the second | 1093 | entry = start; |
1094 | * entry is the TOC value we need to use. | ||
1095 | */ | ||
1096 | __get_user(entry, (unsigned long __user *)start); | ||
1097 | __get_user(toc, (unsigned long __user *)start+1); | ||
1098 | 1094 | ||
1099 | /* Check whether the e_entry function descriptor entries | 1095 | /* |
1100 | * need to be relocated before we can use them. | 1096 | * Ulrich says: |
1101 | */ | 1097 | * The latest iteration of the ABI requires that when |
1102 | if (load_addr != 0) { | 1098 | * calling a function (at its global entry point), |
1103 | entry += load_addr; | 1099 | * the caller must ensure r12 holds the entry point |
1104 | toc += load_addr; | 1100 | * address (so that the function can quickly |
1101 | * establish addressability). | ||
1102 | */ | ||
1103 | regs->gpr[12] = start; | ||
1104 | /* Make sure that's restored on entry to userspace. */ | ||
1105 | set_thread_flag(TIF_RESTOREALL); | ||
1106 | } else { | ||
1107 | unsigned long toc; | ||
1108 | |||
1109 | /* start is a relocated pointer to the function | ||
1110 | * descriptor for the elf _start routine. The first | ||
1111 | * entry in the function descriptor is the entry | ||
1112 | * address of _start and the second entry is the TOC | ||
1113 | * value we need to use. | ||
1114 | */ | ||
1115 | __get_user(entry, (unsigned long __user *)start); | ||
1116 | __get_user(toc, (unsigned long __user *)start+1); | ||
1117 | |||
1118 | /* Check whether the e_entry function descriptor entries | ||
1119 | * need to be relocated before we can use them. | ||
1120 | */ | ||
1121 | if (load_addr != 0) { | ||
1122 | entry += load_addr; | ||
1123 | toc += load_addr; | ||
1124 | } | ||
1125 | regs->gpr[2] = toc; | ||
1105 | } | 1126 | } |
1106 | regs->nip = entry; | 1127 | regs->nip = entry; |
1107 | regs->gpr[2] = toc; | ||
1108 | regs->msr = MSR_USER64; | 1128 | regs->msr = MSR_USER64; |
1109 | } else { | 1129 | } else { |
1110 | regs->nip = start; | 1130 | regs->nip = start; |