ptrace_bps is already an array of size HBP_NUM_MAX. But we use hardcoded index 0 while fetching/updating it. Convert such code to loop over array.
Signed-off-by: Ravi Bangoria <ravi.bango...@linux.ibm.com> --- arch/powerpc/kernel/hw_breakpoint.c | 7 +++++-- arch/powerpc/kernel/process.c | 6 +++++- arch/powerpc/kernel/ptrace.c | 28 +++++++++++++++++++++------- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c index f4d48f87dcb8..b27aca623267 100644 --- a/arch/powerpc/kernel/hw_breakpoint.c +++ b/arch/powerpc/kernel/hw_breakpoint.c @@ -419,10 +419,13 @@ NOKPROBE_SYMBOL(hw_breakpoint_exceptions_notify); */ void flush_ptrace_hw_breakpoint(struct task_struct *tsk) { + int i; struct thread_struct *t = &tsk->thread; - unregister_hw_breakpoint(t->ptrace_bps[0]); - t->ptrace_bps[0] = NULL; + for (i = 0; i < nr_wp_slots(); i++) { + unregister_hw_breakpoint(t->ptrace_bps[i]); + t->ptrace_bps[i] = NULL; + } } void hw_breakpoint_pmu_read(struct perf_event *bp) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 42ff62ef749c..b9ab740fcacf 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1628,6 +1628,9 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp, void (*f)(void); unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; struct thread_info *ti = task_thread_info(p); +#ifdef CONFIG_HAVE_HW_BREAKPOINT + int i; +#endif klp_init_thread_info(p); @@ -1687,7 +1690,8 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp, p->thread.ksp_limit = (unsigned long)end_of_stack(p); #endif #ifdef CONFIG_HAVE_HW_BREAKPOINT - p->thread.ptrace_bps[0] = NULL; + for (i = 0; i < nr_wp_slots(); i++) + p->thread.ptrace_bps[i] = NULL; #endif p->thread.fp_save_area = NULL; diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index f6d7955fc61e..e2651f86d56f 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -2829,6 +2829,19 @@ static int set_dac_range(struct task_struct *child, } #endif /* CONFIG_PPC_ADV_DEBUG_DAC_RANGE */ +#ifdef CONFIG_HAVE_HW_BREAKPOINT +static int empty_ptrace_bp(struct thread_struct *thread) +{ + int i; + + for (i = 0; i < nr_wp_slots(); i++) { + if (!thread->ptrace_bps[i]) + return i; + } + return -1; +} +#endif + #ifndef CONFIG_PPC_ADV_DEBUG_REGS static int empty_hw_brk(struct thread_struct *thread) { @@ -2915,8 +2928,9 @@ static long ppc_set_hwdebug(struct task_struct *child, len = 1; else return -EINVAL; - bp = thread->ptrace_bps[0]; - if (bp) + + i = empty_ptrace_bp(thread); + if (i < 0) return -ENOSPC; /* Create a new breakpoint request if one doesn't exist already */ @@ -2925,14 +2939,14 @@ static long ppc_set_hwdebug(struct task_struct *child, attr.bp_len = len; arch_bp_generic_fields(brk.type, &attr.bp_type); - thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr, + thread->ptrace_bps[i] = bp = register_user_hw_breakpoint(&attr, ptrace_triggered, NULL, child); if (IS_ERR(bp)) { - thread->ptrace_bps[0] = NULL; + thread->ptrace_bps[i] = NULL; return PTR_ERR(bp); } - return 1; + return i + 1; #endif /* CONFIG_HAVE_HW_BREAKPOINT */ if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) @@ -2979,10 +2993,10 @@ static long ppc_del_hwdebug(struct task_struct *child, long data) return -EINVAL; #ifdef CONFIG_HAVE_HW_BREAKPOINT - bp = thread->ptrace_bps[0]; + bp = thread->ptrace_bps[data - 1]; if (bp) { unregister_hw_breakpoint(bp); - thread->ptrace_bps[0] = NULL; + thread->ptrace_bps[data - 1] = NULL; } else ret = -ENOENT; return ret; -- 2.21.1