LCOV - code coverage report
Current view: top level - arch/x86/include/asm - debugreg.h (source / functions) Hit Total Coverage
Test: landlock.info Lines: 39 62 62.9 %
Date: 2021-04-22 12:43:58 Functions: 0 0 -

          Line data    Source code
       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             : 
       9             : DECLARE_PER_CPU(unsigned long, cpu_dr7);
      10             : 
      11             : #ifndef CONFIG_PARAVIRT_XXL
      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             : 
      21           1 : static __always_inline unsigned long native_get_debugreg(int regno)
      22             : {
      23           1 :         unsigned long val = 0;  /* Damn you, gcc! */
      24             : 
      25           1 :         switch (regno) {
      26             :         case 0:
      27           1 :                 asm("mov %%db0, %0" :"=r" (val));
      28           1 :                 break;
      29             :         case 1:
      30           1 :                 asm("mov %%db1, %0" :"=r" (val));
      31           1 :                 break;
      32             :         case 2:
      33           1 :                 asm("mov %%db2, %0" :"=r" (val));
      34           1 :                 break;
      35             :         case 3:
      36           1 :                 asm("mov %%db3, %0" :"=r" (val));
      37           1 :                 break;
      38             :         case 6:
      39           1 :                 asm("mov %%db6, %0" :"=r" (val));
      40           1 :                 break;
      41             :         case 7:
      42           1 :                 asm("mov %%db7, %0" :"=r" (val));
      43           1 :                 break;
      44             :         default:
      45           1 :                 BUG();
      46             :         }
      47           1 :         return val;
      48             : }
      49             : 
      50          24 : static __always_inline void native_set_debugreg(int regno, unsigned long value)
      51             : {
      52          24 :         switch (regno) {
      53           4 :         case 0:
      54           4 :                 asm("mov %0, %%db0"   ::"r" (value));
      55           4 :                 break;
      56           4 :         case 1:
      57           4 :                 asm("mov %0, %%db1"   ::"r" (value));
      58           4 :                 break;
      59           4 :         case 2:
      60           4 :                 asm("mov %0, %%db2"   ::"r" (value));
      61           4 :                 break;
      62           4 :         case 3:
      63           4 :                 asm("mov %0, %%db3"   ::"r" (value));
      64           4 :                 break;
      65           4 :         case 6:
      66           4 :                 asm("mov %0, %%db6"   ::"r" (value));
      67           4 :                 break;
      68           4 :         case 7:
      69           4 :                 asm("mov %0, %%db7"   ::"r" (value));
      70           4 :                 break;
      71           0 :         default:
      72           0 :                 BUG();
      73             :         }
      74           0 : }
      75             : 
      76           0 : static inline void hw_breakpoint_disable(void)
      77             : {
      78             :         /* Zero the control register for HW Breakpoint */
      79           0 :         set_debugreg(0UL, 7);
      80             : 
      81             :         /* Zero-out the individual HW breakpoint address registers */
      82           0 :         set_debugreg(0UL, 0);
      83           0 :         set_debugreg(0UL, 1);
      84           0 :         set_debugreg(0UL, 2);
      85           0 :         set_debugreg(0UL, 3);
      86           0 : }
      87             : 
      88         228 : static __always_inline bool hw_breakpoint_active(void)
      89             : {
      90         228 :         return __this_cpu_read(cpu_dr7) & DR_GLOBAL_ENABLE_MASK;
      91             : }
      92             : 
      93             : extern void hw_breakpoint_restore(void);
      94             : 
      95           0 : static __always_inline unsigned long local_db_save(void)
      96             : {
      97           0 :         unsigned long dr7;
      98             : 
      99           0 :         if (static_cpu_has(X86_FEATURE_HYPERVISOR) && !hw_breakpoint_active())
     100             :                 return 0;
     101             : 
     102           0 :         get_debugreg(dr7, 7);
     103           0 :         dr7 &= ~0x400; /* architecturally set bit */
     104           0 :         if (dr7)
     105           0 :                 set_debugreg(0, 7);
     106             :         /*
     107             :          * Ensure the compiler doesn't lower the above statements into
     108             :          * the critical section; disabling breakpoints late would not
     109             :          * be good.
     110             :          */
     111           0 :         barrier();
     112             : 
     113           0 :         return dr7;
     114             : }
     115             : 
     116           0 : static __always_inline void local_db_restore(unsigned long dr7)
     117             : {
     118             :         /*
     119             :          * Ensure the compiler doesn't raise this statement into
     120             :          * the critical section; enabling breakpoints early would
     121             :          * not be good.
     122             :          */
     123           0 :         barrier();
     124           0 :         if (dr7)
     125           0 :                 set_debugreg(dr7, 7);
     126             : }
     127             : 
     128             : #ifdef CONFIG_CPU_SUP_AMD
     129             : extern void set_dr_addr_mask(unsigned long mask, int dr);
     130             : #else
     131             : static inline void set_dr_addr_mask(unsigned long mask, int dr) { }
     132             : #endif
     133             : 
     134             : #endif /* _ASM_X86_DEBUGREG_H */

Generated by: LCOV version 1.14