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; |
