1 /** @file
2   Machine Check features.
3 
4   Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "CpuCommonFeatures.h"
10 
11 /**
12   Detects if Machine Check Exception feature supported on current processor.
13 
14   @param[in]  ProcessorNumber  The index of the CPU executing this function.
15   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
16                                structure for the CPU executing this function.
17   @param[in]  ConfigData       A pointer to the configuration buffer returned
18                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
19                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
20                                RegisterCpuFeature().
21 
22   @retval TRUE     Machine Check Exception feature is supported.
23   @retval FALSE    Machine Check Exception feature is not supported.
24 
25   @note This service could be called by BSP/APs.
26 **/
27 BOOLEAN
28 EFIAPI
VmxSupport(IN UINTN ProcessorNumber,IN REGISTER_CPU_FEATURE_INFORMATION * CpuInfo,IN VOID * ConfigData OPTIONAL)29 MceSupport (
30   IN UINTN                             ProcessorNumber,
31   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
32   IN VOID                              *ConfigData  OPTIONAL
33   )
34 {
35   return (CpuInfo->CpuIdVersionInfoEdx.Bits.MCE == 1);
36 }
37 
38 /**
39   Initializes Machine Check Exception feature to specific state.
40 
41   @param[in]  ProcessorNumber  The index of the CPU executing this function.
42   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
43                                structure for the CPU executing this function.
44   @param[in]  ConfigData       A pointer to the configuration buffer returned
45                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
46                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
47                                RegisterCpuFeature().
48   @param[in]  State            If TRUE, then the Machine Check Exception feature must be enabled.
49                                If FALSE, then the Machine Check Exception feature must be disabled.
50 
51   @retval RETURN_SUCCESS       Machine Check Exception feature is initialized.
52 
53   @note This service could be called by BSP only.
54 **/
55 RETURN_STATUS
56 EFIAPI
VmxInitialize(IN UINTN ProcessorNumber,IN REGISTER_CPU_FEATURE_INFORMATION * CpuInfo,IN VOID * ConfigData,OPTIONAL IN BOOLEAN State)57 MceInitialize (
58   IN UINTN                             ProcessorNumber,
59   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
60   IN VOID                              *ConfigData,  OPTIONAL
61   IN BOOLEAN                           State
62   )
63 {
64   //
65   // Set MCE bit in CR4
66   //
67   CPU_REGISTER_TABLE_WRITE_FIELD (
68     ProcessorNumber,
69     ControlRegister,
70     4,
71     IA32_CR4,
72     Bits.MCE,
73     (State) ? 1 : 0
74     );
75   return RETURN_SUCCESS;
76 }
77 
78 /**
79   Detects if Machine Check Architecture feature supported on current processor.
80 
81   @param[in]  ProcessorNumber  The index of the CPU executing this function.
82   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
83                                structure for the CPU executing this function.
84   @param[in]  ConfigData       A pointer to the configuration buffer returned
85                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
86                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
87                                RegisterCpuFeature().
88 
89   @retval TRUE     Machine Check Architecture feature is supported.
90   @retval FALSE    Machine Check Architecture feature is not supported.
91 
92   @note This service could be called by BSP/APs.
93 **/
94 BOOLEAN
95 EFIAPI
96 McaSupport (
97   IN UINTN                             ProcessorNumber,
98   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
99   IN VOID                              *ConfigData  OPTIONAL
100   )
101 {
102   if (!MceSupport (ProcessorNumber, CpuInfo, ConfigData)) {
103     return FALSE;
104   }
105   return (CpuInfo->CpuIdVersionInfoEdx.Bits.MCA == 1);
106 }
LockFeatureControlRegisterSupport(IN UINTN ProcessorNumber,IN REGISTER_CPU_FEATURE_INFORMATION * CpuInfo,IN VOID * ConfigData OPTIONAL)107 
108 /**
109   Initializes Machine Check Architecture feature to specific state.
110 
111   @param[in]  ProcessorNumber  The index of the CPU executing this function.
112   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
113                                structure for the CPU executing this function.
114   @param[in]  ConfigData       A pointer to the configuration buffer returned
115                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
116                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
117                                RegisterCpuFeature().
118   @param[in]  State            If TRUE, then the Machine Check Architecture feature must be enabled.
119                                If FALSE, then the Machine Check Architecture feature must be disabled.
120 
121   @retval RETURN_SUCCESS       Machine Check Architecture feature is initialized.
122 
123   @note This service could be called by BSP only.
124 **/
125 RETURN_STATUS
126 EFIAPI
127 McaInitialize (
128   IN UINTN                             ProcessorNumber,
129   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
130   IN VOID                              *ConfigData,  OPTIONAL
131   IN BOOLEAN                           State
132   )
133 {
134   MSR_IA32_MCG_CAP_REGISTER  McgCap;
135   UINT32                     BankIndex;
136 
137   //
138   // The scope of MSR_IA32_MC*_CTL/MSR_IA32_MC*_STATUS is core for below processor type, only program
139   // MSR_IA32_MC*_CTL/MSR_IA32_MC*_STATUS for thread 0 in each core.
140   //
141   if (IS_ATOM_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
142       IS_SILVERMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
143       IS_SANDY_BRIDGE_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
144       IS_SKYLAKE_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
145       IS_XEON_PHI_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
146       IS_PENTIUM_4_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
147       IS_CORE_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {
148     if (CpuInfo->ProcessorInfo.Location.Thread != 0) {
149       return RETURN_SUCCESS;
150     }
151   }
152 
153   //
154   // The scope of MSR_IA32_MC*_CTL/MSR_IA32_MC*_STATUS is package for below processor type, only program
155   // MSR_IA32_MC*_CTL/MSR_IA32_MC*_STATUS for thread 0 core 0 in each package.
156   //
157   if (IS_NEHALEM_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {
158     if ((CpuInfo->ProcessorInfo.Location.Thread != 0) || (CpuInfo->ProcessorInfo.Location.Core != 0)) {
159       return RETURN_SUCCESS;
160     }
161   }
162 
163   if (State) {
164     McgCap.Uint64 = AsmReadMsr64 (MSR_IA32_MCG_CAP);
165     for (BankIndex = 0; BankIndex < (UINT32) McgCap.Bits.Count; BankIndex++) {
166       CPU_REGISTER_TABLE_WRITE64 (
167         ProcessorNumber,
168         Msr,
169         MSR_IA32_MC0_CTL + BankIndex * 4,
170         MAX_UINT64
171         );
172     }
173 
174     if (PcdGetBool (PcdIsPowerOnReset)) {
175       for (BankIndex = 0; BankIndex < (UINTN) McgCap.Bits.Count; BankIndex++) {
176         CPU_REGISTER_TABLE_WRITE64 (
177           ProcessorNumber,
178           Msr,
179           MSR_IA32_MC0_STATUS + BankIndex * 4,
180           0
181           );
182       }
183     }
184   }
185 
186   return RETURN_SUCCESS;
187 }
188 
189 /**
190   Detects if IA32_MCG_CTL feature supported on current processor.
191 
192   @param[in]  ProcessorNumber  The index of the CPU executing this function.
193   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
194                                structure for the CPU executing this function.
195   @param[in]  ConfigData       A pointer to the configuration buffer returned
196                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
197                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
198                                RegisterCpuFeature().
199 
200   @retval TRUE     IA32_MCG_CTL feature is supported.
201   @retval FALSE    IA32_MCG_CTL feature is not supported.
202 
203   @note This service could be called by BSP/APs.
204 **/
205 BOOLEAN
206 EFIAPI
207 McgCtlSupport (
208   IN UINTN                             ProcessorNumber,
209   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
210   IN VOID                              *ConfigData  OPTIONAL
211   )
212 {
213   MSR_IA32_MCG_CAP_REGISTER  McgCap;
SmxInitialize(IN UINTN ProcessorNumber,IN REGISTER_CPU_FEATURE_INFORMATION * CpuInfo,IN VOID * ConfigData,OPTIONAL IN BOOLEAN State)214 
215   if (!McaSupport (ProcessorNumber, CpuInfo, ConfigData)) {
216     return FALSE;
217   }
218   McgCap.Uint64 = AsmReadMsr64 (MSR_IA32_MCG_CAP);
219   return (McgCap.Bits.MCG_CTL_P == 1);
220 }
221 
222 /**
223   Initializes IA32_MCG_CTL feature to specific state.
224 
225   @param[in]  ProcessorNumber  The index of the CPU executing this function.
226   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
227                                structure for the CPU executing this function.
228   @param[in]  ConfigData       A pointer to the configuration buffer returned
229                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
230                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
231                                RegisterCpuFeature().
232   @param[in]  State            If TRUE, then the IA32_MCG_CTL feature must be enabled.
233                                If FALSE, then the IA32_MCG_CTL feature must be disabled.
234 
235   @retval RETURN_SUCCESS       IA32_MCG_CTL feature is initialized.
236 
237   @note This service could be called by BSP only.
238 **/
239 RETURN_STATUS
240 EFIAPI
241 McgCtlInitialize (
242   IN UINTN                             ProcessorNumber,
243   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
244   IN VOID                              *ConfigData,  OPTIONAL
245   IN BOOLEAN                           State
246   )
247 {
248   CPU_REGISTER_TABLE_WRITE64 (
249     ProcessorNumber,
250     Msr,
251     MSR_IA32_MCG_CTL,
252     (State)? MAX_UINT64 : 0
253     );
254   return RETURN_SUCCESS;
255 }
256 
257 /**
258   Detects if Local machine check exception feature supported on current
259   processor.
260 
261   @param[in]  ProcessorNumber  The index of the CPU executing this function.
262   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
263                                structure for the CPU executing this function.
264   @param[in]  ConfigData       A pointer to the configuration buffer returned
265                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
266                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
267                                RegisterCpuFeature().
268 
269   @retval TRUE     Local machine check exception feature is supported.
270   @retval FALSE    Local machine check exception feature is not supported.
271 
272   @note This service could be called by BSP/APs.
273 **/
274 BOOLEAN
275 EFIAPI
276 LmceSupport (
277   IN UINTN                             ProcessorNumber,
278   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
279   IN VOID                              *ConfigData  OPTIONAL
280   )
281 {
282   MSR_IA32_MCG_CAP_REGISTER    McgCap;
283 
284   if (!McaSupport (ProcessorNumber, CpuInfo, ConfigData)) {
285     return FALSE;
286   }
287 
288   McgCap.Uint64 = AsmReadMsr64 (MSR_IA32_MCG_CAP);
289   if (ProcessorNumber == 0) {
290     DEBUG ((DEBUG_INFO, "LMCE enable = %x\n", (BOOLEAN) (McgCap.Bits.MCG_LMCE_P != 0)));
291   }
292   return (BOOLEAN) (McgCap.Bits.MCG_LMCE_P != 0);
293 }
294 
295 /**
296   Initializes Local machine check exception feature to specific state.
297 
298   @param[in]  ProcessorNumber  The index of the CPU executing this function.
299   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
300                                structure for the CPU executing this function.
301   @param[in]  ConfigData       A pointer to the configuration buffer returned
302                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
303                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
304                                RegisterCpuFeature().
305   @param[in]  State            If TRUE, then the Local machine check exception
306                                feature must be enabled.
307                                If FALSE, then the Local machine check exception
308                                feature must be disabled.
309 
310   @retval RETURN_SUCCESS       Local machine check exception feature is initialized.
311 
312 **/
313 RETURN_STATUS
314 EFIAPI
315 LmceInitialize (
316   IN UINTN                             ProcessorNumber,
317   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
318   IN VOID                              *ConfigData,  OPTIONAL
319   IN BOOLEAN                           State
320   )
321 {
322   //
323   // The scope of LcmeOn bit in the MSR_IA32_MISC_ENABLE is core for below processor type, only program
324   // MSR_IA32_MISC_ENABLE for thread 0 in each core.
325   //
326   if (IS_SILVERMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
327       IS_GOLDMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel) ||
328       IS_PENTIUM_4_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {
329     if (CpuInfo->ProcessorInfo.Location.Thread != 0) {
330       return RETURN_SUCCESS;
331     }
332   }
333 
334   CPU_REGISTER_TABLE_TEST_THEN_WRITE_FIELD (
335     ProcessorNumber,
336     Msr,
337     MSR_IA32_FEATURE_CONTROL,
338     MSR_IA32_FEATURE_CONTROL_REGISTER,
339     Bits.LmceOn,
340     (State) ? 1 : 0
341     );
342 
343   return RETURN_SUCCESS;
344 }
345