1/** @file
2The CPU specific programming for PiSmmCpuDxeSmm module.
3
4Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution.  The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT 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**/
49VOID
50FinishSmmCpuFeaturesInitializeProcessor (
51  VOID
52  );
53
54//
55// Set default value to assume SMRR is not supported
56//
57BOOLEAN  mSmrrSupported = FALSE;
58
59//
60// Set default value to assume MSR_SMM_FEATURE_CONTROL is not supported
61//
62BOOLEAN  mSmmFeatureControlSupported = FALSE;
63
64//
65// Set default value to assume IA-32 Architectural MSRs are used
66//
67UINT32  mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE;
68UINT32  mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK;
69
70//
71// Set default value to assume MTRRs need to be configured on each SMI
72//
73BOOLEAN  mNeedConfigureMtrrs = TRUE;
74
75//
76// Array for state of SMRR enable on all CPUs
77//
78BOOLEAN  *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**/
89EFI_STATUS
90EFIAPI
91SmmCpuFeaturesLibConstructor (
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**/
208VOID
209EFIAPI
210SmmCpuFeaturesInitializeProcessor (
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**/
347UINT64
348EFIAPI
349SmmCpuFeaturesHookReturnFromSmm (
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**/
366VOID
367EFIAPI
368SmmCpuFeaturesSmmRelocationComplete (
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**/
382BOOLEAN
383EFIAPI
384SmmCpuFeaturesNeedConfigureMtrrs (
385  VOID
386  )
387{
388  return mNeedConfigureMtrrs;
389}
390
391/**
392  Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
393  returns TRUE.
394**/
395VOID
396EFIAPI
397SmmCpuFeaturesDisableSmrr (
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**/
410VOID
411EFIAPI
412SmmCpuFeaturesReenableSmrr (
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**/
428VOID
429EFIAPI
430SmmCpuFeaturesRendezvousEntry (
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**/
450VOID
451EFIAPI
452SmmCpuFeaturesRendezvousExit (
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**/
471BOOLEAN
472EFIAPI
473SmmCpuFeaturesIsSmmRegisterSupported (
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**/
496UINT64
497EFIAPI
498SmmCpuFeaturesGetSmmRegister (
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**/
520VOID
521EFIAPI
522SmmCpuFeaturesSetSmmRegister (
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**/
551EFI_STATUS
552EFIAPI
553SmmCpuFeaturesReadSaveStateRegister (
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**/
579EFI_STATUS
580EFIAPI
581SmmCpuFeaturesWriteSaveStateRegister (
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**/
595VOID
596EFIAPI
597SmmCpuFeaturesCompleteSmmReadyToLock (
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**/
622VOID *
623EFIAPI
624SmmCpuFeaturesAllocatePageTableMemory (
625  IN UINTN           Pages
626  )
627{
628  return NULL;
629}
630
631