@@ -73,39 +73,84 @@ DEFINE_CPU_DATA(int, state);
73
73
#define VAPIC_FEATURE_VX2APIC_MODE (1 << 5)
74
74
75
75
struct cpu_capability {
76
- bool tsc_adjust_supported ;
77
- bool ibrs_ibpb_supported ;
78
- bool stibp_supported ;
79
76
uint8_t vapic_features ;
80
- bool monitor_supported ;
81
77
};
82
78
static struct cpu_capability cpu_caps ;
83
79
80
+ struct cpuinfo_x86 boot_cpu_data ;
81
+
84
82
static void vapic_cap_detect (void );
85
- static void monitor_cap_detect (void );
86
83
static void cpu_set_logical_id (uint32_t logical_id );
87
84
static void print_hv_banner (void );
88
- static inline bool get_monitor_cap (void );
89
85
int cpu_find_logical_id (uint32_t lapic_id );
90
86
#ifndef CONFIG_EFI_STUB
91
87
static void start_cpus ();
92
88
#endif
93
89
static void pcpu_sync_sleep (unsigned long * sync , int mask_bit );
94
90
int ibrs_type ;
95
- static void check_cpu_capability (void )
91
+
92
+ static inline bool get_tsc_adjust_cap (void )
93
+ {
94
+ return !!(boot_cpu_data .cpuid_leaves [FEAT_7_0_EBX ] & CPUID_EBX_TSC_ADJ );
95
+ }
96
+
97
+ static inline bool get_ibrs_ibpb_cap (void )
98
+ {
99
+ return !!(boot_cpu_data .cpuid_leaves [FEAT_7_0_EDX ] &
100
+ CPUID_EDX_IBRS_IBPB );
101
+ }
102
+
103
+ static inline bool get_stibp_cap (void )
104
+ {
105
+ return !!(boot_cpu_data .cpuid_leaves [FEAT_7_0_EDX ] & CPUID_EDX_STIBP );
106
+ }
107
+
108
+ static inline bool get_monitor_cap (void )
109
+ {
110
+ if (boot_cpu_data .cpuid_leaves [FEAT_1_ECX ] & CPUID_ECX_MONITOR ) {
111
+ /* don't use monitor for CPU (family: 0x6 model: 0x5c)
112
+ * in hypervisor, but still expose it to the guests and
113
+ * let them handle it correctly
114
+ */
115
+ if (boot_cpu_data .x86 != 0x6 || boot_cpu_data .x86_model != 0x5c )
116
+ return true;
117
+ }
118
+
119
+ return false;
120
+ }
121
+
122
+ inline bool get_vmx_cap (void )
96
123
{
97
- uint32_t eax , ebx , ecx , edx ;
124
+ return !!(boot_cpu_data .cpuid_leaves [FEAT_1_ECX ] & CPUID_ECX_VMX );
125
+ }
126
+
127
+ static void get_cpu_capabilities (void )
128
+ {
129
+ uint32_t eax , unused ;
130
+ uint32_t family , model ;
131
+
132
+ cpuid (CPUID_FEATURES , & eax , & unused ,
133
+ & boot_cpu_data .cpuid_leaves [FEAT_1_ECX ],
134
+ & boot_cpu_data .cpuid_leaves [FEAT_1_EDX ]);
135
+ family = (eax >> 8 ) & 0xff ;
136
+ if (family == 0xF )
137
+ family += (eax >> 20 ) & 0xff ;
138
+ boot_cpu_data .x86 = family ;
139
+
140
+ model = (eax >> 4 ) & 0xf ;
141
+ if (family >= 0x06 )
142
+ model += ((eax >> 16 ) & 0xf ) << 4 ;
143
+ boot_cpu_data .x86_model = model ;
98
144
99
- memset (& cpu_caps , 0 , sizeof (struct cpu_capability ));
100
145
101
- cpuid (CPUID_EXTEND_FEATURE , & eax , & ebx , & ecx , & edx );
146
+ cpuid (CPUID_EXTEND_FEATURE , & unused ,
147
+ & boot_cpu_data .cpuid_leaves [FEAT_7_0_EBX ],
148
+ & boot_cpu_data .cpuid_leaves [FEAT_7_0_ECX ],
149
+ & boot_cpu_data .cpuid_leaves [FEAT_7_0_EDX ]);
102
150
103
- cpu_caps .tsc_adjust_supported = (ebx & CPUID_EBX_TSC_ADJ ) ?
104
- (true) : (false);
105
- cpu_caps .ibrs_ibpb_supported = (edx & CPUID_EDX_IBRS_IBPB ) ?
106
- (true) : (false);
107
- cpu_caps .stibp_supported = (edx & CPUID_EDX_STIBP ) ?
108
- (true) : (false);
151
+ cpuid (CPUID_EXTEND_FUNCTION_1 , & unused , & unused ,
152
+ & boot_cpu_data .cpuid_leaves [FEAT_8000_0001_ECX ],
153
+ & boot_cpu_data .cpuid_leaves [FEAT_8000_0001_EDX ]);
109
154
110
155
/* For speculation defence.
111
156
* The default way is to set IBRS at vmexit and then do IBPB at vcpu
@@ -123,29 +168,14 @@ static void check_cpu_capability(void)
123
168
* should be set all the time instead of relying on retpoline
124
169
*/
125
170
#ifndef CONFIG_RETPOLINE
126
- if (cpu_caps . ibrs_ibpb_supported ) {
171
+ if (get_ibrs_ibpb_cap () ) {
127
172
ibrs_type = IBRS_RAW ;
128
- if (cpu_caps . stibp_supported )
173
+ if (get_stibp_cap () )
129
174
ibrs_type = IBRS_OPT ;
130
175
}
131
176
#endif
132
177
}
133
178
134
- bool check_tsc_adjust_support (void )
135
- {
136
- return cpu_caps .tsc_adjust_supported ;
137
- }
138
-
139
- bool check_ibrs_ibpb_support (void )
140
- {
141
- return cpu_caps .ibrs_ibpb_supported ;
142
- }
143
-
144
- bool check_stibp_support (void )
145
- {
146
- return cpu_caps .stibp_supported ;
147
- }
148
-
149
179
static void alloc_phy_cpu_data (int pcpu_num )
150
180
{
151
181
phy_cpu_num = pcpu_num ;
@@ -313,12 +343,10 @@ void bsp_boot_init(void)
313
343
set_fs_base ();
314
344
#endif
315
345
316
- check_cpu_capability ();
346
+ get_cpu_capabilities ();
317
347
318
348
vapic_cap_detect ();
319
349
320
- monitor_cap_detect ();
321
-
322
350
/* Set state for this CPU to initializing */
323
351
cpu_set_current_state (CPU_BOOT_ID , CPU_STATE_INITIALIZING );
324
352
@@ -361,7 +389,7 @@ void bsp_boot_init(void)
361
389
pr_dbg ("Core %d is up" , CPU_BOOT_ID );
362
390
363
391
/* Warn for security feature not ready */
364
- if (!check_ibrs_ibpb_support () && !check_stibp_support ()) {
392
+ if (!get_ibrs_ibpb_cap () && !get_stibp_cap ()) {
365
393
pr_fatal ("SECURITY WARNING!!!!!!" );
366
394
pr_fatal ("Please apply the latest CPU uCode patch!" );
367
395
}
@@ -654,40 +682,3 @@ bool is_vapic_virt_reg_supported(void)
654
682
{
655
683
return ((cpu_caps .vapic_features & VAPIC_FEATURE_VIRT_REG ) != 0 );
656
684
}
657
-
658
- static void monitor_cap_detect (void )
659
- {
660
- uint32_t eax , ebx , ecx , edx ;
661
- uint32_t family ;
662
- uint32_t model ;
663
-
664
- /* Run CPUID to determine if MONITOR support available */
665
- cpuid (CPUID_FEATURES , & eax , & ebx , & ecx , & edx );
666
-
667
- /* See if MONITOR feature bit is set in ECX */
668
- if (ecx & CPUID_ECX_MONITOR )
669
- cpu_caps .monitor_supported = true;
670
-
671
- /* don't use monitor for CPU (family: 0x6 model: 0x5c)
672
- * in hypervisor, but still expose it to the guests and
673
- * let them handle it correctly
674
- */
675
- family = (eax >> 8 ) & 0xff ;
676
- if (family == 0xF )
677
- family += (eax >> 20 ) & 0xff ;
678
-
679
- model = (eax >> 4 ) & 0xf ;
680
- if (family >= 0x06 )
681
- model += ((eax >> 16 ) & 0xf ) << 4 ;
682
-
683
- if (cpu_caps .monitor_supported &&
684
- (family == 0x06 ) &&
685
- (model == 0x5c )) {
686
- cpu_caps .monitor_supported = false;
687
- }
688
- }
689
-
690
- static inline bool get_monitor_cap (void )
691
- {
692
- return cpu_caps .monitor_supported ;
693
- }
0 commit comments