aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2013-11-20 06:15:02 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-11-20 17:19:19 -0500
commit94af3abf995b17f6a008b00152c94841242ec6c7 (patch)
tree97f860cd9c2957d3c51cccfaa927ae94b3b898e4
parent918d03552e031dcbdaa2a22da3c2abff5952c38a (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.c50
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;