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