diff --git a/OvmfPkg/Include/WorkArea.h b/OvmfPkg/Include/WorkArea.h index ce60d97aa8..d982e026de 100644 --- a/OvmfPkg/Include/WorkArea.h +++ b/OvmfPkg/Include/WorkArea.h @@ -46,12 +46,20 @@ typedef struct _CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER { // any changes must stay in sync with its usage. // typedef struct _SEC_SEV_ES_WORK_AREA { - UINT8 SevEsEnabled; - UINT8 Reserved1[7]; + // + // Hold the SevStatus MSR value read by OvmfPkg/ResetVector/Ia32/AmdSev.c + // + UINT64 SevStatusMsrValue; UINT64 RandomData; UINT64 EncryptionMask; + + // + // Indicator that the VC handler is called. It is used during the SevFeature + // detection in OvmfPkg/ResetVector/Ia32/AmdSev.c + // + UINT8 ReceivedVc; } SEC_SEV_ES_WORK_AREA; // diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm index 1f827da3b9..864d683853 100644 --- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm +++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm @@ -157,8 +157,9 @@ SevClearPageEncMaskForGhcbPage: jnz SevClearPageEncMaskForGhcbPageExit ; Check if SEV-ES is enabled - cmp byte[SEV_ES_WORK_AREA], 1 - jnz SevClearPageEncMaskForGhcbPageExit + mov ecx, 1 + bt [SEV_ES_WORK_AREA_STATUS_MSR], ecx + jnc SevClearPageEncMaskForGhcbPageExit ; ; The initial GHCB will live at GHCB_BASE and needs to be un-encrypted. @@ -219,12 +220,16 @@ GetSevCBitMaskAbove31Exit: ; If SEV is disabled then EAX will be zero. ; CheckSevFeatures: - ; Set the first byte of the workarea to zero to communicate to the SEC - ; phase that SEV-ES is not enabled. If SEV-ES is enabled, the CPUID - ; instruction will trigger a #VC exception where the first byte of the - ; workarea will be set to one or, if CPUID is not being intercepted, - ; the MSR check below will set the first byte of the workarea to one. - mov byte[SEV_ES_WORK_AREA], 0 + ; + ; Clear the workarea, if SEV is enabled then later part of routine + ; will populate the workarea fields. + ; + mov ecx, SEV_ES_WORK_AREA_SIZE + mov eax, SEV_ES_WORK_AREA +ClearSevEsWorkArea: + mov byte [eax], 0 + inc eax + loop ClearSevEsWorkArea ; ; Set up exception handlers to check for SEV-ES @@ -265,6 +270,10 @@ CheckSevFeatures: ; Set the work area header to indicate that the SEV is enabled mov byte[WORK_AREA_GUEST_TYPE], 1 + ; Save the SevStatus MSR value in the workarea + mov [SEV_ES_WORK_AREA_STATUS_MSR], eax + mov [SEV_ES_WORK_AREA_STATUS_MSR + 4], edx + ; Check for SEV-ES memory encryption feature: ; CPUID Fn8000_001F[EAX] - Bit 3 ; CPUID raises a #VC exception if running as an SEV-ES guest @@ -280,10 +289,6 @@ CheckSevFeatures: bt eax, 1 jnc GetSevEncBit - ; Set the first byte of the workarea to one to communicate to the SEC - ; phase that SEV-ES is enabled. - mov byte[SEV_ES_WORK_AREA], 1 - GetSevEncBit: ; Get pte bit position to enable memory encryption ; CPUID Fn8000_001F[EBX] - Bits 5:0 @@ -313,7 +318,10 @@ NoSev: ; ; Perform an SEV-ES sanity check by seeing if a #VC exception occurred. ; - cmp byte[SEV_ES_WORK_AREA], 0 + ; If SEV-ES is enabled, the CPUID instruction will trigger a #VC exception + ; where the RECEIVED_VC offset in the workarea will be set to one. + ; + cmp byte[SEV_ES_WORK_AREA_RECEIVED_VC], 0 jz NoSevPass ; @@ -407,9 +415,9 @@ SevEsIdtVmmComm: ; If we're here, then we are an SEV-ES guest and this ; was triggered by a CPUID instruction ; - ; Set the first byte of the workarea to one to communicate that + ; Set the recievedVc field in the workarea to communicate that ; a #VC was taken. - mov byte[SEV_ES_WORK_AREA], 1 + mov byte[SEV_ES_WORK_AREA_RECEIVED_VC], 1 pop ecx ; Error code cmp ecx, 0x72 ; Be sure it was CPUID diff --git a/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm b/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm index eb3546668e..c5c683ebed 100644 --- a/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm +++ b/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm @@ -42,7 +42,8 @@ Transition32FlatTo64Flat: ; xor ebx, ebx - cmp byte[SEV_ES_WORK_AREA], 0 + mov ecx, 1 + bt [SEV_ES_WORK_AREA_STATUS_MSR], ecx jz EnablePaging ; diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb index cc364748b5..9421f48189 100644 --- a/OvmfPkg/ResetVector/ResetVector.nasmb +++ b/OvmfPkg/ResetVector/ResetVector.nasmb @@ -100,8 +100,11 @@ %define GHCB_BASE (FixedPcdGet32 (PcdOvmfSecGhcbBase)) %define GHCB_SIZE (FixedPcdGet32 (PcdOvmfSecGhcbSize)) %define SEV_ES_WORK_AREA (FixedPcdGet32 (PcdSevEsWorkAreaBase)) + %define SEV_ES_WORK_AREA_SIZE 25 + %define SEV_ES_WORK_AREA_STATUS_MSR (FixedPcdGet32 (PcdSevEsWorkAreaBase)) %define SEV_ES_WORK_AREA_RDRAND (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 8) %define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 16) + %define SEV_ES_WORK_AREA_RECEIVED_VC (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 24) %define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)) %define SEV_SNP_SECRETS_BASE (FixedPcdGet32 (PcdOvmfSnpSecretsBase)) %define SEV_SNP_SECRETS_SIZE (FixedPcdGet32 (PcdOvmfSnpSecretsSize)) diff --git a/OvmfPkg/Sec/AmdSev.c b/OvmfPkg/Sec/AmdSev.c index 499d0c27d8..d8fd35650d 100644 --- a/OvmfPkg/Sec/AmdSev.c +++ b/OvmfPkg/Sec/AmdSev.c @@ -278,7 +278,7 @@ SevEsIsEnabled ( SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *)FixedPcdGet32 (PcdSevEsWorkAreaBase); - return (SevEsWorkArea->SevEsEnabled != 0); + return ((SevEsWorkArea->SevStatusMsrValue & BIT1) != 0); } /**