]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/CpuCommonFeaturesLib/FeatureControl.c
8c1eb5eb4f80a1996b177a8b2ee4d559a8598d23
[mirror_edk2.git] / UefiCpuPkg / Library / CpuCommonFeaturesLib / FeatureControl.c
1 /** @file
2 Features in MSR_IA32_FEATURE_CONTROL register.
3
4 Copyright (c) 2017, 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 // The scope of Lock bit in the MSR_IA32_FEATURE_CONTROL is core for
189 // below processor type, only program MSR_IA32_FEATURE_CONTROL for thread 0 in each
190 // core.
191 //
192 if (IS_SILVERMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
193 IS_GOLDMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
194 IS_GOLDMONT_PLUS_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {
195 if (CpuInfo->ProcessorInfo.Location.Thread != 0) {
196 return RETURN_SUCCESS;
197 }
198 }
199
200 ASSERT (ConfigData != NULL);
201 MsrRegister = (MSR_IA32_FEATURE_CONTROL_REGISTER *) ConfigData;
202 if (MsrRegister[ProcessorNumber].Bits.Lock == 0) {
203 CPU_REGISTER_TABLE_WRITE_FIELD (
204 ProcessorNumber,
205 Msr,
206 MSR_IA32_FEATURE_CONTROL,
207 MSR_IA32_FEATURE_CONTROL_REGISTER,
208 Bits.Lock,
209 1
210 );
211 }
212 return RETURN_SUCCESS;
213 }
214
215 /**
216 Detects if SMX feature supported on current processor.
217
218 @param[in] ProcessorNumber The index of the CPU executing this function.
219 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION
220 structure for the CPU executing this function.
221 @param[in] ConfigData A pointer to the configuration buffer returned
222 by CPU_FEATURE_GET_CONFIG_DATA. NULL if
223 CPU_FEATURE_GET_CONFIG_DATA was not provided in
224 RegisterCpuFeature().
225
226 @retval TRUE SMX feature is supported.
227 @retval FALSE SMX feature is not supported.
228
229 @note This service could be called by BSP/APs.
230 **/
231 BOOLEAN
232 EFIAPI
233 SmxSupport (
234 IN UINTN ProcessorNumber,
235 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,
236 IN VOID *ConfigData OPTIONAL
237 )
238 {
239 MSR_IA32_FEATURE_CONTROL_REGISTER *MsrRegister;
240
241 ASSERT (ConfigData != NULL);
242 MsrRegister = (MSR_IA32_FEATURE_CONTROL_REGISTER *) ConfigData;
243 MsrRegister[ProcessorNumber].Uint64 = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);
244 return (CpuInfo->CpuIdVersionInfoEcx.Bits.SMX == 1);
245 }
246
247 /**
248 Initializes SMX feature to specific state.
249
250 @param[in] ProcessorNumber The index of the CPU executing this function.
251 @param[in] CpuInfo A pointer to the REGISTER_CPU_FEATURE_INFORMATION
252 structure for the CPU executing this function.
253 @param[in] ConfigData A pointer to the configuration buffer returned
254 by CPU_FEATURE_GET_CONFIG_DATA. NULL if
255 CPU_FEATURE_GET_CONFIG_DATA was not provided in
256 RegisterCpuFeature().
257 @param[in] State If TRUE, then SMX feature must be enabled.
258 If FALSE, then SMX feature must be disabled.
259
260 @retval RETURN_SUCCESS SMX feature is initialized.
261 @retval RETURN_UNSUPPORTED VMX not initialized.
262
263 @note This service could be called by BSP only.
264 **/
265 RETURN_STATUS
266 EFIAPI
267 SmxInitialize (
268 IN UINTN ProcessorNumber,
269 IN REGISTER_CPU_FEATURE_INFORMATION *CpuInfo,
270 IN VOID *ConfigData, OPTIONAL
271 IN BOOLEAN State
272 )
273 {
274 MSR_IA32_FEATURE_CONTROL_REGISTER *MsrRegister;
275 RETURN_STATUS Status;
276
277 //
278 // The scope of Lock bit in the MSR_IA32_FEATURE_CONTROL is core for
279 // below processor type, only program MSR_IA32_FEATURE_CONTROL for thread 0 in each
280 // core.
281 //
282 if (IS_GOLDMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
283 IS_GOLDMONT_PLUS_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {
284 if (CpuInfo->ProcessorInfo.Location.Thread != 0) {
285 return RETURN_SUCCESS;
286 }
287 }
288
289 Status = RETURN_SUCCESS;
290
291 if (State && (!IsCpuFeatureInSetting (CPU_FEATURE_VMX))) {
292 DEBUG ((DEBUG_WARN, "Warning :: Can't enable SMX feature when VMX feature not enabled, disable it.\n"));
293 State = FALSE;
294 Status = RETURN_UNSUPPORTED;
295 }
296
297 ASSERT (ConfigData != NULL);
298 MsrRegister = (MSR_IA32_FEATURE_CONTROL_REGISTER *) ConfigData;
299 if (MsrRegister[ProcessorNumber].Bits.Lock == 0) {
300 CPU_REGISTER_TABLE_WRITE_FIELD (
301 ProcessorNumber,
302 Msr,
303 MSR_IA32_FEATURE_CONTROL,
304 MSR_IA32_FEATURE_CONTROL_REGISTER,
305 Bits.SenterLocalFunctionEnables,
306 (State) ? 0x7F : 0
307 );
308
309 CPU_REGISTER_TABLE_WRITE_FIELD (
310 ProcessorNumber,
311 Msr,
312 MSR_IA32_FEATURE_CONTROL,
313 MSR_IA32_FEATURE_CONTROL_REGISTER,
314 Bits.SenterGlobalEnable,
315 (State) ? 1 : 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.EnableVmxInsideSmx,
324 (State) ? 1 : 0
325 );
326 }
327 return Status;
328 }