SmmCpuFeaturesLib.c revision d26a7a3fa251e1c2e93bdb834207643eabb847de
1/** @file
2The CPU specific programming for PiSmmCpuDxeSmm module.
3
4Copyright (c) 2010 - 2015, 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// Set default value to assume SMRR is not supported
40//
41BOOLEAN  mSmrrSupported = FALSE;
42
43//
44// Set default value to assume MSR_SMM_FEATURE_CONTROL is not supported
45//
46BOOLEAN  mSmmFeatureControlSupported = FALSE;
47
48//
49// Set default value to assume IA-32 Architectural MSRs are used
50//
51UINT32  mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE;
52UINT32  mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK;
53
54//
55// Set default value to assume MTRRs need to be configured on each SMI
56//
57BOOLEAN  mNeedConfigureMtrrs = TRUE;
58
59//
60// Array for state of SMRR enable on all CPUs
61//
62BOOLEAN  *mSmrrEnabled;
63
64/**
65  The constructor function
66
67  @param[in]  ImageHandle  The firmware allocated handle for the EFI image.
68  @param[in]  SystemTable  A pointer to the EFI System Table.
69
70  @retval EFI_SUCCESS      The constructor always returns EFI_SUCCESS.
71
72**/
73EFI_STATUS
74EFIAPI
75SmmCpuFeaturesLibConstructor (
76  IN EFI_HANDLE        ImageHandle,
77  IN EFI_SYSTEM_TABLE  *SystemTable
78  )
79{
80  UINT32  RegEax;
81  UINT32  RegEdx;
82  UINTN   FamilyId;
83  UINTN   ModelId;
84
85  //
86  // Retrieve CPU Family and Model
87  //
88  AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
89  FamilyId = (RegEax >> 8) & 0xf;
90  ModelId  = (RegEax >> 4) & 0xf;
91  if (FamilyId == 0x06 || FamilyId == 0x0f) {
92    ModelId = ModelId | ((RegEax >> 12) & 0xf0);
93  }
94
95  //
96  // Check CPUID(CPUID_VERSION_INFO).EDX[12] for MTRR capability
97  //
98  if ((RegEdx & BIT12) != 0) {
99    //
100    // Check MTRR_CAP MSR bit 11 for SMRR support
101    //
102    if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MTRR_CAP) & BIT11) != 0) {
103      mSmrrSupported = TRUE;
104    }
105  }
106
107  //
108  // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
109  // Volume 3C, Section 35.3 MSRs in the Intel(R) Atom(TM) Processor Family
110  //
111  // If CPU Family/Model is 06_1CH, 06_26H, 06_27H, 06_35H or 06_36H, then
112  // SMRR Physical Base and SMM Physical Mask MSRs are not available.
113  //
114  if (FamilyId == 0x06) {
115    if (ModelId == 0x1C || ModelId == 0x26 || ModelId == 0x27 || ModelId == 0x35 || ModelId == 0x36) {
116      mSmrrSupported = FALSE;
117    }
118  }
119
120  //
121  // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
122  // Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
123  //
124  // If CPU Family/Model is 06_0F or 06_17, then use Intel(R) Core(TM) 2
125  // Processor Family MSRs
126  //
127  if (FamilyId == 0x06) {
128    if (ModelId == 0x17 || ModelId == 0x0f) {
129      mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE;
130      mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK;
131    }
132  }
133
134  //
135  // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
136  // Volume 3C, Section 35.10.1 MSRs in 4th Generation Intel(R) Core(TM)
137  // Processor Family
138  //
139  // If CPU Family/Model is 06_3C, 06_45, or 06_46 then use 4th Generation
140  // Intel(R) Core(TM) Processor Family MSRs
141  //
142  if (FamilyId == 0x06) {
143    if (ModelId == 0x3C || ModelId == 0x45 || ModelId == 0x46) {
144      mSmmFeatureControlSupported = TRUE;
145    }
146  }
147
148  //
149  // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
150  // Volume 3C, Section 34.4.2 SMRAM Caching
151  //   An IA-32 processor does not automatically write back and invalidate its
152  //   caches before entering SMM or before exiting SMM. Because of this behavior,
153  //   care must be taken in the placement of the SMRAM in system memory and in
154  //   the caching of the SMRAM to prevent cache incoherence when switching back
155  //   and forth between SMM and protected mode operation.
156  //
157  // An IA-32 processor is a processor that does not support the Intel 64
158  // Architecture.  Support for the Intel 64 Architecture can be detected from
159  // CPUID(CPUID_EXTENDED_CPU_SIG).EDX[29]
160  //
161  // If an IA-32 processor is detected, then set mNeedConfigureMtrrs to TRUE,
162  // so caches are flushed on SMI entry and SMI exit, the interrupted code
163  // MTRRs are saved/restored, and MTRRs for SMM are loaded.
164  //
165  AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
166  if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
167    AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
168    if ((RegEdx & BIT29) != 0) {
169      mNeedConfigureMtrrs = FALSE;
170    }
171  }
172
173  //
174  // Allocate array for state of SMRR enable on all CPUs
175  //
176  mSmrrEnabled = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
177  ASSERT (mSmrrEnabled != NULL);
178
179  return EFI_SUCCESS;
180}
181
182/**
183  Called during the very first SMI into System Management Mode to initialize
184  CPU features, including SMBASE, for the currently executing CPU.  Since this
185  is the first SMI, the SMRAM Save State Map is at the default address of
186  SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET.  The currently executing
187  CPU is specified by CpuIndex and CpuIndex can be used to access information
188  about the currently executing CPU in the ProcessorInfo array and the
189  HotPlugCpuData data structure.
190
191  @param[in] CpuIndex        The index of the CPU to initialize.  The value
192                             must be between 0 and the NumberOfCpus field in
193                             the System Management System Table (SMST).
194  @param[in] IsMonarch       TRUE if the CpuIndex is the index of the CPU that
195                             was elected as monarch during System Management
196                             Mode initialization.
197                             FALSE if the CpuIndex is not the index of the CPU
198                             that was elected as monarch during System
199                             Management Mode initialization.
200  @param[in] ProcessorInfo   Pointer to an array of EFI_PROCESSOR_INFORMATION
201                             structures.  ProcessorInfo[CpuIndex] contains the
202                             information for the currently executing CPU.
203  @param[in] CpuHotPlugData  Pointer to the CPU_HOT_PLUG_DATA structure that
204                             contains the ApidId and SmBase arrays.
205**/
206VOID
207EFIAPI
208SmmCpuFeaturesInitializeProcessor (
209  IN UINTN                      CpuIndex,
210  IN BOOLEAN                    IsMonarch,
211  IN EFI_PROCESSOR_INFORMATION  *ProcessorInfo,
212  IN CPU_HOT_PLUG_DATA          *CpuHotPlugData
213  )
214{
215  SMRAM_SAVE_STATE_MAP  *CpuState;
216  UINT64                FeatureControl;
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    AsmWriteMsr64 (mSmrrPhysBaseMsr, CpuHotPlugData->SmrrBase | MTRR_CACHE_WRITE_BACK);
253    AsmWriteMsr64 (mSmrrPhysMaskMsr, (~(CpuHotPlugData->SmrrSize - 1) & EFI_MSR_SMRR_MASK));
254    mSmrrEnabled[CpuIndex] = FALSE;
255  }
256}
257
258/**
259  This function updates the SMRAM save state on the currently executing CPU
260  to resume execution at a specific address after an RSM instruction.  This
261  function must evaluate the SMRAM save state to determine the execution mode
262  the RSM instruction resumes and update the resume execution address with
263  either NewInstructionPointer32 or NewInstructionPoint.  The auto HALT restart
264  flag in the SMRAM save state must always be cleared.  This function returns
265  the value of the instruction pointer from the SMRAM save state that was
266  replaced.  If this function returns 0, then the SMRAM save state was not
267  modified.
268
269  This function is called during the very first SMI on each CPU after
270  SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
271  to signal that the SMBASE of each CPU has been updated before the default
272  SMBASE address is used for the first SMI to the next CPU.
273
274  @param[in] CpuIndex                 The index of the CPU to hook.  The value
275                                      must be between 0 and the NumberOfCpus
276                                      field in the System Management System Table
277                                      (SMST).
278  @param[in] CpuState                 Pointer to SMRAM Save State Map for the
279                                      currently executing CPU.
280  @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to
281                                      32-bit execution mode from 64-bit SMM.
282  @param[in] NewInstructionPointer    Instruction pointer to use if resuming to
283                                      same execution mode as SMM.
284
285  @retval 0    This function did modify the SMRAM save state.
286  @retval > 0  The original instruction pointer value from the SMRAM save state
287               before it was replaced.
288**/
289UINT64
290EFIAPI
291SmmCpuFeaturesHookReturnFromSmm (
292  IN UINTN                 CpuIndex,
293  IN SMRAM_SAVE_STATE_MAP  *CpuState,
294  IN UINT64                NewInstructionPointer32,
295  IN UINT64                NewInstructionPointer
296  )
297{
298  return 0;
299}
300
301/**
302  Hook point in normal execution mode that allows the one CPU that was elected
303  as monarch during System Management Mode initialization to perform additional
304  initialization actions immediately after all of the CPUs have processed their
305  first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
306  into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
307**/
308VOID
309EFIAPI
310SmmCpuFeaturesSmmRelocationComplete (
311  VOID
312  )
313{
314}
315
316/**
317  Return the size, in bytes, of a custom SMI Handler in bytes.  If 0 is
318  returned, then a custom SMI handler is not provided by this library,
319  and the default SMI handler must be used.
320
321  @retval 0    Use the default SMI handler.
322  @retval > 0  Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()
323               The caller is required to allocate enough SMRAM for each CPU to
324               support the size of the custom SMI handler.
325**/
326UINTN
327EFIAPI
328SmmCpuFeaturesGetSmiHandlerSize (
329  VOID
330  )
331{
332  return 0;
333}
334
335/**
336  Install a custom SMI handler for the CPU specified by CpuIndex.  This function
337  is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater
338  than zero and is called by the CPU that was elected as monarch during System
339  Management Mode initialization.
340
341  @param[in] CpuIndex   The index of the CPU to install the custom SMI handler.
342                        The value must be between 0 and the NumberOfCpus field
343                        in the System Management System Table (SMST).
344  @param[in] SmBase     The SMBASE address for the CPU specified by CpuIndex.
345  @param[in] SmiStack   The stack to use when an SMI is processed by the
346                        the CPU specified by CpuIndex.
347  @param[in] StackSize  The size, in bytes, if the stack used when an SMI is
348                        processed by the CPU specified by CpuIndex.
349  @param[in] GdtBase    The base address of the GDT to use when an SMI is
350                        processed by the CPU specified by CpuIndex.
351  @param[in] GdtSize    The size, in bytes, of the GDT used when an SMI is
352                        processed by the CPU specified by CpuIndex.
353  @param[in] IdtBase    The base address of the IDT to use when an SMI is
354                        processed by the CPU specified by CpuIndex.
355  @param[in] IdtSize    The size, in bytes, of the IDT used when an SMI is
356                        processed by the CPU specified by CpuIndex.
357  @param[in] Cr3        The base address of the page tables to use when an SMI
358                        is processed by the CPU specified by CpuIndex.
359**/
360VOID
361EFIAPI
362SmmCpuFeaturesInstallSmiHandler (
363  IN UINTN   CpuIndex,
364  IN UINT32  SmBase,
365  IN VOID    *SmiStack,
366  IN UINTN   StackSize,
367  IN UINTN   GdtBase,
368  IN UINTN   GdtSize,
369  IN UINTN   IdtBase,
370  IN UINTN   IdtSize,
371  IN UINT32  Cr3
372  )
373{
374}
375
376/**
377  Determines if MTRR registers must be configured to set SMRAM cache-ability
378  when executing in System Management Mode.
379
380  @retval TRUE   MTRR registers must be configured to set SMRAM cache-ability.
381  @retval FALSE  MTRR registers do not need to be configured to set SMRAM
382                 cache-ability.
383**/
384BOOLEAN
385EFIAPI
386SmmCpuFeaturesNeedConfigureMtrrs (
387  VOID
388  )
389{
390  return mNeedConfigureMtrrs;
391}
392
393/**
394  Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
395  returns TRUE.
396**/
397VOID
398EFIAPI
399SmmCpuFeaturesDisableSmrr (
400  VOID
401  )
402{
403  if (mSmrrSupported && mNeedConfigureMtrrs) {
404    AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64(mSmrrPhysMaskMsr) & ~EFI_MSR_SMRR_PHYS_MASK_VALID);
405  }
406}
407
408/**
409  Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
410  returns TRUE.
411**/
412VOID
413EFIAPI
414SmmCpuFeaturesReenableSmrr (
415  VOID
416  )
417{
418  if (mSmrrSupported && mNeedConfigureMtrrs) {
419    AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64(mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
420  }
421}
422
423/**
424  Processor specific hook point each time a CPU enters System Management Mode.
425
426  @param[in] CpuIndex  The index of the CPU that has entered SMM.  The value
427                       must be between 0 and the NumberOfCpus field in the
428                       System Management System Table (SMST).
429**/
430VOID
431EFIAPI
432SmmCpuFeaturesRendezvousEntry (
433  IN UINTN  CpuIndex
434  )
435{
436  //
437  // If SMRR is supported and this is the first normal SMI, then enable SMRR
438  //
439  if (mSmrrSupported && !mSmrrEnabled[CpuIndex]) {
440    AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64 (mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
441    mSmrrEnabled[CpuIndex] = TRUE;
442  }
443}
444
445/**
446  Processor specific hook point each time a CPU exits System Management Mode.
447
448  @param[in] CpuIndex  The index of the CPU that is exiting SMM.  The value must
449                       be between 0 and the NumberOfCpus field in the System
450                       Management System Table (SMST).
451**/
452VOID
453EFIAPI
454SmmCpuFeaturesRendezvousExit (
455  IN UINTN  CpuIndex
456  )
457{
458}
459
460/**
461  Check to see if an SMM register is supported by a specified CPU.
462
463  @param[in] CpuIndex  The index of the CPU to check for SMM register support.
464                       The value must be between 0 and the NumberOfCpus field
465                       in the System Management System Table (SMST).
466  @param[in] RegName   Identifies the SMM register to check for support.
467
468  @retval TRUE   The SMM register specified by RegName is supported by the CPU
469                 specified by CpuIndex.
470  @retval FALSE  The SMM register specified by RegName is not supported by the
471                 CPU specified by CpuIndex.
472**/
473BOOLEAN
474EFIAPI
475SmmCpuFeaturesIsSmmRegisterSupported (
476  IN UINTN         CpuIndex,
477  IN SMM_REG_NAME  RegName
478  )
479{
480  if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
481    return TRUE;
482  }
483  return FALSE;
484}
485
486/**
487  Returns the current value of the SMM register for the specified CPU.
488  If the SMM register is not supported, then 0 is returned.
489
490  @param[in] CpuIndex  The index of the CPU to read the SMM register.  The
491                       value must be between 0 and the NumberOfCpus field in
492                       the System Management System Table (SMST).
493  @param[in] RegName   Identifies the SMM register to read.
494
495  @return  The value of the SMM register specified by RegName from the CPU
496           specified by CpuIndex.
497**/
498UINT64
499EFIAPI
500SmmCpuFeaturesGetSmmRegister (
501  IN UINTN         CpuIndex,
502  IN SMM_REG_NAME  RegName
503  )
504{
505  if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
506    return AsmReadMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL);
507  }
508  return 0;
509}
510
511/**
512  Sets the value of an SMM register on a specified CPU.
513  If the SMM register is not supported, then no action is performed.
514
515  @param[in] CpuIndex  The index of the CPU to write the SMM register.  The
516                       value must be between 0 and the NumberOfCpus field in
517                       the System Management System Table (SMST).
518  @param[in] RegName   Identifies the SMM register to write.
519                       registers are read-only.
520  @param[in] Value     The value to write to the SMM register.
521**/
522VOID
523EFIAPI
524SmmCpuFeaturesSetSmmRegister (
525  IN UINTN         CpuIndex,
526  IN SMM_REG_NAME  RegName,
527  IN UINT64        Value
528  )
529{
530  if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
531    AsmWriteMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL, Value);
532  }
533}
534
535/**
536  Read an SMM Save State register on the target processor.  If this function
537  returns EFI_UNSUPPORTED, then the caller is responsible for reading the
538  SMM Save Sate register.
539
540  @param[in]  CpuIndex  The index of the CPU to read the SMM Save State.  The
541                        value must be between 0 and the NumberOfCpus field in
542                        the System Management System Table (SMST).
543  @param[in]  Register  The SMM Save State register to read.
544  @param[in]  Width     The number of bytes to read from the CPU save state.
545  @param[out] Buffer    Upon return, this holds the CPU register value read
546                        from the save state.
547
548  @retval EFI_SUCCESS           The register was read from Save State.
549  @retval EFI_INVALID_PARAMTER  Buffer is NULL.
550  @retval EFI_UNSUPPORTED       This function does not support reading Register.
551
552**/
553EFI_STATUS
554EFIAPI
555SmmCpuFeaturesReadSaveStateRegister (
556  IN  UINTN                        CpuIndex,
557  IN  EFI_SMM_SAVE_STATE_REGISTER  Register,
558  IN  UINTN                        Width,
559  OUT VOID                         *Buffer
560  )
561{
562  return EFI_UNSUPPORTED;
563}
564
565/**
566  Writes an SMM Save State register on the target processor.  If this function
567  returns EFI_UNSUPPORTED, then the caller is responsible for writing the
568  SMM Save Sate register.
569
570  @param[in] CpuIndex  The index of the CPU to write the SMM Save State.  The
571                       value must be between 0 and the NumberOfCpus field in
572                       the System Management System Table (SMST).
573  @param[in] Register  The SMM Save State register to write.
574  @param[in] Width     The number of bytes to write to the CPU save state.
575  @param[in] Buffer    Upon entry, this holds the new CPU register value.
576
577  @retval EFI_SUCCESS           The register was written to Save State.
578  @retval EFI_INVALID_PARAMTER  Buffer is NULL.
579  @retval EFI_UNSUPPORTED       This function does not support writing Register.
580**/
581EFI_STATUS
582EFIAPI
583SmmCpuFeaturesWriteSaveStateRegister (
584  IN UINTN                        CpuIndex,
585  IN EFI_SMM_SAVE_STATE_REGISTER  Register,
586  IN UINTN                        Width,
587  IN CONST VOID                   *Buffer
588  )
589{
590  return EFI_UNSUPPORTED;
591}
592