LCOV - code coverage report
Current view: top level - arch/x86/include/asm - cpufeature.h (source / functions) Hit Total Coverage
Test: combined.info Lines: 5 5 100.0 %
Date: 2022-04-01 13:59:58 Functions: 0 0 -
Branches: 36 92 39.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0 */
       2                 :            : #ifndef _ASM_X86_CPUFEATURE_H
       3                 :            : #define _ASM_X86_CPUFEATURE_H
       4                 :            : 
       5                 :            : #include <asm/processor.h>
       6                 :            : 
       7                 :            : #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
       8                 :            : 
       9                 :            : #include <asm/asm.h>
      10                 :            : #include <linux/bitops.h>
      11                 :            : 
      12                 :            : enum cpuid_leafs
      13                 :            : {
      14                 :            :         CPUID_1_EDX             = 0,
      15                 :            :         CPUID_8000_0001_EDX,
      16                 :            :         CPUID_8086_0001_EDX,
      17                 :            :         CPUID_LNX_1,
      18                 :            :         CPUID_1_ECX,
      19                 :            :         CPUID_C000_0001_EDX,
      20                 :            :         CPUID_8000_0001_ECX,
      21                 :            :         CPUID_LNX_2,
      22                 :            :         CPUID_LNX_3,
      23                 :            :         CPUID_7_0_EBX,
      24                 :            :         CPUID_D_1_EAX,
      25                 :            :         CPUID_LNX_4,
      26                 :            :         CPUID_7_1_EAX,
      27                 :            :         CPUID_8000_0008_EBX,
      28                 :            :         CPUID_6_EAX,
      29                 :            :         CPUID_8000_000A_EDX,
      30                 :            :         CPUID_7_ECX,
      31                 :            :         CPUID_8000_0007_EBX,
      32                 :            :         CPUID_7_EDX,
      33                 :            : };
      34                 :            : 
      35                 :            : #ifdef CONFIG_X86_FEATURE_NAMES
      36                 :            : extern const char * const x86_cap_flags[NCAPINTS*32];
      37                 :            : extern const char * const x86_power_flags[32];
      38                 :            : #define X86_CAP_FMT "%s"
      39                 :            : #define x86_cap_flag(flag) x86_cap_flags[flag]
      40                 :            : #else
      41                 :            : #define X86_CAP_FMT "%d:%d"
      42                 :            : #define x86_cap_flag(flag) ((flag) >> 5), ((flag) & 31)
      43                 :            : #endif
      44                 :            : 
      45                 :            : /*
      46                 :            :  * In order to save room, we index into this array by doing
      47                 :            :  * X86_BUG_<name> - NCAPINTS*32.
      48                 :            :  */
      49                 :            : extern const char * const x86_bug_flags[NBUGINTS*32];
      50                 :            : 
      51                 :            : #define test_cpu_cap(c, bit)                                            \
      52                 :            :          test_bit(bit, (unsigned long *)((c)->x86_capability))
      53                 :            : 
      54                 :            : /*
      55                 :            :  * There are 32 bits/features in each mask word.  The high bits
      56                 :            :  * (selected with (bit>>5) give us the word number and the low 5
      57                 :            :  * bits give us the bit/feature number inside the word.
      58                 :            :  * (1UL<<((bit)&31) gives us a mask for the feature_bit so we can
      59                 :            :  * see if it is set in the mask word.
      60                 :            :  */
      61                 :            : #define CHECK_BIT_IN_MASK_WORD(maskname, word, bit)     \
      62                 :            :         (((bit)>>5)==(word) && (1UL<<((bit)&31) & maskname##word ))
      63                 :            : 
      64                 :            : /*
      65                 :            :  * {REQUIRED,DISABLED}_MASK_CHECK below may seem duplicated with the
      66                 :            :  * following BUILD_BUG_ON_ZERO() check but when NCAPINTS gets changed, all
      67                 :            :  * header macros which use NCAPINTS need to be changed. The duplicated macro
      68                 :            :  * use causes the compiler to issue errors for all headers so that all usage
      69                 :            :  * sites can be corrected.
      70                 :            :  */
      71                 :            : #define REQUIRED_MASK_BIT_SET(feature_bit)              \
      72                 :            :          ( CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK,  0, feature_bit) ||    \
      73                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK,  1, feature_bit) ||    \
      74                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK,  2, feature_bit) ||    \
      75                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK,  3, feature_bit) ||    \
      76                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK,  4, feature_bit) ||    \
      77                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK,  5, feature_bit) ||    \
      78                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK,  6, feature_bit) ||    \
      79                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK,  7, feature_bit) ||    \
      80                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK,  8, feature_bit) ||    \
      81                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK,  9, feature_bit) ||    \
      82                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 10, feature_bit) ||    \
      83                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 11, feature_bit) ||    \
      84                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 12, feature_bit) ||    \
      85                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 13, feature_bit) ||    \
      86                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 14, feature_bit) ||    \
      87                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 15, feature_bit) ||    \
      88                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) ||    \
      89                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) ||    \
      90                 :            :            CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) ||    \
      91                 :            :            REQUIRED_MASK_CHECK                                    ||    \
      92                 :            :            BUILD_BUG_ON_ZERO(NCAPINTS != 19))
      93                 :            : 
      94                 :            : #define DISABLED_MASK_BIT_SET(feature_bit)                              \
      95                 :            :          ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  0, feature_bit) ||    \
      96                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  1, feature_bit) ||    \
      97                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  2, feature_bit) ||    \
      98                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  3, feature_bit) ||    \
      99                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  4, feature_bit) ||    \
     100                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  5, feature_bit) ||    \
     101                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  6, feature_bit) ||    \
     102                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  7, feature_bit) ||    \
     103                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  8, feature_bit) ||    \
     104                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  9, feature_bit) ||    \
     105                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 10, feature_bit) ||    \
     106                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 11, feature_bit) ||    \
     107                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 12, feature_bit) ||    \
     108                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 13, feature_bit) ||    \
     109                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 14, feature_bit) ||    \
     110                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 15, feature_bit) ||    \
     111                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) ||    \
     112                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) ||    \
     113                 :            :            CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) ||    \
     114                 :            :            DISABLED_MASK_CHECK                                    ||    \
     115                 :            :            BUILD_BUG_ON_ZERO(NCAPINTS != 19))
     116                 :            : 
     117                 :            : #define cpu_has(c, bit)                                                 \
     118                 :            :         (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :  \
     119                 :            :          test_cpu_cap(c, bit))
     120                 :            : 
     121                 :            : #define this_cpu_has(bit)                                               \
     122                 :            :         (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :  \
     123                 :            :          x86_this_cpu_test_bit(bit,                                     \
     124                 :            :                 (unsigned long __percpu *)&cpu_info.x86_capability))
     125                 :            : 
     126                 :            : /*
     127                 :            :  * This macro is for detection of features which need kernel
     128                 :            :  * infrastructure to be used.  It may *not* directly test the CPU
     129                 :            :  * itself.  Use the cpu_has() family if you want true runtime
     130                 :            :  * testing of CPU features, like in hypervisor code where you are
     131                 :            :  * supporting a possible guest feature where host support for it
     132                 :            :  * is not relevant.
     133                 :            :  */
     134                 :            : #define cpu_feature_enabled(bit)        \
     135                 :            :         (__builtin_constant_p(bit) && DISABLED_MASK_BIT_SET(bit) ? 0 : static_cpu_has(bit))
     136                 :            : 
     137                 :            : #define boot_cpu_has(bit)       cpu_has(&boot_cpu_data, bit)
     138                 :            : 
     139                 :            : #define set_cpu_cap(c, bit)     set_bit(bit, (unsigned long *)((c)->x86_capability))
     140                 :            : 
     141                 :            : extern void setup_clear_cpu_cap(unsigned int bit);
     142                 :            : extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);
     143                 :            : 
     144                 :            : #define setup_force_cpu_cap(bit) do { \
     145                 :            :         set_cpu_cap(&boot_cpu_data, bit);   \
     146                 :            :         set_bit(bit, (unsigned long *)cpu_caps_set);    \
     147                 :            : } while (0)
     148                 :            : 
     149                 :            : #define setup_force_cpu_bug(bit) setup_force_cpu_cap(bit)
     150                 :            : 
     151                 :            : #if defined(__clang__) && !defined(CONFIG_CC_HAS_ASM_GOTO)
     152                 :            : 
     153                 :            : /*
     154                 :            :  * Workaround for the sake of BPF compilation which utilizes kernel
     155                 :            :  * headers, but clang does not support ASM GOTO and fails the build.
     156                 :            :  */
     157                 :            : #ifndef __BPF_TRACING__
     158                 :            : #warning "Compiler lacks ASM_GOTO support. Add -D __BPF_TRACING__ to your compiler arguments"
     159                 :            : #endif
     160                 :            : 
     161                 :            : #define static_cpu_has(bit)            boot_cpu_has(bit)
     162                 :            : 
     163                 :            : #else
     164                 :            : 
     165                 :            : /*
     166                 :            :  * Static testing of CPU features. Used the same as boot_cpu_has(). It
     167                 :            :  * statically patches the target code for additional performance. Use
     168                 :            :  * static_cpu_has() only in fast paths, where every cycle counts. Which
     169                 :            :  * means that the boot_cpu_has() variant is already fast enough for the
     170                 :            :  * majority of cases and you should stick to using it as it is generally
     171                 :            :  * only two instructions: a RIP-relative MOV and a TEST.
     172                 :            :  */
     173                 : 2950443154 : static __always_inline bool _static_cpu_has(u16 bit)
     174                 :            : {
     175   [ -  +  +  -  : 2950443154 :         asm_volatile_goto("1: jmp 6f\n"
          +  +  +  +  +  
          -  +  +  +  +  
          +  -  +  +  -  
          +  +  -  +  +  
          +  -  +  -  +  
          +  -  +  +  -  
          +  -  -  +  -  
          -  -  +  -  -  
             +  -  -  + ]
     176                 :            :                  "2:\n"
     177                 :            :                  ".skip -(((5f-4f) - (2b-1b)) > 0) * "
     178                 :            :                          "((5f-4f) - (2b-1b)),0x90\n"
     179                 :            :                  "3:\n"
     180                 :            :                  ".section .altinstructions,\"a\"\n"
     181                 :            :                  " .long 1b - .\n"            /* src offset */
     182                 :            :                  " .long 4f - .\n"            /* repl offset */
     183                 :            :                  " .word %P[always]\n"                /* always replace */
     184                 :            :                  " .byte 3b - 1b\n"           /* src len */
     185                 :            :                  " .byte 5f - 4f\n"           /* repl len */
     186                 :            :                  " .byte 3b - 2b\n"           /* pad len */
     187                 :            :                  ".previous\n"
     188                 :            :                  ".section .altinstr_replacement,\"ax\"\n"
     189                 :            :                  "4: jmp %l[t_no]\n"
     190                 :            :                  "5:\n"
     191                 :            :                  ".previous\n"
     192                 :            :                  ".section .altinstructions,\"a\"\n"
     193                 :            :                  " .long 1b - .\n"            /* src offset */
     194                 :            :                  " .long 0\n"                 /* no replacement */
     195                 :            :                  " .word %P[feature]\n"               /* feature bit */
     196                 :            :                  " .byte 3b - 1b\n"           /* src len */
     197                 :            :                  " .byte 0\n"                 /* repl len */
     198                 :            :                  " .byte 0\n"                 /* pad len */
     199                 :            :                  ".previous\n"
     200                 :            :                  ".section .altinstr_aux,\"ax\"\n"
     201                 :            :                  "6:\n"
     202                 :            :                  " testb %[bitnum],%[cap_byte]\n"
     203                 :            :                  " jnz %l[t_yes]\n"
     204                 :            :                  " jmp %l[t_no]\n"
     205                 :            :                  ".previous\n"
     206                 :            :                  : : [feature]  "i" (bit),
     207                 :            :                      [always]   "i" (X86_FEATURE_ALWAYS),
     208                 :            :                      [bitnum]   "i" (1 << (bit & 7)),
     209                 :            :                      [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3])
     210                 :            :                  : : t_yes, t_no);
     211   [ +  +  -  + ]:   41715234 : t_yes:
     212                 :            :         return true;
     213   [ +  -  #  #  : 2789363145 : t_no:
                #  #  # ]
     214   [ +  +  -  +  : 2851054702 :         return false;
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
             -  -  -  - ]
     215                 :            : }
     216                 :            : 
     217                 :            : #define static_cpu_has(bit)                                     \
     218                 :            : (                                                               \
     219                 :            :         __builtin_constant_p(boot_cpu_has(bit)) ?               \
     220                 :            :                 boot_cpu_has(bit) :                             \
     221                 :            :                 _static_cpu_has(bit)                            \
     222                 :            : )
     223                 :            : #endif
     224                 :            : 
     225                 :            : #define cpu_has_bug(c, bit)             cpu_has(c, (bit))
     226                 :            : #define set_cpu_bug(c, bit)             set_cpu_cap(c, (bit))
     227                 :            : #define clear_cpu_bug(c, bit)           clear_cpu_cap(c, (bit))
     228                 :            : 
     229                 :            : #define static_cpu_has_bug(bit)         static_cpu_has((bit))
     230                 :            : #define boot_cpu_has_bug(bit)           cpu_has_bug(&boot_cpu_data, (bit))
     231                 :            : #define boot_cpu_set_bug(bit)           set_cpu_cap(&boot_cpu_data, (bit))
     232                 :            : 
     233                 :            : #define MAX_CPU_FEATURES                (NCAPINTS * 32)
     234                 :            : #define cpu_have_feature                boot_cpu_has
     235                 :            : 
     236                 :            : #define CPU_FEATURE_TYPEFMT             "x86,ven%04Xfam%04Xmod%04X"
     237                 :            : #define CPU_FEATURE_TYPEVAL             boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
     238                 :            :                                         boot_cpu_data.x86_model
     239                 :            : 
     240                 :            : #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
     241                 :            : #endif /* _ASM_X86_CPUFEATURE_H */

Generated by: LCOV version 1.14