Home | History | Annotate | Download | only in SmmCpuFeaturesLib
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    624 SmmCpuFeaturesAllocatePageTableMemory (
    625   IN UINTN           Pages
    626   )
    627 {
    628   return NULL;
    629 }
    630 
    631