1 /** @file
2 The CPU specific programming for PiSmmCpuDxeSmm module.
3 
4 Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <PiSmm.h>
10 #include <Library/SmmCpuFeaturesLib.h>
11 #include <Library/BaseLib.h>
12 #include <Library/MtrrLib.h>
13 #include <Library/PcdLib.h>
14 #include <Library/MemoryAllocationLib.h>
15 #include <Library/DebugLib.h>
16 #include <Register/Intel/Cpuid.h>
17 #include <Register/Intel/SmramSaveStateMap.h>
18 
19 //
20 // Machine Specific Registers (MSRs)
21 //
22 #define  SMM_FEATURES_LIB_IA32_MTRR_CAP            0x0FE
23 #define  SMM_FEATURES_LIB_IA32_FEATURE_CONTROL     0x03A
24 #define  SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE       0x1F2
25 #define  SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK       0x1F3
26 #define  SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE  0x0A0
27 #define  SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK  0x0A1
28 #define    EFI_MSR_SMRR_MASK                       0xFFFFF000
29 #define    EFI_MSR_SMRR_PHYS_MASK_VALID            BIT11
30 #define  SMM_FEATURES_LIB_SMM_FEATURE_CONTROL      0x4E0
31 
32 //
33 // MSRs required for configuration of SMM Code Access Check
34 //
35 #define SMM_FEATURES_LIB_IA32_MCA_CAP              0x17D
36 #define   SMM_CODE_ACCESS_CHK_BIT                  BIT58
37 
38 /**
39   Internal worker function that is called to complete CPU initialization at the
40   end of SmmCpuFeaturesInitializeProcessor().
41 
42 **/
43 VOID
44 FinishSmmCpuFeaturesInitializeProcessor (
45   VOID
46   );
47 
48 //
49 // Set default value to assume SMRR is not supported
50 //
51 BOOLEAN  mSmrrSupported = FALSE;
52 
53 //
54 // Set default value to assume MSR_SMM_FEATURE_CONTROL is not supported
55 //
56 BOOLEAN  mSmmFeatureControlSupported = FALSE;
57 
58 //
59 // Set default value to assume IA-32 Architectural MSRs are used
60 //
61 UINT32  mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE;
62 UINT32  mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK;
63 
64 //
65 // Set default value to assume MTRRs need to be configured on each SMI
66 //
67 BOOLEAN  mNeedConfigureMtrrs = TRUE;
68 
69 //
70 // Array for state of SMRR enable on all CPUs
71 //
72 BOOLEAN  *mSmrrEnabled;
73 
74 /**
75   The constructor function
76 
77   @param[in]  ImageHandle  The firmware allocated handle for the EFI image.
78   @param[in]  SystemTable  A pointer to the EFI System Table.
79 
80   @retval EFI_SUCCESS      The constructor always returns EFI_SUCCESS.
81 
82 **/
83 EFI_STATUS
84 EFIAPI
SmmCpuFeaturesLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)85 SmmCpuFeaturesLibConstructor (
86   IN EFI_HANDLE        ImageHandle,
87   IN EFI_SYSTEM_TABLE  *SystemTable
88   )
89 {
90   UINT32  RegEax;
91   UINT32  RegEdx;
92   UINTN   FamilyId;
93   UINTN   ModelId;
94 
95   //
96   // Retrieve CPU Family and Model
97   //
98   AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
99   FamilyId = (RegEax >> 8) & 0xf;
100   ModelId  = (RegEax >> 4) & 0xf;
101   if (FamilyId == 0x06 || FamilyId == 0x0f) {
102     ModelId = ModelId | ((RegEax >> 12) & 0xf0);
103   }
104 
105   //
106   // Check CPUID(CPUID_VERSION_INFO).EDX[12] for MTRR capability
107   //
108   if ((RegEdx & BIT12) != 0) {
109     //
110     // Check MTRR_CAP MSR bit 11 for SMRR support
111     //
112     if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MTRR_CAP) & BIT11) != 0) {
113       mSmrrSupported = TRUE;
114     }
115   }
116 
117   //
118   // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
119   // Volume 3C, Section 35.3 MSRs in the Intel(R) Atom(TM) Processor Family
120   //
121   // If CPU Family/Model is 06_1CH, 06_26H, 06_27H, 06_35H or 06_36H, then
122   // SMRR Physical Base and SMM Physical Mask MSRs are not available.
123   //
124   if (FamilyId == 0x06) {
125     if (ModelId == 0x1C || ModelId == 0x26 || ModelId == 0x27 || ModelId == 0x35 || ModelId == 0x36) {
126       mSmrrSupported = FALSE;
127     }
128   }
129 
130   //
131   // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
132   // Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
133   //
134   // If CPU Family/Model is 06_0F or 06_17, then use Intel(R) Core(TM) 2
135   // Processor Family MSRs
136   //
137   if (FamilyId == 0x06) {
138     if (ModelId == 0x17 || ModelId == 0x0f) {
139       mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE;
140       mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK;
141     }
142   }
143 
144   //
145   // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
146   // Volume 3C, Section 34.4.2 SMRAM Caching
147   //   An IA-32 processor does not automatically write back and invalidate its
148   //   caches before entering SMM or before exiting SMM. Because of this behavior,
149   //   care must be taken in the placement of the SMRAM in system memory and in
150   //   the caching of the SMRAM to prevent cache incoherence when switching back
151   //   and forth between SMM and protected mode operation.
152   //
153   // An IA-32 processor is a processor that does not support the Intel 64
154   // Architecture.  Support for the Intel 64 Architecture can be detected from
155   // CPUID(CPUID_EXTENDED_CPU_SIG).EDX[29]
156   //
157   // If an IA-32 processor is detected, then set mNeedConfigureMtrrs to TRUE,
158   // so caches are flushed on SMI entry and SMI exit, the interrupted code
159   // MTRRs are saved/restored, and MTRRs for SMM are loaded.
160   //
161   AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
162   if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
163     AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
164     if ((RegEdx & BIT29) != 0) {
165       mNeedConfigureMtrrs = FALSE;
166     }
167   }
168 
169   //
170   // Allocate array for state of SMRR enable on all CPUs
171   //
172   mSmrrEnabled = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
173   ASSERT (mSmrrEnabled != NULL);
174 
175   return EFI_SUCCESS;
176 }
177 
178 /**
179   Called during the very first SMI into System Management Mode to initialize
180   CPU features, including SMBASE, for the currently executing CPU.  Since this
181   is the first SMI, the SMRAM Save State Map is at the default address of
182   SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET.  The currently executing
183   CPU is specified by CpuIndex and CpuIndex can be used to access information
184   about the currently executing CPU in the ProcessorInfo array and the
185   HotPlugCpuData data structure.
186 
187   @param[in] CpuIndex        The index of the CPU to initialize.  The value
188                              must be between 0 and the NumberOfCpus field in
189                              the System Management System Table (SMST).
190   @param[in] IsMonarch       TRUE if the CpuIndex is the index of the CPU that
191                              was elected as monarch during System Management
192                              Mode initialization.
193                              FALSE if the CpuIndex is not the index of the CPU
194                              that was elected as monarch during System
195                              Management Mode initialization.
196   @param[in] ProcessorInfo   Pointer to an array of EFI_PROCESSOR_INFORMATION
197                              structures.  ProcessorInfo[CpuIndex] contains the
198                              information for the currently executing CPU.
199   @param[in] CpuHotPlugData  Pointer to the CPU_HOT_PLUG_DATA structure that
200                              contains the ApidId and SmBase arrays.
201 **/
202 VOID
203 EFIAPI
SmmCpuFeaturesInitializeProcessor(IN UINTN CpuIndex,IN BOOLEAN IsMonarch,IN EFI_PROCESSOR_INFORMATION * ProcessorInfo,IN CPU_HOT_PLUG_DATA * CpuHotPlugData)204 SmmCpuFeaturesInitializeProcessor (
205   IN UINTN                      CpuIndex,
206   IN BOOLEAN                    IsMonarch,
207   IN EFI_PROCESSOR_INFORMATION  *ProcessorInfo,
208   IN CPU_HOT_PLUG_DATA          *CpuHotPlugData
209   )
210 {
211   SMRAM_SAVE_STATE_MAP  *CpuState;
212   UINT64                FeatureControl;
213   UINT32                RegEax;
214   UINT32                RegEdx;
215   UINTN                 FamilyId;
216   UINTN                 ModelId;
217 
218   //
219   // Configure SMBASE.
220   //
221   CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
222   CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
223 
224   //
225   // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
226   // Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
227   //
228   // If Intel(R) Core(TM) Core(TM) 2 Processor Family MSRs are being used, then
229   // make sure SMRR Enable(BIT3) of MSR_FEATURE_CONTROL MSR(0x3A) is set before
230   // accessing SMRR base/mask MSRs.  If Lock(BIT0) of MSR_FEATURE_CONTROL MSR(0x3A)
231   // is set, then the MSR is locked and can not be modified.
232   //
233   if (mSmrrSupported && mSmrrPhysBaseMsr == SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE) {
234     FeatureControl = AsmReadMsr64 (SMM_FEATURES_LIB_IA32_FEATURE_CONTROL);
235     if ((FeatureControl & BIT3) == 0) {
236       if ((FeatureControl & BIT0) == 0) {
237         AsmWriteMsr64 (SMM_FEATURES_LIB_IA32_FEATURE_CONTROL, FeatureControl | BIT3);
238       } else {
239         mSmrrSupported = FALSE;
240       }
241     }
242   }
243 
244   //
245   // If SMRR is supported, then program SMRR base/mask MSRs.
246   // The EFI_MSR_SMRR_PHYS_MASK_VALID bit is not set until the first normal SMI.
247   // The code that initializes SMM environment is running in normal mode
248   // from SMRAM region.  If SMRR is enabled here, then the SMRAM region
249   // is protected and the normal mode code execution will fail.
250   //
251   if (mSmrrSupported) {
252     //
253     // SMRR size cannot be less than 4-KBytes
254     // SMRR size must be of length 2^n
255     // SMRR base alignment cannot be less than SMRR length
256     //
257     if ((CpuHotPlugData->SmrrSize < SIZE_4KB) ||
258         (CpuHotPlugData->SmrrSize != GetPowerOfTwo32 (CpuHotPlugData->SmrrSize)) ||
259         ((CpuHotPlugData->SmrrBase & ~(CpuHotPlugData->SmrrSize - 1)) != CpuHotPlugData->SmrrBase)) {
260       //
261       // Print message and halt if CPU is Monarch
262       //
263       if (IsMonarch) {
264         DEBUG ((DEBUG_ERROR, "SMM Base/Size does not meet alignment/size requirement!\n"));
265         CpuDeadLoop ();
266       }
267     } else {
268       AsmWriteMsr64 (mSmrrPhysBaseMsr, CpuHotPlugData->SmrrBase | MTRR_CACHE_WRITE_BACK);
269       AsmWriteMsr64 (mSmrrPhysMaskMsr, (~(CpuHotPlugData->SmrrSize - 1) & EFI_MSR_SMRR_MASK));
270       mSmrrEnabled[CpuIndex] = FALSE;
271     }
272   }
273 
274   //
275   // Retrieve CPU Family and Model
276   //
277   AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
278   FamilyId = (RegEax >> 8) & 0xf;
279   ModelId  = (RegEax >> 4) & 0xf;
280   if (FamilyId == 0x06 || FamilyId == 0x0f) {
281     ModelId = ModelId | ((RegEax >> 12) & 0xf0);
282   }
283 
284   //
285   // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
286   // Volume 3C, Section 35.10.1 MSRs in 4th Generation Intel(R) Core(TM)
287   // Processor Family.
288   //
289   // If CPU Family/Model is 06_3C, 06_45, or 06_46 then use 4th Generation
290   // Intel(R) Core(TM) Processor Family MSRs.
291   //
292   if (FamilyId == 0x06) {
293     if (ModelId == 0x3C || ModelId == 0x45 || ModelId == 0x46 ||
294         ModelId == 0x3D || ModelId == 0x47 || ModelId == 0x4E || ModelId == 0x4F ||
295         ModelId == 0x3F || ModelId == 0x56 || ModelId == 0x57 || ModelId == 0x5C) {
296       //
297       // Check to see if the CPU supports the SMM Code Access Check feature
298       // Do not access this MSR unless the CPU supports the SmmRegFeatureControl
299       //
300       if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MCA_CAP) & SMM_CODE_ACCESS_CHK_BIT) != 0) {
301         mSmmFeatureControlSupported = TRUE;
302       }
303     }
304   }
305 
306   //
307   //  Call internal worker function that completes the CPU initialization
308   //
309   FinishSmmCpuFeaturesInitializeProcessor ();
310 }
311 
312 /**
313   This function updates the SMRAM save state on the currently executing CPU
314   to resume execution at a specific address after an RSM instruction.  This
315   function must evaluate the SMRAM save state to determine the execution mode
316   the RSM instruction resumes and update the resume execution address with
317   either NewInstructionPointer32 or NewInstructionPoint.  The auto HALT restart
318   flag in the SMRAM save state must always be cleared.  This function returns
319   the value of the instruction pointer from the SMRAM save state that was
320   replaced.  If this function returns 0, then the SMRAM save state was not
321   modified.
322 
323   This function is called during the very first SMI on each CPU after
324   SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
325   to signal that the SMBASE of each CPU has been updated before the default
326   SMBASE address is used for the first SMI to the next CPU.
327 
328   @param[in] CpuIndex                 The index of the CPU to hook.  The value
329                                       must be between 0 and the NumberOfCpus
330                                       field in the System Management System Table
331                                       (SMST).
332   @param[in] CpuState                 Pointer to SMRAM Save State Map for the
333                                       currently executing CPU.
334   @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to
335                                       32-bit execution mode from 64-bit SMM.
336   @param[in] NewInstructionPointer    Instruction pointer to use if resuming to
337                                       same execution mode as SMM.
338 
339   @retval 0    This function did modify the SMRAM save state.
340   @retval > 0  The original instruction pointer value from the SMRAM save state
341                before it was replaced.
342 **/
343 UINT64
344 EFIAPI
SmmCpuFeaturesHookReturnFromSmm(IN UINTN CpuIndex,IN SMRAM_SAVE_STATE_MAP * CpuState,IN UINT64 NewInstructionPointer32,IN UINT64 NewInstructionPointer)345 SmmCpuFeaturesHookReturnFromSmm (
346   IN UINTN                 CpuIndex,
347   IN SMRAM_SAVE_STATE_MAP  *CpuState,
348   IN UINT64                NewInstructionPointer32,
349   IN UINT64                NewInstructionPointer
350   )
351 {
352   return 0;
353 }
354 
355 /**
356   Hook point in normal execution mode that allows the one CPU that was elected
357   as monarch during System Management Mode initialization to perform additional
358   initialization actions immediately after all of the CPUs have processed their
359   first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
360   into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
361 **/
362 VOID
363 EFIAPI
SmmCpuFeaturesSmmRelocationComplete(VOID)364 SmmCpuFeaturesSmmRelocationComplete (
365   VOID
366   )
367 {
368 }
369 
370 /**
371   Determines if MTRR registers must be configured to set SMRAM cache-ability
372   when executing in System Management Mode.
373 
374   @retval TRUE   MTRR registers must be configured to set SMRAM cache-ability.
375   @retval FALSE  MTRR registers do not need to be configured to set SMRAM
376                  cache-ability.
377 **/
378 BOOLEAN
379 EFIAPI
SmmCpuFeaturesNeedConfigureMtrrs(VOID)380 SmmCpuFeaturesNeedConfigureMtrrs (
381   VOID
382   )
383 {
384   return mNeedConfigureMtrrs;
385 }
386 
387 /**
388   Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
389   returns TRUE.
390 **/
391 VOID
392 EFIAPI
SmmCpuFeaturesDisableSmrr(VOID)393 SmmCpuFeaturesDisableSmrr (
394   VOID
395   )
396 {
397   if (mSmrrSupported && mNeedConfigureMtrrs) {
398     AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64(mSmrrPhysMaskMsr) & ~EFI_MSR_SMRR_PHYS_MASK_VALID);
399   }
400 }
401 
402 /**
403   Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
404   returns TRUE.
405 **/
406 VOID
407 EFIAPI
SmmCpuFeaturesReenableSmrr(VOID)408 SmmCpuFeaturesReenableSmrr (
409   VOID
410   )
411 {
412   if (mSmrrSupported && mNeedConfigureMtrrs) {
413     AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64(mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
414   }
415 }
416 
417 /**
418   Processor specific hook point each time a CPU enters System Management Mode.
419 
420   @param[in] CpuIndex  The index of the CPU that has entered SMM.  The value
421                        must be between 0 and the NumberOfCpus field in the
422                        System Management System Table (SMST).
423 **/
424 VOID
425 EFIAPI
SmmCpuFeaturesRendezvousEntry(IN UINTN CpuIndex)426 SmmCpuFeaturesRendezvousEntry (
427   IN UINTN  CpuIndex
428   )
429 {
430   //
431   // If SMRR is supported and this is the first normal SMI, then enable SMRR
432   //
433   if (mSmrrSupported && !mSmrrEnabled[CpuIndex]) {
434     AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64 (mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
435     mSmrrEnabled[CpuIndex] = TRUE;
436   }
437 }
438 
439 /**
440   Processor specific hook point each time a CPU exits System Management Mode.
441 
442   @param[in] CpuIndex  The index of the CPU that is exiting SMM.  The value must
443                        be between 0 and the NumberOfCpus field in the System
444                        Management System Table (SMST).
445 **/
446 VOID
447 EFIAPI
SmmCpuFeaturesRendezvousExit(IN UINTN CpuIndex)448 SmmCpuFeaturesRendezvousExit (
449   IN UINTN  CpuIndex
450   )
451 {
452 }
453 
454 /**
455   Check to see if an SMM register is supported by a specified CPU.
456 
457   @param[in] CpuIndex  The index of the CPU to check for SMM register support.
458                        The value must be between 0 and the NumberOfCpus field
459                        in the System Management System Table (SMST).
460   @param[in] RegName   Identifies the SMM register to check for support.
461 
462   @retval TRUE   The SMM register specified by RegName is supported by the CPU
463                  specified by CpuIndex.
464   @retval FALSE  The SMM register specified by RegName is not supported by the
465                  CPU specified by CpuIndex.
466 **/
467 BOOLEAN
468 EFIAPI
SmmCpuFeaturesIsSmmRegisterSupported(IN UINTN CpuIndex,IN SMM_REG_NAME RegName)469 SmmCpuFeaturesIsSmmRegisterSupported (
470   IN UINTN         CpuIndex,
471   IN SMM_REG_NAME  RegName
472   )
473 {
474   if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
475     return TRUE;
476   }
477   return FALSE;
478 }
479 
480 /**
481   Returns the current value of the SMM register for the specified CPU.
482   If the SMM register is not supported, then 0 is returned.
483 
484   @param[in] CpuIndex  The index of the CPU to read the SMM register.  The
485                        value must be between 0 and the NumberOfCpus field in
486                        the System Management System Table (SMST).
487   @param[in] RegName   Identifies the SMM register to read.
488 
489   @return  The value of the SMM register specified by RegName from the CPU
490            specified by CpuIndex.
491 **/
492 UINT64
493 EFIAPI
SmmCpuFeaturesGetSmmRegister(IN UINTN CpuIndex,IN SMM_REG_NAME RegName)494 SmmCpuFeaturesGetSmmRegister (
495   IN UINTN         CpuIndex,
496   IN SMM_REG_NAME  RegName
497   )
498 {
499   if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
500     return AsmReadMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL);
501   }
502   return 0;
503 }
504 
505 /**
506   Sets the value of an SMM register on a specified CPU.
507   If the SMM register is not supported, then no action is performed.
508 
509   @param[in] CpuIndex  The index of the CPU to write the SMM register.  The
510                        value must be between 0 and the NumberOfCpus field in
511                        the System Management System Table (SMST).
512   @param[in] RegName   Identifies the SMM register to write.
513                        registers are read-only.
514   @param[in] Value     The value to write to the SMM register.
515 **/
516 VOID
517 EFIAPI
SmmCpuFeaturesSetSmmRegister(IN UINTN CpuIndex,IN SMM_REG_NAME RegName,IN UINT64 Value)518 SmmCpuFeaturesSetSmmRegister (
519   IN UINTN         CpuIndex,
520   IN SMM_REG_NAME  RegName,
521   IN UINT64        Value
522   )
523 {
524   if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
525     AsmWriteMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL, Value);
526   }
527 }
528 
529 /**
530   Read an SMM Save State register on the target processor.  If this function
531   returns EFI_UNSUPPORTED, then the caller is responsible for reading the
532   SMM Save Sate register.
533 
534   @param[in]  CpuIndex  The index of the CPU to read the SMM Save State.  The
535                         value must be between 0 and the NumberOfCpus field in
536                         the System Management System Table (SMST).
537   @param[in]  Register  The SMM Save State register to read.
538   @param[in]  Width     The number of bytes to read from the CPU save state.
539   @param[out] Buffer    Upon return, this holds the CPU register value read
540                         from the save state.
541 
542   @retval EFI_SUCCESS           The register was read from Save State.
543   @retval EFI_INVALID_PARAMTER  Buffer is NULL.
544   @retval EFI_UNSUPPORTED       This function does not support reading Register.
545 
546 **/
547 EFI_STATUS
548 EFIAPI
SmmCpuFeaturesReadSaveStateRegister(IN UINTN CpuIndex,IN EFI_SMM_SAVE_STATE_REGISTER Register,IN UINTN Width,OUT VOID * Buffer)549 SmmCpuFeaturesReadSaveStateRegister (
550   IN  UINTN                        CpuIndex,
551   IN  EFI_SMM_SAVE_STATE_REGISTER  Register,
552   IN  UINTN                        Width,
553   OUT VOID                         *Buffer
554   )
555 {
556   return EFI_UNSUPPORTED;
557 }
558 
559 /**
560   Writes an SMM Save State register on the target processor.  If this function
561   returns EFI_UNSUPPORTED, then the caller is responsible for writing the
562   SMM Save Sate register.
563 
564   @param[in] CpuIndex  The index of the CPU to write the SMM Save State.  The
565                        value must be between 0 and the NumberOfCpus field in
566                        the System Management System Table (SMST).
567   @param[in] Register  The SMM Save State register to write.
568   @param[in] Width     The number of bytes to write to the CPU save state.
569   @param[in] Buffer    Upon entry, this holds the new CPU register value.
570 
571   @retval EFI_SUCCESS           The register was written to Save State.
572   @retval EFI_INVALID_PARAMTER  Buffer is NULL.
573   @retval EFI_UNSUPPORTED       This function does not support writing Register.
574 **/
575 EFI_STATUS
576 EFIAPI
SmmCpuFeaturesWriteSaveStateRegister(IN UINTN CpuIndex,IN EFI_SMM_SAVE_STATE_REGISTER Register,IN UINTN Width,IN CONST VOID * Buffer)577 SmmCpuFeaturesWriteSaveStateRegister (
578   IN UINTN                        CpuIndex,
579   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
580   IN UINTN                        Width,
581   IN CONST VOID                   *Buffer
582   )
583 {
584   return EFI_UNSUPPORTED;
585 }
586 
587 /**
588   This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
589   notification is completely processed.
590 **/
591 VOID
592 EFIAPI
SmmCpuFeaturesCompleteSmmReadyToLock(VOID)593 SmmCpuFeaturesCompleteSmmReadyToLock (
594   VOID
595   )
596 {
597 }
598 
599 /**
600   This API provides a method for a CPU to allocate a specific region for storing page tables.
601 
602   This API can be called more once to allocate memory for page tables.
603 
604   Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
605   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
606   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
607   returned.
608 
609   This function can also return NULL if there is no preference on where the page tables are allocated in SMRAM.
610 
611   @param  Pages                 The number of 4 KB pages to allocate.
612 
613   @return A pointer to the allocated buffer for page tables.
614   @retval NULL      Fail to allocate a specific region for storing page tables,
615                     Or there is no preference on where the page tables are allocated in SMRAM.
616 
617 **/
618 VOID *
619 EFIAPI
SmmCpuFeaturesAllocatePageTableMemory(IN UINTN Pages)620 SmmCpuFeaturesAllocatePageTableMemory (
621   IN UINTN           Pages
622   )
623 {
624   return NULL;
625 }
626 
627