Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _ASM_UM_CPUFEATURE_H
0003 #define _ASM_UM_CPUFEATURE_H
0004 
0005 #include <asm/processor.h>
0006 
0007 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
0008 
0009 #include <asm/asm.h>
0010 #include <linux/bitops.h>
0011 
0012 extern const char * const x86_cap_flags[NCAPINTS*32];
0013 extern const char * const x86_power_flags[32];
0014 #define X86_CAP_FMT "%s"
0015 #define x86_cap_flag(flag) x86_cap_flags[flag]
0016 
0017 /*
0018  * In order to save room, we index into this array by doing
0019  * X86_BUG_<name> - NCAPINTS*32.
0020  */
0021 extern const char * const x86_bug_flags[NBUGINTS*32];
0022 
0023 #define test_cpu_cap(c, bit)                        \
0024      test_bit(bit, (unsigned long *)((c)->x86_capability))
0025 
0026 /*
0027  * There are 32 bits/features in each mask word.  The high bits
0028  * (selected with (bit>>5) give us the word number and the low 5
0029  * bits give us the bit/feature number inside the word.
0030  * (1UL<<((bit)&31) gives us a mask for the feature_bit so we can
0031  * see if it is set in the mask word.
0032  */
0033 #define CHECK_BIT_IN_MASK_WORD(maskname, word, bit) \
0034     (((bit)>>5)==(word) && (1UL<<((bit)&31) & maskname##word ))
0035 
0036 #define cpu_has(c, bit)                         \
0037      test_cpu_cap(c, bit)
0038 
0039 #define this_cpu_has(bit)                       \
0040     (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :  \
0041      x86_this_cpu_test_bit(bit,                 \
0042         (unsigned long __percpu *)&cpu_info.x86_capability))
0043 
0044 /*
0045  * This macro is for detection of features which need kernel
0046  * infrastructure to be used.  It may *not* directly test the CPU
0047  * itself.  Use the cpu_has() family if you want true runtime
0048  * testing of CPU features, like in hypervisor code where you are
0049  * supporting a possible guest feature where host support for it
0050  * is not relevant.
0051  */
0052 #define cpu_feature_enabled(bit)    \
0053     (__builtin_constant_p(bit) && DISABLED_MASK_BIT_SET(bit) ? 0 : static_cpu_has(bit))
0054 
0055 #define boot_cpu_has(bit)   cpu_has(&boot_cpu_data, bit)
0056 
0057 #define set_cpu_cap(c, bit) set_bit(bit, (unsigned long *)((c)->x86_capability))
0058 
0059 extern void setup_clear_cpu_cap(unsigned int bit);
0060 
0061 #define setup_force_cpu_cap(bit) do { \
0062     set_cpu_cap(&boot_cpu_data, bit);   \
0063     set_bit(bit, (unsigned long *)cpu_caps_set);    \
0064 } while (0)
0065 
0066 #define setup_force_cpu_bug(bit) setup_force_cpu_cap(bit)
0067 
0068 /*
0069  * Static testing of CPU features. Used the same as boot_cpu_has(). It
0070  * statically patches the target code for additional performance. Use
0071  * static_cpu_has() only in fast paths, where every cycle counts. Which
0072  * means that the boot_cpu_has() variant is already fast enough for the
0073  * majority of cases and you should stick to using it as it is generally
0074  * only two instructions: a RIP-relative MOV and a TEST.
0075  */
0076 static __always_inline bool _static_cpu_has(u16 bit)
0077 {
0078     asm_volatile_goto("1: jmp 6f\n"
0079          "2:\n"
0080          ".skip -(((5f-4f) - (2b-1b)) > 0) * "
0081              "((5f-4f) - (2b-1b)),0x90\n"
0082          "3:\n"
0083          ".section .altinstructions,\"a\"\n"
0084          " .long 1b - .\n"      /* src offset */
0085          " .long 4f - .\n"      /* repl offset */
0086          " .word %P[always]\n"      /* always replace */
0087          " .byte 3b - 1b\n"     /* src len */
0088          " .byte 5f - 4f\n"     /* repl len */
0089          " .byte 3b - 2b\n"     /* pad len */
0090          ".previous\n"
0091          ".section .altinstr_replacement,\"ax\"\n"
0092          "4: jmp %l[t_no]\n"
0093          "5:\n"
0094          ".previous\n"
0095          ".section .altinstructions,\"a\"\n"
0096          " .long 1b - .\n"      /* src offset */
0097          " .long 0\n"           /* no replacement */
0098          " .word %P[feature]\n"     /* feature bit */
0099          " .byte 3b - 1b\n"     /* src len */
0100          " .byte 0\n"           /* repl len */
0101          " .byte 0\n"           /* pad len */
0102          ".previous\n"
0103          ".section .altinstr_aux,\"ax\"\n"
0104          "6:\n"
0105          " testb %[bitnum],%[cap_byte]\n"
0106          " jnz %l[t_yes]\n"
0107          " jmp %l[t_no]\n"
0108          ".previous\n"
0109          : : [feature]  "i" (bit),
0110              [always]   "i" (X86_FEATURE_ALWAYS),
0111              [bitnum]   "i" (1 << (bit & 7)),
0112              [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3])
0113          : : t_yes, t_no);
0114 t_yes:
0115     return true;
0116 t_no:
0117     return false;
0118 }
0119 
0120 #define static_cpu_has(bit)                 \
0121 (                               \
0122     __builtin_constant_p(boot_cpu_has(bit)) ?       \
0123         boot_cpu_has(bit) :             \
0124         _static_cpu_has(bit)                \
0125 )
0126 
0127 #define cpu_has_bug(c, bit)     cpu_has(c, (bit))
0128 #define set_cpu_bug(c, bit)     set_cpu_cap(c, (bit))
0129 
0130 #define static_cpu_has_bug(bit)     static_cpu_has((bit))
0131 #define boot_cpu_has_bug(bit)       cpu_has_bug(&boot_cpu_data, (bit))
0132 #define boot_cpu_set_bug(bit)       set_cpu_cap(&boot_cpu_data, (bit))
0133 
0134 #define MAX_CPU_FEATURES        (NCAPINTS * 32)
0135 #define cpu_have_feature        boot_cpu_has
0136 
0137 #define CPU_FEATURE_TYPEFMT     "x86,ven%04Xfam%04Xmod%04X"
0138 #define CPU_FEATURE_TYPEVAL     boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
0139                     boot_cpu_data.x86_model
0140 
0141 #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
0142 #endif /* _ASM_UM_CPUFEATURE_H */