xref: /openbmc/linux/arch/x86/kernel/hw_breakpoint.c (revision 0067f129)
10067f129SK.Prasad /*
20067f129SK.Prasad  * This program is free software; you can redistribute it and/or modify
30067f129SK.Prasad  * it under the terms of the GNU General Public License as published by
40067f129SK.Prasad  * the Free Software Foundation; either version 2 of the License, or
50067f129SK.Prasad  * (at your option) any later version.
60067f129SK.Prasad  *
70067f129SK.Prasad  * This program is distributed in the hope that it will be useful,
80067f129SK.Prasad  * but WITHOUT ANY WARRANTY; without even the implied warranty of
90067f129SK.Prasad  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
100067f129SK.Prasad  * GNU General Public License for more details.
110067f129SK.Prasad  *
120067f129SK.Prasad  * You should have received a copy of the GNU General Public License
130067f129SK.Prasad  * along with this program; if not, write to the Free Software
140067f129SK.Prasad  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
150067f129SK.Prasad  *
160067f129SK.Prasad  * Copyright (C) 2007 Alan Stern
170067f129SK.Prasad  * Copyright (C) 2009 IBM Corporation
180067f129SK.Prasad  */
190067f129SK.Prasad 
200067f129SK.Prasad /*
210067f129SK.Prasad  * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
220067f129SK.Prasad  * using the CPU's debug registers.
230067f129SK.Prasad  */
240067f129SK.Prasad 
250067f129SK.Prasad #include <linux/irqflags.h>
260067f129SK.Prasad #include <linux/notifier.h>
270067f129SK.Prasad #include <linux/kallsyms.h>
280067f129SK.Prasad #include <linux/kprobes.h>
290067f129SK.Prasad #include <linux/percpu.h>
300067f129SK.Prasad #include <linux/kdebug.h>
310067f129SK.Prasad #include <linux/kernel.h>
320067f129SK.Prasad #include <linux/module.h>
330067f129SK.Prasad #include <linux/sched.h>
340067f129SK.Prasad #include <linux/init.h>
350067f129SK.Prasad #include <linux/smp.h>
360067f129SK.Prasad 
370067f129SK.Prasad #include <asm/hw_breakpoint.h>
380067f129SK.Prasad #include <asm/processor.h>
390067f129SK.Prasad #include <asm/debugreg.h>
400067f129SK.Prasad 
410067f129SK.Prasad /* Unmasked kernel DR7 value */
420067f129SK.Prasad static unsigned long kdr7;
430067f129SK.Prasad 
440067f129SK.Prasad /*
450067f129SK.Prasad  * Masks for the bits corresponding to registers DR0 - DR3 in DR7 register.
460067f129SK.Prasad  * Used to clear and verify the status of bits corresponding to DR0 - DR3
470067f129SK.Prasad  */
480067f129SK.Prasad static const unsigned long	dr7_masks[HBP_NUM] = {
490067f129SK.Prasad 	0x000f0003,	/* LEN0, R/W0, G0, L0 */
500067f129SK.Prasad 	0x00f0000c,	/* LEN1, R/W1, G1, L1 */
510067f129SK.Prasad 	0x0f000030,	/* LEN2, R/W2, G2, L2 */
520067f129SK.Prasad 	0xf00000c0	/* LEN3, R/W3, G3, L3 */
530067f129SK.Prasad };
540067f129SK.Prasad 
550067f129SK.Prasad 
560067f129SK.Prasad /*
570067f129SK.Prasad  * Encode the length, type, Exact, and Enable bits for a particular breakpoint
580067f129SK.Prasad  * as stored in debug register 7.
590067f129SK.Prasad  */
600067f129SK.Prasad static unsigned long encode_dr7(int drnum, unsigned int len, unsigned int type)
610067f129SK.Prasad {
620067f129SK.Prasad 	unsigned long bp_info;
630067f129SK.Prasad 
640067f129SK.Prasad 	bp_info = (len | type) & 0xf;
650067f129SK.Prasad 	bp_info <<= (DR_CONTROL_SHIFT + drnum * DR_CONTROL_SIZE);
660067f129SK.Prasad 	bp_info |= (DR_GLOBAL_ENABLE << (drnum * DR_ENABLE_SIZE)) |
670067f129SK.Prasad 				DR_GLOBAL_SLOWDOWN;
680067f129SK.Prasad 	return bp_info;
690067f129SK.Prasad }
700067f129SK.Prasad 
710067f129SK.Prasad void arch_update_kernel_hw_breakpoint(void *unused)
720067f129SK.Prasad {
730067f129SK.Prasad 	struct hw_breakpoint *bp;
740067f129SK.Prasad 	int i, cpu = get_cpu();
750067f129SK.Prasad 	unsigned long temp_kdr7 = 0;
760067f129SK.Prasad 
770067f129SK.Prasad 	/* Don't allow debug exceptions while we update the registers */
780067f129SK.Prasad 	set_debugreg(0UL, 7);
790067f129SK.Prasad 
800067f129SK.Prasad 	for (i = hbp_kernel_pos; i < HBP_NUM; i++) {
810067f129SK.Prasad 		per_cpu(this_hbp_kernel[i], cpu) = bp = hbp_kernel[i];
820067f129SK.Prasad 		if (bp) {
830067f129SK.Prasad 			temp_kdr7 |= encode_dr7(i, bp->info.len, bp->info.type);
840067f129SK.Prasad 			set_debugreg(bp->info.address, i);
850067f129SK.Prasad 		}
860067f129SK.Prasad 	}
870067f129SK.Prasad 
880067f129SK.Prasad 	/* No need to set DR6. Update the debug registers with kernel-space
890067f129SK.Prasad 	 * breakpoint values from kdr7 and user-space requests from the
900067f129SK.Prasad 	 * current process
910067f129SK.Prasad 	 */
920067f129SK.Prasad 	kdr7 = temp_kdr7;
930067f129SK.Prasad 	set_debugreg(kdr7 | current->thread.debugreg7, 7);
940067f129SK.Prasad 	put_cpu_no_resched();
950067f129SK.Prasad }
960067f129SK.Prasad 
970067f129SK.Prasad /*
980067f129SK.Prasad  * Install the thread breakpoints in their debug registers.
990067f129SK.Prasad  */
1000067f129SK.Prasad void arch_install_thread_hw_breakpoint(struct task_struct *tsk)
1010067f129SK.Prasad {
1020067f129SK.Prasad 	struct thread_struct *thread = &(tsk->thread);
1030067f129SK.Prasad 
1040067f129SK.Prasad 	switch (hbp_kernel_pos) {
1050067f129SK.Prasad 	case 4:
1060067f129SK.Prasad 		set_debugreg(thread->debugreg[3], 3);
1070067f129SK.Prasad 	case 3:
1080067f129SK.Prasad 		set_debugreg(thread->debugreg[2], 2);
1090067f129SK.Prasad 	case 2:
1100067f129SK.Prasad 		set_debugreg(thread->debugreg[1], 1);
1110067f129SK.Prasad 	case 1:
1120067f129SK.Prasad 		set_debugreg(thread->debugreg[0], 0);
1130067f129SK.Prasad 	default:
1140067f129SK.Prasad 		break;
1150067f129SK.Prasad 	}
1160067f129SK.Prasad 
1170067f129SK.Prasad 	/* No need to set DR6 */
1180067f129SK.Prasad 	set_debugreg((kdr7 | thread->debugreg7), 7);
1190067f129SK.Prasad }
1200067f129SK.Prasad 
1210067f129SK.Prasad /*
1220067f129SK.Prasad  * Install the debug register values for just the kernel, no thread.
1230067f129SK.Prasad  */
1240067f129SK.Prasad void arch_uninstall_thread_hw_breakpoint()
1250067f129SK.Prasad {
1260067f129SK.Prasad 	/* Clear the user-space portion of debugreg7 by setting only kdr7 */
1270067f129SK.Prasad 	set_debugreg(kdr7, 7);
1280067f129SK.Prasad 
1290067f129SK.Prasad }
1300067f129SK.Prasad 
1310067f129SK.Prasad static int get_hbp_len(u8 hbp_len)
1320067f129SK.Prasad {
1330067f129SK.Prasad 	unsigned int len_in_bytes = 0;
1340067f129SK.Prasad 
1350067f129SK.Prasad 	switch (hbp_len) {
1360067f129SK.Prasad 	case HW_BREAKPOINT_LEN_1:
1370067f129SK.Prasad 		len_in_bytes = 1;
1380067f129SK.Prasad 		break;
1390067f129SK.Prasad 	case HW_BREAKPOINT_LEN_2:
1400067f129SK.Prasad 		len_in_bytes = 2;
1410067f129SK.Prasad 		break;
1420067f129SK.Prasad 	case HW_BREAKPOINT_LEN_4:
1430067f129SK.Prasad 		len_in_bytes = 4;
1440067f129SK.Prasad 		break;
1450067f129SK.Prasad #ifdef CONFIG_X86_64
1460067f129SK.Prasad 	case HW_BREAKPOINT_LEN_8:
1470067f129SK.Prasad 		len_in_bytes = 8;
1480067f129SK.Prasad 		break;
1490067f129SK.Prasad #endif
1500067f129SK.Prasad 	}
1510067f129SK.Prasad 	return len_in_bytes;
1520067f129SK.Prasad }
1530067f129SK.Prasad 
1540067f129SK.Prasad /*
1550067f129SK.Prasad  * Check for virtual address in user space.
1560067f129SK.Prasad  */
1570067f129SK.Prasad int arch_check_va_in_userspace(unsigned long va, u8 hbp_len)
1580067f129SK.Prasad {
1590067f129SK.Prasad 	unsigned int len;
1600067f129SK.Prasad 
1610067f129SK.Prasad 	len = get_hbp_len(hbp_len);
1620067f129SK.Prasad 
1630067f129SK.Prasad 	return (va <= TASK_SIZE - len);
1640067f129SK.Prasad }
1650067f129SK.Prasad 
1660067f129SK.Prasad /*
1670067f129SK.Prasad  * Check for virtual address in kernel space.
1680067f129SK.Prasad  */
1690067f129SK.Prasad int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len)
1700067f129SK.Prasad {
1710067f129SK.Prasad 	unsigned int len;
1720067f129SK.Prasad 
1730067f129SK.Prasad 	len = get_hbp_len(hbp_len);
1740067f129SK.Prasad 
1750067f129SK.Prasad 	return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
1760067f129SK.Prasad }
1770067f129SK.Prasad 
1780067f129SK.Prasad /*
1790067f129SK.Prasad  * Store a breakpoint's encoded address, length, and type.
1800067f129SK.Prasad  */
1810067f129SK.Prasad static int arch_store_info(struct hw_breakpoint *bp, struct task_struct *tsk)
1820067f129SK.Prasad {
1830067f129SK.Prasad 	/*
1840067f129SK.Prasad 	 * User-space requests will always have the address field populated
1850067f129SK.Prasad 	 * Symbol names from user-space are rejected
1860067f129SK.Prasad 	 */
1870067f129SK.Prasad 	if (tsk && bp->info.name)
1880067f129SK.Prasad 		return -EINVAL;
1890067f129SK.Prasad 	/*
1900067f129SK.Prasad 	 * For kernel-addresses, either the address or symbol name can be
1910067f129SK.Prasad 	 * specified.
1920067f129SK.Prasad 	 */
1930067f129SK.Prasad 	if (bp->info.name)
1940067f129SK.Prasad 		bp->info.address = (unsigned long)
1950067f129SK.Prasad 					kallsyms_lookup_name(bp->info.name);
1960067f129SK.Prasad 	if (bp->info.address)
1970067f129SK.Prasad 		return 0;
1980067f129SK.Prasad 	return -EINVAL;
1990067f129SK.Prasad }
2000067f129SK.Prasad 
2010067f129SK.Prasad /*
2020067f129SK.Prasad  * Validate the arch-specific HW Breakpoint register settings
2030067f129SK.Prasad  */
2040067f129SK.Prasad int arch_validate_hwbkpt_settings(struct hw_breakpoint *bp,
2050067f129SK.Prasad 						struct task_struct *tsk)
2060067f129SK.Prasad {
2070067f129SK.Prasad 	unsigned int align;
2080067f129SK.Prasad 	int ret = -EINVAL;
2090067f129SK.Prasad 
2100067f129SK.Prasad 	switch (bp->info.type) {
2110067f129SK.Prasad 	/*
2120067f129SK.Prasad 	 * Ptrace-refactoring code
2130067f129SK.Prasad 	 * For now, we'll allow instruction breakpoint only for user-space
2140067f129SK.Prasad 	 * addresses
2150067f129SK.Prasad 	 */
2160067f129SK.Prasad 	case HW_BREAKPOINT_EXECUTE:
2170067f129SK.Prasad 		if ((!arch_check_va_in_userspace(bp->info.address,
2180067f129SK.Prasad 							bp->info.len)) &&
2190067f129SK.Prasad 			bp->info.len != HW_BREAKPOINT_LEN_EXECUTE)
2200067f129SK.Prasad 			return ret;
2210067f129SK.Prasad 		break;
2220067f129SK.Prasad 	case HW_BREAKPOINT_WRITE:
2230067f129SK.Prasad 		break;
2240067f129SK.Prasad 	case HW_BREAKPOINT_RW:
2250067f129SK.Prasad 		break;
2260067f129SK.Prasad 	default:
2270067f129SK.Prasad 		return ret;
2280067f129SK.Prasad 	}
2290067f129SK.Prasad 
2300067f129SK.Prasad 	switch (bp->info.len) {
2310067f129SK.Prasad 	case HW_BREAKPOINT_LEN_1:
2320067f129SK.Prasad 		align = 0;
2330067f129SK.Prasad 		break;
2340067f129SK.Prasad 	case HW_BREAKPOINT_LEN_2:
2350067f129SK.Prasad 		align = 1;
2360067f129SK.Prasad 		break;
2370067f129SK.Prasad 	case HW_BREAKPOINT_LEN_4:
2380067f129SK.Prasad 		align = 3;
2390067f129SK.Prasad 		break;
2400067f129SK.Prasad #ifdef CONFIG_X86_64
2410067f129SK.Prasad 	case HW_BREAKPOINT_LEN_8:
2420067f129SK.Prasad 		align = 7;
2430067f129SK.Prasad 		break;
2440067f129SK.Prasad #endif
2450067f129SK.Prasad 	default:
2460067f129SK.Prasad 		return ret;
2470067f129SK.Prasad 	}
2480067f129SK.Prasad 
2490067f129SK.Prasad 	if (bp->triggered)
2500067f129SK.Prasad 		ret = arch_store_info(bp, tsk);
2510067f129SK.Prasad 
2520067f129SK.Prasad 	if (ret < 0)
2530067f129SK.Prasad 		return ret;
2540067f129SK.Prasad 	/*
2550067f129SK.Prasad 	 * Check that the low-order bits of the address are appropriate
2560067f129SK.Prasad 	 * for the alignment implied by len.
2570067f129SK.Prasad 	 */
2580067f129SK.Prasad 	if (bp->info.address & align)
2590067f129SK.Prasad 		return -EINVAL;
2600067f129SK.Prasad 
2610067f129SK.Prasad 	/* Check that the virtual address is in the proper range */
2620067f129SK.Prasad 	if (tsk) {
2630067f129SK.Prasad 		if (!arch_check_va_in_userspace(bp->info.address, bp->info.len))
2640067f129SK.Prasad 			return -EFAULT;
2650067f129SK.Prasad 	} else {
2660067f129SK.Prasad 		if (!arch_check_va_in_kernelspace(bp->info.address,
2670067f129SK.Prasad 								bp->info.len))
2680067f129SK.Prasad 			return -EFAULT;
2690067f129SK.Prasad 	}
2700067f129SK.Prasad 	return 0;
2710067f129SK.Prasad }
2720067f129SK.Prasad 
2730067f129SK.Prasad void arch_update_user_hw_breakpoint(int pos, struct task_struct *tsk)
2740067f129SK.Prasad {
2750067f129SK.Prasad 	struct thread_struct *thread = &(tsk->thread);
2760067f129SK.Prasad 	struct hw_breakpoint *bp = thread->hbp[pos];
2770067f129SK.Prasad 
2780067f129SK.Prasad 	thread->debugreg7 &= ~dr7_masks[pos];
2790067f129SK.Prasad 	if (bp) {
2800067f129SK.Prasad 		thread->debugreg[pos] = bp->info.address;
2810067f129SK.Prasad 		thread->debugreg7 |= encode_dr7(pos, bp->info.len,
2820067f129SK.Prasad 							bp->info.type);
2830067f129SK.Prasad 	} else
2840067f129SK.Prasad 		thread->debugreg[pos] = 0;
2850067f129SK.Prasad }
2860067f129SK.Prasad 
2870067f129SK.Prasad void arch_flush_thread_hw_breakpoint(struct task_struct *tsk)
2880067f129SK.Prasad {
2890067f129SK.Prasad 	int i;
2900067f129SK.Prasad 	struct thread_struct *thread = &(tsk->thread);
2910067f129SK.Prasad 
2920067f129SK.Prasad 	thread->debugreg7 = 0;
2930067f129SK.Prasad 	for (i = 0; i < HBP_NUM; i++)
2940067f129SK.Prasad 		thread->debugreg[i] = 0;
2950067f129SK.Prasad }
2960067f129SK.Prasad 
2970067f129SK.Prasad /*
2980067f129SK.Prasad  * Handle debug exception notifications.
2990067f129SK.Prasad  *
3000067f129SK.Prasad  * Return value is either NOTIFY_STOP or NOTIFY_DONE as explained below.
3010067f129SK.Prasad  *
3020067f129SK.Prasad  * NOTIFY_DONE returned if one of the following conditions is true.
3030067f129SK.Prasad  * i) When the causative address is from user-space and the exception
3040067f129SK.Prasad  * is a valid one, i.e. not triggered as a result of lazy debug register
3050067f129SK.Prasad  * switching
3060067f129SK.Prasad  * ii) When there are more bits than trap<n> set in DR6 register (such
3070067f129SK.Prasad  * as BD, BS or BT) indicating that more than one debug condition is
3080067f129SK.Prasad  * met and requires some more action in do_debug().
3090067f129SK.Prasad  *
3100067f129SK.Prasad  * NOTIFY_STOP returned for all other cases
3110067f129SK.Prasad  *
3120067f129SK.Prasad  */
3130067f129SK.Prasad int __kprobes hw_breakpoint_handler(struct die_args *args)
3140067f129SK.Prasad {
3150067f129SK.Prasad 	int i, cpu, rc = NOTIFY_STOP;
3160067f129SK.Prasad 	struct hw_breakpoint *bp;
3170067f129SK.Prasad 	/* The DR6 value is stored in args->err */
3180067f129SK.Prasad 	unsigned long dr7, dr6 = args->err;
3190067f129SK.Prasad 
3200067f129SK.Prasad 	/* Do an early return if no trap bits are set in DR6 */
3210067f129SK.Prasad 	if ((dr6 & DR_TRAP_BITS) == 0)
3220067f129SK.Prasad 		return NOTIFY_DONE;
3230067f129SK.Prasad 
3240067f129SK.Prasad 	/* Lazy debug register switching */
3250067f129SK.Prasad 	if (!test_tsk_thread_flag(current, TIF_DEBUG))
3260067f129SK.Prasad 		arch_uninstall_thread_hw_breakpoint();
3270067f129SK.Prasad 
3280067f129SK.Prasad 	get_debugreg(dr7, 7);
3290067f129SK.Prasad 	/* Disable breakpoints during exception handling */
3300067f129SK.Prasad 	set_debugreg(0UL, 7);
3310067f129SK.Prasad 	/*
3320067f129SK.Prasad 	 * Assert that local interrupts are disabled
3330067f129SK.Prasad 	 * Reset the DRn bits in the virtualized register value.
3340067f129SK.Prasad 	 * The ptrace trigger routine will add in whatever is needed.
3350067f129SK.Prasad 	 */
3360067f129SK.Prasad 	current->thread.debugreg6 &= ~DR_TRAP_BITS;
3370067f129SK.Prasad 	cpu = get_cpu();
3380067f129SK.Prasad 
3390067f129SK.Prasad 	/* Handle all the breakpoints that were triggered */
3400067f129SK.Prasad 	for (i = 0; i < HBP_NUM; ++i) {
3410067f129SK.Prasad 		if (likely(!(dr6 & (DR_TRAP0 << i))))
3420067f129SK.Prasad 			continue;
3430067f129SK.Prasad 		/*
3440067f129SK.Prasad 		 * Find the corresponding hw_breakpoint structure and
3450067f129SK.Prasad 		 * invoke its triggered callback.
3460067f129SK.Prasad 		 */
3470067f129SK.Prasad 		if (i >= hbp_kernel_pos)
3480067f129SK.Prasad 			bp = per_cpu(this_hbp_kernel[i], cpu);
3490067f129SK.Prasad 		else {
3500067f129SK.Prasad 			bp = current->thread.hbp[i];
3510067f129SK.Prasad 			if (bp)
3520067f129SK.Prasad 				rc = NOTIFY_DONE;
3530067f129SK.Prasad 		}
3540067f129SK.Prasad 		/*
3550067f129SK.Prasad 		 * bp can be NULL due to lazy debug register switching
3560067f129SK.Prasad 		 * or due to the delay between updates of hbp_kernel_pos
3570067f129SK.Prasad 		 * and this_hbp_kernel.
3580067f129SK.Prasad 		 */
3590067f129SK.Prasad 		if (!bp)
3600067f129SK.Prasad 			continue;
3610067f129SK.Prasad 
3620067f129SK.Prasad 		(bp->triggered)(bp, args->regs);
3630067f129SK.Prasad 	}
3640067f129SK.Prasad 	if (dr6 & (~DR_TRAP_BITS))
3650067f129SK.Prasad 		rc = NOTIFY_DONE;
3660067f129SK.Prasad 
3670067f129SK.Prasad 	set_debugreg(dr7, 7);
3680067f129SK.Prasad 	put_cpu_no_resched();
3690067f129SK.Prasad 	return rc;
3700067f129SK.Prasad }
3710067f129SK.Prasad 
3720067f129SK.Prasad /*
3730067f129SK.Prasad  * Handle debug exception notifications.
3740067f129SK.Prasad  */
3750067f129SK.Prasad int __kprobes hw_breakpoint_exceptions_notify(
3760067f129SK.Prasad 		struct notifier_block *unused, unsigned long val, void *data)
3770067f129SK.Prasad {
3780067f129SK.Prasad 	if (val != DIE_DEBUG)
3790067f129SK.Prasad 		return NOTIFY_DONE;
3800067f129SK.Prasad 
3810067f129SK.Prasad 	return hw_breakpoint_handler(data);
3820067f129SK.Prasad }
383