13#define PAGE_TABLE_PAGES 8
14#define ACC_MAX_BIT BIT3
17BOOLEAN m1GPageTableSupport =
FALSE;
18X86_ASSEMBLY_PATCH_LABEL gPatch5LevelPagingNeeded;
36 if (RegEax >= 0x80000001) {
38 if ((RegEdx & BIT26) != 0) {
62 UINT32 MaxExtendedFunctionId;
65 if (MaxExtendedFunctionId >= CPUID_VIR_PHY_ADDRESS_SIZE) {
81 "PhysicalAddressBits = %d, 5LPageTable = %d.\n",
106 IN OUT UINT64 *Entry,
107 IN UINT64 SubEntryNum
149 UINT8 PhysicalAddressBits;
157 PhysicalAddressBits = ((
EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;
160 if (RegEax >= 0x80000008) {
162 PhysicalAddressBits = (UINT8)RegEax;
164 PhysicalAddressBits = 36;
175 ASSERT (PhysicalAddressBits <= 52);
177 PhysicalAddressBits = 47;
180 return PhysicalAddressBits;
198 UINTN PageFaultHandlerHookAddress;
199 IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
217 if (m5LevelPagingNeeded) {
218 mPagingMode = m1GPageTableSupport ? Paging5Level1GB : Paging5Level;
220 mPagingMode = m1GPageTableSupport ? Paging4Level1GB : Paging4Level;
223 DEBUG ((DEBUG_INFO,
"5LevelPaging Needed - %d\n", m5LevelPagingNeeded));
224 DEBUG ((DEBUG_INFO,
"1GPageTable Support - %d\n", m1GPageTableSupport));
225 DEBUG ((DEBUG_INFO,
"PhysicalAddressBits - %d\n", mPhysicalAddressBits));
232 if (mSmmProfileEnabled) {
233 if (m5LevelPagingNeeded) {
234 Pml5Entry = (UINT64 *)PageTable;
239 Pml4Entry = (UINT64 *)((*Pml5Entry) & ~mAddressEncMask & gPhyMask);
241 Pml4Entry = (UINT64 *)PageTable;
247 PdptEntry = (UINT64 *)((*Pml4Entry) & ~mAddressEncMask & gPhyMask);
248 for (Index = 0; Index < 4; Index++) {
249 PdptEntry[Index] |= IA32_PG_PMNT;
261 if (FreePage ==
NULL) {
263 if (Pml5Entry !=
NULL) {
267 ASSERT (FreePage !=
NULL);
271 for (Index = 0; Index < PAGE_TABLE_PAGES; Index++) {
273 FreePage += EFI_PAGE_SIZE /
sizeof (*FreePage);
277 if (mSmmProfileEnabled ||
278 HEAP_GUARD_NONSTOP_MODE ||
279 NULL_DETECTION_NONSTOP_MODE)
286 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)gcSmiIdtr.Base;
287 IdtEntry += EXCEPT_IA32_PAGE_FAULT;
288 IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
289 IdtEntry->Bits.Reserved_0 = 0;
290 IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
291 IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
292 IdtEntry->Bits.OffsetUpper = (UINT32)(PageFaultHandlerHookAddress >> 32);
293 IdtEntry->Bits.Reserved_1 = 0;
306 DEBUG ((DEBUG_INFO,
"Initialize IDT IST field for SMM Stack Guard\n"));
313 if ((
PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
314 DEBUG ((DEBUG_INFO,
"Initialize IDT IST field for SMM Shadow Stack\n"));
322 return (UINT32)PageTable;
334 IN OUT UINT64 *Entry,
379 if ((*Entry & IA32_PG_A) != 0) {
384 *Entry &= ~(UINT64)(
UINTN)IA32_PG_A;
386 return (0x7 + ACC_MAX_BIT);
428 UINT64 SubEntriesNum;
431 UINT64 *ReleasePageAddress;
433 BOOLEAN Enable5LevelPaging;
435 UINT64 PFAddressPml5Index;
436 UINT64 PFAddressPml4Index;
437 UINT64 PFAddressPdptIndex;
438 UINT64 PFAddressPdtIndex;
449 ReleasePageAddress = 0;
457 Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);
460 if (!Enable5LevelPaging) {
465 Pml5Entry = (
UINTN)Pml5 | IA32_PG_P;
472 for (Pml5Index = 0; Pml5Index < (Enable5LevelPaging ? (EFI_PAGE_SIZE /
sizeof (*Pml4)) : 1); Pml5Index++) {
473 if (((Pml5[Pml5Index] & IA32_PG_P) == 0) || ((Pml5[Pml5Index] & IA32_PG_PMNT) != 0)) {
480 Pml4 = (UINT64 *)(
UINTN)(Pml5[Pml5Index] & gPhyMask);
481 for (Pml4Index = 0; Pml4Index < EFI_PAGE_SIZE /
sizeof (*Pml4); Pml4Index++) {
482 if (((Pml4[Pml4Index] & IA32_PG_P) == 0) || ((Pml4[Pml4Index] & IA32_PG_PMNT) != 0)) {
489 Pdpt = (UINT64 *)(
UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & gPhyMask);
491 for (PdptIndex = 0; PdptIndex < EFI_PAGE_SIZE /
sizeof (*Pdpt); PdptIndex++) {
492 if (((Pdpt[PdptIndex] & IA32_PG_P) == 0) || ((Pdpt[PdptIndex] & IA32_PG_PMNT) != 0)) {
496 if ((Pdpt[PdptIndex] & IA32_PG_PMNT) != 0) {
506 if ((Pdpt[PdptIndex] & IA32_PG_PS) == 0) {
512 Pdt = (UINT64 *)(
UINTN)(Pdpt[PdptIndex] & ~mAddressEncMask & gPhyMask);
514 for (PdtIndex = 0; PdtIndex < EFI_PAGE_SIZE /
sizeof (*Pdt); PdtIndex++) {
515 if (((Pdt[PdtIndex] & IA32_PG_P) == 0) || ((Pdt[PdtIndex] & IA32_PG_PMNT) != 0)) {
519 if ((Pdt[PdtIndex] & IA32_PG_PMNT) != 0) {
529 if ((Pdt[PdtIndex] & IA32_PG_PS) == 0) {
535 if ((PdtIndex != PFAddressPdtIndex) || (PdptIndex != PFAddressPdptIndex) ||
536 (Pml4Index != PFAddressPml4Index) || (Pml5Index != PFAddressPml5Index))
549 ReleasePageAddress = Pdt + PdtIndex;
560 if ((PdptIndex != PFAddressPdptIndex) || (Pml4Index != PFAddressPml4Index) ||
561 (Pml5Index != PFAddressPml5Index))
574 ReleasePageAddress = Pdpt + PdptIndex;
586 if ((Pml4Index != PFAddressPml4Index) || (Pml5Index != PFAddressPml5Index)) {
598 ReleasePageAddress = Pml4 + Pml4Index;
608 ASSERT (MinAcc != (UINT64)-1);
614 *ReleasePageAddress = 0;
621 if (MinPdt != (
UINTN)-1) {
625 Pml4 = (UINT64 *)(
UINTN)(Pml5[MinPml5] & gPhyMask);
626 Pdpt = (UINT64 *)(
UINTN)(Pml4[MinPml4] & ~mAddressEncMask & gPhyMask);
628 if ((SubEntriesNum == 0) &&
629 ((MinPdpt != PFAddressPdptIndex) || (MinPml4 != PFAddressPml4Index) || (MinPml5 != PFAddressPml5Index)))
651 if (MinPdpt != (
UINTN)-1) {
656 if ((SubEntriesNum == 0) && ((MinPml4 != PFAddressPml4Index) || (MinPml5 != PFAddressPml5Index))) {
704 RetVal = (UINT64)(
UINTN)mPagePool.ForwardLink;
729 UINTN GuardPageAddress;
730 UINTN ShadowStackGuardPageAddress;
733 ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT);
739 if (PFAddress >=
LShiftU64 (1, (mPhysicalAddressBits - 1))) {
741 DEBUG ((DEBUG_ERROR,
"Do not support address 0x%lx by processor!\n", PFAddress));
750 if ((PFAddress >= mCpuHotPlugData.SmrrBase) &&
751 (PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)))
755 GuardPageAddress = (mSmmStackArrayBase + EFI_PAGE_SIZE + CpuIndex * (mSmmStackSize + mSmmShadowStackSize));
756 ShadowStackGuardPageAddress = (mSmmStackArrayBase + mSmmStackSize + EFI_PAGE_SIZE + CpuIndex * (mSmmStackSize + mSmmShadowStackSize));
758 (PFAddress >= GuardPageAddress) &&
759 (PFAddress < (GuardPageAddress + EFI_PAGE_SIZE)))
761 DEBUG ((DEBUG_ERROR,
"SMM stack overflow!\n"));
763 (mSmmShadowStackSize > 0) &&
764 (PFAddress >= ShadowStackGuardPageAddress) &&
765 (PFAddress < (ShadowStackGuardPageAddress + EFI_PAGE_SIZE)))
767 DEBUG ((DEBUG_ERROR,
"SMM shadow stack overflow!\n"));
769 if ((SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0) {
770 DEBUG ((DEBUG_ERROR,
"SMM exception at execution (0x%lx)\n", PFAddress));
775 DEBUG ((DEBUG_ERROR,
"SMM exception at access (0x%lx)\n", PFAddress));
781 if (HEAP_GUARD_NONSTOP_MODE) {
794 if ((PFAddress < mCpuHotPlugData.SmrrBase) ||
795 (PFAddress >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))
797 if ((SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0) {
799 DEBUG ((DEBUG_ERROR,
"Code executed on IP(0x%lx) out of SMM range after SMM is locked!\n", PFAddress));
810 if (((
PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) &&
811 (PFAddress < EFI_PAGE_SIZE))
814 DEBUG ((DEBUG_ERROR,
"!!! NULL pointer access !!!\n"));
819 if (NULL_DETECTION_NONSTOP_MODE) {
829 DEBUG ((DEBUG_ERROR,
"Access SMM communication forbidden address (0x%lx)!\n", PFAddress));
833 if (mSmmProfileEnabled) {
834 if (mIsStandaloneMm) {
842 SystemContext.SystemContextX64->Rip,
843 SystemContext.SystemContextX64->ExceptionData
873 if (mSmmProfileEnabled) {
894 if (mSmmProfileEnabled) {
VOID *EFIAPI GetFirstHob(IN UINT16 Type)
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
UINT64 EFIAPI BitFieldWrite64(IN UINT64 Operand, IN UINTN StartBit, IN UINTN EndBit, IN UINT64 Value)
VOID EFIAPI CpuDeadLoop(VOID)
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead)
UINT64 EFIAPI BitFieldRead64(IN UINT64 Operand, IN UINTN StartBit, IN UINTN EndBit)
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
UINT32 EFIAPI AsmCpuidEx(IN UINT32 Index, IN UINT32 SubIndex, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
EFI_STATUS EFIAPI SmmRegisterExceptionHandler(IN EFI_SMM_CPU_SERVICE_PROTOCOL *This, IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler)
VOID EFIAPI FreePages(IN VOID *Buffer, IN UINTN Pages)
UINTN EFIAPI AsmReadCr3(VOID)
UINTN EFIAPI AsmWriteCr2(UINTN Cr2)
UINTN EFIAPI AsmReadCr2(VOID)
UINTN EFIAPI AsmReadCr4(VOID)
UINT32 SmmInitPageTable(VOID)
VOID RestoreCr2(IN UINTN Cr2)
VOID EFIAPI SmiPFHandler(IN EFI_EXCEPTION_TYPE InterruptType, IN EFI_SYSTEM_CONTEXT SystemContext)
VOID SaveCr2(OUT UINTN *Cr2)
VOID * AllocatePageTableMemory(IN UINTN Pages)
VOID EFIAPI DumpCpuContext(IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext)
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)
#define DEBUG_CODE(Expression)
#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS
#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO
UINT32 EFIAPI AsmCpuid(IN UINT32 Index, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
BOOLEAN IsNonMmramLoggingAddress(IN UINT64 Address)
BOOLEAN IsSmmCommBufferForbiddenAddress(IN UINT64 Address)
#define PcdGet8(TokenName)
#define PcdGet32(TokenName)
#define FeaturePcdGet(TokenName)
VOID DumpModuleInfoByIp(IN UINTN CallerIpAddress)
VOID EFIAPI InitializeIdtIst(IN EFI_EXCEPTION_TYPE ExceptionType, IN UINT8 Ist)
UINTN GenSmmPageTable(IN PAGING_MODE PagingMode, IN UINT8 PhysicalAddressBits)
VOID SmmProfilePFHandler(UINTN Rip, UINTN ErrorCode)
VOID GuardPagePFHandler(UINTN ErrorCode)
VOID EFIAPI PageFaultIdtHandlerSmmProfile(VOID)
SPIN_LOCK *EFIAPI AcquireSpinLock(IN OUT SPIN_LOCK *SpinLock)
SPIN_LOCK *EFIAPI InitializeSpinLock(OUT SPIN_LOCK *SpinLock)
SPIN_LOCK *EFIAPI ReleaseSpinLock(IN OUT SPIN_LOCK *SpinLock)
VOID EFIAPI Exit(IN EFI_STATUS Status)
BOOLEAN Is5LevelPagingNeeded(VOID)
UINT64 GetSubEntriesNum(IN UINT64 *Entry)
UINT8 CalculateMaximumSupportAddress(BOOLEAN Is5LevelPagingNeeded)
BOOLEAN Is1GPageSupport(VOID)
UINT64 GetAccNum(IN UINT64 *Entry)
VOID SetAccNum(IN OUT UINT64 *Entry, IN UINT64 Acc)
VOID SetSubEntriesNum(IN OUT UINT64 *Entry, IN UINT64 SubEntryNum)
UINT64 GetAndUpdateAccNum(IN OUT UINT64 *Entry)
VOID EFIAPI PatchInstructionX86(OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd, IN UINT64 PatchValue, IN UINTN ValueSize)
struct CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX::@709 Bits
struct CPUID_VIR_PHY_ADDRESS_SIZE_EAX::@753 Bits
UINT32 PhysicalAddressBits