Message ID | 20200309085806.155823-10-ravi.bangoria@linux.ibm.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | powerpc/watchpoint: Preparation for more than one watchpoint | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/apply_patch | success | Successfully applied on branch powerpc/merge (ab326587bb5fb91cc97df9b9f48e9e1469f04621) |
snowpatch_ozlabs/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 208 lines checked |
snowpatch_ozlabs/needsstable | success | Patch has no Fixes tags |
Le 09/03/2020 à 09:58, Ravi Bangoria a écrit : > So far powerpc hw supported only one watchpoint. But Future Power > architecture is introducing 2nd DAWR. Convert thread_struct->hw_brk > into an array. Looks like you are doing a lot more than that in this patch. Should this patch be splitted in two parts ? Christophe > > Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com> > --- > arch/powerpc/include/asm/processor.h | 2 +- > arch/powerpc/kernel/process.c | 43 ++++++++++++++++++++-------- > arch/powerpc/kernel/ptrace.c | 42 ++++++++++++++++++++------- > arch/powerpc/kernel/ptrace32.c | 4 +-- > arch/powerpc/kernel/signal.c | 9 ++++-- > 5 files changed, 72 insertions(+), 28 deletions(-) > > diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h > index 666b2825278c..57a8fac2e72b 100644 > --- a/arch/powerpc/include/asm/processor.h > +++ b/arch/powerpc/include/asm/processor.h > @@ -183,7 +183,7 @@ struct thread_struct { > */ > struct perf_event *last_hit_ubp; > #endif /* CONFIG_HAVE_HW_BREAKPOINT */ > - struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */ > + struct arch_hw_breakpoint hw_brk[HBP_NUM_MAX]; /* hardware breakpoint info */ > unsigned long trap_nr; /* last trap # on this thread */ > u8 load_slb; /* Ages out SLB preload cache entries */ > u8 load_fp; > diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c > index f6bb2586fa5d..42ff62ef749c 100644 > --- a/arch/powerpc/kernel/process.c > +++ b/arch/powerpc/kernel/process.c > @@ -704,21 +704,25 @@ void switch_booke_debug_regs(struct debug_reg *new_debug) > EXPORT_SYMBOL_GPL(switch_booke_debug_regs); > #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ > #ifndef CONFIG_HAVE_HW_BREAKPOINT > -static void set_breakpoint(struct arch_hw_breakpoint *brk) > +static void set_breakpoint(struct arch_hw_breakpoint *brk, int i) > { > preempt_disable(); > - __set_breakpoint(brk, 0); > + __set_breakpoint(brk, i); > preempt_enable(); > } > > static void set_debug_reg_defaults(struct thread_struct *thread) > { > - thread->hw_brk.address = 0; > - thread->hw_brk.type = 0; > - thread->hw_brk.len = 0; > - thread->hw_brk.hw_len = 0; > - if (ppc_breakpoint_available()) > - set_breakpoint(&thread->hw_brk); > + int i; > + > + for (i = 0; i < nr_wp_slots(); i++) { > + thread->hw_brk[i].address = 0; > + thread->hw_brk[i].type = 0; > + thread->hw_brk[i].len = 0; > + thread->hw_brk[i].hw_len = 0; > + if (ppc_breakpoint_available()) > + set_breakpoint(&thread->hw_brk[i], i); > + } > } > #endif /* !CONFIG_HAVE_HW_BREAKPOINT */ > #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ > @@ -1141,6 +1145,24 @@ static inline void restore_sprs(struct thread_struct *old_thread, > thread_pkey_regs_restore(new_thread, old_thread); > } > > +#ifndef CONFIG_HAVE_HW_BREAKPOINT > +static void switch_hw_breakpoint(struct task_struct *new) > +{ > + int i; > + > + for (i = 0; i < nr_wp_slots(); i++) { > + if (unlikely(!hw_brk_match(this_cpu_ptr(¤t_brk[i]), > + &new->thread.hw_brk[i]))) { > + __set_breakpoint(&new->thread.hw_brk[i], i); > + } > + } > +} > +#else > +static void switch_hw_breakpoint(struct task_struct *new) > +{ > +} > +#endif > + > struct task_struct *__switch_to(struct task_struct *prev, > struct task_struct *new) > { > @@ -1172,10 +1194,7 @@ struct task_struct *__switch_to(struct task_struct *prev, > * For PPC_BOOK3S_64, we use the hw-breakpoint interfaces that would > * schedule DABR > */ > -#ifndef CONFIG_HAVE_HW_BREAKPOINT > - if (unlikely(!hw_brk_match(this_cpu_ptr(¤t_brk[0]), &new->thread.hw_brk))) > - __set_breakpoint(&new->thread.hw_brk, 0); > -#endif /* CONFIG_HAVE_HW_BREAKPOINT */ > + switch_hw_breakpoint(new); > #endif > > /* > diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c > index dd46e174dbe7..f6d7955fc61e 100644 > --- a/arch/powerpc/kernel/ptrace.c > +++ b/arch/powerpc/kernel/ptrace.c > @@ -2382,6 +2382,11 @@ void ptrace_triggered(struct perf_event *bp, > } > #endif /* CONFIG_HAVE_HW_BREAKPOINT */ > > +/* > + * ptrace_set_debugreg() fakes DABR and DABR is only one. So even if > + * internal hw supports more than one watchpoint, we support only one > + * watchpoint with this interface. > + */ > static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, > unsigned long data) > { > @@ -2451,7 +2456,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, > return ret; > } > thread->ptrace_bps[0] = bp; > - thread->hw_brk = hw_brk; > + thread->hw_brk[0] = hw_brk; > return 0; > } > > @@ -2473,7 +2478,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, > if (set_bp && (!ppc_breakpoint_available())) > return -ENODEV; > #endif /* CONFIG_HAVE_HW_BREAKPOINT */ > - task->thread.hw_brk = hw_brk; > + task->thread.hw_brk[0] = hw_brk; > #else /* CONFIG_PPC_ADV_DEBUG_REGS */ > /* As described above, it was assumed 3 bits were passed with the data > * address, but we will assume only the mode bits will be passed > @@ -2824,9 +2829,23 @@ static int set_dac_range(struct task_struct *child, > } > #endif /* CONFIG_PPC_ADV_DEBUG_DAC_RANGE */ > > +#ifndef CONFIG_PPC_ADV_DEBUG_REGS > +static int empty_hw_brk(struct thread_struct *thread) > +{ > + int i; > + > + for (i = 0; i < nr_wp_slots(); i++) { > + if (!thread->hw_brk[i].address) > + return i; > + } > + return -1; > +} > +#endif > + > static long ppc_set_hwdebug(struct task_struct *child, > struct ppc_hw_breakpoint *bp_info) > { > + int i; > #ifdef CONFIG_HAVE_HW_BREAKPOINT > int len = 0; > struct thread_struct *thread = &(child->thread); > @@ -2919,15 +2938,16 @@ static long ppc_set_hwdebug(struct task_struct *child, > if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) > return -EINVAL; > > - if (child->thread.hw_brk.address) > + i = empty_hw_brk(&child->thread); > + if (i < 0) > return -ENOSPC; > > if (!ppc_breakpoint_available()) > return -ENODEV; > > - child->thread.hw_brk = brk; > + child->thread.hw_brk[i] = brk; > > - return 1; > + return i + 1; > #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ > } > > @@ -2955,7 +2975,7 @@ static long ppc_del_hwdebug(struct task_struct *child, long data) > } > return rc; > #else > - if (data != 1) > + if (data < 1 || data > nr_wp_slots()) > return -EINVAL; > > #ifdef CONFIG_HAVE_HW_BREAKPOINT > @@ -2967,11 +2987,11 @@ static long ppc_del_hwdebug(struct task_struct *child, long data) > ret = -ENOENT; > return ret; > #else /* CONFIG_HAVE_HW_BREAKPOINT */ > - if (child->thread.hw_brk.address == 0) > + if (child->thread.hw_brk[data - 1].address == 0) > return -ENOENT; > > - child->thread.hw_brk.address = 0; > - child->thread.hw_brk.type = 0; > + child->thread.hw_brk[data - 1].address = 0; > + child->thread.hw_brk[data - 1].type = 0; > #endif /* CONFIG_HAVE_HW_BREAKPOINT */ > > return 0; > @@ -3124,8 +3144,8 @@ long arch_ptrace(struct task_struct *child, long request, > #ifdef CONFIG_PPC_ADV_DEBUG_REGS > ret = put_user(child->thread.debug.dac1, datalp); > #else > - dabr_fake = ((child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) | > - (child->thread.hw_brk.type & HW_BRK_TYPE_DABR)); > + dabr_fake = ((child->thread.hw_brk[0].address & (~HW_BRK_TYPE_DABR)) | > + (child->thread.hw_brk[0].type & HW_BRK_TYPE_DABR)); > ret = put_user(dabr_fake, datalp); > #endif > break; > diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c > index f37eb53de1a1..e227cd320b46 100644 > --- a/arch/powerpc/kernel/ptrace32.c > +++ b/arch/powerpc/kernel/ptrace32.c > @@ -270,8 +270,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, > ret = put_user(child->thread.debug.dac1, (u32 __user *)data); > #else > dabr_fake = ( > - (child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) | > - (child->thread.hw_brk.type & HW_BRK_TYPE_DABR)); > + (child->thread.hw_brk[0].address & (~HW_BRK_TYPE_DABR)) | > + (child->thread.hw_brk[0].type & HW_BRK_TYPE_DABR)); > ret = put_user(dabr_fake, (u32 __user *)data); > #endif > break; > diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c > index 8bc6cc55420a..3116896e89a6 100644 > --- a/arch/powerpc/kernel/signal.c > +++ b/arch/powerpc/kernel/signal.c > @@ -107,6 +107,9 @@ static void do_signal(struct task_struct *tsk) > struct ksignal ksig = { .sig = 0 }; > int ret; > int is32 = is_32bit_task(); > +#ifndef CONFIG_PPC_ADV_DEBUG_REGS > + int i; > +#endif > > BUG_ON(tsk != current); > > @@ -128,8 +131,10 @@ static void do_signal(struct task_struct *tsk) > * user space. The DABR will have been cleared if it > * triggered inside the kernel. > */ > - if (tsk->thread.hw_brk.address && tsk->thread.hw_brk.type) > - __set_breakpoint(&tsk->thread.hw_brk, 0); > + for (i = 0; i < nr_wp_slots(); i++) { > + if (tsk->thread.hw_brk[i].address && tsk->thread.hw_brk[i].type) > + __set_breakpoint(&tsk->thread.hw_brk[i], i); > + } > #endif > /* Re-enable the breakpoints for the signal stack */ > thread_change_pc(tsk, tsk->thread.regs); >
On 3/17/20 4:07 PM, Christophe Leroy wrote: > > > Le 09/03/2020 à 09:58, Ravi Bangoria a écrit : >> So far powerpc hw supported only one watchpoint. But Future Power >> architecture is introducing 2nd DAWR. Convert thread_struct->hw_brk >> into an array. > > Looks like you are doing a lot more than that in this patch. > > Should this patch be splitted in two parts ? So far thread_struct->hw_brk was a normal variable so accessing it was simple. Once it gets converted into an array, loop needs to be used to access it. So all misc changes are basically converting simple access into loops. I don't see how this can be splitted. Thanks, Ravi
Le 18/03/2020 à 09:36, Ravi Bangoria a écrit : > > > On 3/17/20 4:07 PM, Christophe Leroy wrote: >> >> >> Le 09/03/2020 à 09:58, Ravi Bangoria a écrit : >>> So far powerpc hw supported only one watchpoint. But Future Power >>> architecture is introducing 2nd DAWR. Convert thread_struct->hw_brk >>> into an array. >> >> Looks like you are doing a lot more than that in this patch. >> >> Should this patch be splitted in two parts ? > > So far thread_struct->hw_brk was a normal variable so accessing it was > simple. > Once it gets converted into an array, loop needs to be used to access > it. So > all misc changes are basically converting simple access into loops. > > I don't see how this can be splitted. > You could first change all thread_struct->hw_brk to thread_struct->hw_brk[0] or thread_struct->hw_brk[i] when you know that i can only be 0 for now. Then add the loops and new functions in a second patch. Christophe
On 3/18/20 2:26 PM, Christophe Leroy wrote: > > > Le 18/03/2020 à 09:36, Ravi Bangoria a écrit : >> >> >> On 3/17/20 4:07 PM, Christophe Leroy wrote: >>> >>> >>> Le 09/03/2020 à 09:58, Ravi Bangoria a écrit : >>>> So far powerpc hw supported only one watchpoint. But Future Power >>>> architecture is introducing 2nd DAWR. Convert thread_struct->hw_brk >>>> into an array. >>> >>> Looks like you are doing a lot more than that in this patch. >>> >>> Should this patch be splitted in two parts ? >> >> So far thread_struct->hw_brk was a normal variable so accessing it was simple. >> Once it gets converted into an array, loop needs to be used to access it. So >> all misc changes are basically converting simple access into loops. >> >> I don't see how this can be splitted. >> > > You could first change all thread_struct->hw_brk to thread_struct->hw_brk[0] or thread_struct->hw_brk[i] when you know that i can only be 0 for now. Then add the loops and new functions in a second patch. Ok. I've already tried that :) But it looked unnecessary split to me because _all_ hw_brk => hw_brk[0] changes will again need to be changed to use loop in 2nd patch. So I thought it's better to do both changes in one patch. Thanks, Ravi
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 666b2825278c..57a8fac2e72b 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -183,7 +183,7 @@ struct thread_struct { */ struct perf_event *last_hit_ubp; #endif /* CONFIG_HAVE_HW_BREAKPOINT */ - struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */ + struct arch_hw_breakpoint hw_brk[HBP_NUM_MAX]; /* hardware breakpoint info */ unsigned long trap_nr; /* last trap # on this thread */ u8 load_slb; /* Ages out SLB preload cache entries */ u8 load_fp; diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index f6bb2586fa5d..42ff62ef749c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -704,21 +704,25 @@ void switch_booke_debug_regs(struct debug_reg *new_debug) EXPORT_SYMBOL_GPL(switch_booke_debug_regs); #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ #ifndef CONFIG_HAVE_HW_BREAKPOINT -static void set_breakpoint(struct arch_hw_breakpoint *brk) +static void set_breakpoint(struct arch_hw_breakpoint *brk, int i) { preempt_disable(); - __set_breakpoint(brk, 0); + __set_breakpoint(brk, i); preempt_enable(); } static void set_debug_reg_defaults(struct thread_struct *thread) { - thread->hw_brk.address = 0; - thread->hw_brk.type = 0; - thread->hw_brk.len = 0; - thread->hw_brk.hw_len = 0; - if (ppc_breakpoint_available()) - set_breakpoint(&thread->hw_brk); + int i; + + for (i = 0; i < nr_wp_slots(); i++) { + thread->hw_brk[i].address = 0; + thread->hw_brk[i].type = 0; + thread->hw_brk[i].len = 0; + thread->hw_brk[i].hw_len = 0; + if (ppc_breakpoint_available()) + set_breakpoint(&thread->hw_brk[i], i); + } } #endif /* !CONFIG_HAVE_HW_BREAKPOINT */ #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ @@ -1141,6 +1145,24 @@ static inline void restore_sprs(struct thread_struct *old_thread, thread_pkey_regs_restore(new_thread, old_thread); } +#ifndef CONFIG_HAVE_HW_BREAKPOINT +static void switch_hw_breakpoint(struct task_struct *new) +{ + int i; + + for (i = 0; i < nr_wp_slots(); i++) { + if (unlikely(!hw_brk_match(this_cpu_ptr(¤t_brk[i]), + &new->thread.hw_brk[i]))) { + __set_breakpoint(&new->thread.hw_brk[i], i); + } + } +} +#else +static void switch_hw_breakpoint(struct task_struct *new) +{ +} +#endif + struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *new) { @@ -1172,10 +1194,7 @@ struct task_struct *__switch_to(struct task_struct *prev, * For PPC_BOOK3S_64, we use the hw-breakpoint interfaces that would * schedule DABR */ -#ifndef CONFIG_HAVE_HW_BREAKPOINT - if (unlikely(!hw_brk_match(this_cpu_ptr(¤t_brk[0]), &new->thread.hw_brk))) - __set_breakpoint(&new->thread.hw_brk, 0); -#endif /* CONFIG_HAVE_HW_BREAKPOINT */ + switch_hw_breakpoint(new); #endif /* diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index dd46e174dbe7..f6d7955fc61e 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -2382,6 +2382,11 @@ void ptrace_triggered(struct perf_event *bp, } #endif /* CONFIG_HAVE_HW_BREAKPOINT */ +/* + * ptrace_set_debugreg() fakes DABR and DABR is only one. So even if + * internal hw supports more than one watchpoint, we support only one + * watchpoint with this interface. + */ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, unsigned long data) { @@ -2451,7 +2456,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, return ret; } thread->ptrace_bps[0] = bp; - thread->hw_brk = hw_brk; + thread->hw_brk[0] = hw_brk; return 0; } @@ -2473,7 +2478,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, if (set_bp && (!ppc_breakpoint_available())) return -ENODEV; #endif /* CONFIG_HAVE_HW_BREAKPOINT */ - task->thread.hw_brk = hw_brk; + task->thread.hw_brk[0] = hw_brk; #else /* CONFIG_PPC_ADV_DEBUG_REGS */ /* As described above, it was assumed 3 bits were passed with the data * address, but we will assume only the mode bits will be passed @@ -2824,9 +2829,23 @@ static int set_dac_range(struct task_struct *child, } #endif /* CONFIG_PPC_ADV_DEBUG_DAC_RANGE */ +#ifndef CONFIG_PPC_ADV_DEBUG_REGS +static int empty_hw_brk(struct thread_struct *thread) +{ + int i; + + for (i = 0; i < nr_wp_slots(); i++) { + if (!thread->hw_brk[i].address) + return i; + } + return -1; +} +#endif + static long ppc_set_hwdebug(struct task_struct *child, struct ppc_hw_breakpoint *bp_info) { + int i; #ifdef CONFIG_HAVE_HW_BREAKPOINT int len = 0; struct thread_struct *thread = &(child->thread); @@ -2919,15 +2938,16 @@ static long ppc_set_hwdebug(struct task_struct *child, if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) return -EINVAL; - if (child->thread.hw_brk.address) + i = empty_hw_brk(&child->thread); + if (i < 0) return -ENOSPC; if (!ppc_breakpoint_available()) return -ENODEV; - child->thread.hw_brk = brk; + child->thread.hw_brk[i] = brk; - return 1; + return i + 1; #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ } @@ -2955,7 +2975,7 @@ static long ppc_del_hwdebug(struct task_struct *child, long data) } return rc; #else - if (data != 1) + if (data < 1 || data > nr_wp_slots()) return -EINVAL; #ifdef CONFIG_HAVE_HW_BREAKPOINT @@ -2967,11 +2987,11 @@ static long ppc_del_hwdebug(struct task_struct *child, long data) ret = -ENOENT; return ret; #else /* CONFIG_HAVE_HW_BREAKPOINT */ - if (child->thread.hw_brk.address == 0) + if (child->thread.hw_brk[data - 1].address == 0) return -ENOENT; - child->thread.hw_brk.address = 0; - child->thread.hw_brk.type = 0; + child->thread.hw_brk[data - 1].address = 0; + child->thread.hw_brk[data - 1].type = 0; #endif /* CONFIG_HAVE_HW_BREAKPOINT */ return 0; @@ -3124,8 +3144,8 @@ long arch_ptrace(struct task_struct *child, long request, #ifdef CONFIG_PPC_ADV_DEBUG_REGS ret = put_user(child->thread.debug.dac1, datalp); #else - dabr_fake = ((child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) | - (child->thread.hw_brk.type & HW_BRK_TYPE_DABR)); + dabr_fake = ((child->thread.hw_brk[0].address & (~HW_BRK_TYPE_DABR)) | + (child->thread.hw_brk[0].type & HW_BRK_TYPE_DABR)); ret = put_user(dabr_fake, datalp); #endif break; diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index f37eb53de1a1..e227cd320b46 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c @@ -270,8 +270,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ret = put_user(child->thread.debug.dac1, (u32 __user *)data); #else dabr_fake = ( - (child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) | - (child->thread.hw_brk.type & HW_BRK_TYPE_DABR)); + (child->thread.hw_brk[0].address & (~HW_BRK_TYPE_DABR)) | + (child->thread.hw_brk[0].type & HW_BRK_TYPE_DABR)); ret = put_user(dabr_fake, (u32 __user *)data); #endif break; diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 8bc6cc55420a..3116896e89a6 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -107,6 +107,9 @@ static void do_signal(struct task_struct *tsk) struct ksignal ksig = { .sig = 0 }; int ret; int is32 = is_32bit_task(); +#ifndef CONFIG_PPC_ADV_DEBUG_REGS + int i; +#endif BUG_ON(tsk != current); @@ -128,8 +131,10 @@ static void do_signal(struct task_struct *tsk) * user space. The DABR will have been cleared if it * triggered inside the kernel. */ - if (tsk->thread.hw_brk.address && tsk->thread.hw_brk.type) - __set_breakpoint(&tsk->thread.hw_brk, 0); + for (i = 0; i < nr_wp_slots(); i++) { + if (tsk->thread.hw_brk[i].address && tsk->thread.hw_brk[i].type) + __set_breakpoint(&tsk->thread.hw_brk[i], i); + } #endif /* Re-enable the breakpoints for the signal stack */ thread_change_pc(tsk, tsk->thread.regs);
So far powerpc hw supported only one watchpoint. But Future Power architecture is introducing 2nd DAWR. Convert thread_struct->hw_brk into an array. Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com> --- arch/powerpc/include/asm/processor.h | 2 +- arch/powerpc/kernel/process.c | 43 ++++++++++++++++++++-------- arch/powerpc/kernel/ptrace.c | 42 ++++++++++++++++++++------- arch/powerpc/kernel/ptrace32.c | 4 +-- arch/powerpc/kernel/signal.c | 9 ++++-- 5 files changed, 72 insertions(+), 28 deletions(-)