File Index
Files and directories
Sign in
FILE

debug-monitors.c

File preview with syntax highlighting.

linux-6.19.14/arch/arm64/kernel/debug-monitors.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * ARMv8 single-step debug support and mdscr context switching.
  4 *
  5 * Copyright (C) 2012 ARM Limited
  6 *
  7 * Author: Will Deacon <will.deacon@arm.com>
  8 */
  9
 10#include <linux/cpu.h>
 11#include <linux/debugfs.h>
 12#include <linux/hardirq.h>
 13#include <linux/init.h>
 14#include <linux/ptrace.h>
 15#include <linux/kprobes.h>
 16#include <linux/stat.h>
 17#include <linux/uaccess.h>
 18#include <linux/sched/task_stack.h>
 19
 20#include <asm/cpufeature.h>
 21#include <asm/cputype.h>
 22#include <asm/daifflags.h>
 23#include <asm/debug-monitors.h>
 24#include <asm/exception.h>
 25#include <asm/kgdb.h>
 26#include <asm/kprobes.h>
 27#include <asm/system_misc.h>
 28#include <asm/traps.h>
 29#include <asm/uprobes.h>
 30
 31/* Determine debug architecture. */
 32u8 debug_monitors_arch(void)
 33{
 34	return cpuid_feature_extract_unsigned_field(read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1),
 35						ID_AA64DFR0_EL1_DebugVer_SHIFT);
 36}
 37
 38/*
 39 * MDSCR access routines.
 40 */
 41static void mdscr_write(u64 mdscr)
 42{
 43	unsigned long flags;
 44	flags = local_daif_save();
 45	write_sysreg(mdscr, mdscr_el1);
 46	local_daif_restore(flags);
 47}
 48NOKPROBE_SYMBOL(mdscr_write);
 49
 50static u64 mdscr_read(void)
 51{
 52	return read_sysreg(mdscr_el1);
 53}
 54NOKPROBE_SYMBOL(mdscr_read);
 55
 56/*
 57 * Allow root to disable self-hosted debug from userspace.
 58 * This is useful if you want to connect an external JTAG debugger.
 59 */
 60static bool debug_enabled = true;
 61
 62static int create_debug_debugfs_entry(void)
 63{
 64	debugfs_create_bool("debug_enabled", 0644, NULL, &debug_enabled);
 65	return 0;
 66}
 67fs_initcall(create_debug_debugfs_entry);
 68
 69static int __init early_debug_disable(char *buf)
 70{
 71	debug_enabled = false;
 72	return 0;
 73}
 74
 75early_param("nodebugmon", early_debug_disable);
 76
 77/*
 78 * Keep track of debug users on each core.
 79 * The ref counts are per-cpu so we use a local_t type.
 80 */
 81static DEFINE_PER_CPU(int, mde_ref_count);
 82static DEFINE_PER_CPU(int, kde_ref_count);
 83
 84void enable_debug_monitors(enum dbg_active_el el)
 85{
 86	u64 mdscr, enable = 0;
 87
 88	WARN_ON(preemptible());
 89
 90	if (this_cpu_inc_return(mde_ref_count) == 1)
 91		enable = MDSCR_EL1_MDE;
 92
 93	if (el == DBG_ACTIVE_EL1 &&
 94	    this_cpu_inc_return(kde_ref_count) == 1)
 95		enable |= MDSCR_EL1_KDE;
 96
 97	if (enable && debug_enabled) {
 98		mdscr = mdscr_read();
 99		mdscr |= enable;
100		mdscr_write(mdscr);
101	}
102}
103NOKPROBE_SYMBOL(enable_debug_monitors);
104
105void disable_debug_monitors(enum dbg_active_el el)
106{
107	u64 mdscr, disable = 0;
108
109	WARN_ON(preemptible());
110
111	if (this_cpu_dec_return(mde_ref_count) == 0)
112		disable = ~MDSCR_EL1_MDE;
113
114	if (el == DBG_ACTIVE_EL1 &&
115	    this_cpu_dec_return(kde_ref_count) == 0)
116		disable &= ~MDSCR_EL1_KDE;
117
118	if (disable) {
119		mdscr = mdscr_read();
120		mdscr &= disable;
121		mdscr_write(mdscr);
122	}
123}
124NOKPROBE_SYMBOL(disable_debug_monitors);
125
126/*
127 * OS lock clearing.
128 */
129static int clear_os_lock(unsigned int cpu)
130{
131	write_sysreg(0, osdlr_el1);
132	write_sysreg(0, oslar_el1);
133	isb();
134	return 0;
135}
136
137static int __init debug_monitors_init(void)
138{
139	return cpuhp_setup_state(CPUHP_AP_ARM64_DEBUG_MONITORS_STARTING,
140				 "arm64/debug_monitors:starting",
141				 clear_os_lock, NULL);
142}
143postcore_initcall(debug_monitors_init);
144
145/*
146 * Single step API and exception handling.
147 */
148static void set_user_regs_spsr_ss(struct user_pt_regs *regs)
149{
150	regs->pstate |= DBG_SPSR_SS;
151}
152NOKPROBE_SYMBOL(set_user_regs_spsr_ss);
153
154static void clear_user_regs_spsr_ss(struct user_pt_regs *regs)
155{
156	regs->pstate &= ~DBG_SPSR_SS;
157}
158NOKPROBE_SYMBOL(clear_user_regs_spsr_ss);
159
160#define set_regs_spsr_ss(r)	set_user_regs_spsr_ss(&(r)->user_regs)
161#define clear_regs_spsr_ss(r)	clear_user_regs_spsr_ss(&(r)->user_regs)
162
163static void send_user_sigtrap(int si_code)
164{
165	struct pt_regs *regs = current_pt_regs();
166
167	if (WARN_ON(!user_mode(regs)))
168		return;
169
170	if (!regs_irqs_disabled(regs))
171		local_irq_enable();
172
173	arm64_force_sig_fault(SIGTRAP, si_code, instruction_pointer(regs),
174			      "User debug trap");
175}
176
177/*
178 * We have already unmasked interrupts and enabled preemption
179 * when calling do_el0_softstep() from entry-common.c.
180 */
181void do_el0_softstep(unsigned long esr, struct pt_regs *regs)
182{
183	if (uprobe_single_step_handler(regs, esr) == DBG_HOOK_HANDLED)
184		return;
185
186	send_user_sigtrap(TRAP_TRACE);
187	/*
188	 * ptrace will disable single step unless explicitly
189	 * asked to re-enable it. For other clients, it makes
190	 * sense to leave it enabled (i.e. rewind the controls
191	 * to the active-not-pending state).
192	 */
193	user_rewind_single_step(current);
194}
195
196void do_el1_softstep(unsigned long esr, struct pt_regs *regs)
197{
198	if (kgdb_single_step_handler(regs, esr) == DBG_HOOK_HANDLED)
199		return;
200
201	pr_warn("Unexpected kernel single-step exception at EL1\n");
202	/*
203	 * Re-enable stepping since we know that we will be
204	 * returning to regs.
205	 */
206	set_regs_spsr_ss(regs);
207}
208NOKPROBE_SYMBOL(do_el1_softstep);
209
210static int call_el1_break_hook(struct pt_regs *regs, unsigned long esr)
211{
212	if (esr_brk_comment(esr) == BUG_BRK_IMM)
213		return bug_brk_handler(regs, esr);
214
215	if (IS_ENABLED(CONFIG_CFI) && esr_is_cfi_brk(esr))
216		return cfi_brk_handler(regs, esr);
217
218	if (esr_brk_comment(esr) == FAULT_BRK_IMM)
219		return reserved_fault_brk_handler(regs, esr);
220
221	if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) &&
222		(esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
223		return kasan_brk_handler(regs, esr);
224
225	if (IS_ENABLED(CONFIG_UBSAN_TRAP) && esr_is_ubsan_brk(esr))
226		return ubsan_brk_handler(regs, esr);
227
228	if (IS_ENABLED(CONFIG_KGDB)) {
229		if (esr_brk_comment(esr) == KGDB_DYN_DBG_BRK_IMM)
230			return kgdb_brk_handler(regs, esr);
231		if (esr_brk_comment(esr) == KGDB_COMPILED_DBG_BRK_IMM)
232			return kgdb_compiled_brk_handler(regs, esr);
233	}
234
235	if (IS_ENABLED(CONFIG_KPROBES)) {
236		if (esr_brk_comment(esr) == KPROBES_BRK_IMM)
237			return kprobe_brk_handler(regs, esr);
238		if (esr_brk_comment(esr) == KPROBES_BRK_SS_IMM)
239			return kprobe_ss_brk_handler(regs, esr);
240	}
241
242	if (IS_ENABLED(CONFIG_KRETPROBES) &&
243		esr_brk_comment(esr) == KRETPROBES_BRK_IMM)
244		return kretprobe_brk_handler(regs, esr);
245
246	return DBG_HOOK_ERROR;
247}
248NOKPROBE_SYMBOL(call_el1_break_hook);
249
250/*
251 * We have already unmasked interrupts and enabled preemption
252 * when calling do_el0_brk64() from entry-common.c.
253 */
254void do_el0_brk64(unsigned long esr, struct pt_regs *regs)
255{
256	if (IS_ENABLED(CONFIG_UPROBES) &&
257		esr_brk_comment(esr) == UPROBES_BRK_IMM &&
258		uprobe_brk_handler(regs, esr) == DBG_HOOK_HANDLED)
259		return;
260
261	send_user_sigtrap(TRAP_BRKPT);
262}
263
264void do_el1_brk64(unsigned long esr, struct pt_regs *regs)
265{
266	if (call_el1_break_hook(regs, esr) == DBG_HOOK_HANDLED)
267		return;
268
269	die("Oops - BRK", regs, esr);
270}
271NOKPROBE_SYMBOL(do_el1_brk64);
272
273#ifdef CONFIG_COMPAT
274void do_bkpt32(unsigned long esr, struct pt_regs *regs)
275{
276	arm64_notify_die("aarch32 BKPT", regs, SIGTRAP, TRAP_BRKPT, regs->pc, esr);
277}
278#endif /* CONFIG_COMPAT */
279
280bool try_handle_aarch32_break(struct pt_regs *regs)
281{
282	u32 arm_instr;
283	u16 thumb_instr;
284	bool bp = false;
285	void __user *pc = (void __user *)instruction_pointer(regs);
286
287	if (!compat_user_mode(regs))
288		return false;
289
290	if (compat_thumb_mode(regs)) {
291		/* get 16-bit Thumb instruction */
292		__le16 instr;
293		get_user(instr, (__le16 __user *)pc);
294		thumb_instr = le16_to_cpu(instr);
295		if (thumb_instr == AARCH32_BREAK_THUMB2_LO) {
296			/* get second half of 32-bit Thumb-2 instruction */
297			get_user(instr, (__le16 __user *)(pc + 2));
298			thumb_instr = le16_to_cpu(instr);
299			bp = thumb_instr == AARCH32_BREAK_THUMB2_HI;
300		} else {
301			bp = thumb_instr == AARCH32_BREAK_THUMB;
302		}
303	} else {
304		/* 32-bit ARM instruction */
305		__le32 instr;
306		get_user(instr, (__le32 __user *)pc);
307		arm_instr = le32_to_cpu(instr);
308		bp = (arm_instr & ~0xf0000000) == AARCH32_BREAK_ARM;
309	}
310
311	if (!bp)
312		return false;
313
314	send_user_sigtrap(TRAP_BRKPT);
315	return true;
316}
317NOKPROBE_SYMBOL(try_handle_aarch32_break);
318
319/* Re-enable single step for syscall restarting. */
320void user_rewind_single_step(struct task_struct *task)
321{
322	/*
323	 * If single step is active for this thread, then set SPSR.SS
324	 * to 1 to avoid returning to the active-pending state.
325	 */
326	if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
327		set_regs_spsr_ss(task_pt_regs(task));
328}
329NOKPROBE_SYMBOL(user_rewind_single_step);
330
331void user_fastforward_single_step(struct task_struct *task)
332{
333	if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
334		clear_regs_spsr_ss(task_pt_regs(task));
335}
336
337void user_regs_reset_single_step(struct user_pt_regs *regs,
338				 struct task_struct *task)
339{
340	if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
341		set_user_regs_spsr_ss(regs);
342	else
343		clear_user_regs_spsr_ss(regs);
344}
345
346/* Kernel API */
347void kernel_enable_single_step(struct pt_regs *regs)
348{
349	WARN_ON(!irqs_disabled());
350	set_regs_spsr_ss(regs);
351	mdscr_write(mdscr_read() | MDSCR_EL1_SS);
352	enable_debug_monitors(DBG_ACTIVE_EL1);
353}
354NOKPROBE_SYMBOL(kernel_enable_single_step);
355
356void kernel_disable_single_step(void)
357{
358	WARN_ON(!irqs_disabled());
359	mdscr_write(mdscr_read() & ~MDSCR_EL1_SS);
360	disable_debug_monitors(DBG_ACTIVE_EL1);
361}
362NOKPROBE_SYMBOL(kernel_disable_single_step);
363
364int kernel_active_single_step(void)
365{
366	WARN_ON(!irqs_disabled());
367	return mdscr_read() & MDSCR_EL1_SS;
368}
369NOKPROBE_SYMBOL(kernel_active_single_step);
370
371void kernel_rewind_single_step(struct pt_regs *regs)
372{
373	set_regs_spsr_ss(regs);
374}
375
376void kernel_fastforward_single_step(struct pt_regs *regs)
377{
378	clear_regs_spsr_ss(regs);
379}
380
381/* ptrace API */
382void user_enable_single_step(struct task_struct *task)
383{
384	struct thread_info *ti = task_thread_info(task);
385
386	if (!test_and_set_ti_thread_flag(ti, TIF_SINGLESTEP))
387		set_regs_spsr_ss(task_pt_regs(task));
388}
389NOKPROBE_SYMBOL(user_enable_single_step);
390
391void user_disable_single_step(struct task_struct *task)
392{
393	clear_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP);
394}
395NOKPROBE_SYMBOL(user_disable_single_step);
~/ Read-only file preview.