H. Peter Anvin | 1965aae | 2008-10-22 22:26:29 -0700 | [diff] [blame] | 1 | #ifndef _ASM_X86_DEBUGREG_H |
| 2 | #define _ASM_X86_DEBUGREG_H |
Thomas Gleixner | 21ebddd | 2007-10-17 20:35:37 +0200 | [diff] [blame] | 3 | |
| 4 | |
Paul Gortmaker | f649e93 | 2012-01-20 16:24:09 -0500 | [diff] [blame] | 5 | #include <linux/bug.h> |
David Howells | af170c5 | 2012-12-14 22:37:13 +0000 | [diff] [blame] | 6 | #include <uapi/asm/debugreg.h> |
Paul Gortmaker | f649e93 | 2012-01-20 16:24:09 -0500 | [diff] [blame] | 7 | |
Tejun Heo | 28b4e0d | 2009-11-25 22:24:44 +0900 | [diff] [blame] | 8 | DECLARE_PER_CPU(unsigned long, cpu_dr7); |
K.Prasad | b332828c | 2009-06-01 23:43:10 +0530 | [diff] [blame] | 9 | |
Paul Gortmaker | f649e93 | 2012-01-20 16:24:09 -0500 | [diff] [blame] | 10 | #ifndef CONFIG_PARAVIRT |
| 11 | /* |
| 12 | * These special macros can be used to get or set a debugging register |
| 13 | */ |
| 14 | #define get_debugreg(var, register) \ |
| 15 | (var) = native_get_debugreg(register) |
| 16 | #define set_debugreg(value, register) \ |
| 17 | native_set_debugreg(register, value) |
| 18 | #endif |
| 19 | |
| 20 | static inline unsigned long native_get_debugreg(int regno) |
| 21 | { |
| 22 | unsigned long val = 0; /* Damn you, gcc! */ |
| 23 | |
| 24 | switch (regno) { |
| 25 | case 0: |
| 26 | asm("mov %%db0, %0" :"=r" (val)); |
| 27 | break; |
| 28 | case 1: |
| 29 | asm("mov %%db1, %0" :"=r" (val)); |
| 30 | break; |
| 31 | case 2: |
| 32 | asm("mov %%db2, %0" :"=r" (val)); |
| 33 | break; |
| 34 | case 3: |
| 35 | asm("mov %%db3, %0" :"=r" (val)); |
| 36 | break; |
| 37 | case 6: |
| 38 | asm("mov %%db6, %0" :"=r" (val)); |
| 39 | break; |
| 40 | case 7: |
| 41 | asm("mov %%db7, %0" :"=r" (val)); |
| 42 | break; |
| 43 | default: |
| 44 | BUG(); |
| 45 | } |
| 46 | return val; |
| 47 | } |
| 48 | |
| 49 | static inline void native_set_debugreg(int regno, unsigned long value) |
| 50 | { |
| 51 | switch (regno) { |
| 52 | case 0: |
| 53 | asm("mov %0, %%db0" ::"r" (value)); |
| 54 | break; |
| 55 | case 1: |
| 56 | asm("mov %0, %%db1" ::"r" (value)); |
| 57 | break; |
| 58 | case 2: |
| 59 | asm("mov %0, %%db2" ::"r" (value)); |
| 60 | break; |
| 61 | case 3: |
| 62 | asm("mov %0, %%db3" ::"r" (value)); |
| 63 | break; |
| 64 | case 6: |
| 65 | asm("mov %0, %%db6" ::"r" (value)); |
| 66 | break; |
| 67 | case 7: |
| 68 | asm("mov %0, %%db7" ::"r" (value)); |
| 69 | break; |
| 70 | default: |
| 71 | BUG(); |
| 72 | } |
| 73 | } |
| 74 | |
K.Prasad | b332828c | 2009-06-01 23:43:10 +0530 | [diff] [blame] | 75 | static inline void hw_breakpoint_disable(void) |
| 76 | { |
| 77 | /* Zero the control register for HW Breakpoint */ |
| 78 | set_debugreg(0UL, 7); |
| 79 | |
| 80 | /* Zero-out the individual HW breakpoint address registers */ |
| 81 | set_debugreg(0UL, 0); |
| 82 | set_debugreg(0UL, 1); |
| 83 | set_debugreg(0UL, 2); |
| 84 | set_debugreg(0UL, 3); |
| 85 | } |
| 86 | |
Frederic Weisbecker | 59d8eb5 | 2009-11-10 11:03:12 +0100 | [diff] [blame] | 87 | static inline int hw_breakpoint_active(void) |
| 88 | { |
Tejun Heo | 0a3aee0 | 2010-12-18 16:28:55 +0100 | [diff] [blame] | 89 | return __this_cpu_read(cpu_dr7) & DR_GLOBAL_ENABLE_MASK; |
Frederic Weisbecker | 59d8eb5 | 2009-11-10 11:03:12 +0100 | [diff] [blame] | 90 | } |
| 91 | |
Frederic Weisbecker | 9f6b3c2 | 2009-11-09 21:03:43 +0100 | [diff] [blame] | 92 | extern void aout_dump_debugregs(struct user *dump); |
| 93 | |
Frederic Weisbecker | 24f1e32c | 2009-09-09 19:22:48 +0200 | [diff] [blame] | 94 | extern void hw_breakpoint_restore(void); |
Frederic Weisbecker | 24f1e32c | 2009-09-09 19:22:48 +0200 | [diff] [blame] | 95 | |
Steven Rostedt | 4218118 | 2011-12-16 11:43:02 -0500 | [diff] [blame] | 96 | #ifdef CONFIG_X86_64 |
| 97 | DECLARE_PER_CPU(int, debug_stack_usage); |
| 98 | static inline void debug_stack_usage_inc(void) |
| 99 | { |
Christoph Lameter | 89cbc76 | 2014-08-17 12:30:40 -0500 | [diff] [blame] | 100 | __this_cpu_inc(debug_stack_usage); |
Steven Rostedt | 4218118 | 2011-12-16 11:43:02 -0500 | [diff] [blame] | 101 | } |
| 102 | static inline void debug_stack_usage_dec(void) |
| 103 | { |
Christoph Lameter | 89cbc76 | 2014-08-17 12:30:40 -0500 | [diff] [blame] | 104 | __this_cpu_dec(debug_stack_usage); |
Steven Rostedt | 4218118 | 2011-12-16 11:43:02 -0500 | [diff] [blame] | 105 | } |
| 106 | int is_debug_stack(unsigned long addr); |
| 107 | void debug_stack_set_zero(void); |
| 108 | void debug_stack_reset(void); |
| 109 | #else /* !X86_64 */ |
| 110 | static inline int is_debug_stack(unsigned long addr) { return 0; } |
| 111 | static inline void debug_stack_set_zero(void) { } |
| 112 | static inline void debug_stack_reset(void) { } |
| 113 | static inline void debug_stack_usage_inc(void) { } |
| 114 | static inline void debug_stack_usage_dec(void) { } |
| 115 | #endif /* X86_64 */ |
| 116 | |
| 117 | |
H. Peter Anvin | 1965aae | 2008-10-22 22:26:29 -0700 | [diff] [blame] | 118 | #endif /* _ASM_X86_DEBUGREG_H */ |