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

Commit c91e02bd authored by Max Filippov's avatar Max Filippov Committed by Chris Zankel
Browse files

xtensa: support hardware breakpoints/watchpoints



Use perf framework to manage hardware instruction and data breakpoints.
Add two new ptrace calls: PTRACE_GETHBPREGS and PTRACE_SETHBPREGS to
query and set instruction and data breakpoints.
Address bit 0 choose instruction (0) or data (1) break register, bits
31..1 are the register number.
Both calls transfer two 32-bit words: address (0) and control (1).
Instruction breakpoint contorl word is 0 to clear breakpoint, 1 to set.
Data breakpoint control word bit 31 is 'trigger on store', bit 30 is
'trigger on load, bits 29..0 are length. Length 0 is used to clear a
breakpoint. To set a breakpoint length must be a power of 2 in the range
1..64 and the address must be length-aligned.

Introduce new thread_info flag: TIF_DB_DISABLED. Set it if debug
exception is raised by the kernel code accessing watched userspace
address and disable corresponding data breakpoint. On exit to userspace
check that flag and, if set, restore all data breakpoints.

Handle debug exceptions raised with PS.EXCM set. This may happen when
window overflow/underflow handler or fast exception handler hits data
breakpoint, in which case save and disable all data breakpoints,
single-step faulting instruction and restore data breakpoints.

Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent 6ec7026a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ config XTENSA
	select HAVE_DMA_ATTRS
	select HAVE_FUNCTION_TRACER
	select HAVE_FUTEX_CMPXCHG if !MMU
	select HAVE_HW_BREAKPOINT if PERF_EVENTS
	select HAVE_IRQ_TIME_ACCOUNTING
	select HAVE_OPROFILE
	select HAVE_PERF_EVENTS
+58 −0
Original line number Diff line number Diff line
/*
 * Xtensa hardware breakpoints/watchpoints handling functions
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2016 Cadence Design Systems Inc.
 */

#ifndef __ASM_XTENSA_HW_BREAKPOINT_H
#define __ASM_XTENSA_HW_BREAKPOINT_H

#ifdef CONFIG_HAVE_HW_BREAKPOINT

#include <linux/kdebug.h>
#include <linux/types.h>
#include <uapi/linux/hw_breakpoint.h>

/* Breakpoint */
#define XTENSA_BREAKPOINT_EXECUTE	0

/* Watchpoints */
#define XTENSA_BREAKPOINT_LOAD		1
#define XTENSA_BREAKPOINT_STORE		2

struct arch_hw_breakpoint {
	unsigned long address;
	u16 len;
	u16 type;
};

struct perf_event;
struct pt_regs;
struct task_struct;

int hw_breakpoint_slots(int type);
int arch_check_bp_in_kernelspace(struct perf_event *bp);
int arch_validate_hwbkpt_settings(struct perf_event *bp);
int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
				    unsigned long val, void *data);

int arch_install_hw_breakpoint(struct perf_event *bp);
void arch_uninstall_hw_breakpoint(struct perf_event *bp);
void hw_breakpoint_pmu_read(struct perf_event *bp);
int check_hw_breakpoint(struct pt_regs *regs);
void clear_ptrace_hw_breakpoint(struct task_struct *tsk);

#else

struct task_struct;

static inline void clear_ptrace_hw_breakpoint(struct task_struct *tsk)
{
}

#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#endif /* __ASM_XTENSA_HW_BREAKPOINT_H */
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#define _XTENSA_IRQFLAGS_H

#include <linux/types.h>
#include <asm/processor.h>

static inline unsigned long arch_local_save_flags(void)
{
+4 −5
Original line number Diff line number Diff line
@@ -130,11 +130,10 @@ struct thread_struct {
	unsigned long bad_vaddr; /* last user fault */
	unsigned long bad_uaddr; /* last kernel fault accessing user space */
	unsigned long error_code;

	unsigned long ibreak[XCHAL_NUM_IBREAK];
	unsigned long dbreaka[XCHAL_NUM_DBREAK];
	unsigned long dbreakc[XCHAL_NUM_DBREAK];

#ifdef CONFIG_HAVE_HW_BREAKPOINT
	struct perf_event *ptrace_bp[XCHAL_NUM_IBREAK];
	struct perf_event *ptrace_wp[XCHAL_NUM_DBREAK];
#endif
	/* Make structure 16 bytes aligned. */
	int align[0] __attribute__ ((aligned(16)));
};
+3 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
/*  Special registers.  */

#define SREG_MR			32
#define SREG_IBREAKENABLE	96
#define SREG_IBREAKA		128
#define SREG_DBREAKA		144
#define SREG_DBREAKC		160
@@ -103,6 +104,8 @@

/*  DEBUGCAUSE register fields.  */

#define DEBUGCAUSE_DBNUM_MASK		0xf00
#define DEBUGCAUSE_DBNUM_SHIFT		8	/* First bit of DBNUM field */
#define DEBUGCAUSE_DEBUGINT_BIT		5	/* External debug interrupt */
#define DEBUGCAUSE_BREAKN_BIT		4	/* BREAK.N instruction */
#define DEBUGCAUSE_BREAK_BIT		3	/* BREAK instruction */
Loading