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
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
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
// 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
}\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
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
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