Commit 7cedd601 authored by Anton Blanchard's avatar Anton Blanchard

powerpc: Fix kernel thread creation on ABIv2

Change how we setup registers for ret_from_kernel_thread. In
ABIv1, instead of passing a function descriptor in, dereference
it and pass the target in directly.

Use ppc_global_function_entry to get it right on both ABIv1 and ABIv2.
Signed-off-by: default avatarAnton Blanchard <anton@samba.org>
parent b86206e4
...@@ -378,9 +378,11 @@ _GLOBAL(ret_from_fork) ...@@ -378,9 +378,11 @@ _GLOBAL(ret_from_fork)
_GLOBAL(ret_from_kernel_thread) _GLOBAL(ret_from_kernel_thread)
bl schedule_tail bl schedule_tail
REST_NVGPRS(r1) REST_NVGPRS(r1)
ld r14, 0(r14)
mtlr r14 mtlr r14
mr r3,r15 mr r3,r15
#if defined(_CALL_ELF) && _CALL_ELF == 2
mr r12,r14
#endif
blrl blrl
li r3,0 li r3,0
b syscall_exit b syscall_exit
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
#include <asm/firmware.h> #include <asm/firmware.h>
#endif #endif
#include <asm/code-patching.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/kdebug.h> #include <linux/kdebug.h>
...@@ -1108,7 +1109,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, ...@@ -1108,7 +1109,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
struct thread_info *ti = (void *)task_stack_page(p); struct thread_info *ti = (void *)task_stack_page(p);
memset(childregs, 0, sizeof(struct pt_regs)); memset(childregs, 0, sizeof(struct pt_regs));
childregs->gpr[1] = sp + sizeof(struct pt_regs); childregs->gpr[1] = sp + sizeof(struct pt_regs);
childregs->gpr[14] = usp; /* function */ /* function */
if (usp)
childregs->gpr[14] = ppc_function_entry((void *)usp);
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
clear_tsk_thread_flag(p, TIF_32BIT); clear_tsk_thread_flag(p, TIF_32BIT);
childregs->softe = 1; childregs->softe = 1;
...@@ -1187,17 +1190,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, ...@@ -1187,17 +1190,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
if (cpu_has_feature(CPU_FTR_HAS_PPR)) if (cpu_has_feature(CPU_FTR_HAS_PPR))
p->thread.ppr = INIT_PPR; p->thread.ppr = INIT_PPR;
#endif #endif
/* kregs->nip = ppc_function_entry(f);
* The PPC64 ABI makes use of a TOC to contain function
* pointers. The function (ret_from_except) is actually a pointer
* to the TOC entry. The first entry is a pointer to the actual
* function.
*/
#ifdef CONFIG_PPC64
kregs->nip = *((unsigned long *)f);
#else
kregs->nip = (unsigned long)f;
#endif
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment