]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/CpuCommonFeaturesLib/FeatureControl.c
UefiCpuPkg/CommonFeature: Skip locking when the feature is disabled
[mirror_edk2.git] / UefiCpuPkg / Library / CpuCommonFeaturesLib / FeatureControl.c
1 /** @file
2 Features in MSR_IA32_FEATURE_CONTROL register.
3
4 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "CpuCommonFeatures.h"
16
17 /**
18 Prepares for the data used by CPU feature detection and initialization.
19
20 @param[in] NumberOfProcessors The number of CPUs in the platform.
21
22 @return Pointer to a buffer of CPU related configuration data.
23
24 @note This service could be called by BSP only.
25 **/
26 VOID *
27 EFIAPI
28 FeatureControlGetConfigData (
29 IN UINTN NumberOfProcessors
30 )
31 {
32 VOID *ConfigData;
33
34 ConfigData = AllocateZeroPool (sizeof (MSR_IA32_FEATURE_CONTROL_REGISTER) * NumberOfProcessors);
35 ASSERT (ConfigData != NULL);
36 return ConfigData;
37 }
38
39 /**
40 Detects if VMX feature supported on current processor.
41
42 @param[in] ProcessorNumber The index of the CPU executing this function.
43 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION
44 structure for the CPU executing this function.
45 @param[in] ConfigData A pointer to the configuration buffer returned
46 by CPU_FEATURE_GET_CONFIG_DATA. NULL if
47 CPU_FEATURE_GET_CONFIG_DATA was not provided in
48 RegisterCpuFeature().
49
50 @retval TRUE VMX feature is supported.
51 @retval FALSE VMX feature is not supported.
52
53 @note This service could be called by BSP/APs.
54 **/
55 BOOLEAN
56 EFIAPI
57 VmxSupport (
58 IN UINTN ProcessorNumber,
59 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,
60 IN VOID *ConfigData OPTIONAL
61 )
62 {
63 MSR_IA32_FEATURE_CONTROL_REGISTER *MsrRegister;
64
65 ASSERT (ConfigData != NULL);
66 MsrRegister = (MSR_IA32_FEATURE_CONTROL_REGISTER *) ConfigData;
67 MsrRegister[ProcessorNumber].Uint64 = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);
68 return (CpuInfo->CpuIdVersionInfoEcx.Bits.VMX == 1);
69 }
70
71 /**
72 Initializes VMX feature to specific state.
73
74 @param[in] ProcessorNumber The index of the CPU executing this function.
75 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION
76 structure for the CPU executing this function.
77 @param[in] ConfigData A pointer to the configuration buffer returned
78 by CPU_FEATURE_GET_CONFIG_DATA. NULL if
79 CPU_FEATURE_GET_CONFIG_DATA was not provided in
80 RegisterCpuFeature().
81 @param[in] State If TRUE, then the VMX feature must be enabled.
82 If FALSE, then the VMX feature must be disabled.
83
84 @retval RETURN_SUCCESS VMX feature is initialized.
85
86 @note This service could be called by BSP only.
87 **/
88 RETURN_STATUS
89 EFIAPI
90 VmxInitialize (
91 IN UINTN ProcessorNumber,
92 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,
93 IN VOID *ConfigData, OPTIONAL
94 IN BOOLEAN State
95 )
96 {
97 MSR_IA32_FEATURE_CONTROL_REGISTER *MsrRegister;
98
99 //
100 // The scope of EnableVmxOutsideSmx bit in the MSR_IA32_FEATURE_CONTROL is core for
101 // below processor type, only program MSR_IA32_FEATURE_CONTROL for thread 0 in each
102 // core.
103 //
104 if (IS_SILVERMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
105 IS_GOLDMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
106 IS_GOLDMONT_PLUS_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {
107 if (CpuInfo->ProcessorInfo.Location.Thread != 0) {
108 return RETURN_SUCCESS;
109 }
110 }
111
112 ASSERT (ConfigData != NULL);
113 MsrRegister = (MSR_IA32_FEATURE_CONTROL_REGISTER *) ConfigData;
114 if (MsrRegister[ProcessorNumber].Bits.Lock == 0) {
115 CPU_REGISTER_TABLE_WRITE_FIELD (
116 ProcessorNumber,
117 Msr,
118 MSR_IA32_FEATURE_CONTROL,
119 MSR_IA32_FEATURE_CONTROL_REGISTER,
120 Bits.EnableVmxOutsideSmx,
121 (State) ? 1 : 0
122 );
123 }
124 return RETURN_SUCCESS;
125 }
126
127 /**
128 Detects if Lock Feature Control Register feature supported on current processor.
129
130 @param[in] ProcessorNumber The index of the CPU executing this function.
131 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION
132 structure for the CPU executing this function.
133 @param[in] ConfigData A pointer to the configuration buffer returned
134 by CPU_FEATURE_GET_CONFIG_DATA. NULL if
135 CPU_FEATURE_GET_CONFIG_DATA was not provided in
136 RegisterCpuFeature().
137
138 @retval TRUE Lock Feature Control Register feature is supported.
139 @retval FALSE Lock Feature Control Register feature is not supported.
140
141 @note This service could be called by BSP/APs.
142 **/
143 BOOLEAN
144 EFIAPI
145 LockFeatureControlRegisterSupport (
146 IN UINTN ProcessorNumber,
147 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,
148 IN VOID *ConfigData OPTIONAL
149 )
150 {
151 MSR_IA32_FEATURE_CONTROL_REGISTER *MsrRegister;
152
153 ASSERT (ConfigData != NULL);
154 MsrRegister = (MSR_IA32_FEATURE_CONTROL_REGISTER *) ConfigData;
155 MsrRegister[ProcessorNumber].Uint64 = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);
156 return TRUE;
157 }
158
159 /**
160 Initializes Lock Feature Control Register feature to specific state.
161
162 @param[in] ProcessorNumber The index of the CPU executing this function.
163 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION
164 structure for the CPU executing this function.
165 @param[in] ConfigData A pointer to the configuration buffer returned
166 by CPU_FEATURE_GET_CONFIG_DATA. NULL if
167 CPU_FEATURE_GET_CONFIG_DATA was not provided in
168 RegisterCpuFeature().
169 @param[in] State If TRUE, then the Lock Feature Control Register feature must be enabled.
170 If FALSE, then the Lock Feature Control Register feature must be disabled.
171
172 @retval RETURN_SUCCESS Lock Feature Control Register feature is initialized.
173
174 @note This service could be called by BSP only.
175 **/
176 RETURN_STATUS
177 EFIAPI
178 LockFeatureControlRegisterInitialize (
179 IN UINTN ProcessorNumber,
180 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,
181 IN VOID *ConfigData, OPTIONAL
182 IN BOOLEAN State
183 )
184 {
185 MSR_IA32_FEATURE_CONTROL_REGISTER *MsrRegister;
186
187 //
188 // When Lock Feature Control Register feature is disabled,
189 // just skip the MSR lock bit setting.
190 // The MSR lock bit is cleared by default and write-once in a boot.
191 //
192 if (!State) {
193 return RETURN_SUCCESS;
194 }
195
196 //
197 // The scope of Lock bit in the MSR_IA32_FEATURE_CONTROL is core for
198 // below processor type, only program MSR_IA32_FEATURE_CONTROL for thread 0 in each
199 // core.
200 //
201 if (IS_SILVERMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
202 IS_GOLDMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
203 IS_GOLDMONT_PLUS_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {
204 if (CpuInfo->ProcessorInfo.Location.Thread != 0) {
205 return RETURN_SUCCESS;
206 }
207 }
208
209 ASSERT (ConfigData != NULL);
210 MsrRegister = (MSR_IA32_FEATURE_CONTROL_REGISTER *) ConfigData;
211 if (MsrRegister[ProcessorNumber].Bits.Lock == 0) {
212 CPU_REGISTER_TABLE_WRITE_FIELD (
213 ProcessorNumber,
214 Msr,
215 MSR_IA32_FEATURE_CONTROL,
216 MSR_IA32_FEATURE_CONTROL_REGISTER,
217 Bits.Lock,
218 1
219 );
220 }
221 return RETURN_SUCCESS;
222 }
223
224 /**
225 Detects if SMX feature supported on current processor.
226
227 @param[in] ProcessorNumber The index of the CPU executing this function.
228 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION
229 structure for the CPU executing this function.
230 @param[in] ConfigData A pointer to the configuration buffer returned
231 by CPU_FEATURE_GET_CONFIG_DATA. NULL if
232 CPU_FEATURE_GET_CONFIG_DATA was not provided in
233 RegisterCpuFeature().
234
235 @retval TRUE SMX feature is supported.
236 @retval FALSE SMX feature is not supported.
237
238 @note This service could be called by BSP/APs.
239 **/
240 BOOLEAN
241 EFIAPI
242 SmxSupport (
243 IN UINTN ProcessorNumber,
244 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,
245 IN VOID *ConfigData OPTIONAL
246 )
247 {
248 MSR_IA32_FEATURE_CONTROL_REGISTER *MsrRegister;
249
250 ASSERT (ConfigData != NULL);
251 MsrRegister = (MSR_IA32_FEATURE_CONTROL_REGISTER *) ConfigData;
252 MsrRegister[ProcessorNumber].Uint64 = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);
253 return (CpuInfo->CpuIdVersionInfoEcx.Bits.SMX == 1);
254 }
255
256 /**
257 Initializes SMX feature to specific state.
258
259 @param[in] ProcessorNumber The index of the CPU executing this function.
260 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION
261 structure for the CPU executing this function.
262 @param[in] ConfigData A pointer to the configuration buffer returned
263 by CPU_FEATURE_GET_CONFIG_DATA. NULL if
264 CPU_FEATURE_GET_CONFIG_DATA was not provided in
265 RegisterCpuFeature().
266 @param[in] State If TRUE, then SMX feature must be enabled.
267 If FALSE, then SMX feature must be disabled.
268
269 @retval RETURN_SUCCESS SMX feature is initialized.
270 @retval RETURN_UNSUPPORTED VMX not initialized.
271
272 @note This service could be called by BSP only.
273 **/
274 RETURN_STATUS
275 EFIAPI
276 SmxInitialize (
277 IN UINTN ProcessorNumber,
278 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,
279 IN VOID *ConfigData, OPTIONAL
280 IN BOOLEAN State
281 )
282 {
283 MSR_IA32_FEATURE_CONTROL_REGISTER *MsrRegister;
284 RETURN_STATUS Status;
285
286 //
287 // The scope of Lock bit in the MSR_IA32_FEATURE_CONTROL is core for
288 // below processor type, only program MSR_IA32_FEATURE_CONTROL for thread 0 in each
289 // core.
290 //
291 if (IS_GOLDMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
292 IS_GOLDMONT_PLUS_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {
293 if (CpuInfo->ProcessorInfo.Location.Thread != 0) {
294 return RETURN_SUCCESS;
295 }
296 }
297
298 Status = RETURN_SUCCESS;
299
300 if (State && (!IsCpuFeatureInSetting (CPU_FEATURE_VMX))) {
301 DEBUG ((DEBUG_WARN, "Warning :: Can't enable SMX feature when VMX feature not enabled, disable it.\n"));
302 State = FALSE;
303 Status = RETURN_UNSUPPORTED;
304 }
305
306 ASSERT (ConfigData != NULL);
307 MsrRegister = (MSR_IA32_FEATURE_CONTROL_REGISTER *) ConfigData;
308 if (MsrRegister[ProcessorNumber].Bits.Lock == 0) {
309 CPU_REGISTER_TABLE_WRITE_FIELD (
310 ProcessorNumber,
311 Msr,
312 MSR_IA32_FEATURE_CONTROL,
313 MSR_IA32_FEATURE_CONTROL_REGISTER,
314 Bits.SenterLocalFunctionEnables,
315 (State) ? 0x7F : 0
316 );
317
318 CPU_REGISTER_TABLE_WRITE_FIELD (
319 ProcessorNumber,
320 Msr,
321 MSR_IA32_FEATURE_CONTROL,
322 MSR_IA32_FEATURE_CONTROL_REGISTER,
323 Bits.SenterGlobalEnable,
324 (State) ? 1 : 0
325 );
326
327 CPU_REGISTER_TABLE_WRITE_FIELD (
328 ProcessorNumber,
329 Msr,
330 MSR_IA32_FEATURE_CONTROL,
331 MSR_IA32_FEATURE_CONTROL_REGISTER,
332 Bits.EnableVmxInsideSmx,
333 (State) ? 1 : 0
334 );
335 }
336 return Status;
337 }