Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1cedae72 authored by Frederic Weisbecker's avatar Frederic Weisbecker Committed by Ingo Molnar
Browse files

hw-breakpoints: Keep track of user disabled breakpoints



When we disable a breakpoint through dr7, we unregister it right
away, making us lose track of its corresponding address
register value.

It means that the following sequence would be unsupported:

 - set address in dr0
 - enable it through dr7
 - disable it through dr7
 - enable it through dr7

because we lost the address register value when we disabled the
breakpoint.

Don't unregister the disabled breakpoints but rather disable
them.

Reported-by: default avatar"K.Prasad" <prasad@linux.vnet.ibm.com>
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <1259735536-9236-1-git-send-regression-fweisbec@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 6b62fe01
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -595,7 +595,7 @@ static unsigned long ptrace_get_dr7(struct perf_event *bp[])

static struct perf_event *
ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
			 struct task_struct *tsk)
			 struct task_struct *tsk, int disabled)
{
	int err;
	int gen_len, gen_type;
@@ -616,7 +616,7 @@ ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
	attr = bp->attr;
	attr.bp_len = gen_len;
	attr.bp_type = gen_type;
	attr.disabled = 0;
	attr.disabled = disabled;

	return modify_user_hw_breakpoint(bp, &attr, bp->callback, tsk);
}
@@ -655,13 +655,21 @@ static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data)
				 */
				if (!second_pass)
					continue;

				thread->ptrace_bps[i] = NULL;
				bp = ptrace_modify_breakpoint(bp, len, type,
							      tsk, 1);
				if (IS_ERR(bp)) {
					rc = PTR_ERR(bp);
					thread->ptrace_bps[i] = NULL;
				unregister_hw_breakpoint(bp);
					break;
				}
				thread->ptrace_bps[i] = bp;
			}
			continue;
		}

		bp = ptrace_modify_breakpoint(bp, len, type, tsk);
		bp = ptrace_modify_breakpoint(bp, len, type, tsk, 0);

		/* Incorrect bp, or we have a bug in bp API */
		if (IS_ERR(bp)) {