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

Commit e3e94084 authored by K.Prasad's avatar K.Prasad Committed by Paul Mackerras
Browse files

powerpc, hw_breakpoint: Discard extraneous interrupt due to accesses outside symbol length



Many a times, the requested breakpoint length can be less than the
fixed breakpoint length i.e. 8 bytes supported by PowerPC 64-bit
server (Book III S) processors.  This could lead to extraneous
interrupts resulting in false breakpoint notifications.  This
detects and discards such interrupts for non-ptrace requests.
We don't change ptrace behaviour to avoid breaking compatability.

[Suggestion from Paul Mackerras <paulus@samba.org> to add a new flag in
'struct arch_hw_breakpoint' to identify extraneous interrupts]

Signed-off-by: default avatarK.Prasad <prasad@linux.vnet.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 06532a67
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#ifdef CONFIG_HAVE_HW_BREAKPOINT

struct arch_hw_breakpoint {
	bool		extraneous_interrupt;
	u8		len; /* length of the target data symbol */
	int		type;
	unsigned long	address;
+21 −2
Original line number Diff line number Diff line
@@ -204,6 +204,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
	int stepped = 1;
	struct arch_hw_breakpoint *info;
	unsigned int instr;
	unsigned long dar = regs->dar;

	/* Disable breakpoints during exception handling */
	set_dabr(0);
@@ -234,6 +235,22 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
		goto out;
	}

	/*
	 * Verify if dar lies within the address range occupied by the symbol
	 * being watched to filter extraneous exceptions.
	 */
	if (!((bp->attr.bp_addr <= dar) &&
	     (dar <= (bp->attr.bp_addr + bp->attr.bp_len)))) {
		/*
		 * This exception is triggered not because of a memory access
		 * on the monitored variable but in the double-word address
		 * range in which it is contained. We will consume this
		 * exception, considering it as 'noise'.
		 */
		info->extraneous_interrupt = true;
	} else
		info->extraneous_interrupt = false;

	/* Do not emulate user-space instructions, instead single-step them */
	if (user_mode(regs)) {
		bp->ctx->task->thread.last_hit_ubp = bp;
@@ -261,6 +278,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
	 * As a policy, the callback is invoked in a 'trigger-after-execute'
	 * fashion
	 */
	if (!info->extraneous_interrupt)
		perf_bp_event(bp, regs);

	set_dabr(info->address | info->type | DABR_TRANSLATION);
@@ -292,6 +310,7 @@ int __kprobes single_step_dabr_instruction(struct die_args *args)
	 * We shall invoke the user-defined callback function in the single
	 * stepping handler to confirm to 'trigger-after-execute' semantics
	 */
	if (!bp_info->extraneous_interrupt)
		perf_bp_event(bp, regs);

	/*