linux/arch/x86/include/asm/debugreg.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _ASM_X86_DEBUGREG_H
   3#define _ASM_X86_DEBUGREG_H
   4
   5
   6#include <linux/bug.h>
   7#include <uapi/asm/debugreg.h>
   8
   9DECLARE_PER_CPU(unsigned long, cpu_dr7);
  10
  11#ifndef CONFIG_PARAVIRT
  12/*
  13 * These special macros can be used to get or set a debugging register
  14 */
  15#define get_debugreg(var, register)                             \
  16        (var) = native_get_debugreg(register)
  17#define set_debugreg(value, register)                           \
  18        native_set_debugreg(register, value)
  19#endif
  20
  21static inline unsigned long native_get_debugreg(int regno)
  22{
  23        unsigned long val = 0;  /* Damn you, gcc! */
  24
  25        switch (regno) {
  26        case 0:
  27                asm("mov %%db0, %0" :"=r" (val));
  28                break;
  29        case 1:
  30                asm("mov %%db1, %0" :"=r" (val));
  31                break;
  32        case 2:
  33                asm("mov %%db2, %0" :"=r" (val));
  34                break;
  35        case 3:
  36                asm("mov %%db3, %0" :"=r" (val));
  37                break;
  38        case 6:
  39                asm("mov %%db6, %0" :"=r" (val));
  40                break;
  41        case 7:
  42                asm("mov %%db7, %0" :"=r" (val));
  43                break;
  44        default:
  45                BUG();
  46        }
  47        return val;
  48}
  49
  50static inline void native_set_debugreg(int regno, unsigned long value)
  51{
  52        switch (regno) {
  53        case 0:
  54                asm("mov %0, %%db0"     ::"r" (value));
  55                break;
  56        case 1:
  57                asm("mov %0, %%db1"     ::"r" (value));
  58                break;
  59        case 2:
  60                asm("mov %0, %%db2"     ::"r" (value));
  61                break;
  62        case 3:
  63                asm("mov %0, %%db3"     ::"r" (value));
  64                break;
  65        case 6:
  66                asm("mov %0, %%db6"     ::"r" (value));
  67                break;
  68        case 7:
  69                asm("mov %0, %%db7"     ::"r" (value));
  70                break;
  71        default:
  72                BUG();
  73        }
  74}
  75
  76static inline void hw_breakpoint_disable(void)
  77{
  78        /* Zero the control register for HW Breakpoint */
  79        set_debugreg(0UL, 7);
  80
  81        /* Zero-out the individual HW breakpoint address registers */
  82        set_debugreg(0UL, 0);
  83        set_debugreg(0UL, 1);
  84        set_debugreg(0UL, 2);
  85        set_debugreg(0UL, 3);
  86}
  87
  88static inline int hw_breakpoint_active(void)
  89{
  90        return __this_cpu_read(cpu_dr7) & DR_GLOBAL_ENABLE_MASK;
  91}
  92
  93extern void aout_dump_debugregs(struct user *dump);
  94
  95extern void hw_breakpoint_restore(void);
  96
  97#ifdef CONFIG_X86_64
  98DECLARE_PER_CPU(int, debug_stack_usage);
  99static inline void debug_stack_usage_inc(void)
 100{
 101        __this_cpu_inc(debug_stack_usage);
 102}
 103static inline void debug_stack_usage_dec(void)
 104{
 105        __this_cpu_dec(debug_stack_usage);
 106}
 107void debug_stack_set_zero(void);
 108void debug_stack_reset(void);
 109#else /* !X86_64 */
 110static inline void debug_stack_set_zero(void) { }
 111static inline void debug_stack_reset(void) { }
 112static inline void debug_stack_usage_inc(void) { }
 113static inline void debug_stack_usage_dec(void) { }
 114#endif /* X86_64 */
 115
 116static __always_inline unsigned long local_db_save(void)
 117{
 118        unsigned long dr7;
 119
 120        get_debugreg(dr7, 7);
 121        dr7 &= ~0x400; /* architecturally set bit */
 122        if (dr7)
 123                set_debugreg(0, 7);
 124        /*
 125         * Ensure the compiler doesn't lower the above statements into
 126         * the critical section; disabling breakpoints late would not
 127         * be good.
 128         */
 129        barrier();
 130
 131        return dr7;
 132}
 133
 134static __always_inline void local_db_restore(unsigned long dr7)
 135{
 136        /*
 137         * Ensure the compiler doesn't raise this statement into
 138         * the critical section; enabling breakpoints early would
 139         * not be good.
 140         */
 141        barrier();
 142        if (dr7)
 143                set_debugreg(dr7, 7);
 144}
 145
 146#ifdef CONFIG_CPU_SUP_AMD
 147extern void set_dr_addr_mask(unsigned long mask, int dr);
 148#else
 149static inline void set_dr_addr_mask(unsigned long mask, int dr) { }
 150#endif
 151
 152#endif /* _ASM_X86_DEBUGREG_H */
 153