|
@@ -1086,25 +1086,45 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
|
|
|
regs->msr = MSR_USER;
|
|
|
#else
|
|
|
if (!is_32bit_task()) {
|
|
|
- unsigned long entry, toc;
|
|
|
+ unsigned long entry;
|
|
|
|
|
|
- /* start is a relocated pointer to the function descriptor for
|
|
|
- * the elf _start routine. The first entry in the function
|
|
|
- * descriptor is the entry address of _start and the second
|
|
|
- * entry is the TOC value we need to use.
|
|
|
- */
|
|
|
- __get_user(entry, (unsigned long __user *)start);
|
|
|
- __get_user(toc, (unsigned long __user *)start+1);
|
|
|
+ if (is_elf2_task()) {
|
|
|
+ /* Look ma, no function descriptors! */
|
|
|
+ entry = start;
|
|
|
|
|
|
- /* Check whether the e_entry function descriptor entries
|
|
|
- * need to be relocated before we can use them.
|
|
|
- */
|
|
|
- if (load_addr != 0) {
|
|
|
- entry += load_addr;
|
|
|
- toc += load_addr;
|
|
|
+ /*
|
|
|
+ * Ulrich says:
|
|
|
+ * The latest iteration of the ABI requires that when
|
|
|
+ * calling a function (at its global entry point),
|
|
|
+ * the caller must ensure r12 holds the entry point
|
|
|
+ * address (so that the function can quickly
|
|
|
+ * establish addressability).
|
|
|
+ */
|
|
|
+ regs->gpr[12] = start;
|
|
|
+ /* Make sure that's restored on entry to userspace. */
|
|
|
+ set_thread_flag(TIF_RESTOREALL);
|
|
|
+ } else {
|
|
|
+ unsigned long toc;
|
|
|
+
|
|
|
+ /* start is a relocated pointer to the function
|
|
|
+ * descriptor for the elf _start routine. The first
|
|
|
+ * entry in the function descriptor is the entry
|
|
|
+ * address of _start and the second entry is the TOC
|
|
|
+ * value we need to use.
|
|
|
+ */
|
|
|
+ __get_user(entry, (unsigned long __user *)start);
|
|
|
+ __get_user(toc, (unsigned long __user *)start+1);
|
|
|
+
|
|
|
+ /* Check whether the e_entry function descriptor entries
|
|
|
+ * need to be relocated before we can use them.
|
|
|
+ */
|
|
|
+ if (load_addr != 0) {
|
|
|
+ entry += load_addr;
|
|
|
+ toc += load_addr;
|
|
|
+ }
|
|
|
+ regs->gpr[2] = toc;
|
|
|
}
|
|
|
regs->nip = entry;
|
|
|
- regs->gpr[2] = toc;
|
|
|
regs->msr = MSR_USER64;
|
|
|
} else {
|
|
|
regs->nip = start;
|