]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/AmdSevDxe/AmdSevDxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / AmdSevDxe / AmdSevDxe.c
index be26dde71f9def6c85d427bb6d1b3dfc7a53fbb1..a726498e27923424fdc496685a267f09c8cc4daa 100644 (file)
 #include <Library/DxeServicesTableLib.h>\r
 #include <Library/MemEncryptSevLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Guid/ConfidentialComputingSevSnpBlob.h>\r
 #include <Library/PcdLib.h>\r
+#include <Pi/PrePiDxeCis.h>\r
+#include <Protocol/SevMemoryAcceptance.h>\r
+#include <Protocol/MemoryAccept.h>\r
+#include <Uefi/UefiSpec.h>\r
+\r
+// Present, initialized, tested bits defined in MdeModulePkg/Core/Dxe/DxeMain.h\r
+#define EFI_MEMORY_INTERNAL_MASK  0x0700000000000000ULL\r
+\r
+STATIC CONFIDENTIAL_COMPUTING_SNP_BLOB_LOCATION  mSnpBootDxeTable = {\r
+  SIGNATURE_32 ('A',                                    'M', 'D', 'E'),\r
+  1,\r
+  0,\r
+  (UINT64)(UINTN)FixedPcdGet32 (PcdOvmfSnpSecretsBase),\r
+  FixedPcdGet32 (PcdOvmfSnpSecretsSize),\r
+  (UINT64)(UINTN)FixedPcdGet32 (PcdOvmfCpuidBase),\r
+  FixedPcdGet32 (PcdOvmfCpuidSize),\r
+};\r
+\r
+STATIC EFI_HANDLE  mAmdSevDxeHandle = NULL;\r
+\r
+STATIC BOOLEAN  mAcceptAllMemoryAtEBS = TRUE;\r
+\r
+STATIC EFI_EVENT  mAcceptAllMemoryEvent = NULL;\r
+\r
+#define IS_ALIGNED(x, y)  ((((x) & ((y) - 1)) == 0))\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+AmdSevMemoryAccept (\r
+  IN EDKII_MEMORY_ACCEPT_PROTOCOL  *This,\r
+  IN EFI_PHYSICAL_ADDRESS          StartAddress,\r
+  IN UINTN                         Size\r
+  )\r
+{\r
+  //\r
+  // The StartAddress must be page-aligned, and the Size must be a positive\r
+  // multiple of SIZE_4KB. Use an assert instead of returning an erros since\r
+  // this is an EDK2-internal protocol.\r
+  //\r
+  ASSERT (IS_ALIGNED (StartAddress, SIZE_4KB));\r
+  ASSERT (IS_ALIGNED (Size, SIZE_4KB));\r
+  ASSERT (Size != 0);\r
+\r
+  MemEncryptSevSnpPreValidateSystemRam (\r
+    StartAddress,\r
+    EFI_SIZE_TO_PAGES (Size)\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+AcceptAllMemory (\r
+  VOID\r
+  )\r
+{\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *AllDescMap;\r
+  UINTN                            NumEntries;\r
+  UINTN                            Index;\r
+  EFI_STATUS                       Status;\r
+\r
+  DEBUG ((DEBUG_INFO, "Accepting all memory\n"));\r
+\r
+  /*\r
+   * Get a copy of the memory space map to iterate over while\r
+   * changing the map.\r
+   */\r
+  Status = gDS->GetMemorySpaceMap (&NumEntries, &AllDescMap);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  for (Index = 0; Index < NumEntries; Index++) {\r
+    CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *Desc;\r
+\r
+    Desc = &AllDescMap[Index];\r
+    if (Desc->GcdMemoryType != EFI_GCD_MEMORY_TYPE_UNACCEPTED) {\r
+      continue;\r
+    }\r
+\r
+    Status = AmdSevMemoryAccept (\r
+               NULL,\r
+               Desc->BaseAddress,\r
+               Desc->Length\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    Status = gDS->RemoveMemorySpace (Desc->BaseAddress, Desc->Length);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    Status = gDS->AddMemorySpace (\r
+                    EfiGcdMemoryTypeSystemMemory,\r
+                    Desc->BaseAddress,\r
+                    Desc->Length,\r
+                    // Allocable system memory resource capabilities as masked\r
+                    // in MdeModulePkg/Core/Dxe/Mem/Page.c:PromoteMemoryResource\r
+                    Desc->Capabilities & ~(EFI_MEMORY_INTERNAL_MASK | EFI_MEMORY_RUNTIME)\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  gBS->FreePool (AllDescMap);\r
+  gBS->CloseEvent (mAcceptAllMemoryEvent);\r
+  return Status;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+ResolveUnacceptedMemory (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  if (!mAcceptAllMemoryAtEBS) {\r
+    return;\r
+  }\r
+\r
+  Status = AcceptAllMemory ();\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+AllowUnacceptedMemory (\r
+  IN  OVMF_SEV_MEMORY_ACCEPTANCE_PROTOCOL  *This\r
+  )\r
+{\r
+  mAcceptAllMemoryAtEBS = FALSE;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+OVMF_SEV_MEMORY_ACCEPTANCE_PROTOCOL\r
+  mMemoryAcceptanceProtocol = { AllowUnacceptedMemory };\r
+\r
+STATIC EDKII_MEMORY_ACCEPT_PROTOCOL  mMemoryAcceptProtocol = {\r
+  AmdSevMemoryAccept\r
+};\r
 \r
 EFI_STATUS\r
 EFIAPI\r
@@ -135,5 +286,46 @@ AmdSevDxeEntryPoint (
     }\r
   }\r
 \r
+  if (MemEncryptSevSnpIsEnabled ()) {\r
+    //\r
+    // Memory acceptance began being required in SEV-SNP, so install the\r
+    // memory accept protocol implementation for a SEV-SNP active guest.\r
+    //\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &mAmdSevDxeHandle,\r
+                    &gEdkiiMemoryAcceptProtocolGuid,\r
+                    &mMemoryAcceptProtocol,\r
+                    &gOvmfSevMemoryAcceptanceProtocolGuid,\r
+                    &mMemoryAcceptanceProtocol,\r
+                    NULL\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    // SEV-SNP support does not automatically imply unaccepted memory support,\r
+    // so make ExitBootServices accept all unaccepted memory if support is\r
+    // not communicated.\r
+    Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_CALLBACK,\r
+                    ResolveUnacceptedMemory,\r
+                    NULL,\r
+                    &gEfiEventBeforeExitBootServicesGuid,\r
+                    &mAcceptAllMemoryEvent\r
+                    );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR, "AllowUnacceptedMemory event creation for EventBeforeExitBootServices failed.\n"));\r
+    }\r
+\r
+    //\r
+    // If its SEV-SNP active guest then install the CONFIDENTIAL_COMPUTING_SEV_SNP_BLOB.\r
+    // It contains the location for both the Secrets and CPUID page.\r
+    //\r
+    return gBS->InstallConfigurationTable (\r
+                  &gConfidentialComputingSevSnpBlobGuid,\r
+                  &mSnpBootDxeTable\r
+                  );\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r