]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
UefiCpuPkg/PiSmmCpu: Enable 5 level paging when CPU supports
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / SmmProfile.c
index e2b6a2d9b27ad8a77a9a2badeffdaf3bdb2a4406..c5131526f0c638555f922792938c0b0d02f04226 100644 (file)
@@ -534,43 +534,78 @@ InitPaging (
   VOID\r
   )\r
 {\r
+  UINT64                            Pml5Entry;\r
+  UINT64                            Pml4Entry;\r
+  UINT64                            *Pml5;\r
   UINT64                            *Pml4;\r
   UINT64                            *Pdpt;\r
   UINT64                            *Pd;\r
   UINT64                            *Pt;\r
   UINTN                             Address;\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
-      NumberOfPdptEntries = (UINT32)LShiftU64 (1, (SizeOfMemorySpace - 30));\r
-    } else {\r
-      NumberOfPml4Entries = (UINT32)LShiftU64 (1, (SizeOfMemorySpace - 39));\r
-      NumberOfPdptEntries = 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
+    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 (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) {\r
-    if (sizeof (UINTN) == sizeof (UINT64)) {\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
+    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 PML4 entry does not exist, skip it\r
@@ -578,63 +613,76 @@ InitPaging (
         continue;\r
       }\r
       Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
-    } else {\r
-      Pdpt = (UINT64*)(UINTN)mSmmProfileCr3;\r
-    }\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
-        // This is 1G entry, skip it\r
-        //\r
-        continue;\r
-      }\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
+      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 PD entry does not exist, skip it\r
+          // This is 1G entry, skip it\r
           //\r
           continue;\r
         }\r
-        Address = (((PdptIndex << 9) + PdIndex) << 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 (((*Pd & 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 == (*Pd & PHYSICAL_ADDRESS_MASK));\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
-          Pt = AllocatePageTableMemory (1);\r
-          ASSERT (Pt != NULL);\r
+            *Pd = (UINTN) Pt | IA32_PG_RW | IA32_PG_P;\r
 \r
-          // Split it\r
-          for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof(*Pt); PtIndex++) {\r
-            Pt[PtIndex] = 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
+            // 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 (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) {\r
-    if (sizeof (UINTN) == sizeof (UINT64)) {\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
+    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 PML4 entry does not exist, skip it\r
@@ -642,69 +690,73 @@ InitPaging (
         continue;\r
       }\r
       Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
-    } else {\r
-      Pdpt = (UINT64*)(UINTN)mSmmProfileCr3;\r
-    }\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
-        // This is 1G entry, set NX bit and skip it\r
-        //\r
-        if (mXdSupported) {\r
-          *Pdpt = *Pdpt | IA32_PG_NX;\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
-      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
+        if ((*Pdpt & IA32_PG_PS) != 0) {\r
           //\r
-          // If PD 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 = (((PdptIndex << 9) + PdIndex) << 21);\r
-\r
-        if ((*Pd & 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
-            *Pd = *Pd & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);\r
-          }\r
-          if (Nx && mXdSupported) {\r
-            *Pd = *Pd | IA32_PG_NX;\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
+          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
+          } else {\r
+            // 4KB page\r
+            Pt = (UINT64 *)(UINTN)(*Pd & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
+            if (Pt == 0) {\r
+              continue;\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
+            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
@@ -1156,6 +1208,20 @@ RestorePageTableBelow4G (
 {\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