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

Commit 62edab90 authored by K.Prasad's avatar K.Prasad Committed by Frederic Weisbecker
Browse files

hw-breakpoints: reset bits in dr6 after the corresponding exception is handled



This patch resets the bit in dr6 after the corresponding exception is
handled in code, so that we keep a clean track of the current virtual debug
status register.

[ Impact: keep track of breakpoints triggering completion ]

Signed-off-by: default avatarK.Prasad <prasad@linux.vnet.ibm.com>
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
parent 0722db01
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -314,8 +314,12 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
{
	int i, cpu, rc = NOTIFY_STOP;
	struct hw_breakpoint *bp;
	/* The DR6 value is stored in args->err */
	unsigned long dr7, dr6 = args->err;
	unsigned long dr7, dr6;
	unsigned long *dr6_p;

	/* The DR6 value is pointed by args->err */
	dr6_p = (unsigned long *)ERR_PTR(args->err);
	dr6 = *dr6_p;

	/* Do an early return if no trap bits are set in DR6 */
	if ((dr6 & DR_TRAP_BITS) == 0)
@@ -351,6 +355,11 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
			if (bp)
				rc = NOTIFY_DONE;
		}
		/*
		 * Reset the 'i'th TRAP bit in dr6 to denote completion of
		 * exception handling
		 */
		(*dr6_p) &= ~(DR_TRAP0 << i);
		/*
		 * bp can be NULL due to lazy debug register switching
		 * or due to the delay between updates of hbp_kernel_pos
+6 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@
#include <linux/smp.h>
#include <linux/nmi.h>

#include <asm/debugreg.h>
#include <asm/apicdef.h>
#include <asm/system.h>

@@ -434,6 +435,11 @@ single_step_cont(struct pt_regs *regs, struct die_args *args)
			"resuming...\n");
	kgdb_arch_handle_exception(args->trapnr, args->signr,
				   args->err, "c", "", regs);
	/*
	 * Reset the BS bit in dr6 (pointed by args->err) to
	 * denote completion of processing
	 */
	(*(unsigned long *)ERR_PTR(args->err)) &= ~DR_STEP;

	return NOTIFY_STOP;
}
+8 −1
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/alternative.h>
#include <asm/debugreg.h>

void jprobe_return_end(void);

@@ -967,8 +968,14 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
			ret = NOTIFY_STOP;
		break;
	case DIE_DEBUG:
		if (post_kprobe_handler(args->regs))
		if (post_kprobe_handler(args->regs)) {
			/*
			 * Reset the BS bit in dr6 (pointed by args->err) to
			 * denote completion of processing
			 */
			(*(unsigned long *)ERR_PTR(args->err)) &= ~DR_STEP;
			ret = NOTIFY_STOP;
		}
		break;
	case DIE_GPF:
		/*
+2 −2
Original line number Diff line number Diff line
@@ -545,7 +545,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
	/* Store the virtualized DR6 value */
	tsk->thread.debugreg6 = dr6;

	if (notify_die(DIE_DEBUG, "debug", regs, dr6, error_code,
	if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code,
							SIGTRAP) == NOTIFY_STOP)
		return;

+7 −1
Original line number Diff line number Diff line
@@ -540,8 +540,14 @@ kmmio_die_notifier(struct notifier_block *nb, unsigned long val, void *args)
	struct die_args *arg = args;

	if (val == DIE_DEBUG && (arg->err & DR_STEP))
		if (post_kmmio_handler(arg->err, arg->regs) == 1)
		if (post_kmmio_handler(arg->err, arg->regs) == 1) {
			/*
			 * Reset the BS bit in dr6 (pointed by args->err) to
			 * denote completion of processing
			 */
			(*(unsigned long *)ERR_PTR(arg->err)) &= ~DR_STEP;
			return NOTIFY_STOP;
		}

	return NOTIFY_DONE;
}