]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
UefiCpuPkg: Allow AP booting under SEV-ES
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / DxeMpLib.c
index 8ccddf8e9f9c6d198fe9509e3e5903eb8464bcc6..9115ff9e3e30c6645e0e0a48e2e38a2f43e7b012 100644 (file)
@@ -12,6 +12,8 @@
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/DebugAgentLib.h>\r
 #include <Library/DxeServicesTableLib.h>\r
+#include <Register/Amd/Fam17Msr.h>\r
+#include <Register/Amd/Ghcb.h>\r
 \r
 #include <Protocol/Timer.h>\r
 \r
@@ -144,6 +146,39 @@ GetModeTransitionBuffer (
   return (UINTN)StartAddress;\r
 }\r
 \r
+/**\r
+  Return the address of the SEV-ES AP jump table.\r
+\r
+  This buffer is required in order for an SEV-ES guest to transition from\r
+  UEFI into an OS.\r
+\r
+  @return         Return SEV-ES AP jump table buffer\r
+**/\r
+UINTN\r
+GetSevEsAPMemory (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  StartAddress;\r
+\r
+  //\r
+  // Allocate 1 page for AP jump table page\r
+  //\r
+  StartAddress = BASE_4GB - 1;\r
+  Status = gBS->AllocatePages (\r
+                  AllocateMaxAddress,\r
+                  EfiReservedMemoryType,\r
+                  1,\r
+                  &StartAddress\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  DEBUG ((DEBUG_INFO, "Dxe: SevEsAPMemory = %lx\n", (UINTN) StartAddress));\r
+\r
+  return (UINTN) StartAddress;\r
+}\r
+\r
 /**\r
   Checks APs status and updates APs status if needed.\r
 \r
@@ -218,6 +253,38 @@ CheckApsStatus (
   }\r
 }\r
 \r
+/**\r
+  Get Protected mode code segment with 16-bit default addressing\r
+  from current GDT table.\r
+\r
+  @return  Protected mode 16-bit code segment value.\r
+**/\r
+UINT16\r
+GetProtectedMode16CS (\r
+  VOID\r
+  )\r
+{\r
+  IA32_DESCRIPTOR          GdtrDesc;\r
+  IA32_SEGMENT_DESCRIPTOR  *GdtEntry;\r
+  UINTN                    GdtEntryCount;\r
+  UINT16                   Index;\r
+\r
+  Index = (UINT16) -1;\r
+  AsmReadGdtr (&GdtrDesc);\r
+  GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);\r
+  GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;\r
+  for (Index = 0; Index < GdtEntryCount; Index++) {\r
+    if (GdtEntry->Bits.L == 0) {\r
+      if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.DB == 0) {\r
+        break;\r
+      }\r
+    }\r
+    GdtEntry++;\r
+  }\r
+  ASSERT (Index != GdtEntryCount);\r
+  return Index * 8;\r
+}\r
+\r
 /**\r
   Get Protected mode code segment from current GDT table.\r
 \r
@@ -238,7 +305,7 @@ GetProtectedModeCS (
   GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;\r
   for (Index = 0; Index < GdtEntryCount; Index++) {\r
     if (GdtEntry->Bits.L == 0) {\r
-      if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) {\r
+      if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.DB == 1) {\r
         break;\r
       }\r
     }\r
@@ -300,6 +367,7 @@ MpInitChangeApLoopCallback (
 \r
   CpuMpData = GetCpuMpData ();\r
   CpuMpData->PmCodeSegment = GetProtectedModeCS ();\r
+  CpuMpData->Pm16CodeSegment = GetProtectedMode16CS ();\r
   CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode);\r
   mNumberToFinish = CpuMpData->CpuCount - 1;\r
   WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE);\r