]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/MpInitLib: use PcdConfidentialComputingAttr to check SEV status
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / MpLib.c
index 2d8e9512ab98e261f8b6956aee3c98f76b6e7de8..64fddb497e1e7f59c93a95e56690cfe7719c408d 100644 (file)
@@ -295,7 +295,7 @@ GetApLoopMode (
       ApLoopMode = ApInHltLoop;\r
     }\r
 \r
-    if (PcdGetBool (PcdSevEsIsEnabled)) {\r
+    if (ConfidentialComputingGuestHas (CCAttrAmdSevEs)) {\r
       //\r
       // For SEV-ES, force AP in Hlt-loop mode in order to use the GHCB\r
       // protocol for starting APs\r
@@ -599,123 +599,6 @@ InitializeApData (
   SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);\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
-STATIC\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
-        (GdtEntry->Bits.DB == 0) &&\r
-        (GdtEntry->Bits.Type > 8))\r
-    {\r
-      break;\r
-    }\r
-\r
-    GdtEntry++;\r
-  }\r
-\r
-  ASSERT (Index != GdtEntryCount);\r
-  return Index * 8;\r
-}\r
-\r
-/**\r
-  Get Protected mode code segment with 32-bit default addressing\r
-  from current GDT table.\r
-\r
-  @return  Protected mode 32-bit code segment value.\r
-**/\r
-STATIC\r
-UINT16\r
-GetProtectedMode32CS (\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
-        (GdtEntry->Bits.DB == 1) &&\r
-        (GdtEntry->Bits.Type > 8))\r
-    {\r
-      break;\r
-    }\r
-\r
-    GdtEntry++;\r
-  }\r
-\r
-  ASSERT (Index != GdtEntryCount);\r
-  return Index * 8;\r
-}\r
-\r
-/**\r
-  Reset an AP when in SEV-ES mode.\r
-\r
-  If successful, this function never returns.\r
-\r
-  @param[in] Ghcb                 Pointer to the GHCB\r
-  @param[in] CpuMpData            Pointer to CPU MP Data\r
-\r
-**/\r
-STATIC\r
-VOID\r
-MpInitLibSevEsAPReset (\r
-  IN GHCB         *Ghcb,\r
-  IN CPU_MP_DATA  *CpuMpData\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  UINTN       ProcessorNumber;\r
-  UINT16      Code16, Code32;\r
-  AP_RESET    *APResetFn;\r
-  UINTN       BufferStart;\r
-  UINTN       StackStart;\r
-\r
-  Status = GetProcessorNumber (CpuMpData, &ProcessorNumber);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Code16 = GetProtectedMode16CS ();\r
-  Code32 = GetProtectedMode32CS ();\r
-\r
-  if (CpuMpData->WakeupBufferHigh != 0) {\r
-    APResetFn = (AP_RESET *)(CpuMpData->WakeupBufferHigh + CpuMpData->AddressMap.SwitchToRealNoNxOffset);\r
-  } else {\r
-    APResetFn = (AP_RESET *)(CpuMpData->MpCpuExchangeInfo->BufferStart + CpuMpData->AddressMap.SwitchToRealOffset);\r
-  }\r
-\r
-  BufferStart = CpuMpData->MpCpuExchangeInfo->BufferStart;\r
-  StackStart  = CpuMpData->SevEsAPResetStackStart -\r
-                (AP_RESET_STACK_SIZE * ProcessorNumber);\r
-\r
-  //\r
-  // This call never returns.\r
-  //\r
-  APResetFn (BufferStart, Code16, Code32, StackStart);\r
-}\r
-\r
 /**\r
   This function will be called from AP reset code if BSP uses WakeUpAP.\r
 \r
@@ -895,47 +778,7 @@ ApWakeupFunction (
       while (TRUE) {\r
         DisableInterrupts ();\r
         if (CpuMpData->SevEsIsEnabled) {\r
-          MSR_SEV_ES_GHCB_REGISTER  Msr;\r
-          GHCB                      *Ghcb;\r
-          UINT64                    Status;\r
-          BOOLEAN                   DoDecrement;\r
-          BOOLEAN                   InterruptState;\r
-\r
-          DoDecrement = (BOOLEAN)(CpuMpData->InitFlag == ApInitConfig);\r
-\r
-          while (TRUE) {\r
-            Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);\r
-            Ghcb                    = Msr.Ghcb;\r
-\r
-            VmgInit (Ghcb, &InterruptState);\r
-\r
-            if (DoDecrement) {\r
-              DoDecrement = FALSE;\r
-\r
-              //\r
-              // Perform the delayed decrement just before issuing the first\r
-              // VMGEXIT with AP_RESET_HOLD.\r
-              //\r
-              InterlockedDecrement ((UINT32 *)&CpuMpData->MpCpuExchangeInfo->NumApsExecuting);\r
-            }\r
-\r
-            Status = VmgExit (Ghcb, SVM_EXIT_AP_RESET_HOLD, 0, 0);\r
-            if ((Status == 0) && (Ghcb->SaveArea.SwExitInfo2 != 0)) {\r
-              VmgDone (Ghcb, InterruptState);\r
-              break;\r
-            }\r
-\r
-            VmgDone (Ghcb, InterruptState);\r
-          }\r
-\r
-          //\r
-          // Awakened in a new phase? Use the new CpuMpData\r
-          //\r
-          if (CpuMpData->NewCpuMpData != NULL) {\r
-            CpuMpData = CpuMpData->NewCpuMpData;\r
-          }\r
-\r
-          MpInitLibSevEsAPReset (Ghcb, CpuMpData);\r
+          SevEsPlaceApHlt (CpuMpData);\r
         } else {\r
           CpuSleep ();\r
         }\r
@@ -1212,7 +1055,7 @@ AllocateResetVector (
     // The AP reset stack is only used by SEV-ES guests. Do not allocate it\r
     // if SEV-ES is not enabled.\r
     //\r
-    if (PcdGetBool (PcdSevEsIsEnabled)) {\r
+    if (ConfidentialComputingGuestHas (CCAttrAmdSevEs)) {\r
       //\r
       // Stack location is based on ProcessorNumber, so use the total number\r
       // of processors for calculating the total stack area.\r
@@ -1268,71 +1111,6 @@ FreeResetVector (
   }\r
 }\r
 \r
-/**\r
-  Allocate the SEV-ES AP jump table buffer.\r
-\r
-  @param[in, out]  CpuMpData  The pointer to CPU MP Data structure.\r
-**/\r
-VOID\r
-AllocateSevEsAPMemory (\r
-  IN OUT CPU_MP_DATA  *CpuMpData\r
-  )\r
-{\r
-  if (CpuMpData->SevEsAPBuffer == (UINTN)-1) {\r
-    CpuMpData->SevEsAPBuffer =\r
-      CpuMpData->SevEsIsEnabled ? GetSevEsAPMemory () : 0;\r
-  }\r
-}\r
-\r
-/**\r
-  Program the SEV-ES AP jump table buffer.\r
-\r
-  @param[in]  SipiVector  The SIPI vector used for the AP Reset\r
-**/\r
-VOID\r
-SetSevEsJumpTable (\r
-  IN UINTN  SipiVector\r
-  )\r
-{\r
-  SEV_ES_AP_JMP_FAR  *JmpFar;\r
-  UINT32             Offset, InsnByte;\r
-  UINT8              LoNib, HiNib;\r
-\r
-  JmpFar = (SEV_ES_AP_JMP_FAR *)(UINTN)FixedPcdGet32 (PcdSevEsWorkAreaBase);\r
-  ASSERT (JmpFar != NULL);\r
-\r
-  //\r
-  // Obtain the address of the Segment/Rip location in the workarea.\r
-  // This will be set to a value derived from the SIPI vector and will\r
-  // be the memory address used for the far jump below.\r
-  //\r
-  Offset  = FixedPcdGet32 (PcdSevEsWorkAreaBase);\r
-  Offset += sizeof (JmpFar->InsnBuffer);\r
-  LoNib   = (UINT8)Offset;\r
-  HiNib   = (UINT8)(Offset >> 8);\r
-\r
-  //\r
-  // Program the workarea (which is the initial AP boot address) with\r
-  // far jump to the SIPI vector (where XX and YY represent the\r
-  // address of where the SIPI vector is stored.\r
-  //\r
-  //   JMP FAR [CS:XXYY] => 2E FF 2E YY XX\r
-  //\r
-  InsnByte                       = 0;\r
-  JmpFar->InsnBuffer[InsnByte++] = 0x2E;  // CS override prefix\r
-  JmpFar->InsnBuffer[InsnByte++] = 0xFF;  // JMP (FAR)\r
-  JmpFar->InsnBuffer[InsnByte++] = 0x2E;  // ModRM (JMP memory location)\r
-  JmpFar->InsnBuffer[InsnByte++] = LoNib; // YY offset ...\r
-  JmpFar->InsnBuffer[InsnByte++] = HiNib; // XX offset ...\r
-\r
-  //\r
-  // Program the Segment/Rip based on the SIPI vector (always at least\r
-  // 16-byte aligned, so Rip is set to 0).\r
-  //\r
-  JmpFar->Rip     = 0;\r
-  JmpFar->Segment = (UINT16)(SipiVector >> 4);\r
-}\r
-\r
 /**\r
   This function will be called by BSP to wakeup AP.\r
 \r
@@ -2069,7 +1847,7 @@ MpInitLibInitialize (
   CpuMpData->CpuData          = (CPU_AP_DATA *)(CpuMpData + 1);\r
   CpuMpData->CpuInfoInHob     = (UINT64)(UINTN)(CpuMpData->CpuData + MaxLogicalProcessorNumber);\r
   InitializeSpinLock (&CpuMpData->MpLock);\r
-  CpuMpData->SevEsIsEnabled = PcdGetBool (PcdSevEsIsEnabled);\r
+  CpuMpData->SevEsIsEnabled = ConfidentialComputingGuestHas (CCAttrAmdSevEs);\r
   CpuMpData->SevEsAPBuffer  = (UINTN)-1;\r
   CpuMpData->GhcbBase       = PcdGet64 (PcdGhcbBase);\r
 \r
@@ -2977,3 +2755,70 @@ MpInitLibStartupAllCPUs (
            NULL\r
            );\r
 }\r
+\r
+/**\r
+  The function check if the specified Attr is set.\r
+\r
+  @param[in]  CurrentAttr   The current attribute.\r
+  @param[in]  Attr          The attribute to check.\r
+\r
+  @retval  TRUE      The specified Attr is set.\r
+  @retval  FALSE     The specified Attr is not set.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+AmdMemEncryptionAttrCheck (\r
+  IN  UINT64                             CurrentAttr,\r
+  IN  CONFIDENTIAL_COMPUTING_GUEST_ATTR  Attr\r
+  )\r
+{\r
+  switch (Attr) {\r
+    case CCAttrAmdSev:\r
+      //\r
+      // SEV is automatically enabled if SEV-ES or SEV-SNP is active.\r
+      //\r
+      return CurrentAttr >= CCAttrAmdSev;\r
+    case CCAttrAmdSevEs:\r
+      //\r
+      // SEV-ES is automatically enabled if SEV-SNP is active.\r
+      //\r
+      return CurrentAttr >= CCAttrAmdSevEs;\r
+    case CCAttrAmdSevSnp:\r
+      return CurrentAttr == CCAttrAmdSevSnp;\r
+    default:\r
+      return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Check if the specified confidential computing attribute is active.\r
+\r
+  @param[in]  Attr          The attribute to check.\r
+\r
+  @retval TRUE   The specified Attr is active.\r
+  @retval FALSE  The specified Attr is not active.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+ConfidentialComputingGuestHas (\r
+  IN  CONFIDENTIAL_COMPUTING_GUEST_ATTR  Attr\r
+  )\r
+{\r
+  UINT64  CurrentAttr;\r
+\r
+  //\r
+  // Get the current CC attribute.\r
+  //\r
+  CurrentAttr = PcdGet64 (PcdConfidentialComputingGuestAttr);\r
+\r
+  //\r
+  // If attr is for the AMD group then call AMD specific checks.\r
+  //\r
+  if (((RShiftU64 (CurrentAttr, 8)) & 0xff) == 1) {\r
+    return AmdMemEncryptionAttrCheck (CurrentAttr, Attr);\r
+  }\r
+\r
+  return (CurrentAttr == Attr);\r
+}\r