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 <michael.roth@amd.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
This commit is contained in:
Brijesh Singh via groups.io 2021-12-09 11:27:29 +08:00 committed by mergify[bot]
parent c82ab4d8c1
commit 2ddacfb6b8
4 changed files with 239 additions and 154 deletions

164
OvmfPkg/Sec/AmdSev.c Normal file
View File

@ -0,0 +1,164 @@
/** @file
File defines the Sec routines for the AMD SEV
Copyright (c) 2021, Advanced Micro Devices, Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/MemEncryptSevLib.h>
#include <Library/BaseMemoryLib.h>
#include <Register/Amd/Ghcb.h>
#include <Register/Amd/Msr.h>
#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);
}

71
OvmfPkg/Sec/AmdSev.h Normal file
View File

@ -0,0 +1,71 @@
/** @file
File defines the Sec routines for the AMD SEV
Copyright (c) 2021, Advanced Micro Devices, Inc. All rights reserved.<BR>
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

View File

@ -26,12 +26,11 @@
#include <Library/ExtractGuidedSectionLib.h>
#include <Library/LocalApicLib.h>
#include <Library/CpuExceptionHandlerLib.h>
#include <Library/MemEncryptSevLib.h>
#include <Register/Amd/Ghcb.h>
#include <Register/Amd/Msr.h>
#include <Ppi/TemporaryRamSupport.h>
#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 (

View File

@ -23,6 +23,8 @@
[Sources]
SecMain.c
AmdSev.c
AmdSev.h
[Sources.IA32]
Ia32/SecEntry.nasm