]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
Create 4G page table by default, and using PF to handle >4G MMIO access, to improve...
[mirror_edk2.git] / UefiCpuPkg / Universal / Acpi / S3Resume2Pei / S3Resume.c
index 50b2f7bc0a450ae7556f9df059f947d8686eb7f9..de3aec85e185375cce9660e05c219160d461b741 100644 (file)
@@ -284,7 +284,9 @@ WriteToOsS3PerformanceData (
              NULL,\r
              (VOID **) &VariableServices\r
              );\r
-  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
 \r
   VarSize   = sizeof (EFI_PHYSICAL_ADDRESS);\r
   Status = VariableServices->GetVariable (\r
@@ -365,6 +367,41 @@ WriteToOsS3PerformanceData (
   PerfHeader->S3EntryNum = (UINT32) Index;\r
 }\r
 \r
+/**\r
+  The function will check if current waking vector is long mode.\r
+\r
+  @param  AcpiS3Context                 a pointer to a structure of ACPI_S3_CONTEXT\r
+\r
+  @retval TRUE   Current context need long mode waking vector.\r
+  @retval FALSE  Current context need not long mode waking vector.\r
+**/\r
+BOOLEAN\r
+IsLongModeWakingVector (\r
+  IN ACPI_S3_CONTEXT                *AcpiS3Context\r
+  )\r
+{\r
+  EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs;\r
+\r
+  Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable));\r
+  if ((Facs == NULL) ||\r
+      (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||\r
+      ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)) ) {\r
+    // Something wrong with FACS\r
+    return FALSE;\r
+  }\r
+  if (Facs->XFirmwareWakingVector != 0) {\r
+    if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
+        ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&\r
+        ((Facs->Flags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0)) {\r
+      // Both BIOS and OS wants 64bit vector\r
+      if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+        return TRUE;\r
+      }\r
+    }\r
+  }\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Jump to OS waking vector.\r
   The function will install boot script done PPI, report S3 resume status code, and then jump to OS waking vector.\r
@@ -410,17 +447,17 @@ S3ResumeBootOs (
     return ;\r
   }\r
 \r
-  //\r
-  // report status code on S3 resume\r
-  //\r
-  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE);\r
-\r
   //\r
   // Install EndOfPeiPpi\r
   //\r
   Status = PeiServicesInstallPpi (&mPpiListEndOfPeiTable);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  //\r
+  // report status code on S3 resume\r
+  //\r
+  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE);\r
+\r
   PERF_CODE (\r
     WriteToOsS3PerformanceData ();\r
     );\r
@@ -481,10 +518,12 @@ S3ResumeBootOs (
   If BootScriptExector driver will not run in 64-bit mode, this function will do nothing. \r
 \r
   @param S3NvsPageTableAddress   PageTableAddress in ACPINvs\r
+  @param Build4GPageTableOnly    If BIOS just build 4G page table only\r
 **/\r
 VOID\r
 RestoreS3PageTables (\r
-  IN UINTN                                         S3NvsPageTableAddress\r
+  IN UINTN                                         S3NvsPageTableAddress,\r
+  IN BOOLEAN                                       Build4GPageTableOnly\r
   )\r
 {\r
   if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
@@ -511,7 +550,7 @@ RestoreS3PageTables (
     //\r
     // The assumption is : whole page table is allocated in CONTINOUS memory and CR3 points to TOP page.\r
     //\r
-    DEBUG ((EFI_D_ERROR, "S3NvsPageTableAddress - %x\n", S3NvsPageTableAddress));\r
+    DEBUG ((EFI_D_ERROR, "S3NvsPageTableAddress - %x (%x)\n", (UINTN)S3NvsPageTableAddress, (UINTN)Build4GPageTableOnly));\r
 \r
     //\r
     // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.\r
@@ -554,6 +593,14 @@ RestoreS3PageTables (
       PhysicalAddressBits = 48;\r
     }\r
 \r
+    //\r
+    // NOTE: In order to save time to create full page table, we just create 4G page table by default.\r
+    // And let PF handler in BootScript driver to create more on request.\r
+    //\r
+    if (Build4GPageTableOnly) {\r
+      PhysicalAddressBits = 32;\r
+      ZeroMem (PageMap, EFI_PAGES_TO_SIZE(2));\r
+    }\r
     //\r
     // Calculate the table entries needed.\r
     //\r
@@ -681,25 +728,22 @@ S3ResumeExecuteBootScript (
                               NULL,\r
                               (VOID **) &SmmAccess\r
                               );\r
+    if (!EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Close all SMRAM regions before executing boot script\n"));\r
+  \r
+      for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
+        Status = SmmAccess->Close ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+      }\r
 \r
-    DEBUG ((EFI_D_ERROR, "Close all SMRAM regions before executing boot script\n"));\r
-\r
-    for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
-      Status = SmmAccess->Close ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
-    }\r
-\r
-    DEBUG ((EFI_D_ERROR, "Lock all SMRAM regions before executing boot script\n"));\r
-\r
-    for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
-      Status = SmmAccess->Lock ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+      DEBUG ((EFI_D_ERROR, "Lock all SMRAM regions before executing boot script\n"));\r
+  \r
+      for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
+        Status = SmmAccess->Lock ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+      }\r
     }\r
   }\r
 \r
   if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
