]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
OvmfPkg/MemEncryptSevLib: add support to validate > 4GB memory in PEI phase
[mirror_edk2.git] / OvmfPkg / Library / BaseMemEncryptSevLib / X64 / PeiDxeVirtualMemory.c
index bbc48ff6d87903f8904ac6a93db9fbb7c2bbbb6e..f1485722f7cf22abade68fd17f06393750576dfe 100644 (file)
@@ -536,6 +536,120 @@ EnableReadOnlyPageWriteProtect (
   AsmWriteCr0 (AsmReadCr0 () | BIT16);\r
 }\r
 \r
+RETURN_STATUS\r
+EFIAPI\r
+InternalMemEncryptSevCreateIdentityMap1G (\r
+  IN    PHYSICAL_ADDRESS  Cr3BaseAddress,\r
+  IN    PHYSICAL_ADDRESS  PhysicalAddress,\r
+  IN    UINTN             Length\r
+  )\r
+{\r
+  PAGE_MAP_AND_DIRECTORY_POINTER  *PageMapLevel4Entry;\r
+  PAGE_TABLE_1G_ENTRY             *PageDirectory1GEntry;\r
+  UINT64                          PgTableMask;\r
+  UINT64                          AddressEncMask;\r
+  BOOLEAN                         IsWpEnabled;\r
+  RETURN_STATUS                   Status;\r
+\r
+  //\r
+  // Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnings.\r
+  //\r
+  PageMapLevel4Entry = NULL;\r
+\r
+  DEBUG ((\r
+    DEBUG_VERBOSE,\r
+    "%a:%a: Cr3Base=0x%Lx Physical=0x%Lx Length=0x%Lx\n",\r
+    gEfiCallerBaseName,\r
+    __FUNCTION__,\r
+    Cr3BaseAddress,\r
+    PhysicalAddress,\r
+    (UINT64)Length\r
+    ));\r
+\r
+  if (Length == 0) {\r
+    return RETURN_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Check if we have a valid memory encryption mask\r
+  //\r
+  AddressEncMask = InternalGetMemEncryptionAddressMask ();\r
+  if (!AddressEncMask) {\r
+    return RETURN_ACCESS_DENIED;\r
+  }\r
+\r
+  PgTableMask = AddressEncMask | EFI_PAGE_MASK;\r
+\r
+  //\r
+  // Make sure that the page table is changeable.\r
+  //\r
+  IsWpEnabled = IsReadOnlyPageWriteProtected ();\r
+  if (IsWpEnabled) {\r
+    DisableReadOnlyPageWriteProtect ();\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  while (Length) {\r
+    //\r
+    // If Cr3BaseAddress is not specified then read the current CR3\r
+    //\r
+    if (Cr3BaseAddress == 0) {\r
+      Cr3BaseAddress = AsmReadCr3 ();\r
+    }\r
+\r
+    PageMapLevel4Entry  = (VOID *)(Cr3BaseAddress & ~PgTableMask);\r
+    PageMapLevel4Entry += PML4_OFFSET (PhysicalAddress);\r
+    if (!PageMapLevel4Entry->Bits.Present) {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "%a:%a: bad PML4 for Physical=0x%Lx\n",\r
+        gEfiCallerBaseName,\r
+        __FUNCTION__,\r
+        PhysicalAddress\r
+        ));\r
+      Status = RETURN_NO_MAPPING;\r
+      goto Done;\r
+    }\r
+\r
+    PageDirectory1GEntry = (VOID *)(\r
+                                    (PageMapLevel4Entry->Bits.PageTableBaseAddress <<\r
+                                     12) & ~PgTableMask\r
+                                    );\r
+    PageDirectory1GEntry += PDP_OFFSET (PhysicalAddress);\r
+    if (!PageDirectory1GEntry->Bits.Present) {\r
+      PageDirectory1GEntry->Bits.Present    = 1;\r
+      PageDirectory1GEntry->Bits.MustBe1    = 1;\r
+      PageDirectory1GEntry->Bits.MustBeZero = 0;\r
+      PageDirectory1GEntry->Bits.ReadWrite  = 1;\r
+      PageDirectory1GEntry->Uint64         |= (UINT64)PhysicalAddress | AddressEncMask;\r
+    }\r
+\r
+    if (Length <= BIT30) {\r
+      Length = 0;\r
+    } else {\r
+      Length -= BIT30;\r
+    }\r
+\r
+    PhysicalAddress += BIT30;\r
+  }\r
+\r
+  //\r
+  // Flush TLB\r
+  //\r
+  CpuFlushTlb ();\r
+\r
+Done:\r
+  //\r
+  // Restore page table write protection, if any.\r
+  //\r
+  if (IsWpEnabled) {\r
+    EnableReadOnlyPageWriteProtect ();\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   This function either sets or clears memory encryption bit for the memory\r
   region specified by PhysicalAddress and Length from the current page table\r