From 2ddacfb6b86cc6aafc5653336752715da7514f37 Mon Sep 17 00:00:00 2001 From: "Brijesh Singh via groups.io" Date: Thu, 9 Dec 2021 11:27:29 +0800 Subject: [PATCH] OvmfPkg/SecMain: move SEV specific routines in AmdSev.c BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275 Move all the SEV specific function in AmdSev.c. No functional change intended. Cc: Michael Roth Cc: James Bottomley Cc: Min Xu Cc: Jiewen Yao Cc: Tom Lendacky Cc: Jordan Justen Cc: Ard Biesheuvel Cc: Erdem Aktas Cc: Gerd Hoffmann Acked-by: Gerd Hoffmann Acked-by: Jiewen Yao Signed-off-by: Brijesh Singh --- OvmfPkg/Sec/AmdSev.c | 164 ++++++++++++++++++++++++++++++++++++++++ OvmfPkg/Sec/AmdSev.h | 71 +++++++++++++++++ OvmfPkg/Sec/SecMain.c | 156 +------------------------------------- OvmfPkg/Sec/SecMain.inf | 2 + 4 files changed, 239 insertions(+), 154 deletions(-) create mode 100644 OvmfPkg/Sec/AmdSev.c create mode 100644 OvmfPkg/Sec/AmdSev.h diff --git a/OvmfPkg/Sec/AmdSev.c b/OvmfPkg/Sec/AmdSev.c new file mode 100644 index 0000000000..27fd24fc13 --- /dev/null +++ b/OvmfPkg/Sec/AmdSev.c @@ -0,0 +1,164 @@ +/** @file + File defines the Sec routines for the AMD SEV + + Copyright (c) 2021, Advanced Micro Devices, Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#include "AmdSev.h" + +/** + Handle an SEV-ES/GHCB protocol check failure. + + Notify the hypervisor using the VMGEXIT instruction that the SEV-ES guest + wishes to be terminated. + + @param[in] ReasonCode Reason code to provide to the hypervisor for the + termination request. + +**/ +VOID +SevEsProtocolFailure ( + IN UINT8 ReasonCode + ) +{ + MSR_SEV_ES_GHCB_REGISTER Msr; + + // + // Use the GHCB MSR Protocol to request termination by the hypervisor + // + Msr.GhcbPhysicalAddress = 0; + Msr.GhcbTerminate.Function = GHCB_INFO_TERMINATE_REQUEST; + Msr.GhcbTerminate.ReasonCodeSet = GHCB_TERMINATE_GHCB; + Msr.GhcbTerminate.ReasonCode = ReasonCode; + AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); + + AsmVmgExit (); + + ASSERT (FALSE); + CpuDeadLoop (); +} + +/** + Validate the SEV-ES/GHCB protocol level. + + Verify that the level of SEV-ES/GHCB protocol supported by the hypervisor + and the guest intersect. If they don't intersect, request termination. + +**/ +VOID +SevEsProtocolCheck ( + VOID + ) +{ + MSR_SEV_ES_GHCB_REGISTER Msr; + GHCB *Ghcb; + + // + // Use the GHCB MSR Protocol to obtain the GHCB SEV-ES Information for + // protocol checking + // + Msr.GhcbPhysicalAddress = 0; + Msr.GhcbInfo.Function = GHCB_INFO_SEV_INFO_GET; + AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); + + AsmVmgExit (); + + Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB); + + if (Msr.GhcbInfo.Function != GHCB_INFO_SEV_INFO) { + SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL); + } + + if (Msr.GhcbProtocol.SevEsProtocolMin > Msr.GhcbProtocol.SevEsProtocolMax) { + SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL); + } + + if ((Msr.GhcbProtocol.SevEsProtocolMin > GHCB_VERSION_MAX) || + (Msr.GhcbProtocol.SevEsProtocolMax < GHCB_VERSION_MIN)) + { + SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL); + } + + // + // SEV-ES protocol checking succeeded, set the initial GHCB address + // + Msr.GhcbPhysicalAddress = FixedPcdGet32 (PcdOvmfSecGhcbBase); + AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); + + Ghcb = Msr.Ghcb; + SetMem (Ghcb, sizeof (*Ghcb), 0); + + // + // Set the version to the maximum that can be supported + // + Ghcb->ProtocolVersion = MIN (Msr.GhcbProtocol.SevEsProtocolMax, GHCB_VERSION_MAX); + Ghcb->GhcbUsage = GHCB_STANDARD_USAGE; +} + +/** + Determine if the SEV is active. + + During the early booting, GuestType is set in the work area. Verify that it + is an SEV guest. + + @retval TRUE SEV is enabled + @retval FALSE SEV is not enabled + +**/ +BOOLEAN +IsSevGuest ( + VOID + ) +{ + OVMF_WORK_AREA *WorkArea; + + // + // Ensure that the size of the Confidential Computing work area header + // is same as what is provided through a fixed PCD. + // + ASSERT ( + (UINTN)FixedPcdGet32 (PcdOvmfConfidentialComputingWorkAreaHeader) == + sizeof (CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER) + ); + + WorkArea = (OVMF_WORK_AREA *)FixedPcdGet32 (PcdOvmfWorkAreaBase); + + return ((WorkArea != NULL) && (WorkArea->Header.GuestType == GUEST_TYPE_AMD_SEV)); +} + +/** + Determine if SEV-ES is active. + + During early booting, SEV-ES support code will set a flag to indicate that + SEV-ES is enabled. Return the value of this flag as an indicator that SEV-ES + is enabled. + + @retval TRUE SEV-ES is enabled + @retval FALSE SEV-ES is not enabled + +**/ +BOOLEAN +SevEsIsEnabled ( + VOID + ) +{ + SEC_SEV_ES_WORK_AREA *SevEsWorkArea; + + if (!IsSevGuest ()) { + return FALSE; + } + + SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *)FixedPcdGet32 (PcdSevEsWorkAreaBase); + + return (SevEsWorkArea->SevEsEnabled != 0); +} diff --git a/OvmfPkg/Sec/AmdSev.h b/OvmfPkg/Sec/AmdSev.h new file mode 100644 index 0000000000..c0b1ca9618 --- /dev/null +++ b/OvmfPkg/Sec/AmdSev.h @@ -0,0 +1,71 @@ +/** @file + File defines the Sec routines for the AMD SEV + + Copyright (c) 2021, Advanced Micro Devices, Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _AMD_SEV_SEC_INTERNAL_H__ +#define _AMD_SEV_SEC_INTERNAL_H__ + +/** + Handle an SEV-ES/GHCB protocol check failure. + + Notify the hypervisor using the VMGEXIT instruction that the SEV-ES guest + wishes to be terminated. + + @param[in] ReasonCode Reason code to provide to the hypervisor for the + termination request. + +**/ +VOID +SevEsProtocolFailure ( + IN UINT8 ReasonCode + ); + +/** + Validate the SEV-ES/GHCB protocol level. + + Verify that the level of SEV-ES/GHCB protocol supported by the hypervisor + and the guest intersect. If they don't intersect, request termination. + +**/ +VOID +SevEsProtocolCheck ( + VOID + ); + +/** + Determine if the SEV is active. + + During the early booting, GuestType is set in the work area. Verify that it + is an SEV guest. + + @retval TRUE SEV is enabled + @retval FALSE SEV is not enabled + +**/ +BOOLEAN +IsSevGuest ( + VOID + ); + +/** + Determine if SEV-ES is active. + + During early booting, SEV-ES support code will set a flag to indicate that + SEV-ES is enabled. Return the value of this flag as an indicator that SEV-ES + is enabled. + + @retval TRUE SEV-ES is enabled + @retval FALSE SEV-ES is not enabled + +**/ +BOOLEAN +SevEsIsEnabled ( + VOID + ); + +#endif diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c index 6d81d5b629..58e3b923b4 100644 --- a/OvmfPkg/Sec/SecMain.c +++ b/OvmfPkg/Sec/SecMain.c @@ -26,12 +26,11 @@ #include #include #include -#include -#include -#include #include +#include "AmdSev.h" + #define SEC_IDT_ENTRY_COUNT 34 typedef struct _SEC_IDT_TABLE { @@ -726,157 +725,6 @@ FindAndReportEntryPoints ( return; } -/** - Handle an SEV-ES/GHCB protocol check failure. - - Notify the hypervisor using the VMGEXIT instruction that the SEV-ES guest - wishes to be terminated. - - @param[in] ReasonCode Reason code to provide to the hypervisor for the - termination request. - -**/ -STATIC -VOID -SevEsProtocolFailure ( - IN UINT8 ReasonCode - ) -{ - MSR_SEV_ES_GHCB_REGISTER Msr; - - // - // Use the GHCB MSR Protocol to request termination by the hypervisor - // - Msr.GhcbPhysicalAddress = 0; - Msr.GhcbTerminate.Function = GHCB_INFO_TERMINATE_REQUEST; - Msr.GhcbTerminate.ReasonCodeSet = GHCB_TERMINATE_GHCB; - Msr.GhcbTerminate.ReasonCode = ReasonCode; - AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); - - AsmVmgExit (); - - ASSERT (FALSE); - CpuDeadLoop (); -} - -/** - Validate the SEV-ES/GHCB protocol level. - - Verify that the level of SEV-ES/GHCB protocol supported by the hypervisor - and the guest intersect. If they don't intersect, request termination. - -**/ -STATIC -VOID -SevEsProtocolCheck ( - VOID - ) -{ - MSR_SEV_ES_GHCB_REGISTER Msr; - GHCB *Ghcb; - - // - // Use the GHCB MSR Protocol to obtain the GHCB SEV-ES Information for - // protocol checking - // - Msr.GhcbPhysicalAddress = 0; - Msr.GhcbInfo.Function = GHCB_INFO_SEV_INFO_GET; - AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); - - AsmVmgExit (); - - Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB); - - if (Msr.GhcbInfo.Function != GHCB_INFO_SEV_INFO) { - SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL); - } - - if (Msr.GhcbProtocol.SevEsProtocolMin > Msr.GhcbProtocol.SevEsProtocolMax) { - SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL); - } - - if ((Msr.GhcbProtocol.SevEsProtocolMin > GHCB_VERSION_MAX) || - (Msr.GhcbProtocol.SevEsProtocolMax < GHCB_VERSION_MIN)) - { - SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL); - } - - // - // SEV-ES protocol checking succeeded, set the initial GHCB address - // - Msr.GhcbPhysicalAddress = FixedPcdGet32 (PcdOvmfSecGhcbBase); - AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); - - Ghcb = Msr.Ghcb; - SetMem (Ghcb, sizeof (*Ghcb), 0); - - // - // Set the version to the maximum that can be supported - // - Ghcb->ProtocolVersion = MIN (Msr.GhcbProtocol.SevEsProtocolMax, GHCB_VERSION_MAX); - Ghcb->GhcbUsage = GHCB_STANDARD_USAGE; -} - -/** - Determine if the SEV is active. - - During the early booting, GuestType is set in the work area. Verify that it - is an SEV guest. - - @retval TRUE SEV is enabled - @retval FALSE SEV is not enabled - -**/ -STATIC -BOOLEAN -IsSevGuest ( - VOID - ) -{ - OVMF_WORK_AREA *WorkArea; - - // - // Ensure that the size of the Confidential Computing work area header - // is same as what is provided through a fixed PCD. - // - ASSERT ( - (UINTN)FixedPcdGet32 (PcdOvmfConfidentialComputingWorkAreaHeader) == - sizeof (CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER) - ); - - WorkArea = (OVMF_WORK_AREA *)FixedPcdGet32 (PcdOvmfWorkAreaBase); - - return ((WorkArea != NULL) && (WorkArea->Header.GuestType == GUEST_TYPE_AMD_SEV)); -} - -/** - Determine if SEV-ES is active. - - During early booting, SEV-ES support code will set a flag to indicate that - SEV-ES is enabled. Return the value of this flag as an indicator that SEV-ES - is enabled. - - @retval TRUE SEV-ES is enabled - @retval FALSE SEV-ES is not enabled - -**/ -STATIC -BOOLEAN -SevEsIsEnabled ( - VOID - ) -{ - SEC_SEV_ES_WORK_AREA *SevEsWorkArea; - - if (!IsSevGuest ()) { - return FALSE; - } - - SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *)FixedPcdGet32 (PcdSevEsWorkAreaBase); - - return (SevEsWorkArea->SevEsEnabled != 0); -} - VOID EFIAPI SecCoreStartupWithStack ( diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf index ea4b9611f5..41dcdba120 100644 --- a/OvmfPkg/Sec/SecMain.inf +++ b/OvmfPkg/Sec/SecMain.inf @@ -23,6 +23,8 @@ [Sources] SecMain.c + AmdSev.c + AmdSev.h [Sources.IA32] Ia32/SecEntry.nasm -- 2.39.2