1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2478fcb2cSWill Deacon /*
3478fcb2cSWill Deacon  * ARMv8 single-step debug support and mdscr context switching.
4478fcb2cSWill Deacon  *
5478fcb2cSWill Deacon  * Copyright (C) 2012 ARM Limited
6478fcb2cSWill Deacon  *
7478fcb2cSWill Deacon  * Author: Will Deacon <will.deacon@arm.com>
8478fcb2cSWill Deacon  */
9478fcb2cSWill Deacon 
10478fcb2cSWill Deacon #include <linux/cpu.h>
11478fcb2cSWill Deacon #include <linux/debugfs.h>
12478fcb2cSWill Deacon #include <linux/hardirq.h>
13478fcb2cSWill Deacon #include <linux/init.h>
14478fcb2cSWill Deacon #include <linux/ptrace.h>
152dd0e8d2SSandeepa Prabhu #include <linux/kprobes.h>
16478fcb2cSWill Deacon #include <linux/stat.h>
171442b6edSWill Deacon #include <linux/uaccess.h>
1868db0cf1SIngo Molnar #include <linux/sched/task_stack.h>
19478fcb2cSWill Deacon 
203085bb01SSuzuki K. Poulose #include <asm/cpufeature.h>
21478fcb2cSWill Deacon #include <asm/cputype.h>
2265be7a1bSJames Morse #include <asm/daifflags.h>
233085bb01SSuzuki K. Poulose #include <asm/debug-monitors.h>
24478fcb2cSWill Deacon #include <asm/system_misc.h>
254e829b67SWill Deacon #include <asm/traps.h>
26478fcb2cSWill Deacon 
27478fcb2cSWill Deacon /* Determine debug architecture. */
debug_monitors_arch(void)28478fcb2cSWill Deacon u8 debug_monitors_arch(void)
29478fcb2cSWill Deacon {
3046823dd1SDave Martin 	return cpuid_feature_extract_unsigned_field(read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1),
31fcf37b38SMark Brown 						ID_AA64DFR0_EL1_DebugVer_SHIFT);
32478fcb2cSWill Deacon }
33478fcb2cSWill Deacon 
34478fcb2cSWill Deacon /*
35478fcb2cSWill Deacon  * MDSCR access routines.
36478fcb2cSWill Deacon  */
mdscr_write(u32 mdscr)37478fcb2cSWill Deacon static void mdscr_write(u32 mdscr)
38478fcb2cSWill Deacon {
39478fcb2cSWill Deacon 	unsigned long flags;
4065be7a1bSJames Morse 	flags = local_daif_save();
41adf75899SMark Rutland 	write_sysreg(mdscr, mdscr_el1);
4265be7a1bSJames Morse 	local_daif_restore(flags);
43478fcb2cSWill Deacon }
4444b53f67SPratyush Anand NOKPROBE_SYMBOL(mdscr_write);
45478fcb2cSWill Deacon 
mdscr_read(void)46478fcb2cSWill Deacon static u32 mdscr_read(void)
47478fcb2cSWill Deacon {
48adf75899SMark Rutland 	return read_sysreg(mdscr_el1);
49478fcb2cSWill Deacon }
5044b53f67SPratyush Anand NOKPROBE_SYMBOL(mdscr_read);
51478fcb2cSWill Deacon 
52478fcb2cSWill Deacon /*
53478fcb2cSWill Deacon  * Allow root to disable self-hosted debug from userspace.
54478fcb2cSWill Deacon  * This is useful if you want to connect an external JTAG debugger.
55478fcb2cSWill Deacon  */
56621a5f7aSViresh Kumar static bool debug_enabled = true;
57478fcb2cSWill Deacon 
create_debug_debugfs_entry(void)58478fcb2cSWill Deacon static int create_debug_debugfs_entry(void)
59478fcb2cSWill Deacon {
60478fcb2cSWill Deacon 	debugfs_create_bool("debug_enabled", 0644, NULL, &debug_enabled);
61478fcb2cSWill Deacon 	return 0;
62478fcb2cSWill Deacon }
63478fcb2cSWill Deacon fs_initcall(create_debug_debugfs_entry);
64478fcb2cSWill Deacon 
early_debug_disable(char * buf)65478fcb2cSWill Deacon static int __init early_debug_disable(char *buf)
66478fcb2cSWill Deacon {
67621a5f7aSViresh Kumar 	debug_enabled = false;
68478fcb2cSWill Deacon 	return 0;
69478fcb2cSWill Deacon }
70478fcb2cSWill Deacon 
71478fcb2cSWill Deacon early_param("nodebugmon", early_debug_disable);
72478fcb2cSWill Deacon 
73478fcb2cSWill Deacon /*
74478fcb2cSWill Deacon  * Keep track of debug users on each core.
75478fcb2cSWill Deacon  * The ref counts are per-cpu so we use a local_t type.
76478fcb2cSWill Deacon  */
771436c1aaSChristoph Lameter static DEFINE_PER_CPU(int, mde_ref_count);
781436c1aaSChristoph Lameter static DEFINE_PER_CPU(int, kde_ref_count);
79478fcb2cSWill Deacon 
enable_debug_monitors(enum dbg_active_el el)806f883d10SWill Deacon void enable_debug_monitors(enum dbg_active_el el)
81478fcb2cSWill Deacon {
82478fcb2cSWill Deacon 	u32 mdscr, enable = 0;
83478fcb2cSWill Deacon 
84478fcb2cSWill Deacon 	WARN_ON(preemptible());
85478fcb2cSWill Deacon 
861436c1aaSChristoph Lameter 	if (this_cpu_inc_return(mde_ref_count) == 1)
87478fcb2cSWill Deacon 		enable = DBG_MDSCR_MDE;
88478fcb2cSWill Deacon 
89478fcb2cSWill Deacon 	if (el == DBG_ACTIVE_EL1 &&
901436c1aaSChristoph Lameter 	    this_cpu_inc_return(kde_ref_count) == 1)
91478fcb2cSWill Deacon 		enable |= DBG_MDSCR_KDE;
92478fcb2cSWill Deacon 
93478fcb2cSWill Deacon 	if (enable && debug_enabled) {
94478fcb2cSWill Deacon 		mdscr = mdscr_read();
95478fcb2cSWill Deacon 		mdscr |= enable;
96478fcb2cSWill Deacon 		mdscr_write(mdscr);
97478fcb2cSWill Deacon 	}
98478fcb2cSWill Deacon }
9944b53f67SPratyush Anand NOKPROBE_SYMBOL(enable_debug_monitors);
100478fcb2cSWill Deacon 
disable_debug_monitors(enum dbg_active_el el)1016f883d10SWill Deacon void disable_debug_monitors(enum dbg_active_el el)
102478fcb2cSWill Deacon {
103478fcb2cSWill Deacon 	u32 mdscr, disable = 0;
104478fcb2cSWill Deacon 
105478fcb2cSWill Deacon 	WARN_ON(preemptible());
106478fcb2cSWill Deacon 
1071436c1aaSChristoph Lameter 	if (this_cpu_dec_return(mde_ref_count) == 0)
108478fcb2cSWill Deacon 		disable = ~DBG_MDSCR_MDE;
109478fcb2cSWill Deacon 
110478fcb2cSWill Deacon 	if (el == DBG_ACTIVE_EL1 &&
1111436c1aaSChristoph Lameter 	    this_cpu_dec_return(kde_ref_count) == 0)
112478fcb2cSWill Deacon 		disable &= ~DBG_MDSCR_KDE;
113478fcb2cSWill Deacon 
114478fcb2cSWill Deacon 	if (disable) {
115478fcb2cSWill Deacon 		mdscr = mdscr_read();
116478fcb2cSWill Deacon 		mdscr &= disable;
117478fcb2cSWill Deacon 		mdscr_write(mdscr);
118478fcb2cSWill Deacon 	}
119478fcb2cSWill Deacon }
12044b53f67SPratyush Anand NOKPROBE_SYMBOL(disable_debug_monitors);
121478fcb2cSWill Deacon 
122478fcb2cSWill Deacon /*
123478fcb2cSWill Deacon  * OS lock clearing.
124478fcb2cSWill Deacon  */
clear_os_lock(unsigned int cpu)125e937dd57SWill Deacon static int clear_os_lock(unsigned int cpu)
126478fcb2cSWill Deacon {
1276fda41bfSJean-Philippe Brucker 	write_sysreg(0, osdlr_el1);
128adf75899SMark Rutland 	write_sysreg(0, oslar_el1);
129e937dd57SWill Deacon 	isb();
130e937dd57SWill Deacon 	return 0;
131478fcb2cSWill Deacon }
132478fcb2cSWill Deacon 
debug_monitors_init(void)1335311ebfbSChristophe JAILLET static int __init debug_monitors_init(void)
134478fcb2cSWill Deacon {
135e937dd57SWill Deacon 	return cpuhp_setup_state(CPUHP_AP_ARM64_DEBUG_MONITORS_STARTING,
13673c1b41eSThomas Gleixner 				 "arm64/debug_monitors:starting",
137e937dd57SWill Deacon 				 clear_os_lock, NULL);
138478fcb2cSWill Deacon }
139478fcb2cSWill Deacon postcore_initcall(debug_monitors_init);
140478fcb2cSWill Deacon 
141478fcb2cSWill Deacon /*
142478fcb2cSWill Deacon  * Single step API and exception handling.
143478fcb2cSWill Deacon  */
set_user_regs_spsr_ss(struct user_pt_regs * regs)1443a5a4366SWill Deacon static void set_user_regs_spsr_ss(struct user_pt_regs *regs)
145478fcb2cSWill Deacon {
1466b68e14eSWill Deacon 	regs->pstate |= DBG_SPSR_SS;
147478fcb2cSWill Deacon }
1483a5a4366SWill Deacon NOKPROBE_SYMBOL(set_user_regs_spsr_ss);
149478fcb2cSWill Deacon 
clear_user_regs_spsr_ss(struct user_pt_regs * regs)1503a5a4366SWill Deacon static void clear_user_regs_spsr_ss(struct user_pt_regs *regs)
151478fcb2cSWill Deacon {
1526b68e14eSWill Deacon 	regs->pstate &= ~DBG_SPSR_SS;
153478fcb2cSWill Deacon }
1543a5a4366SWill Deacon NOKPROBE_SYMBOL(clear_user_regs_spsr_ss);
1553a5a4366SWill Deacon 
1563a5a4366SWill Deacon #define set_regs_spsr_ss(r)	set_user_regs_spsr_ss(&(r)->user_regs)
1573a5a4366SWill Deacon #define clear_regs_spsr_ss(r)	clear_user_regs_spsr_ss(&(r)->user_regs)
158478fcb2cSWill Deacon 
15926a04d84SWill Deacon static DEFINE_SPINLOCK(debug_hook_lock);
16026a04d84SWill Deacon static LIST_HEAD(user_step_hook);
16126a04d84SWill Deacon static LIST_HEAD(kernel_step_hook);
162ee6214ceSSandeepa Prabhu 
register_debug_hook(struct list_head * node,struct list_head * list)16326a04d84SWill Deacon static void register_debug_hook(struct list_head *node, struct list_head *list)
164ee6214ceSSandeepa Prabhu {
16526a04d84SWill Deacon 	spin_lock(&debug_hook_lock);
16626a04d84SWill Deacon 	list_add_rcu(node, list);
16726a04d84SWill Deacon 	spin_unlock(&debug_hook_lock);
16826a04d84SWill Deacon 
169ee6214ceSSandeepa Prabhu }
170ee6214ceSSandeepa Prabhu 
unregister_debug_hook(struct list_head * node)17126a04d84SWill Deacon static void unregister_debug_hook(struct list_head *node)
172ee6214ceSSandeepa Prabhu {
17326a04d84SWill Deacon 	spin_lock(&debug_hook_lock);
17426a04d84SWill Deacon 	list_del_rcu(node);
17526a04d84SWill Deacon 	spin_unlock(&debug_hook_lock);
176cf0a2543SYang Shi 	synchronize_rcu();
177ee6214ceSSandeepa Prabhu }
178ee6214ceSSandeepa Prabhu 
register_user_step_hook(struct step_hook * hook)17926a04d84SWill Deacon void register_user_step_hook(struct step_hook *hook)
18026a04d84SWill Deacon {
18126a04d84SWill Deacon 	register_debug_hook(&hook->node, &user_step_hook);
18226a04d84SWill Deacon }
18326a04d84SWill Deacon 
unregister_user_step_hook(struct step_hook * hook)18426a04d84SWill Deacon void unregister_user_step_hook(struct step_hook *hook)
18526a04d84SWill Deacon {
18626a04d84SWill Deacon 	unregister_debug_hook(&hook->node);
18726a04d84SWill Deacon }
18826a04d84SWill Deacon 
register_kernel_step_hook(struct step_hook * hook)18926a04d84SWill Deacon void register_kernel_step_hook(struct step_hook *hook)
19026a04d84SWill Deacon {
19126a04d84SWill Deacon 	register_debug_hook(&hook->node, &kernel_step_hook);
19226a04d84SWill Deacon }
19326a04d84SWill Deacon 
unregister_kernel_step_hook(struct step_hook * hook)19426a04d84SWill Deacon void unregister_kernel_step_hook(struct step_hook *hook)
19526a04d84SWill Deacon {
19626a04d84SWill Deacon 	unregister_debug_hook(&hook->node);
19726a04d84SWill Deacon }
19826a04d84SWill Deacon 
199ee6214ceSSandeepa Prabhu /*
20095485fdcSYang Shi  * Call registered single step handlers
201ee6214ceSSandeepa Prabhu  * There is no Syndrome info to check for determining the handler.
202ee6214ceSSandeepa Prabhu  * So we call all the registered handlers, until the right handler is
203ee6214ceSSandeepa Prabhu  * found which returns zero.
204ee6214ceSSandeepa Prabhu  */
call_step_hook(struct pt_regs * regs,unsigned long esr)2058d56e5c5SAlexandru Elisei static int call_step_hook(struct pt_regs *regs, unsigned long esr)
206ee6214ceSSandeepa Prabhu {
207ee6214ceSSandeepa Prabhu 	struct step_hook *hook;
20826a04d84SWill Deacon 	struct list_head *list;
209ee6214ceSSandeepa Prabhu 	int retval = DBG_HOOK_ERROR;
210ee6214ceSSandeepa Prabhu 
21126a04d84SWill Deacon 	list = user_mode(regs) ? &user_step_hook : &kernel_step_hook;
21226a04d84SWill Deacon 
213760d8ed0SMasami Hiramatsu 	/*
214760d8ed0SMasami Hiramatsu 	 * Since single-step exception disables interrupt, this function is
215760d8ed0SMasami Hiramatsu 	 * entirely not preemptible, and we can use rcu list safely here.
216760d8ed0SMasami Hiramatsu 	 */
21726a04d84SWill Deacon 	list_for_each_entry_rcu(hook, list, node)	{
218ee6214ceSSandeepa Prabhu 		retval = hook->fn(regs, esr);
219ee6214ceSSandeepa Prabhu 		if (retval == DBG_HOOK_HANDLED)
220ee6214ceSSandeepa Prabhu 			break;
221ee6214ceSSandeepa Prabhu 	}
222ee6214ceSSandeepa Prabhu 
223ee6214ceSSandeepa Prabhu 	return retval;
224ee6214ceSSandeepa Prabhu }
22544b53f67SPratyush Anand NOKPROBE_SYMBOL(call_step_hook);
226ee6214ceSSandeepa Prabhu 
send_user_sigtrap(int si_code)227e04a28d4SWill Deacon static void send_user_sigtrap(int si_code)
228e04a28d4SWill Deacon {
229e04a28d4SWill Deacon 	struct pt_regs *regs = current_pt_regs();
230e04a28d4SWill Deacon 
231e04a28d4SWill Deacon 	if (WARN_ON(!user_mode(regs)))
232e04a28d4SWill Deacon 		return;
233e04a28d4SWill Deacon 
234e04a28d4SWill Deacon 	if (interrupts_enabled(regs))
235e04a28d4SWill Deacon 		local_irq_enable();
236e04a28d4SWill Deacon 
237dceec3ffSPeter Collingbourne 	arm64_force_sig_fault(SIGTRAP, si_code, instruction_pointer(regs),
238feca355bSEric W. Biederman 			      "User debug trap");
239e04a28d4SWill Deacon }
240e04a28d4SWill Deacon 
single_step_handler(unsigned long unused,unsigned long esr,struct pt_regs * regs)2418d56e5c5SAlexandru Elisei static int single_step_handler(unsigned long unused, unsigned long esr,
242478fcb2cSWill Deacon 			       struct pt_regs *regs)
243478fcb2cSWill Deacon {
2443fb69640SPratyush Anand 	bool handler_found = false;
2453fb69640SPratyush Anand 
246478fcb2cSWill Deacon 	/*
247478fcb2cSWill Deacon 	 * If we are stepping a pending breakpoint, call the hw_breakpoint
248478fcb2cSWill Deacon 	 * handler first.
249478fcb2cSWill Deacon 	 */
250478fcb2cSWill Deacon 	if (!reinstall_suspended_bps(regs))
251478fcb2cSWill Deacon 		return 0;
252478fcb2cSWill Deacon 
2533fb69640SPratyush Anand 	if (!handler_found && call_step_hook(regs, esr) == DBG_HOOK_HANDLED)
2543fb69640SPratyush Anand 		handler_found = true;
2553fb69640SPratyush Anand 
2563fb69640SPratyush Anand 	if (!handler_found && user_mode(regs)) {
257adeb68efSWill Deacon 		send_user_sigtrap(TRAP_TRACE);
258478fcb2cSWill Deacon 
259478fcb2cSWill Deacon 		/*
260478fcb2cSWill Deacon 		 * ptrace will disable single step unless explicitly
261478fcb2cSWill Deacon 		 * asked to re-enable it. For other clients, it makes
262478fcb2cSWill Deacon 		 * sense to leave it enabled (i.e. rewind the controls
263478fcb2cSWill Deacon 		 * to the active-not-pending state).
264478fcb2cSWill Deacon 		 */
265478fcb2cSWill Deacon 		user_rewind_single_step(current);
2663fb69640SPratyush Anand 	} else if (!handler_found) {
2673fb69640SPratyush Anand 		pr_warn("Unexpected kernel single-step exception at EL1\n");
268478fcb2cSWill Deacon 		/*
269478fcb2cSWill Deacon 		 * Re-enable stepping since we know that we will be
270478fcb2cSWill Deacon 		 * returning to regs.
271478fcb2cSWill Deacon 		 */
272478fcb2cSWill Deacon 		set_regs_spsr_ss(regs);
273478fcb2cSWill Deacon 	}
274478fcb2cSWill Deacon 
275478fcb2cSWill Deacon 	return 0;
276478fcb2cSWill Deacon }
27744b53f67SPratyush Anand NOKPROBE_SYMBOL(single_step_handler);
278478fcb2cSWill Deacon 
27926a04d84SWill Deacon static LIST_HEAD(user_break_hook);
28026a04d84SWill Deacon static LIST_HEAD(kernel_break_hook);
281ee6214ceSSandeepa Prabhu 
register_user_break_hook(struct break_hook * hook)28226a04d84SWill Deacon void register_user_break_hook(struct break_hook *hook)
283ee6214ceSSandeepa Prabhu {
28426a04d84SWill Deacon 	register_debug_hook(&hook->node, &user_break_hook);
285ee6214ceSSandeepa Prabhu }
286ee6214ceSSandeepa Prabhu 
unregister_user_break_hook(struct break_hook * hook)28726a04d84SWill Deacon void unregister_user_break_hook(struct break_hook *hook)
288ee6214ceSSandeepa Prabhu {
28926a04d84SWill Deacon 	unregister_debug_hook(&hook->node);
29026a04d84SWill Deacon }
29126a04d84SWill Deacon 
register_kernel_break_hook(struct break_hook * hook)29226a04d84SWill Deacon void register_kernel_break_hook(struct break_hook *hook)
29326a04d84SWill Deacon {
29426a04d84SWill Deacon 	register_debug_hook(&hook->node, &kernel_break_hook);
29526a04d84SWill Deacon }
29626a04d84SWill Deacon 
unregister_kernel_break_hook(struct break_hook * hook)29726a04d84SWill Deacon void unregister_kernel_break_hook(struct break_hook *hook)
29826a04d84SWill Deacon {
29926a04d84SWill Deacon 	unregister_debug_hook(&hook->node);
300ee6214ceSSandeepa Prabhu }
301ee6214ceSSandeepa Prabhu 
call_break_hook(struct pt_regs * regs,unsigned long esr)3028d56e5c5SAlexandru Elisei static int call_break_hook(struct pt_regs *regs, unsigned long esr)
303ee6214ceSSandeepa Prabhu {
304ee6214ceSSandeepa Prabhu 	struct break_hook *hook;
30526a04d84SWill Deacon 	struct list_head *list;
3068d56e5c5SAlexandru Elisei 	int (*fn)(struct pt_regs *regs, unsigned long esr) = NULL;
307ee6214ceSSandeepa Prabhu 
30826a04d84SWill Deacon 	list = user_mode(regs) ? &user_break_hook : &kernel_break_hook;
30926a04d84SWill Deacon 
310760d8ed0SMasami Hiramatsu 	/*
311760d8ed0SMasami Hiramatsu 	 * Since brk exception disables interrupt, this function is
312760d8ed0SMasami Hiramatsu 	 * entirely not preemptible, and we can use rcu list safely here.
313760d8ed0SMasami Hiramatsu 	 */
31426a04d84SWill Deacon 	list_for_each_entry_rcu(hook, list, node) {
3158d56e5c5SAlexandru Elisei 		unsigned long comment = esr & ESR_ELx_BRK64_ISS_COMMENT_MASK;
31626a04d84SWill Deacon 
31726a04d84SWill Deacon 		if ((comment & ~hook->mask) == hook->imm)
318ee6214ceSSandeepa Prabhu 			fn = hook->fn;
31926a04d84SWill Deacon 	}
320ee6214ceSSandeepa Prabhu 
321ee6214ceSSandeepa Prabhu 	return fn ? fn(regs, esr) : DBG_HOOK_ERROR;
322ee6214ceSSandeepa Prabhu }
32344b53f67SPratyush Anand NOKPROBE_SYMBOL(call_break_hook);
324ee6214ceSSandeepa Prabhu 
brk_handler(unsigned long unused,unsigned long esr,struct pt_regs * regs)3258d56e5c5SAlexandru Elisei static int brk_handler(unsigned long unused, unsigned long esr,
3261442b6edSWill Deacon 		       struct pt_regs *regs)
3271442b6edSWill Deacon {
328ab6211c9SWill Deacon 	if (call_break_hook(regs, esr) == DBG_HOOK_HANDLED)
329ab6211c9SWill Deacon 		return 0;
33053d07e21SPratyush Anand 
331ab6211c9SWill Deacon 	if (user_mode(regs)) {
33253d07e21SPratyush Anand 		send_user_sigtrap(TRAP_BRKPT);
333ab6211c9SWill Deacon 	} else {
3342dd0e8d2SSandeepa Prabhu 		pr_warn("Unexpected kernel BRK exception at EL1\n");
335c878e0cfSWill Deacon 		return -EFAULT;
336c878e0cfSWill Deacon 	}
337c878e0cfSWill Deacon 
3381442b6edSWill Deacon 	return 0;
3391442b6edSWill Deacon }
34044b53f67SPratyush Anand NOKPROBE_SYMBOL(brk_handler);
3411442b6edSWill Deacon 
aarch32_break_handler(struct pt_regs * regs)3421442b6edSWill Deacon int aarch32_break_handler(struct pt_regs *regs)
3431442b6edSWill Deacon {
3442dacab73SMatthew Leach 	u32 arm_instr;
3452dacab73SMatthew Leach 	u16 thumb_instr;
3461442b6edSWill Deacon 	bool bp = false;
3471442b6edSWill Deacon 	void __user *pc = (void __user *)instruction_pointer(regs);
3481442b6edSWill Deacon 
3491442b6edSWill Deacon 	if (!compat_user_mode(regs))
3501442b6edSWill Deacon 		return -EFAULT;
3511442b6edSWill Deacon 
3521442b6edSWill Deacon 	if (compat_thumb_mode(regs)) {
3531442b6edSWill Deacon 		/* get 16-bit Thumb instruction */
354a5018b0eSLuc Van Oostenryck 		__le16 instr;
355a5018b0eSLuc Van Oostenryck 		get_user(instr, (__le16 __user *)pc);
356a5018b0eSLuc Van Oostenryck 		thumb_instr = le16_to_cpu(instr);
3572dacab73SMatthew Leach 		if (thumb_instr == AARCH32_BREAK_THUMB2_LO) {
3581442b6edSWill Deacon 			/* get second half of 32-bit Thumb-2 instruction */
359a5018b0eSLuc Van Oostenryck 			get_user(instr, (__le16 __user *)(pc + 2));
360a5018b0eSLuc Van Oostenryck 			thumb_instr = le16_to_cpu(instr);
3612dacab73SMatthew Leach 			bp = thumb_instr == AARCH32_BREAK_THUMB2_HI;
3621442b6edSWill Deacon 		} else {
3632dacab73SMatthew Leach 			bp = thumb_instr == AARCH32_BREAK_THUMB;
3641442b6edSWill Deacon 		}
3651442b6edSWill Deacon 	} else {
3661442b6edSWill Deacon 		/* 32-bit ARM instruction */
367a5018b0eSLuc Van Oostenryck 		__le32 instr;
368a5018b0eSLuc Van Oostenryck 		get_user(instr, (__le32 __user *)pc);
369a5018b0eSLuc Van Oostenryck 		arm_instr = le32_to_cpu(instr);
3702dacab73SMatthew Leach 		bp = (arm_instr & ~0xf0000000) == AARCH32_BREAK_ARM;
3711442b6edSWill Deacon 	}
3721442b6edSWill Deacon 
3731442b6edSWill Deacon 	if (!bp)
3741442b6edSWill Deacon 		return -EFAULT;
3751442b6edSWill Deacon 
376e04a28d4SWill Deacon 	send_user_sigtrap(TRAP_BRKPT);
3771442b6edSWill Deacon 	return 0;
3781442b6edSWill Deacon }
37944b53f67SPratyush Anand NOKPROBE_SYMBOL(aarch32_break_handler);
3801442b6edSWill Deacon 
debug_traps_init(void)381b322c65fSDouglas Anderson void __init debug_traps_init(void)
382478fcb2cSWill Deacon {
383478fcb2cSWill Deacon 	hook_debug_fault_code(DBG_ESR_EVT_HWSS, single_step_handler, SIGTRAP,
384adeb68efSWill Deacon 			      TRAP_TRACE, "single-step handler");
3851442b6edSWill Deacon 	hook_debug_fault_code(DBG_ESR_EVT_BRK, brk_handler, SIGTRAP,
3860fdb64c2SWill Deacon 			      TRAP_BRKPT, "BRK handler");
387478fcb2cSWill Deacon }
388478fcb2cSWill Deacon 
389478fcb2cSWill Deacon /* Re-enable single step for syscall restarting. */
user_rewind_single_step(struct task_struct * task)390478fcb2cSWill Deacon void user_rewind_single_step(struct task_struct *task)
391478fcb2cSWill Deacon {
392478fcb2cSWill Deacon 	/*
393478fcb2cSWill Deacon 	 * If single step is active for this thread, then set SPSR.SS
394478fcb2cSWill Deacon 	 * to 1 to avoid returning to the active-pending state.
395478fcb2cSWill Deacon 	 */
3965afc7855SWill Deacon 	if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
397478fcb2cSWill Deacon 		set_regs_spsr_ss(task_pt_regs(task));
398478fcb2cSWill Deacon }
39944b53f67SPratyush Anand NOKPROBE_SYMBOL(user_rewind_single_step);
400478fcb2cSWill Deacon 
user_fastforward_single_step(struct task_struct * task)401478fcb2cSWill Deacon void user_fastforward_single_step(struct task_struct *task)
402478fcb2cSWill Deacon {
4035afc7855SWill Deacon 	if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
404478fcb2cSWill Deacon 		clear_regs_spsr_ss(task_pt_regs(task));
405478fcb2cSWill Deacon }
406478fcb2cSWill Deacon 
user_regs_reset_single_step(struct user_pt_regs * regs,struct task_struct * task)4073a5a4366SWill Deacon void user_regs_reset_single_step(struct user_pt_regs *regs,
4083a5a4366SWill Deacon 				 struct task_struct *task)
4093a5a4366SWill Deacon {
4103a5a4366SWill Deacon 	if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
4113a5a4366SWill Deacon 		set_user_regs_spsr_ss(regs);
4123a5a4366SWill Deacon 	else
4133a5a4366SWill Deacon 		clear_user_regs_spsr_ss(regs);
4143a5a4366SWill Deacon }
4153a5a4366SWill Deacon 
416478fcb2cSWill Deacon /* Kernel API */
kernel_enable_single_step(struct pt_regs * regs)417478fcb2cSWill Deacon void kernel_enable_single_step(struct pt_regs *regs)
418478fcb2cSWill Deacon {
419478fcb2cSWill Deacon 	WARN_ON(!irqs_disabled());
420478fcb2cSWill Deacon 	set_regs_spsr_ss(regs);
421478fcb2cSWill Deacon 	mdscr_write(mdscr_read() | DBG_MDSCR_SS);
422478fcb2cSWill Deacon 	enable_debug_monitors(DBG_ACTIVE_EL1);
423478fcb2cSWill Deacon }
42444b53f67SPratyush Anand NOKPROBE_SYMBOL(kernel_enable_single_step);
425478fcb2cSWill Deacon 
kernel_disable_single_step(void)426478fcb2cSWill Deacon void kernel_disable_single_step(void)
427478fcb2cSWill Deacon {
428478fcb2cSWill Deacon 	WARN_ON(!irqs_disabled());
429478fcb2cSWill Deacon 	mdscr_write(mdscr_read() & ~DBG_MDSCR_SS);
430478fcb2cSWill Deacon 	disable_debug_monitors(DBG_ACTIVE_EL1);
431478fcb2cSWill Deacon }
43244b53f67SPratyush Anand NOKPROBE_SYMBOL(kernel_disable_single_step);
433478fcb2cSWill Deacon 
kernel_active_single_step(void)434478fcb2cSWill Deacon int kernel_active_single_step(void)
435478fcb2cSWill Deacon {
436478fcb2cSWill Deacon 	WARN_ON(!irqs_disabled());
437478fcb2cSWill Deacon 	return mdscr_read() & DBG_MDSCR_SS;
438478fcb2cSWill Deacon }
43944b53f67SPratyush Anand NOKPROBE_SYMBOL(kernel_active_single_step);
440478fcb2cSWill Deacon 
kernel_rewind_single_step(struct pt_regs * regs)441*af6c0bd5SSumit Garg void kernel_rewind_single_step(struct pt_regs *regs)
442*af6c0bd5SSumit Garg {
443*af6c0bd5SSumit Garg 	set_regs_spsr_ss(regs);
444*af6c0bd5SSumit Garg }
445*af6c0bd5SSumit Garg 
446478fcb2cSWill Deacon /* ptrace API */
user_enable_single_step(struct task_struct * task)447478fcb2cSWill Deacon void user_enable_single_step(struct task_struct *task)
448478fcb2cSWill Deacon {
4493a402a70SWill Deacon 	struct thread_info *ti = task_thread_info(task);
4503a402a70SWill Deacon 
4513a402a70SWill Deacon 	if (!test_and_set_ti_thread_flag(ti, TIF_SINGLESTEP))
452478fcb2cSWill Deacon 		set_regs_spsr_ss(task_pt_regs(task));
453478fcb2cSWill Deacon }
45444b53f67SPratyush Anand NOKPROBE_SYMBOL(user_enable_single_step);
455478fcb2cSWill Deacon 
user_disable_single_step(struct task_struct * task)456478fcb2cSWill Deacon void user_disable_single_step(struct task_struct *task)
457478fcb2cSWill Deacon {
458478fcb2cSWill Deacon 	clear_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP);
459478fcb2cSWill Deacon }
46044b53f67SPratyush Anand NOKPROBE_SYMBOL(user_disable_single_step);
461