]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c
Use CPU_HOB to detect max address support from platform, and added 1G page table...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / Acpi / AcpiS3SaveDxe / AcpiS3Save.c
index 73074a2684f74b45e194a07ae215fa4e52c58584..27e693957295c43add12335ba0e8ba85dfa6f9ff 100644 (file)
@@ -20,6 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/HobLib.h>\r
 #include <Library/LockBoxLib.h>\r
 #include <Library/PcdLib.h>\r
 #include <Library/DebugLib.h>\r
@@ -201,46 +202,76 @@ S3CreateIdentityMappingPageTables (
 {  \r
   if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
     UINT32                                        RegEax;\r
+    UINT32                                        RegEdx;\r
     UINT8                                         PhysicalAddressBits;\r
     EFI_PHYSICAL_ADDRESS                          PageAddress;\r
     UINTN                                         IndexOfPml4Entries;\r
     UINTN                                         IndexOfPdpEntries;\r
     UINTN                                         IndexOfPageDirectoryEntries;\r
-    UINT                                        NumberOfPml4EntriesNeeded;\r
-    UINT                                        NumberOfPdpEntriesNeeded;\r
+    UINT32                                        NumberOfPml4EntriesNeeded;\r
+    UINT32                                        NumberOfPdpEntriesNeeded;\r
     PAGE_MAP_AND_DIRECTORY_POINTER                *PageMapLevel4Entry;\r
     PAGE_MAP_AND_DIRECTORY_POINTER                *PageMap;\r
     PAGE_MAP_AND_DIRECTORY_POINTER                *PageDirectoryPointerEntry;\r
     PAGE_TABLE_ENTRY                              *PageDirectoryEntry;\r
     EFI_PHYSICAL_ADDRESS                          S3NvsPageTableAddress;\r
     UINTN                                         TotalPageTableSize;\r
+    VOID                                          *Hob;\r
+    BOOLEAN                                       Page1GSupport;\r
+    PAGE_TABLE_1G_ENTRY                           *PageDirectory1GEntry;\r
+\r
+    Page1GSupport = FALSE;\r
+    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+    if (RegEax >= 0x80000001) {\r
+      AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
+      if ((RegEdx & BIT26) != 0) {\r
+        Page1GSupport = TRUE;\r
+      }\r
+    }\r
 \r
     //\r
     // Get physical address bits supported.\r
     //\r
-    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
-    if (RegEax >= 0x80000008) {\r
-      AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
-      PhysicalAddressBits = (UINT8) RegEax;\r
+    Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
+    if (Hob != NULL) {\r
+      PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
     } else {\r
-      PhysicalAddressBits = 36;\r
+      AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+      if (RegEax >= 0x80000008) {\r
+        AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+        PhysicalAddressBits = (UINT8) RegEax;\r
+      } else {\r
+        PhysicalAddressBits = 36;\r
+      }\r
     }\r
     \r
+    //\r
+    // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.\r
+    //\r
+    ASSERT (PhysicalAddressBits <= 52);\r
+    if (PhysicalAddressBits > 48) {\r
+      PhysicalAddressBits = 48;\r
+    }\r
+\r
     //\r
     // Calculate the table entries needed.\r
     //\r
     if (PhysicalAddressBits <= 39 ) {\r
       NumberOfPml4EntriesNeeded = 1;\r
-      NumberOfPdpEntriesNeeded = (UINTN)LShiftU64 (1, (PhysicalAddressBits - 30));\r
+      NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));\r
     } else {\r
-      NumberOfPml4EntriesNeeded = (UINTN)LShiftU64 (1, (PhysicalAddressBits - 39));\r
+      NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));\r
       NumberOfPdpEntriesNeeded = 512;\r
     }\r
 \r
     //\r
     // We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs.\r
     //\r
-    TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded);\r
+    if (!Page1GSupport) {\r
+      TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded);\r
+    } else {\r
+      TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded);\r
+    }\r
     DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %x pages\n", TotalPageTableSize));\r
 \r
     //\r
@@ -267,29 +298,44 @@ S3CreateIdentityMappingPageTables (
       PageMapLevel4Entry->Bits.ReadWrite = 1;\r
       PageMapLevel4Entry->Bits.Present = 1;\r
     \r
-      for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
-        //\r
-        // Each Directory Pointer entries points to a page of Page Directory entires.\r
-        // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.\r
-        //       \r
-        PageDirectoryEntry = (PAGE_TABLE_ENTRY *)(UINTN)S3NvsPageTableAddress;\r
+      if (Page1GSupport) {\r
+        PageDirectory1GEntry = (VOID *) S3NvsPageTableAddress;\r
         S3NvsPageTableAddress += SIZE_4KB;\r
     \r
-        //\r
-        // Fill in a Page Directory Pointer Entries\r
-        //\r
-        PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;\r
-        PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
-        PageDirectoryPointerEntry->Bits.Present = 1;\r
-    \r
-        for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += 0x200000) {\r
+        for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {\r
           //\r
           // Fill in the Page Directory entries\r
           //\r
-          PageDirectoryEntry->Uint64 = (UINT64)PageAddress;\r
-          PageDirectoryEntry->Bits.ReadWrite = 1;\r
-          PageDirectoryEntry->Bits.Present = 1;\r
-          PageDirectoryEntry->Bits.MustBe1 = 1;\r
+          PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;\r
+          PageDirectory1GEntry->Bits.ReadWrite = 1;\r
+          PageDirectory1GEntry->Bits.Present = 1;\r
+          PageDirectory1GEntry->Bits.MustBe1 = 1;\r
+        }\r
+      } else {\r
+        for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
+          //\r
+          // Each Directory Pointer entries points to a page of Page Directory entires.\r
+          // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.\r
+          //       \r
+          PageDirectoryEntry = (PAGE_TABLE_ENTRY *)(UINTN)S3NvsPageTableAddress;\r
+          S3NvsPageTableAddress += SIZE_4KB;\r
+      \r
+          //\r
+          // Fill in a Page Directory Pointer Entries\r
+          //\r
+          PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;\r
+          PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
+          PageDirectoryPointerEntry->Bits.Present = 1;\r
+      \r
+          for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {\r
+            //\r
+            // Fill in the Page Directory entries\r
+            //\r
+            PageDirectoryEntry->Uint64 = (UINT64)PageAddress;\r
+            PageDirectoryEntry->Bits.ReadWrite = 1;\r
+            PageDirectoryEntry->Bits.Present = 1;\r
+            PageDirectoryEntry->Bits.MustBe1 = 1;\r
+          }\r
         }\r
       }\r
     }\r