* [PATCH 0/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instruction
@ 2019-09-10 10:24 Ravi Bangoria
2019-09-10 10:24 ` [PATCH 1/2] powerpc/hw_breakpoint: move instruction stepping out of hw_breakpoint_handler() Ravi Bangoria
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Ravi Bangoria @ 2019-09-10 10:24 UTC (permalink / raw)
To: mpe, mikey; +Cc: Ravi Bangoria, linux-kernel, paulus, linuxppc-dev
I've prepared my patch on top of Christophe's patch as it's easy
to change stepping_handler() rather than hw_breakpoint_handler().
2nd patch is the actual fix.
Christophe Leroy (1):
powerpc/hw_breakpoint: move instruction stepping out of
hw_breakpoint_handler()
Ravi Bangoria (1):
powerpc/watchpoint: Disable watchpoint hit by larx/stcx instructions
arch/powerpc/kernel/hw_breakpoint.c | 77 +++++++++++++++++++----------
1 file changed, 50 insertions(+), 27 deletions(-)
--
2.21.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] powerpc/hw_breakpoint: move instruction stepping out of hw_breakpoint_handler()
2019-09-10 10:24 [PATCH 0/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instruction Ravi Bangoria
@ 2019-09-10 10:24 ` Ravi Bangoria
2019-09-10 10:24 ` [PATCH 2/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instructions Ravi Bangoria
2019-09-10 10:30 ` [PATCH 0/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instruction Christophe Leroy
2 siblings, 0 replies; 5+ messages in thread
From: Ravi Bangoria @ 2019-09-10 10:24 UTC (permalink / raw)
To: mpe, mikey; +Cc: Ravi Bangoria, linux-kernel, paulus, linuxppc-dev
From: Christophe Leroy <christophe.leroy@c-s.fr>
On 8xx, breakpoints stop after executing the instruction, so
stepping/emulation is not needed. Move it into a sub-function and
remove the #ifdefs.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Reviewed-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---
arch/powerpc/kernel/hw_breakpoint.c | 60 ++++++++++++++++-------------
1 file changed, 33 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index c8d1fa2e9d53..28ad3171bb82 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -198,15 +198,43 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
/*
* Handle debug exception notifications.
*/
+static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
+ unsigned long addr)
+{
+ int stepped;
+ unsigned int instr;
+
+ /* Do not emulate user-space instructions, instead single-step them */
+ if (user_mode(regs)) {
+ current->thread.last_hit_ubp = bp;
+ regs->msr |= MSR_SE;
+ return false;
+ }
+
+ stepped = 0;
+ instr = 0;
+ if (!__get_user_inatomic(instr, (unsigned int *)regs->nip))
+ stepped = emulate_step(regs, instr);
+
+ /*
+ * emulate_step() could not execute it. We've failed in reliably
+ * handling the hw-breakpoint. Unregister it and throw a warning
+ * message to let the user know about it.
+ */
+ if (!stepped) {
+ WARN(1, "Unable to handle hardware breakpoint. Breakpoint at "
+ "0x%lx will be disabled.", addr);
+ perf_event_disable_inatomic(bp);
+ return false;
+ }
+ return true;
+}
+
int hw_breakpoint_handler(struct die_args *args)
{
int rc = NOTIFY_STOP;
struct perf_event *bp;
struct pt_regs *regs = args->regs;
-#ifndef CONFIG_PPC_8xx
- int stepped = 1;
- unsigned int instr;
-#endif
struct arch_hw_breakpoint *info;
unsigned long dar = regs->dar;
@@ -251,31 +279,9 @@ int hw_breakpoint_handler(struct die_args *args)
(dar - bp->attr.bp_addr < bp->attr.bp_len)))
info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
-#ifndef CONFIG_PPC_8xx
- /* Do not emulate user-space instructions, instead single-step them */
- if (user_mode(regs)) {
- current->thread.last_hit_ubp = bp;
- regs->msr |= MSR_SE;
+ if (!IS_ENABLED(CONFIG_PPC_8xx) && !stepping_handler(regs, bp, info->address))
goto out;
- }
-
- stepped = 0;
- instr = 0;
- if (!__get_user_inatomic(instr, (unsigned int *) regs->nip))
- stepped = emulate_step(regs, instr);
- /*
- * emulate_step() could not execute it. We've failed in reliably
- * handling the hw-breakpoint. Unregister it and throw a warning
- * message to let the user know about it.
- */
- if (!stepped) {
- WARN(1, "Unable to handle hardware breakpoint. Breakpoint at "
- "0x%lx will be disabled.", info->address);
- perf_event_disable_inatomic(bp);
- goto out;
- }
-#endif
/*
* As a policy, the callback is invoked in a 'trigger-after-execute'
* fashion
--
2.21.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instructions
2019-09-10 10:24 [PATCH 0/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instruction Ravi Bangoria
2019-09-10 10:24 ` [PATCH 1/2] powerpc/hw_breakpoint: move instruction stepping out of hw_breakpoint_handler() Ravi Bangoria
@ 2019-09-10 10:24 ` Ravi Bangoria
2019-09-10 10:44 ` Naveen N. Rao
2019-09-10 10:30 ` [PATCH 0/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instruction Christophe Leroy
2 siblings, 1 reply; 5+ messages in thread
From: Ravi Bangoria @ 2019-09-10 10:24 UTC (permalink / raw)
To: mpe, mikey; +Cc: Ravi Bangoria, linux-kernel, paulus, linuxppc-dev
If watchpoint exception is generated by larx/stcx instructions, the
reservation created by larx gets lost while handling exception, and
thus stcx instruction always fails. Generally these instructions are
used in a while(1) loop, for example spinlocks. And because stcx
never succeeds, it loops forever and ultimately hangs the system.
Note that ptrace anyway works in one-shot mode and thus for ptrace
we don't change the behaviour. It's up to ptrace user to take care
of this.
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---
arch/powerpc/kernel/hw_breakpoint.c | 49 +++++++++++++++++++----------
1 file changed, 33 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 28ad3171bb82..9fa496a598ce 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -195,14 +195,32 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
tsk->thread.last_hit_ubp = NULL;
}
+static bool is_larx_stcx_instr(struct pt_regs *regs, unsigned int instr)
+{
+ int ret, type;
+ struct instruction_op op;
+
+ ret = analyse_instr(&op, regs, instr);
+ type = GETTYPE(op.type);
+ return (!ret && (type == LARX || type == STCX));
+}
+
/*
* Handle debug exception notifications.
*/
static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
unsigned long addr)
{
- int stepped;
- unsigned int instr;
+ unsigned int instr = 0;
+
+ if (__get_user_inatomic(instr, (unsigned int *)regs->nip))
+ goto fail;
+
+ if (is_larx_stcx_instr(regs, instr)) {
+ printk_ratelimited("Watchpoint: Can't emulate/single-step larx/"
+ "stcx instructions. Disabling watchpoint.\n");
+ goto disable;
+ }
/* Do not emulate user-space instructions, instead single-step them */
if (user_mode(regs)) {
@@ -211,23 +229,22 @@ static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
return false;
}
- stepped = 0;
- instr = 0;
- if (!__get_user_inatomic(instr, (unsigned int *)regs->nip))
- stepped = emulate_step(regs, instr);
+ if (!emulate_step(regs, instr))
+ goto fail;
+ return true;
+
+fail:
/*
- * emulate_step() could not execute it. We've failed in reliably
- * handling the hw-breakpoint. Unregister it and throw a warning
- * message to let the user know about it.
+ * We've failed in reliably handling the hw-breakpoint. Unregister
+ * it and throw a warning message to let the user know about it.
*/
- if (!stepped) {
- WARN(1, "Unable to handle hardware breakpoint. Breakpoint at "
- "0x%lx will be disabled.", addr);
- perf_event_disable_inatomic(bp);
- return false;
- }
- return true;
+ WARN(1, "Unable to handle hardware breakpoint. Breakpoint at "
+ "0x%lx will be disabled.", addr);
+
+disable:
+ perf_event_disable_inatomic(bp);
+ return false;
}
int hw_breakpoint_handler(struct die_args *args)
--
2.21.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instruction
2019-09-10 10:24 [PATCH 0/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instruction Ravi Bangoria
2019-09-10 10:24 ` [PATCH 1/2] powerpc/hw_breakpoint: move instruction stepping out of hw_breakpoint_handler() Ravi Bangoria
2019-09-10 10:24 ` [PATCH 2/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instructions Ravi Bangoria
@ 2019-09-10 10:30 ` Christophe Leroy
2 siblings, 0 replies; 5+ messages in thread
From: Christophe Leroy @ 2019-09-10 10:30 UTC (permalink / raw)
To: Ravi Bangoria, mpe, mikey; +Cc: paulus, linuxppc-dev, linux-kernel
Le 10/09/2019 à 12:24, Ravi Bangoria a écrit :
> I've prepared my patch on top of Christophe's patch as it's easy
> to change stepping_handler() rather than hw_breakpoint_handler().
> 2nd patch is the actual fix.
Anyway, my patch is already commited on powerpc/next
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20190904&id=658d029df0bce6472c94b724ca54d74bc6659c2e
Christophe
>
> Christophe Leroy (1):
> powerpc/hw_breakpoint: move instruction stepping out of
> hw_breakpoint_handler()
>
> Ravi Bangoria (1):
> powerpc/watchpoint: Disable watchpoint hit by larx/stcx instructions
>
> arch/powerpc/kernel/hw_breakpoint.c | 77 +++++++++++++++++++----------
> 1 file changed, 50 insertions(+), 27 deletions(-)
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instructions
2019-09-10 10:24 ` [PATCH 2/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instructions Ravi Bangoria
@ 2019-09-10 10:44 ` Naveen N. Rao
0 siblings, 0 replies; 5+ messages in thread
From: Naveen N. Rao @ 2019-09-10 10:44 UTC (permalink / raw)
To: mikey, mpe, Ravi Bangoria; +Cc: linuxppc-dev, linux-kernel, paulus
Ravi Bangoria wrote:
> If watchpoint exception is generated by larx/stcx instructions, the
> reservation created by larx gets lost while handling exception, and
> thus stcx instruction always fails. Generally these instructions are
> used in a while(1) loop, for example spinlocks. And because stcx
> never succeeds, it loops forever and ultimately hangs the system.
>
> Note that ptrace anyway works in one-shot mode and thus for ptrace
> we don't change the behaviour. It's up to ptrace user to take care
> of this.
>
> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
> ---
> arch/powerpc/kernel/hw_breakpoint.c | 49 +++++++++++++++++++----------
> 1 file changed, 33 insertions(+), 16 deletions(-)
>
> diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
> index 28ad3171bb82..9fa496a598ce 100644
> --- a/arch/powerpc/kernel/hw_breakpoint.c
> +++ b/arch/powerpc/kernel/hw_breakpoint.c
> @@ -195,14 +195,32 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
> tsk->thread.last_hit_ubp = NULL;
> }
>
> +static bool is_larx_stcx_instr(struct pt_regs *regs, unsigned int instr)
> +{
> + int ret, type;
> + struct instruction_op op;
> +
> + ret = analyse_instr(&op, regs, instr);
> + type = GETTYPE(op.type);
> + return (!ret && (type == LARX || type == STCX));
> +}
> +
> /*
> * Handle debug exception notifications.
> */
> static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
> unsigned long addr)
> {
> - int stepped;
> - unsigned int instr;
> + unsigned int instr = 0;
> +
> + if (__get_user_inatomic(instr, (unsigned int *)regs->nip))
> + goto fail;
> +
> + if (is_larx_stcx_instr(regs, instr)) {
> + printk_ratelimited("Watchpoint: Can't emulate/single-step larx/"
> + "stcx instructions. Disabling watchpoint.\n");
The below WARN() uses the term 'breakpoint'. Better to use consistent
terminology. I would rewrite the above as:
printk_ratelimited("Breakpoint hit on instruction that can't be emulated. "
"Breakpoint at 0x%lx will be disabled.\n", addr);
Otherwise:
Acked-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
- Naveen
> + goto disable;
> + }
>
> /* Do not emulate user-space instructions, instead single-step them */
> if (user_mode(regs)) {
> @@ -211,23 +229,22 @@ static bool stepping_handler(struct pt_regs *regs, struct perf_event *bp,
> return false;
> }
>
> - stepped = 0;
> - instr = 0;
> - if (!__get_user_inatomic(instr, (unsigned int *)regs->nip))
> - stepped = emulate_step(regs, instr);
> + if (!emulate_step(regs, instr))
> + goto fail;
>
> + return true;
> +
> +fail:
> /*
> - * emulate_step() could not execute it. We've failed in reliably
> - * handling the hw-breakpoint. Unregister it and throw a warning
> - * message to let the user know about it.
> + * We've failed in reliably handling the hw-breakpoint. Unregister
> + * it and throw a warning message to let the user know about it.
> */
> - if (!stepped) {
> - WARN(1, "Unable to handle hardware breakpoint. Breakpoint at "
> - "0x%lx will be disabled.", addr);
> - perf_event_disable_inatomic(bp);
> - return false;
> - }
> - return true;
> + WARN(1, "Unable to handle hardware breakpoint. Breakpoint at "
> + "0x%lx will be disabled.", addr);
> +
> +disable:
> + perf_event_disable_inatomic(bp);
> + return false;
> }
>
> int hw_breakpoint_handler(struct die_args *args)
> --
> 2.21.0
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-09-10 11:14 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-10 10:24 [PATCH 0/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instruction Ravi Bangoria
2019-09-10 10:24 ` [PATCH 1/2] powerpc/hw_breakpoint: move instruction stepping out of hw_breakpoint_handler() Ravi Bangoria
2019-09-10 10:24 ` [PATCH 2/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instructions Ravi Bangoria
2019-09-10 10:44 ` Naveen N. Rao
2019-09-10 10:30 ` [PATCH 0/2] powerpc/watchpoint: Disable watchpoint hit by larx/stcx instruction Christophe Leroy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).