1
2#ifndef _ASM_UM_CPUFEATURE_H
3#define _ASM_UM_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
12extern const char * const x86_cap_flags[NCAPINTS*32];
13extern const char * const x86_power_flags[32];
14#define X86_CAP_FMT "%s"
15#define x86_cap_flag(flag) x86_cap_flags[flag]
16
17
18
19
20
21extern const char * const x86_bug_flags[NBUGINTS*32];
22
23#define test_cpu_cap(c, bit) \
24 test_bit(bit, (unsigned long *)((c)->x86_capability))
25
26
27
28
29
30
31
32
33#define CHECK_BIT_IN_MASK_WORD(maskname, word, bit) \
34 (((bit)>>5)==(word) && (1UL<<((bit)&31) & maskname##word ))
35
36#define cpu_has(c, bit) \
37 test_cpu_cap(c, bit)
38
39#define this_cpu_has(bit) \
40 (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \
41 x86_this_cpu_test_bit(bit, \
42 (unsigned long __percpu *)&cpu_info.x86_capability))
43
44
45
46
47
48
49
50
51
52#define cpu_feature_enabled(bit) \
53 (__builtin_constant_p(bit) && DISABLED_MASK_BIT_SET(bit) ? 0 : static_cpu_has(bit))
54
55#define boot_cpu_has(bit) cpu_has(&boot_cpu_data, bit)
56
57#define set_cpu_cap(c, bit) set_bit(bit, (unsigned long *)((c)->x86_capability))
58
59extern void setup_clear_cpu_cap(unsigned int bit);
60
61#define setup_force_cpu_cap(bit) do { \
62 set_cpu_cap(&boot_cpu_data, bit); \
63 set_bit(bit, (unsigned long *)cpu_caps_set); \
64} while (0)
65
66#define setup_force_cpu_bug(bit) setup_force_cpu_cap(bit)
67
68#if defined(__clang__) && !defined(CONFIG_CC_HAS_ASM_GOTO)
69
70
71
72
73
74#ifndef __BPF_TRACING__
75#warning "Compiler lacks ASM_GOTO support. Add -D __BPF_TRACING__ to your compiler arguments"
76#endif
77
78#define static_cpu_has(bit) boot_cpu_has(bit)
79
80#else
81
82
83
84
85
86
87
88
89
90static __always_inline bool _static_cpu_has(u16 bit)
91{
92 asm_volatile_goto("1: jmp 6f\n"
93 "2:\n"
94 ".skip -(((5f-4f) - (2b-1b)) > 0) * "
95 "((5f-4f) - (2b-1b)),0x90\n"
96 "3:\n"
97 ".section .altinstructions,\"a\"\n"
98 " .long 1b - .\n"
99 " .long 4f - .\n"
100 " .word %P[always]\n"
101 " .byte 3b - 1b\n"
102 " .byte 5f - 4f\n"
103 " .byte 3b - 2b\n"
104 ".previous\n"
105 ".section .altinstr_replacement,\"ax\"\n"
106 "4: jmp %l[t_no]\n"
107 "5:\n"
108 ".previous\n"
109 ".section .altinstructions,\"a\"\n"
110 " .long 1b - .\n"
111 " .long 0\n"
112 " .word %P[feature]\n"
113 " .byte 3b - 1b\n"
114 " .byte 0\n"
115 " .byte 0\n"
116 ".previous\n"
117 ".section .altinstr_aux,\"ax\"\n"
118 "6:\n"
119 " testb %[bitnum],%[cap_byte]\n"
120 " jnz %l[t_yes]\n"
121 " jmp %l[t_no]\n"
122 ".previous\n"
123 : : [feature] "i" (bit),
124 [always] "i" (X86_FEATURE_ALWAYS),
125 [bitnum] "i" (1 << (bit & 7)),
126 [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3])
127 : : t_yes, t_no);
128t_yes:
129 return true;
130t_no:
131 return false;
132}
133
134#define static_cpu_has(bit) \
135( \
136 __builtin_constant_p(boot_cpu_has(bit)) ? \
137 boot_cpu_has(bit) : \
138 _static_cpu_has(bit) \
139)
140#endif
141
142#define cpu_has_bug(c, bit) cpu_has(c, (bit))
143#define set_cpu_bug(c, bit) set_cpu_cap(c, (bit))
144
145#define static_cpu_has_bug(bit) static_cpu_has((bit))
146#define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit))
147#define boot_cpu_set_bug(bit) set_cpu_cap(&boot_cpu_data, (bit))
148
149#define MAX_CPU_FEATURES (NCAPINTS * 32)
150#define cpu_have_feature boot_cpu_has
151
152#define CPU_FEATURE_TYPEFMT "x86,ven%04Xfam%04Xmod%04X"
153#define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
154 boot_cpu_data.x86_model
155
156#endif
157#endif
158