diff options
Diffstat (limited to 'arch/x86/include')
-rw-r--r-- | arch/x86/include/asm/a.out-core.h | 8 | ||||
-rw-r--r-- | arch/x86/include/asm/debugreg.h | 29 | ||||
-rw-r--r-- | arch/x86/include/asm/hw_breakpoint.h | 55 | ||||
-rw-r--r-- | arch/x86/include/asm/processor.h | 8 |
4 files changed, 92 insertions, 8 deletions
diff --git a/arch/x86/include/asm/a.out-core.h b/arch/x86/include/asm/a.out-core.h index bb70e397aa84..fc4685dd6e4d 100644 --- a/arch/x86/include/asm/a.out-core.h +++ b/arch/x86/include/asm/a.out-core.h | |||
@@ -32,10 +32,10 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump) | |||
32 | >> PAGE_SHIFT; | 32 | >> PAGE_SHIFT; |
33 | dump->u_dsize -= dump->u_tsize; | 33 | dump->u_dsize -= dump->u_tsize; |
34 | dump->u_ssize = 0; | 34 | dump->u_ssize = 0; |
35 | dump->u_debugreg[0] = current->thread.debugreg0; | 35 | dump->u_debugreg[0] = current->thread.debugreg[0]; |
36 | dump->u_debugreg[1] = current->thread.debugreg1; | 36 | dump->u_debugreg[1] = current->thread.debugreg[1]; |
37 | dump->u_debugreg[2] = current->thread.debugreg2; | 37 | dump->u_debugreg[2] = current->thread.debugreg[2]; |
38 | dump->u_debugreg[3] = current->thread.debugreg3; | 38 | dump->u_debugreg[3] = current->thread.debugreg[3]; |
39 | dump->u_debugreg[4] = 0; | 39 | dump->u_debugreg[4] = 0; |
40 | dump->u_debugreg[5] = 0; | 40 | dump->u_debugreg[5] = 0; |
41 | dump->u_debugreg[6] = current->thread.debugreg6; | 41 | dump->u_debugreg[6] = current->thread.debugreg6; |
diff --git a/arch/x86/include/asm/debugreg.h b/arch/x86/include/asm/debugreg.h index 3ea6f37be9e2..23439fbb1d0e 100644 --- a/arch/x86/include/asm/debugreg.h +++ b/arch/x86/include/asm/debugreg.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #define DR_TRAP1 (0x2) /* db1 */ | 18 | #define DR_TRAP1 (0x2) /* db1 */ |
19 | #define DR_TRAP2 (0x4) /* db2 */ | 19 | #define DR_TRAP2 (0x4) /* db2 */ |
20 | #define DR_TRAP3 (0x8) /* db3 */ | 20 | #define DR_TRAP3 (0x8) /* db3 */ |
21 | #define DR_TRAP_BITS (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3) | ||
21 | 22 | ||
22 | #define DR_STEP (0x4000) /* single-step */ | 23 | #define DR_STEP (0x4000) /* single-step */ |
23 | #define DR_SWITCH (0x8000) /* task switch */ | 24 | #define DR_SWITCH (0x8000) /* task switch */ |
@@ -49,6 +50,8 @@ | |||
49 | 50 | ||
50 | #define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */ | 51 | #define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */ |
51 | #define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */ | 52 | #define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */ |
53 | #define DR_LOCAL_ENABLE (0x1) /* Local enable for reg 0 */ | ||
54 | #define DR_GLOBAL_ENABLE (0x2) /* Global enable for reg 0 */ | ||
52 | #define DR_ENABLE_SIZE 2 /* 2 enable bits per register */ | 55 | #define DR_ENABLE_SIZE 2 /* 2 enable bits per register */ |
53 | 56 | ||
54 | #define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */ | 57 | #define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */ |
@@ -67,4 +70,30 @@ | |||
67 | #define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ | 70 | #define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ |
68 | #define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ | 71 | #define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ |
69 | 72 | ||
73 | /* | ||
74 | * HW breakpoint additions | ||
75 | */ | ||
76 | #ifdef __KERNEL__ | ||
77 | |||
78 | /* For process management */ | ||
79 | extern void flush_thread_hw_breakpoint(struct task_struct *tsk); | ||
80 | extern int copy_thread_hw_breakpoint(struct task_struct *tsk, | ||
81 | struct task_struct *child, unsigned long clone_flags); | ||
82 | |||
83 | /* For CPU management */ | ||
84 | extern void load_debug_registers(void); | ||
85 | static inline void hw_breakpoint_disable(void) | ||
86 | { | ||
87 | /* Zero the control register for HW Breakpoint */ | ||
88 | set_debugreg(0UL, 7); | ||
89 | |||
90 | /* Zero-out the individual HW breakpoint address registers */ | ||
91 | set_debugreg(0UL, 0); | ||
92 | set_debugreg(0UL, 1); | ||
93 | set_debugreg(0UL, 2); | ||
94 | set_debugreg(0UL, 3); | ||
95 | } | ||
96 | |||
97 | #endif /* __KERNEL__ */ | ||
98 | |||
70 | #endif /* _ASM_X86_DEBUGREG_H */ | 99 | #endif /* _ASM_X86_DEBUGREG_H */ |
diff --git a/arch/x86/include/asm/hw_breakpoint.h b/arch/x86/include/asm/hw_breakpoint.h new file mode 100644 index 000000000000..1acb4d45de70 --- /dev/null +++ b/arch/x86/include/asm/hw_breakpoint.h | |||
@@ -0,0 +1,55 @@ | |||
1 | #ifndef _I386_HW_BREAKPOINT_H | ||
2 | #define _I386_HW_BREAKPOINT_H | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | #define __ARCH_HW_BREAKPOINT_H | ||
6 | |||
7 | struct arch_hw_breakpoint { | ||
8 | char *name; /* Contains name of the symbol to set bkpt */ | ||
9 | unsigned long address; | ||
10 | u8 len; | ||
11 | u8 type; | ||
12 | }; | ||
13 | |||
14 | #include <linux/kdebug.h> | ||
15 | #include <asm-generic/hw_breakpoint.h> | ||
16 | |||
17 | /* Available HW breakpoint length encodings */ | ||
18 | #define HW_BREAKPOINT_LEN_1 0x40 | ||
19 | #define HW_BREAKPOINT_LEN_2 0x44 | ||
20 | #define HW_BREAKPOINT_LEN_4 0x4c | ||
21 | #define HW_BREAKPOINT_LEN_EXECUTE 0x40 | ||
22 | |||
23 | #ifdef CONFIG_X86_64 | ||
24 | #define HW_BREAKPOINT_LEN_8 0x48 | ||
25 | #endif | ||
26 | |||
27 | /* Available HW breakpoint type encodings */ | ||
28 | |||
29 | /* trigger on instruction execute */ | ||
30 | #define HW_BREAKPOINT_EXECUTE 0x80 | ||
31 | /* trigger on memory write */ | ||
32 | #define HW_BREAKPOINT_WRITE 0x81 | ||
33 | /* trigger on memory read or write */ | ||
34 | #define HW_BREAKPOINT_RW 0x83 | ||
35 | |||
36 | /* Total number of available HW breakpoint registers */ | ||
37 | #define HBP_NUM 4 | ||
38 | |||
39 | extern struct hw_breakpoint *hbp_kernel[HBP_NUM]; | ||
40 | DECLARE_PER_CPU(struct hw_breakpoint*, this_hbp_kernel[HBP_NUM]); | ||
41 | extern unsigned int hbp_user_refcount[HBP_NUM]; | ||
42 | |||
43 | extern void arch_install_thread_hw_breakpoint(struct task_struct *tsk); | ||
44 | extern void arch_uninstall_thread_hw_breakpoint(void); | ||
45 | extern int arch_check_va_in_userspace(unsigned long va, u8 hbp_len); | ||
46 | extern int arch_validate_hwbkpt_settings(struct hw_breakpoint *bp, | ||
47 | struct task_struct *tsk); | ||
48 | extern void arch_update_user_hw_breakpoint(int pos, struct task_struct *tsk); | ||
49 | extern void arch_flush_thread_hw_breakpoint(struct task_struct *tsk); | ||
50 | extern void arch_update_kernel_hw_breakpoint(void *); | ||
51 | extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, | ||
52 | unsigned long val, void *data); | ||
53 | #endif /* __KERNEL__ */ | ||
54 | #endif /* _I386_HW_BREAKPOINT_H */ | ||
55 | |||
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index c7768269b1cf..2b03f700d3f2 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -29,6 +29,7 @@ struct mm_struct; | |||
29 | #include <linux/threads.h> | 29 | #include <linux/threads.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | 31 | ||
32 | #define HBP_NUM 4 | ||
32 | /* | 33 | /* |
33 | * Default implementation of macro that returns current | 34 | * Default implementation of macro that returns current |
34 | * instruction pointer ("program counter"). | 35 | * instruction pointer ("program counter"). |
@@ -433,12 +434,11 @@ struct thread_struct { | |||
433 | #endif | 434 | #endif |
434 | unsigned long gs; | 435 | unsigned long gs; |
435 | /* Hardware debugging registers: */ | 436 | /* Hardware debugging registers: */ |
436 | unsigned long debugreg0; | 437 | unsigned long debugreg[HBP_NUM]; |
437 | unsigned long debugreg1; | ||
438 | unsigned long debugreg2; | ||
439 | unsigned long debugreg3; | ||
440 | unsigned long debugreg6; | 438 | unsigned long debugreg6; |
441 | unsigned long debugreg7; | 439 | unsigned long debugreg7; |
440 | /* Hardware breakpoint info */ | ||
441 | struct hw_breakpoint *hbp[HBP_NUM]; | ||
442 | /* Fault info: */ | 442 | /* Fault info: */ |
443 | unsigned long cr2; | 443 | unsigned long cr2; |
444 | unsigned long trap_no; | 444 | unsigned long trap_no; |