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: Anton Blanchard <anton@samba.org>
This commit is contained in:
parent
b86206e4c3
commit
7cedd6014b
@ -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 @@
|
|||||||
#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,
|
|||||||
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,
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user