#include <Protocol/SmmCpuService.h>\r
\r
#include <Guid/AcpiS3Context.h>\r
+#include <Guid/PiSmmMemoryAttributesTable.h>\r
\r
#include <Library/BaseLib.h>\r
#include <Library/IoLib.h>\r
#define IA32_PG_PMNT BIT62\r
#define IA32_PG_NX BIT63\r
\r
-#define PAGE_ATTRIBUTE_BITS (IA32_PG_RW | IA32_PG_P)\r
+#define PAGE_ATTRIBUTE_BITS (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P)\r
//\r
// Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE\r
// X64 PAE PDPTE does not have such restriction\r
//\r
#define IA32_PAE_PDPTE_ATTRIBUTE_BITS (IA32_PG_P)\r
\r
+#define PAGE_PROGATE_BITS (IA32_PG_NX | PAGE_ATTRIBUTE_BITS)\r
+\r
+#define PAGING_4K_MASK 0xFFF\r
+#define PAGING_2M_MASK 0x1FFFFF\r
+#define PAGING_1G_MASK 0x3FFFFFFF\r
+\r
+#define PAGING_PAE_INDEX_MASK 0x1FF\r
+\r
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull\r
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull\r
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull\r
+\r
+typedef enum {\r
+ PageNone,\r
+ Page4K,\r
+ Page2M,\r
+ Page1G,\r
+} PAGE_ATTRIBUTE;\r
+\r
+typedef struct {\r
+ PAGE_ATTRIBUTE Attribute;\r
+ UINT64 Length;\r
+ UINT64 AddressMask;\r
+} PAGE_ATTRIBUTE_TABLE;\r
+\r
//\r
// Size of Task-State Segment defined in IA32 Manual\r
//\r
#define TSS_IA32_CR3_OFFSET 28\r
#define TSS_IA32_ESP_OFFSET 56\r
\r
+#define CR0_WP BIT16\r
+\r
//\r
// Code select value\r
//\r
extern CPU_HOT_PLUG_DATA mCpuHotPlugData;\r
extern UINTN mMaxNumberOfCpus;\r
extern UINTN mNumberOfCpus;\r
-extern BOOLEAN mRestoreSmmConfigurationInS3;\r
extern EFI_SMM_CPU_PROTOCOL mSmmCpu;\r
\r
///\r
#define MSR_SPIN_LOCK_INIT_NUM 15\r
\r
typedef struct {\r
- SPIN_LOCK SpinLock;\r
+ SPIN_LOCK *SpinLock;\r
UINT32 MsrIndex;\r
} MP_MSR_LOCK;\r
\r
#define SMM_PSD_OFFSET 0xfb00\r
\r
-typedef struct {\r
- UINT64 Signature; // Offset 0x00\r
- UINT16 Reserved1; // Offset 0x08\r
- UINT16 Reserved2; // Offset 0x0A\r
- UINT16 Reserved3; // Offset 0x0C\r
- UINT16 SmmCs; // Offset 0x0E\r
- UINT16 SmmDs; // Offset 0x10\r
- UINT16 SmmSs; // Offset 0x12\r
- UINT16 SmmOtherSegment; // Offset 0x14\r
- UINT16 Reserved4; // Offset 0x16\r
- UINT64 Reserved5; // Offset 0x18\r
- UINT64 Reserved6; // Offset 0x20\r
- UINT64 Reserved7; // Offset 0x28\r
- UINT64 SmmGdtPtr; // Offset 0x30\r
- UINT32 SmmGdtSize; // Offset 0x38\r
- UINT32 Reserved8; // Offset 0x3C\r
- UINT64 Reserved9; // Offset 0x40\r
- UINT64 Reserved10; // Offset 0x48\r
- UINT16 Reserved11; // Offset 0x50\r
- UINT16 Reserved12; // Offset 0x52\r
- UINT32 Reserved13; // Offset 0x54\r
- UINT64 MtrrBaseMaskPtr; // Offset 0x58\r
-} PROCESSOR_SMM_DESCRIPTOR;\r
-\r
-\r
///\r
/// All global semaphores' pointer\r
///\r
volatile BOOLEAN *AllCpusInSync;\r
SPIN_LOCK *PFLock;\r
SPIN_LOCK *CodeAccessCheckLock;\r
+ SPIN_LOCK *MemoryMappedLock;\r
} SMM_CPU_SEMAPHORE_GLOBAL;\r
\r
///\r
} SMM_CPU_SEMAPHORES;\r
\r
extern IA32_DESCRIPTOR gcSmiGdtr;\r
+extern EFI_PHYSICAL_ADDRESS mGdtBuffer;\r
+extern UINTN mGdtBufferSize;\r
extern IA32_DESCRIPTOR gcSmiIdtr;\r
extern VOID *gcSmiIdtrPtr;\r
-extern CONST PROCESSOR_SMM_DESCRIPTOR gcPsd;\r
extern UINT64 gPhyMask;\r
-extern ACPI_CPU_DATA mAcpiCpuData;\r
extern SMM_DISPATCHER_MP_SYNC_DATA *mSmmMpSyncData;\r
-extern VOID *mGdtForAp;\r
-extern VOID *mIdtForAp;\r
-extern VOID *mMachineCheckHandlerForAp;\r
extern UINTN mSmmStackArrayBase;\r
extern UINTN mSmmStackArrayEnd;\r
extern UINTN mSmmStackSize;\r
extern EFI_SMM_CPU_SERVICE_PROTOCOL mSmmCpuService;\r
extern IA32_DESCRIPTOR gcSmiInitGdtr;\r
+extern SMM_CPU_SEMAPHORES mSmmCpuSemaphores;\r
+extern UINTN mSemaphoreSize;\r
extern SPIN_LOCK *mPFLock;\r
extern SPIN_LOCK *mConfigSmmCodeAccessCheckLock;\r
+extern SPIN_LOCK *mMemoryMappedLock;\r
\r
/**\r
Create 4G PageTable in SMRAM.\r
\r
- @param ExtraPages Additional page numbers besides for 4G memory\r
- @param Is32BitPageTable Whether the page table is 32-bit PAE\r
+ @param[in] Is32BitPageTable Whether the page table is 32-bit PAE\r
@return PageTable Address\r
\r
**/\r
UINT32\r
Gen4GPageTable (\r
- IN UINTN ExtraPages,\r
IN BOOLEAN Is32BitPageTable\r
);\r
\r
\r
/**\r
Initialize Gdt for all processors.\r
- \r
+\r
@param[in] Cr3 CR3 value.\r
@param[out] GdtStepSize The step size for GDT table.\r
\r
OUT UINTN *GdtStepSize\r
);\r
\r
+/**\r
+ This function sets GDT/IDT buffer to be RO and XP.\r
+**/\r
+VOID\r
+PatchGdtIdtMap (\r
+ VOID\r
+ );\r
+\r
/**\r
\r
Register the SMM Foundation entry point.\r
IN OUT VOID *ProcArguments OPTIONAL\r
);\r
\r
+/**\r
+ This function sets the attributes for the memory region specified by BaseAddress and\r
+ Length from their current attributes to the attributes specified by Attributes.\r
+\r
+ @param[in] BaseAddress The physical address that is the start address of a memory region.\r
+ @param[in] Length The size in bytes of the memory region.\r
+ @param[in] Attributes The bit mask of attributes to set for the memory region.\r
+\r
+ @retval EFI_SUCCESS The attributes were set for the memory region.\r
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
+ BaseAddress and Length cannot be modified.\r
+ @retval EFI_INVALID_PARAMETER Length is zero.\r
+ Attributes specified an illegal combination of attributes that\r
+ cannot be set together.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
+ the memory resource range.\r
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
+ resource range specified by BaseAddress and Length.\r
+ The bit mask of attributes is not support for the memory resource\r
+ range specified by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmSetMemoryAttributes (\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes\r
+ );\r
+\r
+/**\r
+ This function clears the attributes for the memory region specified by BaseAddress and\r
+ Length from their current attributes to the attributes specified by Attributes.\r
+\r
+ @param[in] BaseAddress The physical address that is the start address of a memory region.\r
+ @param[in] Length The size in bytes of the memory region.\r
+ @param[in] Attributes The bit mask of attributes to clear for the memory region.\r
+\r
+ @retval EFI_SUCCESS The attributes were cleared for the memory region.\r
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
+ BaseAddress and Length cannot be modified.\r
+ @retval EFI_INVALID_PARAMETER Length is zero.\r
+ Attributes specified an illegal combination of attributes that\r
+ cannot be set together.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
+ the memory resource range.\r
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
+ resource range specified by BaseAddress and Length.\r
+ The bit mask of attributes is not support for the memory resource\r
+ range specified by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmClearMemoryAttributes (\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes\r
+ );\r
+\r
/**\r
Initialize MP synchronization data.\r
\r
);\r
\r
/**\r
- The function is invoked before SMBASE relocation in S3 path to restores CPU status.\r
+ Relocate SmmBases for each processor.\r
\r
- The function is invoked before SMBASE relocation in S3 path. It does first time microcode load\r
- and restores MTRRs for both BSP and APs.\r
+ Execute on first boot and all S3 resumes\r
\r
**/\r
VOID\r
-EarlyInitializeCpu (\r
- VOID\r
- );\r
-\r
-/**\r
- The function is invoked after SMBASE relocation in S3 path to restores CPU status.\r
-\r
- The function is invoked after SMBASE relocation in S3 path. It restores configuration according to\r
- data saved by normal boot path for both BSP and APs.\r
-\r
-**/\r
-VOID\r
-InitializeCpu (\r
+EFIAPI\r
+SmmRelocateBases (\r
VOID\r
);\r
\r
IN UINTN CallerIpAddress\r
);\r
\r
+/**\r
+ This function sets memory attribute according to MemoryAttributesTable.\r
+**/\r
+VOID\r
+SetMemMapAttributes (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function sets UEFI memory attribute according to UEFI memory map.\r
+**/\r
+VOID\r
+SetUefiMemMapAttributes (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Return if the Address is forbidden as SMM communication buffer.\r
+\r
+ @param[in] Address the address to be checked\r
+\r
+ @return TRUE The address is forbidden as SMM communication buffer.\r
+ @return FALSE The address is allowed as SMM communication buffer.\r
+**/\r
+BOOLEAN\r
+IsSmmCommBufferForbiddenAddress (\r
+ IN UINT64 Address\r
+ );\r
+\r
+/**\r
+ This function caches the UEFI memory map information.\r
+**/\r
+VOID\r
+GetUefiMemoryMap (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function sets memory attribute for page table.\r
+**/\r
+VOID\r
+SetPageTableAttributes (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Return page table base.\r
+\r
+ @return page table base.\r
+**/\r
+UINTN\r
+GetPageTableBase (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function sets the attributes for the memory region specified by BaseAddress and\r
+ Length from their current attributes to the attributes specified by Attributes.\r
+\r
+ @param[in] BaseAddress The physical address that is the start address of a memory region.\r
+ @param[in] Length The size in bytes of the memory region.\r
+ @param[in] Attributes The bit mask of attributes to set for the memory region.\r
+ @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.\r
+\r
+ @retval EFI_SUCCESS The attributes were set for the memory region.\r
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
+ BaseAddress and Length cannot be modified.\r
+ @retval EFI_INVALID_PARAMETER Length is zero.\r
+ Attributes specified an illegal combination of attributes that\r
+ cannot be set together.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
+ the memory resource range.\r
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
+ resource range specified by BaseAddress and Length.\r
+ The bit mask of attributes is not support for the memory resource\r
+ range specified by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmSetMemoryAttributesEx (\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes,\r
+ OUT BOOLEAN *IsSplitted OPTIONAL\r
+ );\r
+\r
+/**\r
+ This function clears the attributes for the memory region specified by BaseAddress and\r
+ Length from their current attributes to the attributes specified by Attributes.\r
+\r
+ @param[in] BaseAddress The physical address that is the start address of a memory region.\r
+ @param[in] Length The size in bytes of the memory region.\r
+ @param[in] Attributes The bit mask of attributes to clear for the memory region.\r
+ @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.\r
+\r
+ @retval EFI_SUCCESS The attributes were cleared for the memory region.\r
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
+ BaseAddress and Length cannot be modified.\r
+ @retval EFI_INVALID_PARAMETER Length is zero.\r
+ Attributes specified an illegal combination of attributes that\r
+ cannot be set together.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
+ the memory resource range.\r
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
+ resource range specified by BaseAddress and Length.\r
+ The bit mask of attributes is not support for the memory resource\r
+ range specified by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmClearMemoryAttributesEx (\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes,\r
+ OUT BOOLEAN *IsSplitted OPTIONAL\r
+ );\r
+\r
/**\r
This API provides a way to allocate memory for page table.\r
\r
IN UINTN Pages\r
);\r
\r
+/**\r
+ Allocate pages for code.\r
+\r
+ @param[in] Pages Number of pages to be allocated.\r
+\r
+ @return Allocated memory.\r
+**/\r
+VOID *\r
+AllocateCodePages (\r
+ IN UINTN Pages\r
+ );\r
+\r
+/**\r
+ Allocate aligned pages for code.\r
+\r
+ @param[in] Pages Number of pages to be allocated.\r
+ @param[in] Alignment The requested alignment of the allocation.\r
+ Must be a power of two.\r
+ If Alignment is zero, then byte alignment is used.\r
+\r
+ @return Allocated memory.\r
+**/\r
+VOID *\r
+AllocateAlignedCodePages (\r
+ IN UINTN Pages,\r
+ IN UINTN Alignment\r
+ );\r
+\r
+\r
+//\r
+// S3 related global variable and function prototype.\r
+//\r
+\r
+extern BOOLEAN mSmmS3Flag;\r
+\r
+/**\r
+ Initialize SMM S3 resume state structure used during S3 Resume.\r
+\r
+ @param[in] Cr3 The base address of the page tables to use in SMM.\r
+\r
+**/\r
+VOID\r
+InitSmmS3ResumeState (\r
+ IN UINT32 Cr3\r
+ );\r
+\r
+/**\r
+ Get ACPI CPU data.\r
+\r
+**/\r
+VOID\r
+GetAcpiCpuData (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Restore SMM Configuration in S3 boot path.\r
+\r
+**/\r
+VOID\r
+RestoreSmmConfigurationInS3 (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get ACPI S3 enable flag.\r
+\r
+**/\r
+VOID\r
+GetAcpiS3EnableFlag (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.\r
+\r
+ @param[in] ApHltLoopCode The address of the safe hlt-loop function.\r
+ @param[in] TopOfStack A pointer to the new stack to use for the ApHltLoopCode.\r
+ @param[in] NumberToFinishAddress Address of Semaphore of APs finish count.\r
+\r
+**/\r
+VOID\r
+TransferApToSafeState (\r
+ IN UINTN ApHltLoopCode,\r
+ IN UINTN TopOfStack,\r
+ IN UINTN NumberToFinishAddress\r
+ );\r
+\r
#endif\r