-    //\r
-    // Need reconstruct page table here, since we do not trust ACPINvs.\r
-    //\r
-    RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress);\r
     AsmWriteCr3 ((UINTN)AcpiS3Context->S3NvsPageTableAddress);\r
   }\r
 \r
@@ -821,7 +865,6 @@ S3RestoreConfig2 (
   PEI_SMM_ACCESS_PPI                            *SmmAccess;\r
   UINTN                                         Index;\r
   ACPI_S3_CONTEXT                               *AcpiS3Context;\r
-  EFI_PEI_READ_ONLY_VARIABLE2_PPI               *VariableServices;\r
   EFI_PHYSICAL_ADDRESS                          TempEfiBootScriptExecutorVariable;\r
   EFI_PHYSICAL_ADDRESS                          TempAcpiS3Context;\r
   BOOT_SCRIPT_EXECUTOR_VARIABLE                 *EfiBootScriptExecutorVariable;\r
@@ -829,29 +872,10 @@ S3RestoreConfig2 (
   EFI_SMRAM_DESCRIPTOR                          *SmramDescriptor;\r
   SMM_S3_RESUME_STATE                           *SmmS3ResumeState;\r
   VOID                                          *GuidHob;\r
+  BOOLEAN                                       Build4GPageTableOnly;\r
 \r
   DEBUG ((EFI_D_ERROR, "Enter S3 PEIM\r\n"));\r
 \r
-  Status = PeiServicesLocatePpi (\r
-                            &gPeiSmmAccessPpiGuid,\r
-                            0,\r
-                            NULL,\r
-                            (VOID **) &SmmAccess\r
-                            );\r
-  for (Index = 0; !EFI_ERROR (Status); Index++) {\r
-    Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
-  }\r
-\r
-  Status = PeiServicesLocatePpi (\r
-                            &gEfiPeiReadOnlyVariable2PpiGuid,\r
-                            0,\r
-                            NULL,\r
-                            (VOID **) &VariableServices\r
-                            );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
   VarSize = sizeof (EFI_PHYSICAL_ADDRESS);\r
   Status = RestoreLockBox (\r
              &gEfiAcpiVariableGuid,\r
@@ -906,11 +930,33 @@ S3RestoreConfig2 (
     CpuDeadLoop ();\r
   }\r
 \r
+  if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+    //\r
+    // Need reconstruct page table here, since we do not trust ACPINvs.\r
+    //\r
+    if (IsLongModeWakingVector (AcpiS3Context)) {\r
+      Build4GPageTableOnly = FALSE;\r
+    } else {\r
+      Build4GPageTableOnly = TRUE;\r
+    }\r
+    RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress, Build4GPageTableOnly);\r
+  }\r
+\r
   //\r
   // Attempt to use content from SMRAM first\r
   //\r
   GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);\r
   if (GuidHob != NULL) {\r
+    Status = PeiServicesLocatePpi (\r
+                              &gPeiSmmAccessPpiGuid,\r
+                              0,\r
+                              NULL,\r
+                              (VOID **) &SmmAccess\r
+                              );\r
+    for (Index = 0; !EFI_ERROR (Status); Index++) {\r
+      Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+    }\r
+\r
     SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);\r
     SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;\r
 \r