From 7cedd6014bfe353d4b552ed8d54d63f6e06e26ba Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 4 Feb 2014 16:08:51 +1100 Subject: 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 --- arch/powerpc/kernel/process.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'arch/powerpc/kernel/process.c') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 31d021506d2..2ae1b99166c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -54,6 +54,7 @@ #ifdef CONFIG_PPC64 #include #endif +#include #include #include @@ -1108,7 +1109,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, struct thread_info *ti = (void *)task_stack_page(p); memset(childregs, 0, 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 clear_tsk_thread_flag(p, TIF_32BIT); 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)) p->thread.ppr = INIT_PPR; #endif - /* - * 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 + kregs->nip = ppc_function_entry(f); return 0; } -- cgit v1.2.3-18-g5258 From 04c32a516806ec74b62048baf4cddcbb840927db Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 29 Apr 2014 15:25:16 -0400 Subject: powerpc: Drop return value from set_breakpoint as it is unused None of the callers check the return value, so it might as well not have one at all. Signed-off-by: Paul Gortmaker Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/process.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/kernel/process.c') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 2ae1b99166c..f895a506228 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -496,14 +496,14 @@ static inline int set_dawr(struct arch_hw_breakpoint *brk) return 0; } -int set_breakpoint(struct arch_hw_breakpoint *brk) +void set_breakpoint(struct arch_hw_breakpoint *brk) { __get_cpu_var(current_brk) = *brk; if (cpu_has_feature(CPU_FTR_DAWR)) - return set_dawr(brk); - - return set_dabr(brk); + set_dawr(brk); + else + set_dabr(brk); } #ifdef CONFIG_PPC64 -- cgit v1.2.3-18-g5258 From 21f585073d6347651f2262da187606fa1c4ee16d Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 29 Apr 2014 15:25:17 -0400 Subject: powerpc: Fix smp_processor_id() in preemptible splat in set_breakpoint Currently, on 8641D, which doesn't set CONFIG_HAVE_HW_BREAKPOINT we get the following splat: BUG: using smp_processor_id() in preemptible [00000000] code: login/1382 caller is set_breakpoint+0x1c/0xa0 CPU: 0 PID: 1382 Comm: login Not tainted 3.15.0-rc3-00041-g2aafe1a4d451 #1 Call Trace: [decd5d80] [c0008dc4] show_stack+0x50/0x158 (unreliable) [decd5dc0] [c03c6fa0] dump_stack+0x7c/0xdc [decd5de0] [c01f8818] check_preemption_disabled+0xf4/0x104 [decd5e00] [c00086b8] set_breakpoint+0x1c/0xa0 [decd5e10] [c00d4530] flush_old_exec+0x2bc/0x588 [decd5e40] [c011c468] load_elf_binary+0x2ac/0x1164 [decd5ec0] [c00d35f8] search_binary_handler+0xc4/0x1f8 [decd5ef0] [c00d4ee8] do_execve+0x3d8/0x4b8 [decd5f40] [c001185c] ret_from_syscall+0x0/0x38 --- Exception: c01 at 0xfeee554 LR = 0xfeee7d4 The call path in this case is: flush_thread --> set_debug_reg_defaults --> set_breakpoint --> __get_cpu_var Since preemption is enabled in the cleanup of flush thread, and there is no need to disable it, introduce the distinction between set_breakpoint and __set_breakpoint, leaving only the flush_thread instance as the current user of set_breakpoint. Signed-off-by: Paul Gortmaker Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/process.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/kernel/process.c') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index f895a506228..8a1edbe26b8 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -496,7 +496,7 @@ static inline int set_dawr(struct arch_hw_breakpoint *brk) return 0; } -void set_breakpoint(struct arch_hw_breakpoint *brk) +void __set_breakpoint(struct arch_hw_breakpoint *brk) { __get_cpu_var(current_brk) = *brk; @@ -506,6 +506,13 @@ void set_breakpoint(struct arch_hw_breakpoint *brk) set_dabr(brk); } +void set_breakpoint(struct arch_hw_breakpoint *brk) +{ + preempt_disable(); + __set_breakpoint(brk); + preempt_enable(); +} + #ifdef CONFIG_PPC64 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); #endif @@ -835,7 +842,7 @@ struct task_struct *__switch_to(struct task_struct *prev, */ #ifndef CONFIG_HAVE_HW_BREAKPOINT if (unlikely(!hw_brk_match(&__get_cpu_var(current_brk), &new->thread.hw_brk))) - set_breakpoint(&new->thread.hw_brk); + __set_breakpoint(&new->thread.hw_brk); #endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif -- cgit v1.2.3-18-g5258