/** @file\r
Enable SMM profile.\r
\r
-Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>\r
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
\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
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
VOID\r
)\r
{\r
+ UINT64 Pml5Entry;\r
+ UINT64 Pml4Entry;\r
+ UINT64 *Pml5;\r
UINT64 *Pml4;\r
- UINT64 *Pde;\r
- UINT64 *Pte;\r
+ UINT64 *Pdpt;\r
+ UINT64 *Pd;\r
UINT64 *Pt;\r
UINTN Address;\r
- UINTN Level1;\r
- UINTN Level2;\r
- UINTN Level3;\r
- UINTN Level4;\r
- UINTN NumberOfPdpEntries;\r
+ UINTN Pml5Index;\r
+ UINTN Pml4Index;\r
+ UINTN PdptIndex;\r
+ UINTN PdIndex;\r
+ UINTN PtIndex;\r
+ UINTN NumberOfPdptEntries;\r
UINTN NumberOfPml4Entries;\r
+ UINTN NumberOfPml5Entries;\r
UINTN SizeOfMemorySpace;\r
BOOLEAN Nx;\r
+ IA32_CR4 Cr4;\r
+ BOOLEAN Enable5LevelPaging;\r
+\r
+ Cr4.UintN = AsmReadCr4 ();\r
+ Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);\r
\r
if (sizeof (UINTN) == sizeof (UINT64)) {\r
- Pml4 = (UINT64*)(UINTN)mSmmProfileCr3;\r
+ if (!Enable5LevelPaging) {\r
+ Pml5Entry = (UINTN) mSmmProfileCr3 | IA32_PG_P;\r
+ Pml5 = &Pml5Entry;\r
+ } else {\r
+ Pml5 = (UINT64*) (UINTN) mSmmProfileCr3;\r
+ }\r
SizeOfMemorySpace = HighBitSet64 (gPhyMask) + 1;\r
//\r
// Calculate the table entries of PML4E and PDPTE.\r
//\r
- if (SizeOfMemorySpace <= 39 ) {\r
- NumberOfPml4Entries = 1;\r
- NumberOfPdpEntries = (UINT32)LShiftU64 (1, (SizeOfMemorySpace - 30));\r
- } else {\r
- NumberOfPml4Entries = (UINT32)LShiftU64 (1, (SizeOfMemorySpace - 39));\r
- NumberOfPdpEntries = 512;\r
+ NumberOfPml5Entries = 1;\r
+ if (SizeOfMemorySpace > 48) {\r
+ NumberOfPml5Entries = (UINTN) LShiftU64 (1, SizeOfMemorySpace - 48);\r
+ SizeOfMemorySpace = 48;\r
}\r
- } else {\r
+\r
NumberOfPml4Entries = 1;\r
- NumberOfPdpEntries = 4;\r
+ if (SizeOfMemorySpace > 39) {\r
+ NumberOfPml4Entries = (UINTN) LShiftU64 (1, SizeOfMemorySpace - 39);\r
+ SizeOfMemorySpace = 39;\r
+ }\r
+\r
+ NumberOfPdptEntries = 1;\r
+ ASSERT (SizeOfMemorySpace > 30);\r
+ NumberOfPdptEntries = (UINTN) LShiftU64 (1, SizeOfMemorySpace - 30);\r
+ } else {\r
+ Pml4Entry = (UINTN) mSmmProfileCr3 | IA32_PG_P;\r
+ Pml4 = &Pml4Entry;\r
+ Pml5Entry = (UINTN) Pml4 | IA32_PG_P;\r
+ Pml5 = &Pml5Entry;\r
+ NumberOfPml5Entries = 1;\r
+ NumberOfPml4Entries = 1;\r
+ NumberOfPdptEntries = 4;\r
}\r
\r
//\r
// Go through page table and change 2MB-page into 4KB-page.\r
//\r
- for (Level1 = 0; Level1 < NumberOfPml4Entries; Level1++) {\r
- if (sizeof (UINTN) == sizeof (UINT64)) {\r
- if ((Pml4[Level1] & IA32_PG_P) == 0) {\r
- //\r
- // If Pml4 entry does not exist, skip it\r
- //\r
- continue;\r
- }\r
- Pde = (UINT64 *)(UINTN)(Pml4[Level1] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
- } else {\r
- Pde = (UINT64*)(UINTN)mSmmProfileCr3;\r
+ for (Pml5Index = 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) {\r
+ if ((Pml5[Pml5Index] & IA32_PG_P) == 0) {\r
+ //\r
+ // If PML5 entry does not exist, skip it\r
+ //\r
+ continue;\r
}\r
- for (Level2 = 0; Level2 < NumberOfPdpEntries; Level2++, Pde++) {\r
- if ((*Pde & IA32_PG_P) == 0) {\r
- //\r
- // If PDE entry does not exist, skip it\r
- //\r
- continue;\r
- }\r
- if ((*Pde & IA32_PG_PS) != 0) {\r
+ Pml4 = (UINT64 *) (UINTN) (Pml5[Pml5Index] & PHYSICAL_ADDRESS_MASK);\r
+ for (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) {\r
+ if ((Pml4[Pml4Index] & IA32_PG_P) == 0) {\r
//\r
- // This is 1G entry, skip it\r
+ // If PML4 entry does not exist, skip it\r
//\r
continue;\r
}\r
- Pte = (UINT64 *)(UINTN)(*Pde & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
- if (Pte == 0) {\r
- continue;\r
- }\r
- for (Level3 = 0; Level3 < SIZE_4KB / sizeof (*Pte); Level3++, Pte++) {\r
- if ((*Pte & IA32_PG_P) == 0) {\r
+ Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
+ for (PdptIndex = 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pdpt++) {\r
+ if ((*Pdpt & IA32_PG_P) == 0) {\r
+ //\r
+ // If PDPT entry does not exist, skip it\r
+ //\r
+ continue;\r
+ }\r
+ if ((*Pdpt & IA32_PG_PS) != 0) {\r
//\r
- // If PTE entry does not exist, skip it\r
+ // This is 1G entry, skip it\r
//\r
continue;\r
}\r
- Address = (((Level2 << 9) + Level3) << 21);\r
+ Pd = (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
+ if (Pd == 0) {\r
+ continue;\r
+ }\r
+ for (PdIndex = 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, Pd++) {\r
+ if ((*Pd & IA32_PG_P) == 0) {\r
+ //\r
+ // If PD entry does not exist, skip it\r
+ //\r
+ continue;\r
+ }\r
+ Address = (UINTN) LShiftU64 (\r
+ LShiftU64 (\r
+ LShiftU64 ((Pml5Index << 9) + Pml4Index, 9) + PdptIndex,\r
+ 9\r
+ ) + PdIndex,\r
+ 21\r
+ );\r
\r
- //\r
- // If it is 2M page, check IsAddressSplit()\r
- //\r
- if (((*Pte & IA32_PG_PS) != 0) && IsAddressSplit (Address)) {\r
//\r
- // Based on current page table, create 4KB page table for split area.\r
+ // If it is 2M page, check IsAddressSplit()\r
//\r
- ASSERT (Address == (*Pte & PHYSICAL_ADDRESS_MASK));\r
-\r
- Pt = AllocatePageTableMemory (1);\r
- ASSERT (Pt != NULL);\r
-\r
- // Split it\r
- for (Level4 = 0; Level4 < SIZE_4KB / sizeof(*Pt); Level4++) {\r
- Pt[Level4] = Address + ((Level4 << 12) | mAddressEncMask | PAGE_ATTRIBUTE_BITS);\r
- } // end for PT\r
- *Pte = (UINT64)(UINTN)Pt | mAddressEncMask | PAGE_ATTRIBUTE_BITS;\r
- } // end if IsAddressSplit\r
- } // end for PTE\r
- } // end for PDE\r
- }\r
+ if (((*Pd & IA32_PG_PS) != 0) && IsAddressSplit (Address)) {\r
+ //\r
+ // Based on current page table, create 4KB page table for split area.\r
+ //\r
+ ASSERT (Address == (*Pd & PHYSICAL_ADDRESS_MASK));\r
+\r
+ Pt = AllocatePageTableMemory (1);\r
+ ASSERT (Pt != NULL);\r
+\r
+ *Pd = (UINTN) Pt | IA32_PG_RW | IA32_PG_P;\r
+\r
+ // Split it\r
+ for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof(*Pt); PtIndex++, Pt++) {\r
+ *Pt = Address + ((PtIndex << 12) | mAddressEncMask | PAGE_ATTRIBUTE_BITS);\r
+ } // end for PT\r
+ *Pd = (UINT64)(UINTN)Pt | mAddressEncMask | PAGE_ATTRIBUTE_BITS;\r
+ } // end if IsAddressSplit\r
+ } // end for PD\r
+ } // end for PDPT\r
+ } // end for PML4\r
+ } // end for PML5\r
\r
//\r
// Go through page table and set several page table entries to absent or execute-disable.\r
//\r
DEBUG ((EFI_D_INFO, "Patch page table start ...\n"));\r
- for (Level1 = 0; Level1 < NumberOfPml4Entries; Level1++) {\r
- if (sizeof (UINTN) == sizeof (UINT64)) {\r
- if ((Pml4[Level1] & IA32_PG_P) == 0) {\r
- //\r
- // If Pml4 entry does not exist, skip it\r
- //\r
- continue;\r
- }\r
- Pde = (UINT64 *)(UINTN)(Pml4[Level1] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
- } else {\r
- Pde = (UINT64*)(UINTN)mSmmProfileCr3;\r
+ for (Pml5Index = 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) {\r
+ if ((Pml5[Pml5Index] & IA32_PG_P) == 0) {\r
+ //\r
+ // If PML5 entry does not exist, skip it\r
+ //\r
+ continue;\r
}\r
- for (Level2 = 0; Level2 < NumberOfPdpEntries; Level2++, Pde++) {\r
- if ((*Pde & IA32_PG_P) == 0) {\r
+ Pml4 = (UINT64 *) (UINTN) (Pml5[Pml5Index] & PHYSICAL_ADDRESS_MASK);\r
+ for (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) {\r
+ if ((Pml4[Pml4Index] & IA32_PG_P) == 0) {\r
//\r
- // If PDE entry does not exist, skip it\r
+ // If PML4 entry does not exist, skip it\r
//\r
continue;\r
}\r
- if ((*Pde & IA32_PG_PS) != 0) {\r
- //\r
- // This is 1G entry, set NX bit and skip it\r
- //\r
- if (mXdSupported) {\r
- *Pde = *Pde | IA32_PG_NX;\r
+ Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
+ for (PdptIndex = 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pdpt++) {\r
+ if ((*Pdpt & IA32_PG_P) == 0) {\r
+ //\r
+ // If PDPT entry does not exist, skip it\r
+ //\r
+ continue;\r
}\r
- continue;\r
- }\r
- Pte = (UINT64 *)(UINTN)(*Pde & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
- if (Pte == 0) {\r
- continue;\r
- }\r
- for (Level3 = 0; Level3 < SIZE_4KB / sizeof (*Pte); Level3++, Pte++) {\r
- if ((*Pte & IA32_PG_P) == 0) {\r
+ if ((*Pdpt & IA32_PG_PS) != 0) {\r
//\r
- // If PTE entry does not exist, skip it\r
+ // This is 1G entry, set NX bit and skip it\r
//\r
+ if (mXdSupported) {\r
+ *Pdpt = *Pdpt | IA32_PG_NX;\r
+ }\r
continue;\r
}\r
- Address = (((Level2 << 9) + Level3) << 21);\r
-\r
- if ((*Pte & IA32_PG_PS) != 0) {\r
- // 2MB page\r
-\r
- if (!IsAddressValid (Address, &Nx)) {\r
+ Pd = (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
+ if (Pd == 0) {\r
+ continue;\r
+ }\r
+ for (PdIndex = 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, Pd++) {\r
+ if ((*Pd & IA32_PG_P) == 0) {\r
//\r
- // Patch to remove Present flag and RW flag\r
+ // If PD entry does not exist, skip it\r
//\r
- *Pte = *Pte & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);\r
- }\r
- if (Nx && mXdSupported) {\r
- *Pte = *Pte | IA32_PG_NX;\r
- }\r
- } else {\r
- // 4KB page\r
- Pt = (UINT64 *)(UINTN)(*Pte & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
- if (Pt == 0) {\r
continue;\r
}\r
- for (Level4 = 0; Level4 < SIZE_4KB / sizeof(*Pt); Level4++, Pt++) {\r
+ Address = (UINTN) LShiftU64 (\r
+ LShiftU64 (\r
+ LShiftU64 ((Pml5Index << 9) + Pml4Index, 9) + PdptIndex,\r
+ 9\r
+ ) + PdIndex,\r
+ 21\r
+ );\r
+\r
+ if ((*Pd & IA32_PG_PS) != 0) {\r
+ // 2MB page\r
+\r
if (!IsAddressValid (Address, &Nx)) {\r
- *Pt = *Pt & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);\r
+ //\r
+ // Patch to remove Present flag and RW flag\r
+ //\r
+ *Pd = *Pd & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);\r
}\r
if (Nx && mXdSupported) {\r
- *Pt = *Pt | IA32_PG_NX;\r
+ *Pd = *Pd | IA32_PG_NX;\r
}\r
- Address += SIZE_4KB;\r
- } // end for PT\r
- } // end if PS\r
- } // end for PTE\r
- } // end for PDE\r
- }\r
+ } else {\r
+ // 4KB page\r
+ Pt = (UINT64 *)(UINTN)(*Pd & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
+ if (Pt == 0) {\r
+ continue;\r
+ }\r
+ for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof(*Pt); PtIndex++, Pt++) {\r
+ if (!IsAddressValid (Address, &Nx)) {\r
+ *Pt = *Pt & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);\r
+ }\r
+ if (Nx && mXdSupported) {\r
+ *Pt = *Pt | IA32_PG_NX;\r
+ }\r
+ Address += SIZE_4KB;\r
+ } // end for PT\r
+ } // end if PS\r
+ } // end for PD\r
+ } // end for PDPT\r
+ } // end for PML4\r
+ } // end for PML5\r
\r
//\r
// Flush TLB\r
}\r
\r
/**\r
- Check if XD feature is supported by a processor.\r
+ Check if feature is supported by a processor.\r
\r
**/\r
VOID\r
)\r
{\r
UINT32 RegEax;\r
+ UINT32 RegEcx;\r
UINT32 RegEdx;\r
MSR_IA32_MISC_ENABLE_REGISTER MiscEnableMsr;\r
\r
+ if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {\r
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax <= CPUID_EXTENDED_FUNCTION) {\r
+ mCetSupported = FALSE;\r
+ PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);\r
+ }\r
+ AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, NULL, &RegEcx, NULL);\r
+ if ((RegEcx & CPUID_CET_SS) == 0) {\r
+ mCetSupported = FALSE;\r
+ PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);\r
+ }\r
+ }\r
+\r
if (mXdSupported) {\r
AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
if (RegEax <= CPUID_EXTENDED_FUNCTION) {\r
{\r
UINTN PTIndex;\r
UINTN PFIndex;\r
+ IA32_CR4 Cr4;\r
+ BOOLEAN Enable5LevelPaging;\r
+\r
+ Cr4.UintN = AsmReadCr4 ();\r
+ Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);\r
+\r
+ //\r
+ // PML5\r
+ //\r
+ if (Enable5LevelPaging) {\r
+ PTIndex = (UINTN)BitFieldRead64 (PFAddress, 48, 56);\r
+ ASSERT (PageTable[PTIndex] != 0);\r
+ PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);\r
+ }\r
\r
//\r
// PML4\r