0001
0002 #ifndef _ASM_X86_DEBUGREG_H
0003 #define _ASM_X86_DEBUGREG_H
0004
0005
0006 #include <linux/bug.h>
0007 #include <uapi/asm/debugreg.h>
0008
0009 DECLARE_PER_CPU(unsigned long, cpu_dr7);
0010
0011 #ifndef CONFIG_PARAVIRT_XXL
0012
0013
0014
0015 #define get_debugreg(var, register) \
0016 (var) = native_get_debugreg(register)
0017 #define set_debugreg(value, register) \
0018 native_set_debugreg(register, value)
0019 #endif
0020
0021 static __always_inline unsigned long native_get_debugreg(int regno)
0022 {
0023 unsigned long val = 0;
0024
0025 switch (regno) {
0026 case 0:
0027 asm("mov %%db0, %0" :"=r" (val));
0028 break;
0029 case 1:
0030 asm("mov %%db1, %0" :"=r" (val));
0031 break;
0032 case 2:
0033 asm("mov %%db2, %0" :"=r" (val));
0034 break;
0035 case 3:
0036 asm("mov %%db3, %0" :"=r" (val));
0037 break;
0038 case 6:
0039 asm("mov %%db6, %0" :"=r" (val));
0040 break;
0041 case 7:
0042 asm("mov %%db7, %0" :"=r" (val));
0043 break;
0044 default:
0045 BUG();
0046 }
0047 return val;
0048 }
0049
0050 static __always_inline void native_set_debugreg(int regno, unsigned long value)
0051 {
0052 switch (regno) {
0053 case 0:
0054 asm("mov %0, %%db0" ::"r" (value));
0055 break;
0056 case 1:
0057 asm("mov %0, %%db1" ::"r" (value));
0058 break;
0059 case 2:
0060 asm("mov %0, %%db2" ::"r" (value));
0061 break;
0062 case 3:
0063 asm("mov %0, %%db3" ::"r" (value));
0064 break;
0065 case 6:
0066 asm("mov %0, %%db6" ::"r" (value));
0067 break;
0068 case 7:
0069 asm("mov %0, %%db7" ::"r" (value));
0070 break;
0071 default:
0072 BUG();
0073 }
0074 }
0075
0076 static inline void hw_breakpoint_disable(void)
0077 {
0078
0079 set_debugreg(0UL, 7);
0080
0081
0082 set_debugreg(0UL, 0);
0083 set_debugreg(0UL, 1);
0084 set_debugreg(0UL, 2);
0085 set_debugreg(0UL, 3);
0086 }
0087
0088 static __always_inline bool hw_breakpoint_active(void)
0089 {
0090 return __this_cpu_read(cpu_dr7) & DR_GLOBAL_ENABLE_MASK;
0091 }
0092
0093 extern void hw_breakpoint_restore(void);
0094
0095 static __always_inline unsigned long local_db_save(void)
0096 {
0097 unsigned long dr7;
0098
0099 if (static_cpu_has(X86_FEATURE_HYPERVISOR) && !hw_breakpoint_active())
0100 return 0;
0101
0102 get_debugreg(dr7, 7);
0103 dr7 &= ~0x400;
0104 if (dr7)
0105 set_debugreg(0, 7);
0106
0107
0108
0109
0110
0111 barrier();
0112
0113 return dr7;
0114 }
0115
0116 static __always_inline void local_db_restore(unsigned long dr7)
0117 {
0118
0119
0120
0121
0122
0123 barrier();
0124 if (dr7)
0125 set_debugreg(dr7, 7);
0126 }
0127
0128 #ifdef CONFIG_CPU_SUP_AMD
0129 extern void set_dr_addr_mask(unsigned long mask, int dr);
0130 #else
0131 static inline void set_dr_addr_mask(unsigned long mask, int dr) { }
0132 #endif
0133
0134 #endif