--- /dev/null
+/** @file\r
+Library that provides CPU specific functions to support the PiSmmCpuDxeSmm module.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __SMM_FEATURES_LIB_H__\r
+#define __SMM_FEATURES_LIB_H__\r
+\r
+#include <Protocol/MpService.h>\r
+#include <Protocol/SmmCpu.h>\r
+#include <Register/SmramSaveStateMap.h>\r
+#include <CpuHotPlugData.h>\r
+\r
+///\r
+/// Enumeration of SMM registers that are accessed using the library functions\r
+/// SmmCpuFeaturesIsSmmRegisterSupported (), SmmCpuFeaturesGetSmmRegister (),\r
+/// and SmmCpuFeaturesSetSmmRegister ().\r
+///\r
+typedef enum {\r
+ ///\r
+ /// Read-write register to provides access to MSR_SMM_FEATURE_CONTROL if the\r
+ /// CPU supports this MSR.\r
+ ///\r
+ SmmRegFeatureControl,\r
+ ///\r
+ /// Read-only register that returns a non-zero value if the CPU is able to\r
+ /// respond to SMIs.\r
+ ///\r
+ SmmRegSmmEnable,\r
+ ///\r
+ /// Read-only register that returns a non-zero value if the CPU is able to\r
+ /// respond to SMIs, but is busy with other actions that are causing a delay\r
+ /// in responding to an SMI. This register abstracts access to MSR_SMM_DELAYED\r
+ /// if the CPU supports this MSR.\r
+ ///\r
+ SmmRegSmmDelayed,\r
+ ///\r
+ /// Read-only register that returns a non-zero value if the CPU is able to\r
+ /// respond to SMIs, but is busy with other actions that are blocking its\r
+ /// ability to respond to an SMI. This register abstracts access to\r
+ /// MSR_SMM_BLOCKED if the CPU supports this MSR.\r
+ ///\r
+ SmmRegSmmBlocked\r
+} SMM_REG_NAME;\r
+\r
+/**\r
+ Called during the very first SMI into System Management Mode to initialize\r
+ CPU features, including SMBASE, for the currently executing CPU. Since this\r
+ is the first SMI, the SMRAM Save State Map is at the default address of\r
+ SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET. The currently executing\r
+ CPU is specified by CpuIndex and CpuIndex can be used to access information\r
+ about the currently executing CPU in the ProcessorInfo array and the\r
+ HotPlugCpuData data structure.\r
+\r
+ @param[in] CpuIndex The index of the CPU to initialize. The value\r
+ must be between 0 and the NumberOfCpus field in\r
+ the System Management System Table (SMST).\r
+ @param[in] IsMonarch TRUE if the CpuIndex is the index of the CPU that\r
+ was elected as monarch during System Management\r
+ Mode initialization.\r
+ FALSE if the CpuIndex is not the index of the CPU\r
+ that was elected as monarch during System\r
+ Management Mode initialization.\r
+ @param[in] ProcessorInfo Pointer to an array of EFI_PROCESSOR_INFORMATION\r
+ structures. ProcessorInfo[CpuIndex] contains the\r
+ information for the currently executing CPU.\r
+ @param[in] CpuHotPlugData Pointer to the CPU_HOT_PLUG_DATA structure that\r
+ contains the ApidId and SmBase arrays.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesInitializeProcessor (\r
+ IN UINTN CpuIndex,\r
+ IN BOOLEAN IsMonarch,\r
+ IN EFI_PROCESSOR_INFORMATION *ProcessorInfo,\r
+ IN CPU_HOT_PLUG_DATA *CpuHotPlugData\r
+ );\r
+\r
+/**\r
+ This function updates the SMRAM save state on the currently executing CPU\r
+ to resume execution at a specific address after an RSM instruction. This\r
+ function must evaluate the SMRAM save state to determine the execution mode\r
+ the RSM instruction resumes and update the resume execution address with\r
+ either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart\r
+ flag in the SMRAM save state must always be cleared. This function returns\r
+ the value of the instruction pointer from the SMRAM save state that was\r
+ replaced. If this function returns 0, then the SMRAM save state was not\r
+ modified.\r
+\r
+ This function is called during the very first SMI on each CPU after\r
+ SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode\r
+ to signal that the SMBASE of each CPU has been updated before the default\r
+ SMBASE address is used for the first SMI to the next CPU.\r
+\r
+ @param[in] CpuIndex The index of the CPU to hook. The value\r
+ must be between 0 and the NumberOfCpus\r
+ field in the System Management System Table\r
+ (SMST).\r
+ @param[in] CpuState Pointer to SMRAM Save State Map for the\r
+ currently executing CPU.\r
+ @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to\r
+ 32-bit execution mode from 64-bit SMM.\r
+ @param[in] NewInstructionPointer Instruction pointer to use if resuming to\r
+ same execution mode as SMM.\r
+\r
+ @retval 0 This function did modify the SMRAM save state.\r
+ @retval > 0 The original instruction pointer value from the SMRAM save state\r
+ before it was replaced.\r
+**/\r
+UINT64\r
+EFIAPI\r
+SmmCpuFeaturesHookReturnFromSmm (\r
+ IN UINTN CpuIndex,\r
+ IN SMRAM_SAVE_STATE_MAP *CpuState,\r
+ IN UINT64 NewInstructionPointer32,\r
+ IN UINT64 NewInstructionPointer\r
+ );\r
+\r
+/**\r
+ Hook point in normal execution mode that allows the one CPU that was elected\r
+ as monarch during System Management Mode initialization to perform additional\r
+ initialization actions immediately after all of the CPUs have processed their\r
+ first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE\r
+ into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesSmmRelocationComplete (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Return the size, in bytes, of a custom SMI Handler in bytes. If 0 is\r
+ returned, then a custom SMI handler is not provided by this library,\r
+ and the default SMI handler must be used.\r
+\r
+ @retval 0 Use the default SMI handler.\r
+ @retval > 0 Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()\r
+ The caller is required to allocate enough SMRAM for each CPU to\r
+ support the size of the custom SMI handler.\r
+**/\r
+UINTN\r
+EFIAPI\r
+SmmCpuFeaturesGetSmiHandlerSize (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Install a custom SMI handler for the CPU specified by CpuIndex. This function\r
+ is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater\r
+ than zero and is called by the CPU that was elected as monarch during System\r
+ Management Mode initialization.\r
+\r
+ @param[in] CpuIndex The index of the CPU to install the custom SMI handler.\r
+ The value must be between 0 and the NumberOfCpus field\r
+ in the System Management System Table (SMST).\r
+ @param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.\r
+ @param[in] SmiStack The stack to use when an SMI is processed by the\r
+ the CPU specified by CpuIndex.\r
+ @param[in] StackSize The size, in bytes, if the stack used when an SMI is\r
+ processed by the CPU specified by CpuIndex.\r
+ @param[in] GdtBase The base address of the GDT to use when an SMI is\r
+ processed by the CPU specified by CpuIndex.\r
+ @param[in] GdtSize The size, in bytes, of the GDT used when an SMI is\r
+ processed by the CPU specified by CpuIndex.\r
+ @param[in] IdtBase The base address of the IDT to use when an SMI is\r
+ processed by the CPU specified by CpuIndex.\r
+ @param[in] IdtSize The size, in bytes, of the IDT used when an SMI is\r
+ processed by the CPU specified by CpuIndex.\r
+ @param[in] Cr3 The base address of the page tables to use when an SMI\r
+ is processed by the CPU specified by CpuIndex.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesInstallSmiHandler (\r
+ IN UINTN CpuIndex,\r
+ IN UINT32 SmBase,\r
+ IN VOID *SmiStack,\r
+ IN UINTN StackSize,\r
+ IN UINTN GdtBase,\r
+ IN UINTN GdtSize,\r
+ IN UINTN IdtBase,\r
+ IN UINTN IdtSize,\r
+ IN UINT32 Cr3\r
+ );\r
+\r
+/**\r
+ Determines if MTRR registers must be configured to set SMRAM cache-ability\r
+ when executing in System Management Mode.\r
+\r
+ @retval TRUE MTRR registers must be configured to set SMRAM cache-ability.\r
+ @retval FALSE MTRR registers do not need to be configured to set SMRAM\r
+ cache-ability.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+SmmCpuFeaturesNeedConfigureMtrrs (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()\r
+ returns TRUE.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesDisableSmrr (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()\r
+ returns TRUE.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesReenableSmrr (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Processor specific hook point each time a CPU enters System Management Mode.\r
+\r
+ @param[in] CpuIndex The index of the CPU that has entered SMM. The value\r
+ must be between 0 and the NumberOfCpus field in the\r
+ System Management System Table (SMST).\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesRendezvousEntry (\r
+ IN UINTN CpuIndex\r
+ );\r
+\r
+/**\r
+ Processor specific hook point each time a CPU exits System Management Mode.\r
+\r
+ @param[in] CpuIndex The index of the CPU that is exiting SMM. The value must\r
+ be between 0 and the NumberOfCpus field in the System\r
+ Management System Table (SMST).\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesRendezvousExit (\r
+ IN UINTN CpuIndex\r
+ );\r
+\r
+/**\r
+ Check to see if an SMM register is supported by a specified CPU.\r
+\r
+ @param[in] CpuIndex The index of the CPU to check for SMM register support.\r
+ The value must be between 0 and the NumberOfCpus field\r
+ in the System Management System Table (SMST).\r
+ @param[in] RegName Identifies the SMM register to check for support.\r
+\r
+ @retval TRUE The SMM register specified by RegName is supported by the CPU\r
+ specified by CpuIndex.\r
+ @retval FALSE The SMM register specified by RegName is not supported by the\r
+ CPU specified by CpuIndex.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+SmmCpuFeaturesIsSmmRegisterSupported (\r
+ IN UINTN CpuIndex,\r
+ IN SMM_REG_NAME RegName\r
+ );\r
+\r
+/**\r
+ Returns the current value of the SMM register for the specified CPU.\r
+ If the SMM register is not supported, then 0 is returned.\r
+\r
+ @param[in] CpuIndex The index of the CPU to read the SMM register. The\r
+ value must be between 0 and the NumberOfCpus field in\r
+ the System Management System Table (SMST).\r
+ @param[in] RegName Identifies the SMM register to read.\r
+\r
+ @return The value of the SMM register specified by RegName from the CPU\r
+ specified by CpuIndex.\r
+**/\r
+UINT64\r
+EFIAPI\r
+SmmCpuFeaturesGetSmmRegister (\r
+ IN UINTN CpuIndex,\r
+ IN SMM_REG_NAME RegName\r
+ );\r
+\r
+/**\r
+ Sets the value of an SMM register on a specified CPU.\r
+ If the SMM register is not supported, then no action is performed.\r
+\r
+ @param[in] CpuIndex The index of the CPU to write the SMM register. The\r
+ value must be between 0 and the NumberOfCpus field in\r
+ the System Management System Table (SMST).\r
+ @param[in] RegName Identifies the SMM register to write.\r
+ registers are read-only.\r
+ @param[in] Value The value to write to the SMM register.\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmCpuFeaturesSetSmmRegister (\r
+ IN UINTN CpuIndex,\r
+ IN SMM_REG_NAME RegName,\r
+ IN UINT64 Value\r
+ );\r
+\r
+/**\r
+ Read an SMM Save State register on the target processor. If this function\r
+ returns EFI_UNSUPPORTED, then the caller is responsible for reading the\r
+ SMM Save Sate register.\r
+\r
+ @param[in] CpuIndex The index of the CPU to read the SMM Save State. The\r
+ value must be between 0 and the NumberOfCpus field in\r
+ the System Management System Table (SMST).\r
+ @param[in] Register The SMM Save State register to read.\r
+ @param[in] Width The number of bytes to read from the CPU save state.\r
+ @param[out] Buffer Upon return, this holds the CPU register value read\r
+ from the save state.\r
+\r
+ @retval EFI_SUCCESS The register was read from Save State.\r
+ @retval EFI_INVALID_PARAMTER Buffer is NULL.\r
+ @retval EFI_UNSUPPORTED This function does not support reading Register.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmCpuFeaturesReadSaveStateRegister (\r
+ IN UINTN CpuIndex,\r
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,\r
+ IN UINTN Width,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+/**\r
+ Writes an SMM Save State register on the target processor. If this function\r
+ returns EFI_UNSUPPORTED, then the caller is responsible for writing the\r
+ SMM Save Sate register.\r
+\r
+ @param[in] CpuIndex The index of the CPU to write the SMM Save State. The\r
+ value must be between 0 and the NumberOfCpus field in\r
+ the System Management System Table (SMST).\r
+ @param[in] Register The SMM Save State register to write.\r
+ @param[in] Width The number of bytes to write to the CPU save state.\r
+ @param[in] Buffer Upon entry, this holds the new CPU register value.\r
+\r
+ @retval EFI_SUCCESS The register was written to Save State.\r
+ @retval EFI_INVALID_PARAMTER Buffer is NULL.\r
+ @retval EFI_UNSUPPORTED This function does not support writing Register.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmCpuFeaturesWriteSaveStateRegister (\r
+ IN UINTN CpuIndex,\r
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,\r
+ IN UINTN Width,\r
+ IN CONST VOID *Buffer\r
+ );\r
+\r
+#endif\r