diff options
author | Anton Blanchard <anton@samba.org> | 2014-02-04 00:08:51 -0500 |
---|---|---|
committer | Anton Blanchard <anton@samba.org> | 2014-04-22 20:05:23 -0400 |
commit | 7cedd6014bfe353d4b552ed8d54d63f6e06e26ba (patch) | |
tree | e65291b54d3de8d90c370581d776dbb4d2aafe05 /arch/powerpc/kernel/process.c | |
parent | b86206e4c32cbe6ac3de1c6dc52c2d64bcf461cb (diff) |
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>
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r-- | arch/powerpc/kernel/process.c | 17 |
1 files changed, 5 insertions, 12 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 31d021506d21..2ae1b99166c6 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #ifdef CONFIG_PPC64 | 54 | #ifdef CONFIG_PPC64 |
55 | #include <asm/firmware.h> | 55 | #include <asm/firmware.h> |
56 | #endif | 56 | #endif |
57 | #include <asm/code-patching.h> | ||
57 | #include <linux/kprobes.h> | 58 | #include <linux/kprobes.h> |
58 | #include <linux/kdebug.h> | 59 | #include <linux/kdebug.h> |
59 | 60 | ||
@@ -1108,7 +1109,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
1108 | struct thread_info *ti = (void *)task_stack_page(p); | 1109 | struct thread_info *ti = (void *)task_stack_page(p); |
1109 | memset(childregs, 0, sizeof(struct pt_regs)); | 1110 | memset(childregs, 0, sizeof(struct pt_regs)); |
1110 | childregs->gpr[1] = sp + sizeof(struct pt_regs); | 1111 | childregs->gpr[1] = sp + sizeof(struct pt_regs); |
1111 | childregs->gpr[14] = usp; /* function */ | 1112 | /* function */ |
1113 | if (usp) | ||
1114 | childregs->gpr[14] = ppc_function_entry((void *)usp); | ||
1112 | #ifdef CONFIG_PPC64 | 1115 | #ifdef CONFIG_PPC64 |
1113 | clear_tsk_thread_flag(p, TIF_32BIT); | 1116 | clear_tsk_thread_flag(p, TIF_32BIT); |
1114 | childregs->softe = 1; | 1117 | childregs->softe = 1; |
@@ -1187,17 +1190,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
1187 | if (cpu_has_feature(CPU_FTR_HAS_PPR)) | 1190 | if (cpu_has_feature(CPU_FTR_HAS_PPR)) |
1188 | p->thread.ppr = INIT_PPR; | 1191 | p->thread.ppr = INIT_PPR; |
1189 | #endif | 1192 | #endif |
1190 | /* | 1193 | kregs->nip = ppc_function_entry(f); |
1191 | * The PPC64 ABI makes use of a TOC to contain function | ||
1192 | * pointers. The function (ret_from_except) is actually a pointer | ||
1193 | * to the TOC entry. The first entry is a pointer to the actual | ||
1194 | * function. | ||
1195 | */ | ||
1196 | #ifdef CONFIG_PPC64 | ||
1197 | kregs->nip = *((unsigned long *)f); | ||
1198 | #else | ||
1199 | kregs->nip = (unsigned long)f; | ||
1200 | #endif | ||
1201 | return 0; | 1194 | return 0; |
1202 | } | 1195 | } |
1203 | 1196 | ||