From nobody Mon Feb 9 08:56:40 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+95921+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+95921+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1667517628; cv=none; d=zohomail.com; s=zohoarc; b=hlOCgLKo2qh40Q3G1n8pfTphhmio3JfCytt5MqFwN0Vo/wz9PYr+GR5eDckvqPFAxaBWjgC0VI0F2cWxljxEAlb8b4YLNoYWI+V02L+GRSTnrnS3NiIksWQ7BALQ66pHZNZxeb6Csc5FwJ8vw6Z24xqJkmbLUGGWncWoGnRqrUw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1667517628; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=J/6rULzhoiZr+GJZ/28ctAbQk96JhtNjJs1c6vunhQ8=; b=ekNZebF3BXM65I1vnH0tRNQemzRb3L5HG+Du+kZdgu5MhEqAFdIIGF+CS4QCGfXJxaf60yLkpZ3ujK7VEpePHWBndwK7OtrhyJQEl4d9FQzS1T0Vy3yev7netYQIDu/0VdA+8J9dqRq1q69gLObu6ln+cYeKsvNFEcDAjmmH1eE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+95921+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1667517628766995.8506433340021; Thu, 3 Nov 2022 16:20:28 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id nYfLYY1788612xe731mp4gOE; Thu, 03 Nov 2022 16:20:28 -0700 X-Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by mx.groups.io with SMTP id smtpd.web09.5284.1667517610553055782 for ; Thu, 03 Nov 2022 16:20:27 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10520"; a="310947349" X-IronPort-AV: E=Sophos;i="5.96,135,1665471600"; d="scan'208";a="310947349" X-Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Nov 2022 16:20:26 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10520"; a="724132001" X-IronPort-AV: E=Sophos;i="5.96,135,1665471600"; d="scan'208";a="724132001" X-Received: from yananliu-mobl.ccr.corp.intel.com (HELO mxu9-mobl1.ccr.corp.intel.com) ([10.255.30.132]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Nov 2022 16:20:24 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min M Xu , Brijesh Singh , Erdem Aktas , Gerd Hoffmann , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 7/9] OvmfPkg: Delete VmgExitLib Date: Fri, 4 Nov 2022 07:19:53 +0800 Message-Id: <20221103231955.1365-8-min.m.xu@intel.com> In-Reply-To: <20221103231955.1365-1-min.m.xu@intel.com> References: <20221103231955.1365-1-min.m.xu@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: aVYFOgxv03YQRBDtvck5LvDox1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1667517628; bh=i2N8eCyDrPMHO7OrFLdDvwznNQzSO/+QvG2QzxlNihs=; h=Cc:Date:From:Reply-To:Subject:To; b=xJlJDYdCTh8snmsjozSxR3HLJykCkTIwHec+rPVUtnCYxn/bP2kS4RBvQ0PEXkY7c7A +0auWe5qsz52qqOjSZu2j4f2TLWVXZ47/qtnuySmuf3ENBzb8UL9PcchiO6aE32nS/NZh HoXGqhvNpOThyXX7GNfPaJMQFVmUw2H5vm0= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1667517629427100007 Content-Type: text/plain; charset="utf-8" From: Min M Xu BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4123 Delete VmgExitLib because it is replaced by CcExitLib. Cc: Brijesh Singh Cc: Erdem Aktas Cc: Gerd Hoffmann Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- .../VmgExitLib/PeiDxeVmgExitVcHandler.c | 103 - OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf | 48 - .../Library/VmgExitLib/SecVmgExitVcHandler.c | 109 - OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h | 32 - .../Library/VmgExitLib/VmTdExitVeHandler.c | 559 ---- OvmfPkg/Library/VmgExitLib/VmgExitLib.c | 238 -- OvmfPkg/Library/VmgExitLib/VmgExitLib.inf | 45 - OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 2356 ----------------- OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h | 53 - .../Library/VmgExitLib/X64/TdVmcallCpuid.nasm | 146 - 10 files changed, 3689 deletions(-) delete mode 100644 OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c delete mode 100644 OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf delete mode 100644 OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c delete mode 100644 OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h delete mode 100644 OvmfPkg/Library/VmgExitLib/VmTdExitVeHandler.c delete mode 100644 OvmfPkg/Library/VmgExitLib/VmgExitLib.c delete mode 100644 OvmfPkg/Library/VmgExitLib/VmgExitLib.inf delete mode 100644 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c delete mode 100644 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h delete mode 100644 OvmfPkg/Library/VmgExitLib/X64/TdVmcallCpuid.nasm diff --git a/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c b/OvmfPkg/= Library/VmgExitLib/PeiDxeVmgExitVcHandler.c deleted file mode 100644 index e3d071583750..000000000000 --- a/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c +++ /dev/null @@ -1,103 +0,0 @@ -/** @file - X64 #VC Exception Handler functon. - - Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include -#include -#include -#include - -#include "VmgExitVcHandler.h" - -/** - Handle a #VC exception. - - Performs the necessary processing to handle a #VC exception. - - @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et - as value to use on error. - @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT - - @retval EFI_SUCCESS Exception handled - @retval EFI_UNSUPPORTED #VC not supported, (new) exception value= to - propagate provided - @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception val= ue to - propagate provided - -**/ -EFI_STATUS -EFIAPI -VmgExitHandleVc ( - IN OUT EFI_EXCEPTION_TYPE *ExceptionType, - IN OUT EFI_SYSTEM_CONTEXT SystemContext - ) -{ - MSR_SEV_ES_GHCB_REGISTER Msr; - GHCB *Ghcb; - GHCB *GhcbBackup; - EFI_STATUS VcRet; - BOOLEAN InterruptState; - SEV_ES_PER_CPU_DATA *SevEsData; - - InterruptState =3D GetInterruptState (); - if (InterruptState) { - DisableInterrupts (); - } - - Msr.GhcbPhysicalAddress =3D AsmReadMsr64 (MSR_SEV_ES_GHCB); - ASSERT (Msr.GhcbInfo.Function =3D=3D 0); - ASSERT (Msr.Ghcb !=3D 0); - - Ghcb =3D Msr.Ghcb; - GhcbBackup =3D NULL; - - SevEsData =3D (SEV_ES_PER_CPU_DATA *)(Ghcb + 1); - SevEsData->VcCount++; - - // - // Check for maximum PEI/DXE #VC nesting. - // - if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) { - VmgExitIssueAssert (SevEsData); - } else if (SevEsData->VcCount > 1) { - // - // Nested #VC - // - if (SevEsData->GhcbBackupPages =3D=3D NULL) { - VmgExitIssueAssert (SevEsData); - } - - // - // Save the active GHCB to a backup page. - // To access the correct backup page, increment the backup page poin= ter - // based on the current VcCount. - // - GhcbBackup =3D (GHCB *)SevEsData->GhcbBackupPages; - GhcbBackup +=3D (SevEsData->VcCount - 2); - - CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb)); - } - - VcRet =3D InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext); - - if (GhcbBackup !=3D NULL) { - // - // Restore the active GHCB from the backup page. - // - CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb)); - } - - SevEsData->VcCount--; - - if (InterruptState) { - EnableInterrupts (); - } - - return VcRet; -} diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/OvmfPkg/Library= /VmgExitLib/SecVmgExitLib.inf deleted file mode 100644 index f9bd4974f6dc..000000000000 --- a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf +++ /dev/null @@ -1,48 +0,0 @@ -## @file -# VMGEXIT Support Library. -# -# Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. -# SPDX-License-Identifier: BSD-2-Clause-Patent -# -## - -[Defines] - INF_VERSION =3D 0x00010005 - BASE_NAME =3D SecVmgExitLib - FILE_GUID =3D dafff819-f86c-4cff-a70e-83161e5bcf9a - MODULE_TYPE =3D BASE - VERSION_STRING =3D 1.0 - LIBRARY_CLASS =3D VmgExitLib|SEC - -# -# The following information is for reference only and not required by the = build tools. -# -# VALID_ARCHITECTURES =3D X64 -# - -[Sources.common] - VmgExitLib.c - VmgExitVcHandler.c - VmgExitVcHandler.h - SecVmgExitVcHandler.c - VmTdExitVeHandler.c - X64/TdVmcallCpuid.nasm - -[Packages] - MdePkg/MdePkg.dec - OvmfPkg/OvmfPkg.dec - UefiCpuPkg/UefiCpuPkg.dec - -[LibraryClasses] - BaseLib - BaseMemoryLib - DebugLib - LocalApicLib - MemEncryptSevLib - PcdLib - -[FixedPcd] - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c b/OvmfPkg/Lib= rary/VmgExitLib/SecVmgExitVcHandler.c deleted file mode 100644 index fe8680f831d9..000000000000 --- a/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c +++ /dev/null @@ -1,109 +0,0 @@ -/** @file - X64 #VC Exception Handler functon. - - Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include -#include -#include -#include - -#include "VmgExitVcHandler.h" - -/** - Handle a #VC exception. - - Performs the necessary processing to handle a #VC exception. - - @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et - as value to use on error. - @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT - - @retval EFI_SUCCESS Exception handled - @retval EFI_UNSUPPORTED #VC not supported, (new) exception value= to - propagate provided - @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception val= ue to - propagate provided - -**/ -EFI_STATUS -EFIAPI -VmgExitHandleVc ( - IN OUT EFI_EXCEPTION_TYPE *ExceptionType, - IN OUT EFI_SYSTEM_CONTEXT SystemContext - ) -{ - MSR_SEV_ES_GHCB_REGISTER Msr; - GHCB *Ghcb; - GHCB *GhcbBackup; - EFI_STATUS VcRet; - BOOLEAN InterruptState; - SEV_ES_PER_CPU_DATA *SevEsData; - - InterruptState =3D GetInterruptState (); - if (InterruptState) { - DisableInterrupts (); - } - - Msr.GhcbPhysicalAddress =3D AsmReadMsr64 (MSR_SEV_ES_GHCB); - ASSERT (Msr.GhcbInfo.Function =3D=3D 0); - ASSERT (Msr.Ghcb !=3D 0); - - Ghcb =3D Msr.Ghcb; - GhcbBackup =3D NULL; - - SevEsData =3D (SEV_ES_PER_CPU_DATA *)(Ghcb + 1); - SevEsData->VcCount++; - - // - // Check for maximum SEC #VC nesting. - // - if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) { - VmgExitIssueAssert (SevEsData); - } else if (SevEsData->VcCount > 1) { - UINTN GhcbBackupSize; - - // - // Be sure that the proper amount of pages are allocated - // - GhcbBackupSize =3D (VMGEXIT_MAXIMUM_VC_COUNT - 1) * sizeof (*Ghcb); - if (GhcbBackupSize > FixedPcdGet32 (PcdOvmfSecGhcbBackupSize)) { - // - // Not enough SEC backup pages allocated. - // - VmgExitIssueAssert (SevEsData); - } - - // - // Save the active GHCB to a backup page. - // To access the correct backup page, increment the backup page poin= ter - // based on the current VcCount. - // - GhcbBackup =3D (GHCB *)FixedPcdGet32 (PcdOvmfSecGhcbBackupBase); - GhcbBackup +=3D (SevEsData->VcCount - 2); - - CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb)); - } - - VcRet =3D InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext); - - if (GhcbBackup !=3D NULL) { - // - // Restore the active GHCB from the backup page. - // - CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb)); - } - - SevEsData->VcCount--; - - if (InterruptState) { - EnableInterrupts (); - } - - return VcRet; -} diff --git a/OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h b/OvmfPkg/Library= /VmgExitLib/VmTdExitHandler.h deleted file mode 100644 index 7eacd0872f46..000000000000 --- a/OvmfPkg/Library/VmgExitLib/VmTdExitHandler.h +++ /dev/null @@ -1,32 +0,0 @@ -/** @file - - Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef VMTD_EXIT_HANDLER_H_ -#define VMTD_EXIT_HANDLER_H_ - -#include -#include - -/** - This function enable the TD guest to request the VMM to emulate CPUID - operation, especially for non-architectural, CPUID leaves. - - @param[in] Eax Main leaf of the CPUID - @param[in] Ecx Sub-leaf of the CPUID - @param[out] Results Returned result of CPUID operation - - @return EFI_SUCCESS -**/ -EFI_STATUS -EFIAPI -TdVmCallCpuid ( - IN UINT64 Eax, - IN UINT64 Ecx, - OUT VOID *Results - ); - -#endif diff --git a/OvmfPkg/Library/VmgExitLib/VmTdExitVeHandler.c b/OvmfPkg/Libra= ry/VmgExitLib/VmTdExitVeHandler.c deleted file mode 100644 index b73e877c093b..000000000000 --- a/OvmfPkg/Library/VmgExitLib/VmTdExitVeHandler.c +++ /dev/null @@ -1,559 +0,0 @@ -/** @file - - Copyright (c) 2021, Intel Corporation. All rights reserved.
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include "VmTdExitHandler.h" -#include -#include -#include -#include - -typedef union { - struct { - UINT32 Eax; - UINT32 Edx; - } Regs; - UINT64 Val; -} MSR_DATA; - -typedef union { - UINT8 Val; - struct { - UINT8 B : 1; - UINT8 X : 1; - UINT8 R : 1; - UINT8 W : 1; - } Bits; -} REX; - -typedef union { - UINT8 Val; - struct { - UINT8 Rm : 3; - UINT8 Reg : 3; - UINT8 Mod : 2; - } Bits; -} MODRM; - -typedef struct { - UINT64 Regs[4]; -} CPUID_DATA; - -/** - Handle an CPUID event. - - Use the TDVMCALL instruction to handle cpuid #ve - - @param[in, out] Regs x64 processor context - @param[in] Veinfo VE Info - - @retval 0 Event handled successfully - @return New exception value to propagate -**/ -STATIC -UINT64 -EFIAPI -CpuIdExit ( - IN EFI_SYSTEM_CONTEXT_X64 *Regs, - IN TDCALL_VEINFO_RETURN_DATA *Veinfo - ) -{ - CPUID_DATA CpuIdData; - UINT64 Status; - - Status =3D TdVmCallCpuid (Regs->Rax, Regs->Rcx, &CpuIdData); - - if (Status =3D=3D 0) { - Regs->Rax =3D CpuIdData.Regs[0]; - Regs->Rbx =3D CpuIdData.Regs[1]; - Regs->Rcx =3D CpuIdData.Regs[2]; - Regs->Rdx =3D CpuIdData.Regs[3]; - } - - return Status; -} - -/** - Handle an IO event. - - Use the TDVMCALL instruction to handle either an IO read or an IO write. - - @param[in, out] Regs x64 processor context - @param[in] Veinfo VE Info - - @retval 0 Event handled successfully - @return New exception value to propagate -**/ -STATIC -UINT64 -EFIAPI -IoExit ( - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN TDCALL_VEINFO_RETURN_DATA *Veinfo - ) -{ - BOOLEAN Write; - UINTN Size; - UINTN Port; - UINT64 Val; - UINT64 RepCnt; - UINT64 Status; - - Val =3D 0; - Write =3D Veinfo->ExitQualification.Io.Direction ? FALSE : TRUE; - Size =3D Veinfo->ExitQualification.Io.Size + 1; - Port =3D Veinfo->ExitQualification.Io.Port; - - if (Veinfo->ExitQualification.Io.String) { - // - // If REP is set, get rep-cnt from Rcx - // - RepCnt =3D Veinfo->ExitQualification.Io.Rep ? Regs->Rcx : 1; - - while (RepCnt) { - Val =3D 0; - if (Write =3D=3D TRUE) { - CopyMem (&Val, (VOID *)Regs->Rsi, Size); - Regs->Rsi +=3D Size; - } - - Status =3D TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, = Val, (Write ? NULL : &Val)); - if (Status !=3D 0) { - break; - } - - if (Write =3D=3D FALSE) { - CopyMem ((VOID *)Regs->Rdi, &Val, Size); - Regs->Rdi +=3D Size; - } - - if (Veinfo->ExitQualification.Io.Rep) { - Regs->Rcx -=3D 1; - } - - RepCnt -=3D 1; - } - } else { - if (Write =3D=3D TRUE) { - CopyMem (&Val, (VOID *)&Regs->Rax, Size); - } - - Status =3D TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Va= l, (Write ? NULL : &Val)); - if ((Status =3D=3D 0) && (Write =3D=3D FALSE)) { - CopyMem ((VOID *)&Regs->Rax, &Val, Size); - } - } - - return Status; -} - -/** - Handle an READ MSR event. - - Use the TDVMCALL instruction to handle msr read - - @param[in, out] Regs x64 processor context - @param[in] Veinfo VE Info - - @retval 0 Event handled successfully - @return New exception value to propagate -**/ -STATIC -UINT64 -ReadMsrExit ( - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN TDCALL_VEINFO_RETURN_DATA *Veinfo - ) -{ - MSR_DATA Data; - UINT64 Status; - - Status =3D TdVmCall (EXIT_REASON_MSR_READ, Regs->Rcx, 0, 0, 0, &Data); - if (Status =3D=3D 0) { - Regs->Rax =3D Data.Regs.Eax; - Regs->Rdx =3D Data.Regs.Edx; - } - - return Status; -} - -/** - Handle an WRITE MSR event. - - Use the TDVMCALL instruction to handle msr write - - @param[in, out] Regs x64 processor context - @param[in] Veinfo VE Info - - @retval 0 Event handled successfully - @return New exception value to propagate -**/ -STATIC -UINT64 -WriteMsrExit ( - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN TDCALL_VEINFO_RETURN_DATA *Veinfo - ) -{ - UINT64 Status; - MSR_DATA Data; - - Data.Regs.Eax =3D (UINT32)Regs->Rax; - Data.Regs.Edx =3D (UINT32)Regs->Rdx; - - Status =3D TdVmCall (EXIT_REASON_MSR_WRITE, Regs->Rcx, Data.Val, 0, 0, = NULL); - - return Status; -} - -STATIC -VOID -EFIAPI -TdxDecodeInstruction ( - IN UINT8 *Rip - ) -{ - UINTN i; - - DEBUG ((DEBUG_INFO, "TDX: #TD[EPT] instruction (%p):", Rip)); - for (i =3D 0; i < 15; i++) { - DEBUG ((DEBUG_INFO, "%02x:", Rip[i])); - } - - DEBUG ((DEBUG_INFO, "\n")); -} - -#define TDX_DECODER_BUG_ON(x) \ - if ((x)) { \ - TdxDecodeInstruction(Rip); \ - TdVmCall(TDVMCALL_HALT, 0, 0, 0, 0, 0); \ - } - -STATIC -UINT64 * -EFIAPI -GetRegFromContext ( - IN EFI_SYSTEM_CONTEXT_X64 *Regs, - IN UINTN RegIndex - ) -{ - switch (RegIndex) { - case 0: return &Regs->Rax; - break; - case 1: return &Regs->Rcx; - break; - case 2: return &Regs->Rdx; - break; - case 3: return &Regs->Rbx; - break; - case 4: return &Regs->Rsp; - break; - case 5: return &Regs->Rbp; - break; - case 6: return &Regs->Rsi; - break; - case 7: return &Regs->Rdi; - break; - case 8: return &Regs->R8; - break; - case 9: return &Regs->R9; - break; - case 10: return &Regs->R10; - break; - case 11: return &Regs->R11; - break; - case 12: return &Regs->R12; - break; - case 13: return &Regs->R13; - break; - case 14: return &Regs->R14; - break; - case 15: return &Regs->R15; - break; - } - - return NULL; -} - -/** - Handle an MMIO event. - - Use the TDVMCALL instruction to handle either an mmio read or an mmio wr= ite. - - @param[in, out] Regs x64 processor context - @param[in] Veinfo VE Info - - @retval 0 Event handled successfully - @return New exception value to propagate -**/ -STATIC -INTN -EFIAPI -MmioExit ( - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN TDCALL_VEINFO_RETURN_DATA *Veinfo - ) -{ - UINT64 Status; - UINT32 MmioSize; - UINT32 RegSize; - UINT8 OpCode; - BOOLEAN SeenRex; - UINT64 *Reg; - UINT8 *Rip; - UINT64 Val; - UINT32 OpSize; - MODRM ModRm; - REX Rex; - - Rip =3D (UINT8 *)Regs->Rip; - Val =3D 0; - Rex.Val =3D 0; - SeenRex =3D FALSE; - - // - // Default to 32bit transfer - // - OpSize =3D 4; - - do { - OpCode =3D *Rip++; - if (OpCode =3D=3D 0x66) { - OpSize =3D 2; - } else if ((OpCode =3D=3D 0x64) || (OpCode =3D=3D 0x65) || (OpCode =3D= =3D 0x67)) { - continue; - } else if ((OpCode >=3D 0x40) && (OpCode <=3D 0x4f)) { - SeenRex =3D TRUE; - Rex.Val =3D OpCode; - } else { - break; - } - } while (TRUE); - - // - // We need to have at least 2 more bytes for this instruction - // - TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 13); - - OpCode =3D *Rip++; - // - // Two-byte opecode, get next byte - // - if (OpCode =3D=3D 0x0F) { - OpCode =3D *Rip++; - } - - switch (OpCode) { - case 0x88: - case 0x8A: - case 0xB6: - MmioSize =3D 1; - break; - case 0xB7: - MmioSize =3D 2; - break; - default: - MmioSize =3D Rex.Bits.W ? 8 : OpSize; - break; - } - - /* Punt on AH/BH/CH/DH unless it shows up. */ - ModRm.Val =3D *Rip++; - TDX_DECODER_BUG_ON (MmioSize =3D=3D 1 && ModRm.Bits.Reg > 4 && !SeenRex = && OpCode !=3D 0xB6); - Reg =3D GetRegFromContext (Regs, ModRm.Bits.Reg | ((int)Rex.Bits.R << 3)= ); - TDX_DECODER_BUG_ON (!Reg); - - if (ModRm.Bits.Rm =3D=3D 4) { - ++Rip; /* SIB byte */ - } - - if ((ModRm.Bits.Mod =3D=3D 2) || ((ModRm.Bits.Mod =3D=3D 0) && (ModRm.Bi= ts.Rm =3D=3D 5))) { - Rip +=3D 4; /* DISP32 */ - } else if (ModRm.Bits.Mod =3D=3D 1) { - ++Rip; /* DISP8 */ - } - - switch (OpCode) { - case 0x88: - case 0x89: - CopyMem ((void *)&Val, Reg, MmioSize); - Status =3D TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Va= l, 0); - break; - case 0xC7: - CopyMem ((void *)&Val, Rip, OpSize); - Status =3D TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Va= l, 0); - Rip +=3D OpSize; - default: - // - // 32-bit write registers are zero extended to the full register - // Hence 'MOVZX r[32/64], r/m16' is - // hardcoded to reg size 8, and the straight MOV case has a reg - // size of 8 in the 32-bit read case. - // - switch (OpCode) { - case 0xB6: - RegSize =3D Rex.Bits.W ? 8 : OpSize; - break; - case 0xB7: - RegSize =3D 8; - break; - default: - RegSize =3D MmioSize =3D=3D 4 ? 8 : MmioSize; - break; - } - - Status =3D TdVmCall (TDVMCALL_MMIO, MmioSize, 0, Veinfo->GuestPA, 0,= &Val); - if (Status =3D=3D 0) { - ZeroMem (Reg, RegSize); - CopyMem (Reg, (void *)&Val, MmioSize); - } - } - - if (Status =3D=3D 0) { - TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 15); - - // - // We change instruction length to reflect true size so handler can - // bump rip - // - Veinfo->ExitInstructionLength =3D (UINT32)((UINT64)Rip - Regs->Rip); - } - - return Status; -} - -/** - Handle a #VE exception. - - Performs the necessary processing to handle a #VE exception. - - @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et - as value to use on error. - @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT - - @retval EFI_SUCCESS Exception handled - @retval EFI_UNSUPPORTED #VE not supported, (new) exception value= to - propagate provided - @retval EFI_PROTOCOL_ERROR #VE handling failed, (new) exception val= ue to - propagate provided - -**/ -EFI_STATUS -EFIAPI -VmTdExitHandleVe ( - IN OUT EFI_EXCEPTION_TYPE *ExceptionType, - IN OUT EFI_SYSTEM_CONTEXT SystemContext - ) -{ - UINT64 Status; - TD_RETURN_DATA ReturnData; - EFI_SYSTEM_CONTEXT_X64 *Regs; - - Regs =3D SystemContext.SystemContextX64; - Status =3D TdCall (TDCALL_TDGETVEINFO, 0, 0, 0, &ReturnData); - ASSERT (Status =3D=3D 0); - if (Status !=3D 0) { - DEBUG ((DEBUG_ERROR, "#VE happened. TDGETVEINFO failed with Status =3D= 0x%llx\n", Status)); - TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); - } - - switch (ReturnData.VeInfo.ExitReason) { - case EXIT_REASON_CPUID: - Status =3D CpuIdExit (Regs, &ReturnData.VeInfo); - DEBUG (( - DEBUG_VERBOSE, - "CPUID #VE happened, ExitReasion is %d, ExitQualification =3D 0x%x= .\n", - ReturnData.VeInfo.ExitReason, - ReturnData.VeInfo.ExitQualification.Val - )); - break; - - case EXIT_REASON_HLT: - Status =3D TdVmCall (EXIT_REASON_HLT, 0, 0, 0, 0, 0); - break; - - case EXIT_REASON_IO_INSTRUCTION: - Status =3D IoExit (Regs, &ReturnData.VeInfo); - DEBUG (( - DEBUG_VERBOSE, - "IO_Instruction #VE happened, ExitReasion is %d, ExitQualification= =3D 0x%x.\n", - ReturnData.VeInfo.ExitReason, - ReturnData.VeInfo.ExitQualification.Val - )); - break; - - case EXIT_REASON_MSR_READ: - Status =3D ReadMsrExit (Regs, &ReturnData.VeInfo); - DEBUG (( - DEBUG_VERBOSE, - "RDMSR #VE happened, ExitReasion is %d, ExitQualification =3D 0x%x= . Regs->Rcx=3D0x%llx, Status =3D 0x%llx\n", - ReturnData.VeInfo.ExitReason, - ReturnData.VeInfo.ExitQualification.Val, - Regs->Rcx, - Status - )); - break; - - case EXIT_REASON_MSR_WRITE: - Status =3D WriteMsrExit (Regs, &ReturnData.VeInfo); - DEBUG (( - DEBUG_VERBOSE, - "WRMSR #VE happened, ExitReasion is %d, ExitQualification =3D 0x%x= . Regs->Rcx=3D0x%llx, Status =3D 0x%llx\n", - ReturnData.VeInfo.ExitReason, - ReturnData.VeInfo.ExitQualification.Val, - Regs->Rcx, - Status - )); - break; - - case EXIT_REASON_EPT_VIOLATION: - Status =3D MmioExit (Regs, &ReturnData.VeInfo); - DEBUG (( - DEBUG_VERBOSE, - "MMIO #VE happened, ExitReasion is %d, ExitQualification =3D 0x%x.= \n", - ReturnData.VeInfo.ExitReason, - ReturnData.VeInfo.ExitQualification.Val - )); - break; - - case EXIT_REASON_VMCALL: - case EXIT_REASON_MWAIT_INSTRUCTION: - case EXIT_REASON_MONITOR_INSTRUCTION: - case EXIT_REASON_WBINVD: - case EXIT_REASON_RDPMC: - /* Handle as nops. */ - break; - - default: - DEBUG (( - DEBUG_ERROR, - "Unsupported #VE happened, ExitReason is %d, ExitQualification =3D= 0x%x.\n", - ReturnData.VeInfo.ExitReason, - ReturnData.VeInfo.ExitQualification.Val - )); - - ASSERT (FALSE); - CpuDeadLoop (); - } - - if (Status) { - DEBUG (( - DEBUG_ERROR, - "#VE Error (0x%llx) returned from host, ExitReason is %d, ExitQualif= ication =3D 0x%x.\n", - Status, - ReturnData.VeInfo.ExitReason, - ReturnData.VeInfo.ExitQualification.Val - )); - - TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); - } - - SystemContext.SystemContextX64->Rip +=3D ReturnData.VeInfo.ExitInstructi= onLength; - return EFI_SUCCESS; -} diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.c b/OvmfPkg/Library/VmgE= xitLib/VmgExitLib.c deleted file mode 100644 index c20552187074..000000000000 --- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.c +++ /dev/null @@ -1,238 +0,0 @@ -/** @file - VMGEXIT Support Library. - - Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include -#include -#include - -/** - Check for VMGEXIT error - - Check if the hypervisor has returned an error after completion of the VM= GEXIT - by examining the SwExitInfo1 field of the GHCB. - - @param[in] Ghcb A pointer to the GHCB - - @retval 0 VMGEXIT succeeded. - @return Exception number to be propagated, VMGEXIT proces= sing - did not succeed. - -**/ -STATIC -UINT64 -VmgExitErrorCheck ( - IN GHCB *Ghcb - ) -{ - GHCB_EVENT_INJECTION Event; - GHCB_EXIT_INFO ExitInfo; - UINT64 Status; - - ExitInfo.Uint64 =3D Ghcb->SaveArea.SwExitInfo1; - ASSERT ( - (ExitInfo.Elements.Lower32Bits =3D=3D 0) || - (ExitInfo.Elements.Lower32Bits =3D=3D 1) - ); - - Status =3D 0; - if (ExitInfo.Elements.Lower32Bits =3D=3D 0) { - return Status; - } - - if (ExitInfo.Elements.Lower32Bits =3D=3D 1) { - ASSERT (Ghcb->SaveArea.SwExitInfo2 !=3D 0); - - // - // Check that the return event is valid - // - Event.Uint64 =3D Ghcb->SaveArea.SwExitInfo2; - if (Event.Elements.Valid && - (Event.Elements.Type =3D=3D GHCB_EVENT_INJECTION_TYPE_EXCEPTION)) - { - switch (Event.Elements.Vector) { - case GP_EXCEPTION: - case UD_EXCEPTION: - // - // Use returned event as return code - // - Status =3D Event.Uint64; - } - } - } - - if (Status =3D=3D 0) { - GHCB_EVENT_INJECTION GpEvent; - - GpEvent.Uint64 =3D 0; - GpEvent.Elements.Vector =3D GP_EXCEPTION; - GpEvent.Elements.Type =3D GHCB_EVENT_INJECTION_TYPE_EXCEPTION; - GpEvent.Elements.Valid =3D 1; - - Status =3D GpEvent.Uint64; - } - - return Status; -} - -/** - Perform VMGEXIT. - - Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction a= nd - then handles the return actions. - - @param[in, out] Ghcb A pointer to the GHCB - @param[in] ExitCode VMGEXIT code to be assigned to the SwExitCode - field of the GHCB. - @param[in] ExitInfo1 VMGEXIT information to be assigned to the - SwExitInfo1 field of the GHCB. - @param[in] ExitInfo2 VMGEXIT information to be assigned to the - SwExitInfo2 field of the GHCB. - - @retval 0 VMGEXIT succeeded. - @return Exception number to be propagated, VMGEXIT - processing did not succeed. - -**/ -UINT64 -EFIAPI -VmgExit ( - IN OUT GHCB *Ghcb, - IN UINT64 ExitCode, - IN UINT64 ExitInfo1, - IN UINT64 ExitInfo2 - ) -{ - Ghcb->SaveArea.SwExitCode =3D ExitCode; - Ghcb->SaveArea.SwExitInfo1 =3D ExitInfo1; - Ghcb->SaveArea.SwExitInfo2 =3D ExitInfo2; - - VmgSetOffsetValid (Ghcb, GhcbSwExitCode); - VmgSetOffsetValid (Ghcb, GhcbSwExitInfo1); - VmgSetOffsetValid (Ghcb, GhcbSwExitInfo2); - - // - // Guest memory is used for the guest-hypervisor communication, so fence - // the invocation of the VMGEXIT instruction to ensure GHCB accesses are - // synchronized properly. - // - MemoryFence (); - AsmVmgExit (); - MemoryFence (); - - return VmgExitErrorCheck (Ghcb); -} - -/** - Perform pre-VMGEXIT initialization/preparation. - - Performs the necessary steps in preparation for invoking VMGEXIT. Must be - called before setting any fields within the GHCB. - - @param[in, out] Ghcb A pointer to the GHCB - @param[in, out] InterruptState A pointer to hold the current interrupt - state, used for restoring in VmgDone () - -**/ -VOID -EFIAPI -VmgInit ( - IN OUT GHCB *Ghcb, - IN OUT BOOLEAN *InterruptState - ) -{ - // - // Be sure that an interrupt can't cause a #VC while the GHCB is - // being used. - // - *InterruptState =3D GetInterruptState (); - if (*InterruptState) { - DisableInterrupts (); - } - - SetMem (&Ghcb->SaveArea, sizeof (Ghcb->SaveArea), 0); -} - -/** - Perform post-VMGEXIT cleanup. - - Performs the necessary steps to cleanup after invoking VMGEXIT. Must be - called after obtaining needed fields within the GHCB. - - @param[in, out] Ghcb A pointer to the GHCB - @param[in] InterruptState An indicator to conditionally (re)enable - interrupts - -**/ -VOID -EFIAPI -VmgDone ( - IN OUT GHCB *Ghcb, - IN BOOLEAN InterruptState - ) -{ - if (InterruptState) { - EnableInterrupts (); - } -} - -/** - Marks a field at the specified offset as valid in the GHCB. - - The ValidBitmap area represents the areas of the GHCB that have been mar= ked - valid. Set the bit in ValidBitmap for the input offset. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication Bl= ock - @param[in] Offset Qword offset in the GHCB to mark valid - -**/ -VOID -EFIAPI -VmgSetOffsetValid ( - IN OUT GHCB *Ghcb, - IN GHCB_REGISTER Offset - ) -{ - UINT32 OffsetIndex; - UINT32 OffsetBit; - - OffsetIndex =3D Offset / 8; - OffsetBit =3D Offset % 8; - - Ghcb->SaveArea.ValidBitmap[OffsetIndex] |=3D (1 << OffsetBit); -} - -/** - Checks if a specified offset is valid in the GHCB. - - The ValidBitmap area represents the areas of the GHCB that have been mar= ked - valid. Return whether the bit in the ValidBitmap is set for the input of= fset. - - @param[in] Ghcb A pointer to the GHCB - @param[in] Offset Qword offset in the GHCB to mark valid - - @retval TRUE Offset is marked valid in the GHCB - @retval FALSE Offset is not marked valid in the GHCB - -**/ -BOOLEAN -EFIAPI -VmgIsOffsetValid ( - IN GHCB *Ghcb, - IN GHCB_REGISTER Offset - ) -{ - UINT32 OffsetIndex; - UINT32 OffsetBit; - - OffsetIndex =3D Offset / 8; - OffsetBit =3D Offset % 8; - - return ((Ghcb->SaveArea.ValidBitmap[OffsetIndex] & (1 << OffsetBit)) != =3D 0); -} diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/Vm= gExitLib/VmgExitLib.inf deleted file mode 100644 index 255b0c1a2f7f..000000000000 --- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf +++ /dev/null @@ -1,45 +0,0 @@ -## @file -# VMGEXIT Support Library. -# -# Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. -# SPDX-License-Identifier: BSD-2-Clause-Patent -# -## - -[Defines] - INF_VERSION =3D 0x00010005 - BASE_NAME =3D VmgExitLib - FILE_GUID =3D 0e923c25-13cd-430b-8714-ffe85652a97b - MODULE_TYPE =3D BASE - VERSION_STRING =3D 1.0 - LIBRARY_CLASS =3D VmgExitLib|PEIM DXE_CORE DXE_DRIVER D= XE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER - -# -# The following information is for reference only and not required by the = build tools. -# -# VALID_ARCHITECTURES =3D X64 -# - -[Sources.common] - VmgExitLib.c - VmgExitVcHandler.c - VmgExitVcHandler.h - PeiDxeVmgExitVcHandler.c - VmTdExitVeHandler.c - X64/TdVmcallCpuid.nasm - -[Packages] - MdePkg/MdePkg.dec - OvmfPkg/OvmfPkg.dec - UefiCpuPkg/UefiCpuPkg.dec - -[LibraryClasses] - BaseLib - BaseMemoryLib - DebugLib - LocalApicLib - MemEncryptSevLib - -[Pcd] - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Librar= y/VmgExitLib/VmgExitVcHandler.c deleted file mode 100644 index a4393dffbd63..000000000000 --- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c +++ /dev/null @@ -1,2356 +0,0 @@ -/** @file - X64 #VC Exception Handler functon. - - Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "VmgExitVcHandler.h" -// #include - -// -// Instruction execution mode definition -// -typedef enum { - LongMode64Bit =3D 0, - LongModeCompat32Bit, - LongModeCompat16Bit, -} SEV_ES_INSTRUCTION_MODE; - -// -// Instruction size definition (for operand and address) -// -typedef enum { - Size8Bits =3D 0, - Size16Bits, - Size32Bits, - Size64Bits, -} SEV_ES_INSTRUCTION_SIZE; - -// -// Intruction segment definition -// -typedef enum { - SegmentEs =3D 0, - SegmentCs, - SegmentSs, - SegmentDs, - SegmentFs, - SegmentGs, -} SEV_ES_INSTRUCTION_SEGMENT; - -// -// Instruction rep function definition -// -typedef enum { - RepNone =3D 0, - RepZ, - RepNZ, -} SEV_ES_INSTRUCTION_REP; - -typedef struct { - UINT8 Rm; - UINT8 Reg; - UINT8 Mod; -} SEV_ES_INSTRUCTION_MODRM_EXT; - -typedef struct { - UINT8 Base; - UINT8 Index; - UINT8 Scale; -} SEV_ES_INSTRUCTION_SIB_EXT; - -// -// Instruction opcode definition -// -typedef struct { - SEV_ES_INSTRUCTION_MODRM_EXT ModRm; - - SEV_ES_INSTRUCTION_SIB_EXT Sib; - - UINTN RegData; - UINTN RmData; -} SEV_ES_INSTRUCTION_OPCODE_EXT; - -// -// Instruction parsing context definition -// -typedef struct { - GHCB *Ghcb; - - SEV_ES_INSTRUCTION_MODE Mode; - SEV_ES_INSTRUCTION_SIZE DataSize; - SEV_ES_INSTRUCTION_SIZE AddrSize; - BOOLEAN SegmentSpecified; - SEV_ES_INSTRUCTION_SEGMENT Segment; - SEV_ES_INSTRUCTION_REP RepMode; - - UINT8 *Begin; - UINT8 *End; - - UINT8 *Prefixes; - UINT8 *OpCodes; - UINT8 *Displacement; - UINT8 *Immediate; - - INSTRUCTION_REX_PREFIX RexPrefix; - - BOOLEAN ModRmPresent; - INSTRUCTION_MODRM ModRm; - - BOOLEAN SibPresent; - INSTRUCTION_SIB Sib; - - UINTN PrefixSize; - UINTN OpCodeSize; - UINTN DisplacementSize; - UINTN ImmediateSize; - - SEV_ES_INSTRUCTION_OPCODE_EXT Ext; -} SEV_ES_INSTRUCTION_DATA; - -// -// Non-automatic Exit function prototype -// -typedef -UINT64 -(*NAE_EXIT) ( - GHCB *Ghcb, - EFI_SYSTEM_CONTEXT_X64 *Regs, - SEV_ES_INSTRUCTION_DATA *InstructionData - ); - -// -// SEV-SNP Cpuid table entry/function -// -typedef PACKED struct { - UINT32 EaxIn; - UINT32 EcxIn; - UINT64 Unused; - UINT64 Unused2; - UINT32 Eax; - UINT32 Ebx; - UINT32 Ecx; - UINT32 Edx; - UINT64 Reserved; -} SEV_SNP_CPUID_FUNCTION; - -// -// SEV-SNP Cpuid page format -// -typedef PACKED struct { - UINT32 Count; - UINT32 Reserved1; - UINT64 Reserved2; - SEV_SNP_CPUID_FUNCTION function[0]; -} SEV_SNP_CPUID_INFO; - -/** - Return a pointer to the contents of the specified register. - - Based upon the input register, return a pointer to the registers contents - in the x86 processor context. - - @param[in] Regs x64 processor context - @param[in] Register Register to obtain pointer for - - @return Pointer to the contents of the requested register - -**/ -STATIC -UINT64 * -GetRegisterPointer ( - IN EFI_SYSTEM_CONTEXT_X64 *Regs, - IN UINT8 Register - ) -{ - UINT64 *Reg; - - switch (Register) { - case 0: - Reg =3D &Regs->Rax; - break; - case 1: - Reg =3D &Regs->Rcx; - break; - case 2: - Reg =3D &Regs->Rdx; - break; - case 3: - Reg =3D &Regs->Rbx; - break; - case 4: - Reg =3D &Regs->Rsp; - break; - case 5: - Reg =3D &Regs->Rbp; - break; - case 6: - Reg =3D &Regs->Rsi; - break; - case 7: - Reg =3D &Regs->Rdi; - break; - case 8: - Reg =3D &Regs->R8; - break; - case 9: - Reg =3D &Regs->R9; - break; - case 10: - Reg =3D &Regs->R10; - break; - case 11: - Reg =3D &Regs->R11; - break; - case 12: - Reg =3D &Regs->R12; - break; - case 13: - Reg =3D &Regs->R13; - break; - case 14: - Reg =3D &Regs->R14; - break; - case 15: - Reg =3D &Regs->R15; - break; - default: - Reg =3D NULL; - } - - ASSERT (Reg !=3D NULL); - - return Reg; -} - -/** - Update the instruction parsing context for displacement bytes. - - @param[in, out] InstructionData Instruction parsing context - @param[in] Size The instruction displacement size - -**/ -STATIC -VOID -UpdateForDisplacement ( - IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData, - IN UINTN Size - ) -{ - InstructionData->DisplacementSize =3D Size; - InstructionData->Immediate +=3D Size; - InstructionData->End +=3D Size; -} - -/** - Determine if an instruction address if RIP relative. - - Examine the instruction parsing context to determine if the address offs= et - is relative to the instruction pointer. - - @param[in] InstructionData Instruction parsing context - - @retval TRUE Instruction addressing is RIP relative - @retval FALSE Instruction addressing is not RIP relative - -**/ -STATIC -BOOLEAN -IsRipRelative ( - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - SEV_ES_INSTRUCTION_OPCODE_EXT *Ext; - - Ext =3D &InstructionData->Ext; - - return ((InstructionData->Mode =3D=3D LongMode64Bit) && - (Ext->ModRm.Mod =3D=3D 0) && - (Ext->ModRm.Rm =3D=3D 5) && - (InstructionData->SibPresent =3D=3D FALSE)); -} - -/** - Return the effective address of a memory operand. - - Examine the instruction parsing context to obtain the effective memory - address of a memory operand. - - @param[in] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @return The memory operand effective address - -**/ -STATIC -UINT64 -GetEffectiveMemoryAddress ( - IN EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - SEV_ES_INSTRUCTION_OPCODE_EXT *Ext; - UINT64 EffectiveAddress; - - Ext =3D &InstructionData->Ext; - EffectiveAddress =3D 0; - - if (IsRipRelative (InstructionData)) { - // - // RIP-relative displacement is a 32-bit signed value - // - INT32 RipRelative; - - RipRelative =3D *(INT32 *)InstructionData->Displacement; - - UpdateForDisplacement (InstructionData, 4); - - // - // Negative displacement is handled by standard UINT64 wrap-around. - // - return Regs->Rip + (UINT64)RipRelative; - } - - switch (Ext->ModRm.Mod) { - case 1: - UpdateForDisplacement (InstructionData, 1); - EffectiveAddress +=3D (UINT64)(*(INT8 *)(InstructionData->Displaceme= nt)); - break; - case 2: - switch (InstructionData->AddrSize) { - case Size16Bits: - UpdateForDisplacement (InstructionData, 2); - EffectiveAddress +=3D (UINT64)(*(INT16 *)(InstructionData->Displ= acement)); - break; - default: - UpdateForDisplacement (InstructionData, 4); - EffectiveAddress +=3D (UINT64)(*(INT32 *)(InstructionData->Displ= acement)); - break; - } - - break; - } - - if (InstructionData->SibPresent) { - INT64 Displacement; - - if (Ext->Sib.Index !=3D 4) { - CopyMem ( - &Displacement, - GetRegisterPointer (Regs, Ext->Sib.Index), - sizeof (Displacement) - ); - Displacement *=3D (INT64)(1 << Ext->Sib.Scale); - - // - // Negative displacement is handled by standard UINT64 wrap-around. - // - EffectiveAddress +=3D (UINT64)Displacement; - } - - if ((Ext->Sib.Base !=3D 5) || Ext->ModRm.Mod) { - EffectiveAddress +=3D *GetRegisterPointer (Regs, Ext->Sib.Base); - } else { - UpdateForDisplacement (InstructionData, 4); - EffectiveAddress +=3D (UINT64)(*(INT32 *)(InstructionData->Displacem= ent)); - } - } else { - EffectiveAddress +=3D *GetRegisterPointer (Regs, Ext->ModRm.Rm); - } - - return EffectiveAddress; -} - -/** - Decode a ModRM byte. - - Examine the instruction parsing context to decode a ModRM byte and the S= IB - byte, if present. - - @param[in] Regs x64 processor context - @param[in, out] InstructionData Instruction parsing context - -**/ -STATIC -VOID -DecodeModRm ( - IN EFI_SYSTEM_CONTEXT_X64 *Regs, - IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - SEV_ES_INSTRUCTION_OPCODE_EXT *Ext; - INSTRUCTION_REX_PREFIX *RexPrefix; - INSTRUCTION_MODRM *ModRm; - INSTRUCTION_SIB *Sib; - - RexPrefix =3D &InstructionData->RexPrefix; - Ext =3D &InstructionData->Ext; - ModRm =3D &InstructionData->ModRm; - Sib =3D &InstructionData->Sib; - - InstructionData->ModRmPresent =3D TRUE; - ModRm->Uint8 =3D *(InstructionData->End); - - InstructionData->Displacement++; - InstructionData->Immediate++; - InstructionData->End++; - - Ext->ModRm.Mod =3D ModRm->Bits.Mod; - Ext->ModRm.Reg =3D (RexPrefix->Bits.BitR << 3) | ModRm->Bits.Reg; - Ext->ModRm.Rm =3D (RexPrefix->Bits.BitB << 3) | ModRm->Bits.Rm; - - Ext->RegData =3D *GetRegisterPointer (Regs, Ext->ModRm.Reg); - - if (Ext->ModRm.Mod =3D=3D 3) { - Ext->RmData =3D *GetRegisterPointer (Regs, Ext->ModRm.Rm); - } else { - if (ModRm->Bits.Rm =3D=3D 4) { - InstructionData->SibPresent =3D TRUE; - Sib->Uint8 =3D *(InstructionData->End); - - InstructionData->Displacement++; - InstructionData->Immediate++; - InstructionData->End++; - - Ext->Sib.Scale =3D Sib->Bits.Scale; - Ext->Sib.Index =3D (RexPrefix->Bits.BitX << 3) | Sib->Bits.Index; - Ext->Sib.Base =3D (RexPrefix->Bits.BitB << 3) | Sib->Bits.Base; - } - - Ext->RmData =3D GetEffectiveMemoryAddress (Regs, InstructionData); - } -} - -/** - Decode instruction prefixes. - - Parse the instruction data to track the instruction prefixes that have - been used. - - @param[in] Regs x64 processor context - @param[in, out] InstructionData Instruction parsing context - -**/ -STATIC -VOID -DecodePrefixes ( - IN EFI_SYSTEM_CONTEXT_X64 *Regs, - IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - SEV_ES_INSTRUCTION_MODE Mode; - SEV_ES_INSTRUCTION_SIZE ModeDataSize; - SEV_ES_INSTRUCTION_SIZE ModeAddrSize; - UINT8 *Byte; - - // - // Always in 64-bit mode - // - Mode =3D LongMode64Bit; - ModeDataSize =3D Size32Bits; - ModeAddrSize =3D Size64Bits; - - InstructionData->Mode =3D Mode; - InstructionData->DataSize =3D ModeDataSize; - InstructionData->AddrSize =3D ModeAddrSize; - - InstructionData->Prefixes =3D InstructionData->Begin; - - Byte =3D InstructionData->Prefixes; - for ( ; ; Byte++, InstructionData->PrefixSize++) { - // - // Check the 0x40 to 0x4F range using an if statement here since some - // compilers don't like the "case 0x40 ... 0x4F:" syntax. This avoids - // 16 case statements below. - // - if ((*Byte >=3D REX_PREFIX_START) && (*Byte <=3D REX_PREFIX_STOP)) { - InstructionData->RexPrefix.Uint8 =3D *Byte; - if ((*Byte & REX_64BIT_OPERAND_SIZE_MASK) !=3D 0) { - InstructionData->DataSize =3D Size64Bits; - } - - continue; - } - - switch (*Byte) { - case OVERRIDE_SEGMENT_CS: - case OVERRIDE_SEGMENT_DS: - case OVERRIDE_SEGMENT_ES: - case OVERRIDE_SEGMENT_SS: - if (Mode !=3D LongMode64Bit) { - InstructionData->SegmentSpecified =3D TRUE; - InstructionData->Segment =3D (*Byte >> 3) & 3; - } - - break; - - case OVERRIDE_SEGMENT_FS: - case OVERRIDE_SEGMENT_GS: - InstructionData->SegmentSpecified =3D TRUE; - InstructionData->Segment =3D *Byte & 7; - break; - - case OVERRIDE_OPERAND_SIZE: - if (InstructionData->RexPrefix.Uint8 =3D=3D 0) { - InstructionData->DataSize =3D - (Mode =3D=3D LongMode64Bit) ? Size16Bits : - (Mode =3D=3D LongModeCompat32Bit) ? Size16Bits : - (Mode =3D=3D LongModeCompat16Bit) ? Size32Bits : 0; - } - - break; - - case OVERRIDE_ADDRESS_SIZE: - InstructionData->AddrSize =3D - (Mode =3D=3D LongMode64Bit) ? Size32Bits : - (Mode =3D=3D LongModeCompat32Bit) ? Size16Bits : - (Mode =3D=3D LongModeCompat16Bit) ? Size32Bits : 0; - break; - - case LOCK_PREFIX: - break; - - case REPZ_PREFIX: - InstructionData->RepMode =3D RepZ; - break; - - case REPNZ_PREFIX: - InstructionData->RepMode =3D RepNZ; - break; - - default: - InstructionData->OpCodes =3D Byte; - InstructionData->OpCodeSize =3D (*Byte =3D=3D TWO_BYTE_OPCODE_ESCA= PE) ? 2 : 1; - - InstructionData->End =3D Byte + InstructionData->OpCodeSi= ze; - InstructionData->Displacement =3D InstructionData->End; - InstructionData->Immediate =3D InstructionData->End; - return; - } - } -} - -/** - Determine instruction length - - Return the total length of the parsed instruction. - - @param[in] InstructionData Instruction parsing context - - @return Length of parsed instruction - -**/ -STATIC -UINT64 -InstructionLength ( - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - return (UINT64)(InstructionData->End - InstructionData->Begin); -} - -/** - Initialize the instruction parsing context. - - Initialize the instruction parsing context, which includes decoding the - instruction prefixes. - - @param[in, out] InstructionData Instruction parsing context - @param[in] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in] Regs x64 processor context - -**/ -STATIC -VOID -InitInstructionData ( - IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData, - IN GHCB *Ghcb, - IN EFI_SYSTEM_CONTEXT_X64 *Regs - ) -{ - SetMem (InstructionData, sizeof (*InstructionData), 0); - InstructionData->Ghcb =3D Ghcb; - InstructionData->Begin =3D (UINT8 *)Regs->Rip; - InstructionData->End =3D (UINT8 *)Regs->Rip; - - DecodePrefixes (Regs, InstructionData); -} - -/** - Report an unsupported event to the hypervisor - - Use the VMGEXIT support to report an unsupported event to the hypervisor. - - @param[in] Ghcb Pointer to the Guest-Hypervisor Communication - Block - @param[in] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @return New exception value to propagate - -**/ -STATIC -UINT64 -UnsupportedExit ( - IN GHCB *Ghcb, - IN EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - UINT64 Status; - - Status =3D VmgExit (Ghcb, SVM_EXIT_UNSUPPORTED, Regs->ExceptionData, 0); - if (Status =3D=3D 0) { - GHCB_EVENT_INJECTION Event; - - Event.Uint64 =3D 0; - Event.Elements.Vector =3D GP_EXCEPTION; - Event.Elements.Type =3D GHCB_EVENT_INJECTION_TYPE_EXCEPTION; - Event.Elements.Valid =3D 1; - - Status =3D Event.Uint64; - } - - return Status; -} - -/** - Validate that the MMIO memory access is not to encrypted memory. - - Examine the pagetable entry for the memory specified. MMIO should not be - performed against encrypted memory. MMIO to the APIC page is always allo= wed. - - @param[in] Ghcb Pointer to the Guest-Hypervisor Communication = Block - @param[in] MemoryAddress Memory address to validate - @param[in] MemoryLength Memory length to validate - - @retval 0 Memory is not encrypted - @return New exception value to propogate - -**/ -STATIC -UINT64 -ValidateMmioMemory ( - IN GHCB *Ghcb, - IN UINTN MemoryAddress, - IN UINTN MemoryLength - ) -{ - MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE State; - GHCB_EVENT_INJECTION GpEvent; - UINTN Address; - - // - // Allow APIC accesses (which will have the encryption bit set during - // SEC and PEI phases). - // - Address =3D MemoryAddress & ~(SIZE_4KB - 1); - if (Address =3D=3D GetLocalApicBaseAddress ()) { - return 0; - } - - State =3D MemEncryptSevGetAddressRangeState ( - 0, - MemoryAddress, - MemoryLength - ); - if (State =3D=3D MemEncryptSevAddressRangeUnencrypted) { - return 0; - } - - // - // Any state other than unencrypted is an error, issue a #GP. - // - DEBUG (( - DEBUG_ERROR, - "MMIO using encrypted memory: %lx\n", - (UINT64)MemoryAddress - )); - GpEvent.Uint64 =3D 0; - GpEvent.Elements.Vector =3D GP_EXCEPTION; - GpEvent.Elements.Type =3D GHCB_EVENT_INJECTION_TYPE_EXCEPTION; - GpEvent.Elements.Valid =3D 1; - - return GpEvent.Uint64; -} - -/** - Handle an MMIO event. - - Use the VMGEXIT instruction to handle either an MMIO read or an MMIO wri= te. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in, out] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -MmioExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - UINT64 ExitInfo1, ExitInfo2, Status; - UINTN Bytes; - UINT64 *Register; - UINT8 OpCode, SignByte; - UINTN Address; - - Bytes =3D 0; - - OpCode =3D *(InstructionData->OpCodes); - if (OpCode =3D=3D TWO_BYTE_OPCODE_ESCAPE) { - OpCode =3D *(InstructionData->OpCodes + 1); - } - - switch (OpCode) { - // - // MMIO write (MOV reg/memX, regX) - // - case 0x88: - Bytes =3D 1; - // - // fall through - // - case 0x89: - DecodeModRm (Regs, InstructionData); - Bytes =3D ((Bytes !=3D 0) ? Bytes : - (InstructionData->DataSize =3D=3D Size16Bits) ? 2 : - (InstructionData->DataSize =3D=3D Size32Bits) ? 4 : - (InstructionData->DataSize =3D=3D Size64Bits) ? 8 : - 0); - - if (InstructionData->Ext.ModRm.Mod =3D=3D 3) { - // - // NPF on two register operands??? - // - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - Status =3D ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, By= tes); - if (Status !=3D 0) { - return Status; - } - - ExitInfo1 =3D InstructionData->Ext.RmData; - ExitInfo2 =3D Bytes; - CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes); - - Ghcb->SaveArea.SwScratch =3D (UINT64)Ghcb->SharedBuffer; - VmgSetOffsetValid (Ghcb, GhcbSwScratch); - Status =3D VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2); - if (Status !=3D 0) { - return Status; - } - - break; - - // - // MMIO write (MOV moffsetX, aX) - // - case 0xA2: - Bytes =3D 1; - // - // fall through - // - case 0xA3: - Bytes =3D ((Bytes !=3D 0) ? Bytes : - (InstructionData->DataSize =3D=3D Size16Bits) ? 2 : - (InstructionData->DataSize =3D=3D Size32Bits) ? 4 : - (InstructionData->DataSize =3D=3D Size64Bits) ? 8 : - 0); - - InstructionData->ImmediateSize =3D (UINTN)(1 << InstructionData->Add= rSize); - InstructionData->End +=3D InstructionData->ImmediateSize; - - // - // This code is X64 only, so a possible 8-byte copy to a UINTN is ok. - // Use a STATIC_ASSERT to be certain the code is being built as X64. - // - STATIC_ASSERT ( - sizeof (UINTN) =3D=3D sizeof (UINT64), - "sizeof (UINTN) !=3D sizeof (UINT64), this file must be built as X= 64" - ); - - Address =3D 0; - CopyMem ( - &Address, - InstructionData->Immediate, - InstructionData->ImmediateSize - ); - - Status =3D ValidateMmioMemory (Ghcb, Address, Bytes); - if (Status !=3D 0) { - return Status; - } - - ExitInfo1 =3D Address; - ExitInfo2 =3D Bytes; - CopyMem (Ghcb->SharedBuffer, &Regs->Rax, Bytes); - - Ghcb->SaveArea.SwScratch =3D (UINT64)Ghcb->SharedBuffer; - VmgSetOffsetValid (Ghcb, GhcbSwScratch); - Status =3D VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2); - if (Status !=3D 0) { - return Status; - } - - break; - - // - // MMIO write (MOV reg/memX, immX) - // - case 0xC6: - Bytes =3D 1; - // - // fall through - // - case 0xC7: - DecodeModRm (Regs, InstructionData); - Bytes =3D ((Bytes !=3D 0) ? Bytes : - (InstructionData->DataSize =3D=3D Size16Bits) ? 2 : - (InstructionData->DataSize =3D=3D Size32Bits) ? 4 : - 0); - - InstructionData->ImmediateSize =3D Bytes; - InstructionData->End +=3D Bytes; - - Status =3D ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, By= tes); - if (Status !=3D 0) { - return Status; - } - - ExitInfo1 =3D InstructionData->Ext.RmData; - ExitInfo2 =3D Bytes; - CopyMem (Ghcb->SharedBuffer, InstructionData->Immediate, Bytes); - - Ghcb->SaveArea.SwScratch =3D (UINT64)Ghcb->SharedBuffer; - VmgSetOffsetValid (Ghcb, GhcbSwScratch); - Status =3D VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2); - if (Status !=3D 0) { - return Status; - } - - break; - - // - // MMIO read (MOV regX, reg/memX) - // - case 0x8A: - Bytes =3D 1; - // - // fall through - // - case 0x8B: - DecodeModRm (Regs, InstructionData); - Bytes =3D ((Bytes !=3D 0) ? Bytes : - (InstructionData->DataSize =3D=3D Size16Bits) ? 2 : - (InstructionData->DataSize =3D=3D Size32Bits) ? 4 : - (InstructionData->DataSize =3D=3D Size64Bits) ? 8 : - 0); - if (InstructionData->Ext.ModRm.Mod =3D=3D 3) { - // - // NPF on two register operands??? - // - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - Status =3D ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, By= tes); - if (Status !=3D 0) { - return Status; - } - - ExitInfo1 =3D InstructionData->Ext.RmData; - ExitInfo2 =3D Bytes; - - Ghcb->SaveArea.SwScratch =3D (UINT64)Ghcb->SharedBuffer; - VmgSetOffsetValid (Ghcb, GhcbSwScratch); - Status =3D VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2); - if (Status !=3D 0) { - return Status; - } - - Register =3D GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Re= g); - if (Bytes =3D=3D 4) { - // - // Zero-extend for 32-bit operation - // - *Register =3D 0; - } - - CopyMem (Register, Ghcb->SharedBuffer, Bytes); - break; - - // - // MMIO read (MOV aX, moffsetX) - // - case 0xA0: - Bytes =3D 1; - // - // fall through - // - case 0xA1: - Bytes =3D ((Bytes !=3D 0) ? Bytes : - (InstructionData->DataSize =3D=3D Size16Bits) ? 2 : - (InstructionData->DataSize =3D=3D Size32Bits) ? 4 : - (InstructionData->DataSize =3D=3D Size64Bits) ? 8 : - 0); - - InstructionData->ImmediateSize =3D (UINTN)(1 << InstructionData->Add= rSize); - InstructionData->End +=3D InstructionData->ImmediateSize; - - // - // This code is X64 only, so a possible 8-byte copy to a UINTN is ok. - // Use a STATIC_ASSERT to be certain the code is being built as X64. - // - STATIC_ASSERT ( - sizeof (UINTN) =3D=3D sizeof (UINT64), - "sizeof (UINTN) !=3D sizeof (UINT64), this file must be built as X= 64" - ); - - Address =3D 0; - CopyMem ( - &Address, - InstructionData->Immediate, - InstructionData->ImmediateSize - ); - - Status =3D ValidateMmioMemory (Ghcb, Address, Bytes); - if (Status !=3D 0) { - return Status; - } - - ExitInfo1 =3D Address; - ExitInfo2 =3D Bytes; - - Ghcb->SaveArea.SwScratch =3D (UINT64)Ghcb->SharedBuffer; - VmgSetOffsetValid (Ghcb, GhcbSwScratch); - Status =3D VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2); - if (Status !=3D 0) { - return Status; - } - - if (Bytes =3D=3D 4) { - // - // Zero-extend for 32-bit operation - // - Regs->Rax =3D 0; - } - - CopyMem (&Regs->Rax, Ghcb->SharedBuffer, Bytes); - break; - - // - // MMIO read w/ zero-extension ((MOVZX regX, reg/memX) - // - case 0xB6: - Bytes =3D 1; - // - // fall through - // - case 0xB7: - DecodeModRm (Regs, InstructionData); - Bytes =3D (Bytes !=3D 0) ? Bytes : 2; - - Status =3D ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, By= tes); - if (Status !=3D 0) { - return Status; - } - - ExitInfo1 =3D InstructionData->Ext.RmData; - ExitInfo2 =3D Bytes; - - Ghcb->SaveArea.SwScratch =3D (UINT64)Ghcb->SharedBuffer; - VmgSetOffsetValid (Ghcb, GhcbSwScratch); - Status =3D VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2); - if (Status !=3D 0) { - return Status; - } - - Register =3D GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Re= g); - SetMem (Register, (UINTN)(1 << InstructionData->DataSize), 0); - CopyMem (Register, Ghcb->SharedBuffer, Bytes); - break; - - // - // MMIO read w/ sign-extension (MOVSX regX, reg/memX) - // - case 0xBE: - Bytes =3D 1; - // - // fall through - // - case 0xBF: - DecodeModRm (Regs, InstructionData); - Bytes =3D (Bytes !=3D 0) ? Bytes : 2; - - Status =3D ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, By= tes); - if (Status !=3D 0) { - return Status; - } - - ExitInfo1 =3D InstructionData->Ext.RmData; - ExitInfo2 =3D Bytes; - - Ghcb->SaveArea.SwScratch =3D (UINT64)Ghcb->SharedBuffer; - VmgSetOffsetValid (Ghcb, GhcbSwScratch); - Status =3D VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2); - if (Status !=3D 0) { - return Status; - } - - if (Bytes =3D=3D 1) { - UINT8 *Data; - - Data =3D (UINT8 *)Ghcb->SharedBuffer; - SignByte =3D ((*Data & BIT7) !=3D 0) ? 0xFF : 0x00; - } else { - UINT16 *Data; - - Data =3D (UINT16 *)Ghcb->SharedBuffer; - SignByte =3D ((*Data & BIT15) !=3D 0) ? 0xFF : 0x00; - } - - Register =3D GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Re= g); - SetMem (Register, (UINTN)(1 << InstructionData->DataSize), SignByte); - CopyMem (Register, Ghcb->SharedBuffer, Bytes); - break; - - default: - DEBUG ((DEBUG_ERROR, "Invalid MMIO opcode (%x)\n", OpCode)); - Status =3D GP_EXCEPTION; - ASSERT (FALSE); - } - - return Status; -} - -/** - Handle a MWAIT event. - - Use the VMGEXIT instruction to handle a MWAIT event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -MwaitExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - DecodeModRm (Regs, InstructionData); - - Ghcb->SaveArea.Rax =3D Regs->Rax; - VmgSetOffsetValid (Ghcb, GhcbRax); - Ghcb->SaveArea.Rcx =3D Regs->Rcx; - VmgSetOffsetValid (Ghcb, GhcbRcx); - - return VmgExit (Ghcb, SVM_EXIT_MWAIT, 0, 0); -} - -/** - Handle a MONITOR event. - - Use the VMGEXIT instruction to handle a MONITOR event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -MonitorExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - DecodeModRm (Regs, InstructionData); - - Ghcb->SaveArea.Rax =3D Regs->Rax; // Identity mapped, so VA =3D PA - VmgSetOffsetValid (Ghcb, GhcbRax); - Ghcb->SaveArea.Rcx =3D Regs->Rcx; - VmgSetOffsetValid (Ghcb, GhcbRcx); - Ghcb->SaveArea.Rdx =3D Regs->Rdx; - VmgSetOffsetValid (Ghcb, GhcbRdx); - - return VmgExit (Ghcb, SVM_EXIT_MONITOR, 0, 0); -} - -/** - Handle a WBINVD event. - - Use the VMGEXIT instruction to handle a WBINVD event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -WbinvdExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - return VmgExit (Ghcb, SVM_EXIT_WBINVD, 0, 0); -} - -/** - Handle a RDTSCP event. - - Use the VMGEXIT instruction to handle a RDTSCP event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -RdtscpExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - UINT64 Status; - - DecodeModRm (Regs, InstructionData); - - Status =3D VmgExit (Ghcb, SVM_EXIT_RDTSCP, 0, 0); - if (Status !=3D 0) { - return Status; - } - - if (!VmgIsOffsetValid (Ghcb, GhcbRax) || - !VmgIsOffsetValid (Ghcb, GhcbRcx) || - !VmgIsOffsetValid (Ghcb, GhcbRdx)) - { - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - Regs->Rax =3D Ghcb->SaveArea.Rax; - Regs->Rcx =3D Ghcb->SaveArea.Rcx; - Regs->Rdx =3D Ghcb->SaveArea.Rdx; - - return 0; -} - -/** - Handle a VMMCALL event. - - Use the VMGEXIT instruction to handle a VMMCALL event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -VmmCallExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - UINT64 Status; - - DecodeModRm (Regs, InstructionData); - - Ghcb->SaveArea.Rax =3D Regs->Rax; - VmgSetOffsetValid (Ghcb, GhcbRax); - Ghcb->SaveArea.Cpl =3D (UINT8)(Regs->Cs & 0x3); - VmgSetOffsetValid (Ghcb, GhcbCpl); - - Status =3D VmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0); - if (Status !=3D 0) { - return Status; - } - - if (!VmgIsOffsetValid (Ghcb, GhcbRax)) { - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - Regs->Rax =3D Ghcb->SaveArea.Rax; - - return 0; -} - -/** - Handle an MSR event. - - Use the VMGEXIT instruction to handle either a RDMSR or WRMSR event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -MsrExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - UINT64 ExitInfo1, Status; - - ExitInfo1 =3D 0; - - switch (*(InstructionData->OpCodes + 1)) { - case 0x30: // WRMSR - ExitInfo1 =3D 1; - Ghcb->SaveArea.Rax =3D Regs->Rax; - VmgSetOffsetValid (Ghcb, GhcbRax); - Ghcb->SaveArea.Rdx =3D Regs->Rdx; - VmgSetOffsetValid (Ghcb, GhcbRdx); - // - // fall through - // - case 0x32: // RDMSR - Ghcb->SaveArea.Rcx =3D Regs->Rcx; - VmgSetOffsetValid (Ghcb, GhcbRcx); - break; - default: - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - Status =3D VmgExit (Ghcb, SVM_EXIT_MSR, ExitInfo1, 0); - if (Status !=3D 0) { - return Status; - } - - if (ExitInfo1 =3D=3D 0) { - if (!VmgIsOffsetValid (Ghcb, GhcbRax) || - !VmgIsOffsetValid (Ghcb, GhcbRdx)) - { - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - Regs->Rax =3D Ghcb->SaveArea.Rax; - Regs->Rdx =3D Ghcb->SaveArea.Rdx; - } - - return 0; -} - -/** - Build the IOIO event information. - - The IOIO event information identifies the type of IO operation to be per= formed - by the hypervisor. Build this information based on the instruction data. - - @param[in] Regs x64 processor context - @param[in, out] InstructionData Instruction parsing context - - @return IOIO event information value - -**/ -STATIC -UINT64 -IoioExitInfo ( - IN EFI_SYSTEM_CONTEXT_X64 *Regs, - IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - UINT64 ExitInfo; - - ExitInfo =3D 0; - - switch (*(InstructionData->OpCodes)) { - // - // INS opcodes - // - case 0x6C: - case 0x6D: - ExitInfo |=3D IOIO_TYPE_INS; - ExitInfo |=3D IOIO_SEG_ES; - ExitInfo |=3D ((Regs->Rdx & 0xffff) << 16); - break; - - // - // OUTS opcodes - // - case 0x6E: - case 0x6F: - ExitInfo |=3D IOIO_TYPE_OUTS; - ExitInfo |=3D IOIO_SEG_DS; - ExitInfo |=3D ((Regs->Rdx & 0xffff) << 16); - break; - - // - // IN immediate opcodes - // - case 0xE4: - case 0xE5: - InstructionData->ImmediateSize =3D 1; - InstructionData->End++; - ExitInfo |=3D IOIO_TYPE_IN; - ExitInfo |=3D ((*(InstructionData->OpCodes + 1)) << 16); - break; - - // - // OUT immediate opcodes - // - case 0xE6: - case 0xE7: - InstructionData->ImmediateSize =3D 1; - InstructionData->End++; - ExitInfo |=3D IOIO_TYPE_OUT; - ExitInfo |=3D ((*(InstructionData->OpCodes + 1)) << 16) | IOIO_TYPE_= OUT; - break; - - // - // IN register opcodes - // - case 0xEC: - case 0xED: - ExitInfo |=3D IOIO_TYPE_IN; - ExitInfo |=3D ((Regs->Rdx & 0xffff) << 16); - break; - - // - // OUT register opcodes - // - case 0xEE: - case 0xEF: - ExitInfo |=3D IOIO_TYPE_OUT; - ExitInfo |=3D ((Regs->Rdx & 0xffff) << 16); - break; - - default: - return 0; - } - - switch (*(InstructionData->OpCodes)) { - // - // Single-byte opcodes - // - case 0x6C: - case 0x6E: - case 0xE4: - case 0xE6: - case 0xEC: - case 0xEE: - ExitInfo |=3D IOIO_DATA_8; - break; - - // - // Length determined by instruction parsing - // - default: - ExitInfo |=3D (InstructionData->DataSize =3D=3D Size16Bits) ? IOIO_D= ATA_16 - : IOIO_DATA_32; - } - - switch (InstructionData->AddrSize) { - case Size16Bits: - ExitInfo |=3D IOIO_ADDR_16; - break; - - case Size32Bits: - ExitInfo |=3D IOIO_ADDR_32; - break; - - case Size64Bits: - ExitInfo |=3D IOIO_ADDR_64; - break; - - default: - break; - } - - if (InstructionData->RepMode !=3D 0) { - ExitInfo |=3D IOIO_REP; - } - - return ExitInfo; -} - -/** - Handle an IOIO event. - - Use the VMGEXIT instruction to handle an IOIO event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -IoioExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - UINT64 ExitInfo1, ExitInfo2, Status; - BOOLEAN IsString; - - ExitInfo1 =3D IoioExitInfo (Regs, InstructionData); - if (ExitInfo1 =3D=3D 0) { - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - IsString =3D ((ExitInfo1 & IOIO_TYPE_STR) !=3D 0) ? TRUE : FALSE; - if (IsString) { - UINTN IoBytes, VmgExitBytes; - UINTN GhcbCount, OpCount; - - Status =3D 0; - - IoBytes =3D IOIO_DATA_BYTES (ExitInfo1); - GhcbCount =3D sizeof (Ghcb->SharedBuffer) / IoBytes; - - OpCount =3D ((ExitInfo1 & IOIO_REP) !=3D 0) ? Regs->Rcx : 1; - while (OpCount !=3D 0) { - ExitInfo2 =3D MIN (OpCount, GhcbCount); - VmgExitBytes =3D ExitInfo2 * IoBytes; - - if ((ExitInfo1 & IOIO_TYPE_IN) =3D=3D 0) { - CopyMem (Ghcb->SharedBuffer, (VOID *)Regs->Rsi, VmgExitBytes); - Regs->Rsi +=3D VmgExitBytes; - } - - Ghcb->SaveArea.SwScratch =3D (UINT64)Ghcb->SharedBuffer; - VmgSetOffsetValid (Ghcb, GhcbSwScratch); - Status =3D VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, ExitInfo2); - if (Status !=3D 0) { - return Status; - } - - if ((ExitInfo1 & IOIO_TYPE_IN) !=3D 0) { - CopyMem ((VOID *)Regs->Rdi, Ghcb->SharedBuffer, VmgExitBytes); - Regs->Rdi +=3D VmgExitBytes; - } - - if ((ExitInfo1 & IOIO_REP) !=3D 0) { - Regs->Rcx -=3D ExitInfo2; - } - - OpCount -=3D ExitInfo2; - } - } else { - if ((ExitInfo1 & IOIO_TYPE_IN) !=3D 0) { - Ghcb->SaveArea.Rax =3D 0; - } else { - CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1= )); - } - - VmgSetOffsetValid (Ghcb, GhcbRax); - - Status =3D VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0); - if (Status !=3D 0) { - return Status; - } - - if ((ExitInfo1 & IOIO_TYPE_IN) !=3D 0) { - if (!VmgIsOffsetValid (Ghcb, GhcbRax)) { - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1= )); - } - } - - return 0; -} - -/** - Handle a INVD event. - - Use the VMGEXIT instruction to handle a INVD event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -InvdExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - return VmgExit (Ghcb, SVM_EXIT_INVD, 0, 0); -} - -/** - Fetch CPUID leaf/function via hypervisor/VMGEXIT. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communicati= on - Block - @param[in] EaxIn EAX input for cpuid instruction - @param[in] EcxIn ECX input for cpuid instruction - @param[in] Xcr0In XCR0 at time of cpuid instruction - @param[in, out] Eax Pointer to store leaf's EAX value - @param[in, out] Ebx Pointer to store leaf's EBX value - @param[in, out] Ecx Pointer to store leaf's ECX value - @param[in, out] Edx Pointer to store leaf's EDX value - @param[in, out] Status Pointer to store status from VMGEXIT (alway= s 0 - unless return value indicates failure) - @param[in, out] Unsupported Pointer to store indication of unsupported - VMGEXIT (always false unless return value - indicates failure) - - @retval TRUE CPUID leaf fetch successfully. - @retval FALSE Error occurred while fetching CPUID leaf. C= allers - should Status and Unsupported and handle - accordingly if they indicate a more precise - error condition. - -**/ -STATIC -BOOLEAN -GetCpuidHyp ( - IN OUT GHCB *Ghcb, - IN UINT32 EaxIn, - IN UINT32 EcxIn, - IN UINT64 XCr0, - IN OUT UINT32 *Eax, - IN OUT UINT32 *Ebx, - IN OUT UINT32 *Ecx, - IN OUT UINT32 *Edx, - IN OUT UINT64 *Status, - IN OUT BOOLEAN *UnsupportedExit - ) -{ - *UnsupportedExit =3D FALSE; - Ghcb->SaveArea.Rax =3D EaxIn; - VmgSetOffsetValid (Ghcb, GhcbRax); - Ghcb->SaveArea.Rcx =3D EcxIn; - VmgSetOffsetValid (Ghcb, GhcbRcx); - if (EaxIn =3D=3D CPUID_EXTENDED_STATE) { - Ghcb->SaveArea.XCr0 =3D XCr0; - VmgSetOffsetValid (Ghcb, GhcbXCr0); - } - - *Status =3D VmgExit (Ghcb, SVM_EXIT_CPUID, 0, 0); - if (*Status !=3D 0) { - return FALSE; - } - - if (!VmgIsOffsetValid (Ghcb, GhcbRax) || - !VmgIsOffsetValid (Ghcb, GhcbRbx) || - !VmgIsOffsetValid (Ghcb, GhcbRcx) || - !VmgIsOffsetValid (Ghcb, GhcbRdx)) - { - *UnsupportedExit =3D TRUE; - return FALSE; - } - - if (Eax) { - *Eax =3D (UINT32)(UINTN)Ghcb->SaveArea.Rax; - } - - if (Ebx) { - *Ebx =3D (UINT32)(UINTN)Ghcb->SaveArea.Rbx; - } - - if (Ecx) { - *Ecx =3D (UINT32)(UINTN)Ghcb->SaveArea.Rcx; - } - - if (Edx) { - *Edx =3D (UINT32)(UINTN)Ghcb->SaveArea.Rdx; - } - - return TRUE; -} - -/** - Check if SEV-SNP enabled. - - @retval TRUE SEV-SNP is enabled. - @retval FALSE SEV-SNP is disabled. - -**/ -STATIC -BOOLEAN -SnpEnabled ( - VOID - ) -{ - MSR_SEV_STATUS_REGISTER Msr; - - Msr.Uint32 =3D AsmReadMsr32 (MSR_SEV_STATUS); - - return !!Msr.Bits.SevSnpBit; -} - -/** - Calculate the total XSAVE area size for enabled XSAVE areas - - @param[in] XFeaturesEnabled Bit-mask of enabled XSAVE features/are= as as - indicated by XCR0/MSR_IA32_XSS bits - @param[in] XSaveBaseSize Base/legacy XSAVE area size (e.g. when - XCR0 is 1) - @param[in, out] XSaveSize Pointer to storage for calculated XSAV= E area - size - @param[in] Compacted Whether or not the calculation is for = the - normal XSAVE area size (leaf 0xD,0x0,E= BX) or - compacted XSAVE area size (leaf 0xD,0x= 1,EBX) - - - @retval TRUE XSAVE size calculation was successful. - @retval FALSE XSAVE size calculation was unsuccessfu= l. -**/ -STATIC -BOOLEAN -GetCpuidXSaveSize ( - IN UINT64 XFeaturesEnabled, - IN UINT32 XSaveBaseSize, - IN OUT UINT32 *XSaveSize, - IN BOOLEAN Compacted - ) -{ - SEV_SNP_CPUID_INFO *CpuidInfo; - UINT64 XFeaturesFound =3D 0; - UINT32 Idx; - - *XSaveSize =3D XSaveBaseSize; - CpuidInfo =3D (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase); - - for (Idx =3D 0; Idx < CpuidInfo->Count; Idx++) { - SEV_SNP_CPUID_FUNCTION *CpuidFn =3D &CpuidInfo->function[Idx]; - - if (!((CpuidFn->EaxIn =3D=3D 0xD) && - ((CpuidFn->EcxIn =3D=3D 0) || (CpuidFn->EcxIn =3D=3D 1)))) - { - continue; - } - - if (XFeaturesFound & (1ULL << CpuidFn->EcxIn) || - !(XFeaturesEnabled & (1ULL << CpuidFn->EcxIn))) - { - continue; - } - - XFeaturesFound |=3D (1ULL << CpuidFn->EcxIn); - if (Compacted) { - *XSaveSize +=3D CpuidFn->Eax; - } else { - *XSaveSize =3D MAX (*XSaveSize, CpuidFn->Eax + CpuidFn->Ebx); - } - } - - /* - * Either the guest set unsupported XCR0/XSS bits, or the corresponding - * entries in the CPUID table were not present. This is an invalid state. - */ - if (XFeaturesFound !=3D (XFeaturesEnabled & ~3UL)) { - return FALSE; - } - - return TRUE; -} - -/** - Check if a CPUID leaf/function is indexed via ECX sub-leaf/sub-function - - @param[in] EaxIn EAX input for cpuid instruction - - @retval FALSE cpuid leaf/function is not indexed by ECX i= nput - @retval TRUE cpuid leaf/function is indexed by ECX input - -**/ -STATIC -BOOLEAN -IsFunctionIndexed ( - IN UINT32 EaxIn - ) -{ - switch (EaxIn) { - case CPUID_CACHE_PARAMS: - case CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS: - case CPUID_EXTENDED_TOPOLOGY: - case CPUID_EXTENDED_STATE: - case CPUID_INTEL_RDT_MONITORING: - case CPUID_INTEL_RDT_ALLOCATION: - case CPUID_INTEL_SGX: - case CPUID_INTEL_PROCESSOR_TRACE: - case CPUID_DETERMINISTIC_ADDRESS_TRANSLATION_PARAMETERS: - case CPUID_V2_EXTENDED_TOPOLOGY: - case 0x8000001D: /* Cache Topology Information */ - return TRUE; - } - - return FALSE; -} - -/** - Fetch CPUID leaf/function via SEV-SNP CPUID table. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communicati= on - Block - @param[in] EaxIn EAX input for cpuid instruction - @param[in] EcxIn ECX input for cpuid instruction - @param[in] Xcr0In XCR0 at time of cpuid instruction - @param[in, out] Eax Pointer to store leaf's EAX value - @param[in, out] Ebx Pointer to store leaf's EBX value - @param[in, out] Ecx Pointer to store leaf's ECX value - @param[in, out] Edx Pointer to store leaf's EDX value - @param[in, out] Status Pointer to store status from VMGEXIT (alway= s 0 - unless return value indicates failure) - @param[in, out] Unsupported Pointer to store indication of unsupported - VMGEXIT (always false unless return value - indicates failure) - - @retval TRUE CPUID leaf fetch successfully. - @retval FALSE Error occurred while fetching CPUID leaf. C= allers - should Status and Unsupported and handle - accordingly if they indicate a more precise - error condition. - -**/ -STATIC -BOOLEAN -GetCpuidFw ( - IN OUT GHCB *Ghcb, - IN UINT32 EaxIn, - IN UINT32 EcxIn, - IN UINT64 XCr0, - IN OUT UINT32 *Eax, - IN OUT UINT32 *Ebx, - IN OUT UINT32 *Ecx, - IN OUT UINT32 *Edx, - IN OUT UINT64 *Status, - IN OUT BOOLEAN *Unsupported - ) -{ - SEV_SNP_CPUID_INFO *CpuidInfo; - BOOLEAN Found; - UINT32 Idx; - - CpuidInfo =3D (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase); - Found =3D FALSE; - - for (Idx =3D 0; Idx < CpuidInfo->Count; Idx++) { - SEV_SNP_CPUID_FUNCTION *CpuidFn =3D &CpuidInfo->function[Idx]; - - if (CpuidFn->EaxIn !=3D EaxIn) { - continue; - } - - if (IsFunctionIndexed (CpuidFn->EaxIn) && (CpuidFn->EcxIn !=3D EcxIn))= { - continue; - } - - *Eax =3D CpuidFn->Eax; - *Ebx =3D CpuidFn->Ebx; - *Ecx =3D CpuidFn->Ecx; - *Edx =3D CpuidFn->Edx; - - Found =3D TRUE; - break; - } - - if (!Found) { - *Eax =3D *Ebx =3D *Ecx =3D *Edx =3D 0; - goto Out; - } - - if (EaxIn =3D=3D CPUID_VERSION_INFO) { - IA32_CR4 Cr4; - UINT32 Ebx2; - UINT32 Edx2; - - if (!GetCpuidHyp ( - Ghcb, - EaxIn, - EcxIn, - XCr0, - NULL, - &Ebx2, - NULL, - &Edx2, - Status, - Unsupported - )) - { - return FALSE; - } - - /* initial APIC ID */ - *Ebx =3D (*Ebx & 0x00FFFFFF) | (Ebx2 & 0xFF000000); - /* APIC enabled bit */ - *Edx =3D (*Edx & ~BIT9) | (Edx2 & BIT9); - /* OSXSAVE enabled bit */ - Cr4.UintN =3D AsmReadCr4 (); - *Ecx =3D (Cr4.Bits.OSXSAVE) ? (*Ecx & ~BIT27) | (*Ecx & BIT27) - : (*Ecx & ~BIT27); - } else if (EaxIn =3D=3D CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) { - IA32_CR4 Cr4; - - Cr4.UintN =3D AsmReadCr4 (); - /* OSPKE enabled bit */ - *Ecx =3D (Cr4.Bits.PKE) ? (*Ecx | BIT4) : (*Ecx & ~BIT4); - } else if (EaxIn =3D=3D CPUID_EXTENDED_TOPOLOGY) { - if (!GetCpuidHyp ( - Ghcb, - EaxIn, - EcxIn, - XCr0, - NULL, - NULL, - NULL, - Edx, - Status, - Unsupported - )) - { - return FALSE; - } - } else if ((EaxIn =3D=3D CPUID_EXTENDED_STATE) && ((EcxIn =3D=3D 0) || (= EcxIn =3D=3D 1))) { - MSR_IA32_XSS_REGISTER XssMsr; - BOOLEAN Compacted; - UINT32 XSaveSize; - - XssMsr.Uint64 =3D 0; - Compacted =3D FALSE; - if (EcxIn =3D=3D 1) { - /* - * The PPR and APM aren't clear on what size should be encoded in - * 0xD:0x1:EBX when compaction is not enabled by either XSAVEC or - * XSAVES, as these are generally fixed to 1 on real CPUs. Report - * this undefined case as an error. - */ - if (!(*Eax & (BIT3 | BIT1))) { - /* (XSAVES | XSAVEC) */ - return FALSE; - } - - Compacted =3D TRUE; - XssMsr.Uint64 =3D AsmReadMsr64 (MSR_IA32_XSS); - } - - if (!GetCpuidXSaveSize ( - XCr0 | XssMsr.Uint64, - *Ebx, - &XSaveSize, - Compacted - )) - { - return FALSE; - } - - *Ebx =3D XSaveSize; - } else if (EaxIn =3D=3D 0x8000001E) { - UINT32 Ebx2; - UINT32 Ecx2; - - /* extended APIC ID */ - if (!GetCpuidHyp ( - Ghcb, - EaxIn, - EcxIn, - XCr0, - Eax, - &Ebx2, - &Ecx2, - NULL, - Status, - Unsupported - )) - { - return FALSE; - } - - /* compute ID */ - *Ebx =3D (*Ebx & 0xFFFFFF00) | (Ebx2 & 0x000000FF); - /* node ID */ - *Ecx =3D (*Ecx & 0xFFFFFF00) | (Ecx2 & 0x000000FF); - } - -Out: - *Status =3D 0; - *Unsupported =3D FALSE; - return TRUE; -} - -/** - Handle a CPUID event. - - Use VMGEXIT instruction or CPUID table to handle a CPUID event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -CpuidExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - BOOLEAN Unsupported; - UINT64 Status; - UINT32 EaxIn; - UINT32 EcxIn; - UINT64 XCr0; - UINT32 Eax; - UINT32 Ebx; - UINT32 Ecx; - UINT32 Edx; - - EaxIn =3D (UINT32)(UINTN)Regs->Rax; - EcxIn =3D (UINT32)(UINTN)Regs->Rcx; - - if (EaxIn =3D=3D CPUID_EXTENDED_STATE) { - IA32_CR4 Cr4; - - Cr4.UintN =3D AsmReadCr4 (); - Ghcb->SaveArea.XCr0 =3D (Cr4.Bits.OSXSAVE =3D=3D 1) ? AsmXGetBv (0) : = 1; - XCr0 =3D (Cr4.Bits.OSXSAVE =3D=3D 1) ? AsmXGetBv (0) : = 1; - } - - if (SnpEnabled ()) { - if (!GetCpuidFw ( - Ghcb, - EaxIn, - EcxIn, - XCr0, - &Eax, - &Ebx, - &Ecx, - &Edx, - &Status, - &Unsupported - )) - { - goto CpuidFail; - } - } else { - if (!GetCpuidHyp ( - Ghcb, - EaxIn, - EcxIn, - XCr0, - &Eax, - &Ebx, - &Ecx, - &Edx, - &Status, - &Unsupported - )) - { - goto CpuidFail; - } - } - - Regs->Rax =3D Eax; - Regs->Rbx =3D Ebx; - Regs->Rcx =3D Ecx; - Regs->Rdx =3D Edx; - - return 0; - -CpuidFail: - if (Unsupported) { - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - return Status; -} - -/** - Handle a RDPMC event. - - Use the VMGEXIT instruction to handle a RDPMC event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -RdpmcExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - UINT64 Status; - - Ghcb->SaveArea.Rcx =3D Regs->Rcx; - VmgSetOffsetValid (Ghcb, GhcbRcx); - - Status =3D VmgExit (Ghcb, SVM_EXIT_RDPMC, 0, 0); - if (Status !=3D 0) { - return Status; - } - - if (!VmgIsOffsetValid (Ghcb, GhcbRax) || - !VmgIsOffsetValid (Ghcb, GhcbRdx)) - { - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - Regs->Rax =3D Ghcb->SaveArea.Rax; - Regs->Rdx =3D Ghcb->SaveArea.Rdx; - - return 0; -} - -/** - Handle a RDTSC event. - - Use the VMGEXIT instruction to handle a RDTSC event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -RdtscExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - UINT64 Status; - - Status =3D VmgExit (Ghcb, SVM_EXIT_RDTSC, 0, 0); - if (Status !=3D 0) { - return Status; - } - - if (!VmgIsOffsetValid (Ghcb, GhcbRax) || - !VmgIsOffsetValid (Ghcb, GhcbRdx)) - { - return UnsupportedExit (Ghcb, Regs, InstructionData); - } - - Regs->Rax =3D Ghcb->SaveArea.Rax; - Regs->Rdx =3D Ghcb->SaveArea.Rdx; - - return 0; -} - -/** - Handle a DR7 register write event. - - Use the VMGEXIT instruction to handle a DR7 write event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - @return New exception value to propagate - -**/ -STATIC -UINT64 -Dr7WriteExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - SEV_ES_INSTRUCTION_OPCODE_EXT *Ext; - SEV_ES_PER_CPU_DATA *SevEsData; - UINT64 *Register; - UINT64 Status; - - Ext =3D &InstructionData->Ext; - SevEsData =3D (SEV_ES_PER_CPU_DATA *)(Ghcb + 1); - - DecodeModRm (Regs, InstructionData); - - // - // MOV DRn always treats MOD =3D=3D 3 no matter how encoded - // - Register =3D GetRegisterPointer (Regs, Ext->ModRm.Rm); - - // - // Using a value of 0 for ExitInfo1 means RAX holds the value - // - Ghcb->SaveArea.Rax =3D *Register; - VmgSetOffsetValid (Ghcb, GhcbRax); - - Status =3D VmgExit (Ghcb, SVM_EXIT_DR7_WRITE, 0, 0); - if (Status !=3D 0) { - return Status; - } - - SevEsData->Dr7 =3D *Register; - SevEsData->Dr7Cached =3D 1; - - return 0; -} - -/** - Handle a DR7 register read event. - - Use the VMGEXIT instruction to handle a DR7 read event. - - @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communi= cation - Block - @param[in, out] Regs x64 processor context - @param[in] InstructionData Instruction parsing context - - @retval 0 Event handled successfully - -**/ -STATIC -UINT64 -Dr7ReadExit ( - IN OUT GHCB *Ghcb, - IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, - IN SEV_ES_INSTRUCTION_DATA *InstructionData - ) -{ - SEV_ES_INSTRUCTION_OPCODE_EXT *Ext; - SEV_ES_PER_CPU_DATA *SevEsData; - UINT64 *Register; - - Ext =3D &InstructionData->Ext; - SevEsData =3D (SEV_ES_PER_CPU_DATA *)(Ghcb + 1); - - DecodeModRm (Regs, InstructionData); - - // - // MOV DRn always treats MOD =3D=3D 3 no matter how encoded - // - Register =3D GetRegisterPointer (Regs, Ext->ModRm.Rm); - - // - // If there is a cached valued for DR7, return that. Otherwise return the - // DR7 standard reset value of 0x400 (no debug breakpoints set). - // - *Register =3D (SevEsData->Dr7Cached =3D=3D 1) ? SevEsData->Dr7 : 0x400; - - return 0; -} - -/** - Handle a #VC exception. - - Performs the necessary processing to handle a #VC exception. - - @param[in, out] Ghcb Pointer to the GHCB - @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et - as value to use on error. - @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT - - @retval EFI_SUCCESS Exception handled - @retval EFI_UNSUPPORTED #VC not supported, (new) exception value= to - propagate provided - @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception val= ue to - propagate provided - -**/ -EFI_STATUS -EFIAPI -InternalVmgExitHandleVc ( - IN OUT GHCB *Ghcb, - IN OUT EFI_EXCEPTION_TYPE *ExceptionType, - IN OUT EFI_SYSTEM_CONTEXT SystemContext - ) -{ - EFI_SYSTEM_CONTEXT_X64 *Regs; - NAE_EXIT NaeExit; - SEV_ES_INSTRUCTION_DATA InstructionData; - UINT64 ExitCode, Status; - EFI_STATUS VcRet; - BOOLEAN InterruptState; - - VcRet =3D EFI_SUCCESS; - - Regs =3D SystemContext.SystemContextX64; - - VmgInit (Ghcb, &InterruptState); - - ExitCode =3D Regs->ExceptionData; - switch (ExitCode) { - case SVM_EXIT_DR7_READ: - NaeExit =3D Dr7ReadExit; - break; - - case SVM_EXIT_DR7_WRITE: - NaeExit =3D Dr7WriteExit; - break; - - case SVM_EXIT_RDTSC: - NaeExit =3D RdtscExit; - break; - - case SVM_EXIT_RDPMC: - NaeExit =3D RdpmcExit; - break; - - case SVM_EXIT_CPUID: - NaeExit =3D CpuidExit; - break; - - case SVM_EXIT_INVD: - NaeExit =3D InvdExit; - break; - - case SVM_EXIT_IOIO_PROT: - NaeExit =3D IoioExit; - break; - - case SVM_EXIT_MSR: - NaeExit =3D MsrExit; - break; - - case SVM_EXIT_VMMCALL: - NaeExit =3D VmmCallExit; - break; - - case SVM_EXIT_RDTSCP: - NaeExit =3D RdtscpExit; - break; - - case SVM_EXIT_WBINVD: - NaeExit =3D WbinvdExit; - break; - - case SVM_EXIT_MONITOR: - NaeExit =3D MonitorExit; - break; - - case SVM_EXIT_MWAIT: - NaeExit =3D MwaitExit; - break; - - case SVM_EXIT_NPF: - NaeExit =3D MmioExit; - break; - - default: - NaeExit =3D UnsupportedExit; - } - - InitInstructionData (&InstructionData, Ghcb, Regs); - - Status =3D NaeExit (Ghcb, Regs, &InstructionData); - if (Status =3D=3D 0) { - Regs->Rip +=3D InstructionLength (&InstructionData); - } else { - GHCB_EVENT_INJECTION Event; - - Event.Uint64 =3D Status; - if (Event.Elements.ErrorCodeValid !=3D 0) { - Regs->ExceptionData =3D Event.Elements.ErrorCode; - } else { - Regs->ExceptionData =3D 0; - } - - *ExceptionType =3D Event.Elements.Vector; - - VcRet =3D EFI_PROTOCOL_ERROR; - } - - VmgDone (Ghcb, InterruptState); - - return VcRet; -} - -/** - Routine to allow ASSERT from within #VC. - - @param[in, out] SevEsData Pointer to the per-CPU data - -**/ -VOID -EFIAPI -VmgExitIssueAssert ( - IN OUT SEV_ES_PER_CPU_DATA *SevEsData - ) -{ - // - // Progress will be halted, so set VcCount to allow for ASSERT output - // to be seen. - // - SevEsData->VcCount =3D 0; - - ASSERT (FALSE); - CpuDeadLoop (); -} diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h b/OvmfPkg/Librar= y/VmgExitLib/VmgExitVcHandler.h deleted file mode 100644 index 3a37cb04f616..000000000000 --- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - X64 #VC Exception Handler functon header file. - - Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef __VMG_EXIT_VC_HANDLER_H__ -#define __VMG_EXIT_VC_HANDLER_H__ - -#include -#include -#include - -/** - Handle a #VC exception. - - Performs the necessary processing to handle a #VC exception. - - @param[in, out] Ghcb Pointer to the GHCB - @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et - as value to use on error. - @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT - - @retval EFI_SUCCESS Exception handled - @retval EFI_UNSUPPORTED #VC not supported, (new) exception value= to - propagate provided - @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception val= ue to - propagate provided - -**/ -EFI_STATUS -EFIAPI -InternalVmgExitHandleVc ( - IN OUT GHCB *Ghcb, - IN OUT EFI_EXCEPTION_TYPE *ExceptionType, - IN OUT EFI_SYSTEM_CONTEXT SystemContext - ); - -/** - Routine to allow ASSERT from within #VC. - - @param[in, out] SevEsData Pointer to the per-CPU data - -**/ -VOID -EFIAPI -VmgExitIssueAssert ( - IN OUT SEV_ES_PER_CPU_DATA *SevEsData - ); - -#endif diff --git a/OvmfPkg/Library/VmgExitLib/X64/TdVmcallCpuid.nasm b/OvmfPkg/Li= brary/VmgExitLib/X64/TdVmcallCpuid.nasm deleted file mode 100644 index fa86440904fe..000000000000 --- a/OvmfPkg/Library/VmgExitLib/X64/TdVmcallCpuid.nasm +++ /dev/null @@ -1,146 +0,0 @@ -;-------------------------------------------------------------------------= ----- -;* -;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
-;* SPDX-License-Identifier: BSD-2-Clause-Patent -;* -;* -;-------------------------------------------------------------------------= ----- - -DEFAULT REL -SECTION .text - -%define TDVMCALL_EXPOSE_REGS_MASK 0xffec -%define TDVMCALL 0x0 -%define EXIT_REASON_CPUID 0xa - -%macro tdcall 0 - db 0x66,0x0f,0x01,0xcc -%endmacro - -%macro tdcall_push_regs 0 - push rbp - mov rbp, rsp - push r15 - push r14 - push r13 - push r12 - push rbx - push rsi - push rdi -%endmacro - -%macro tdcall_pop_regs 0 - pop rdi - pop rsi - pop rbx - pop r12 - pop r13 - pop r14 - pop r15 - pop rbp -%endmacro - -%define number_of_regs_pushed 8 -%define number_of_parameters 4 - -; -; Keep these in sync for push_regs/pop_regs, code below -; uses them to find 5th or greater parameters -; -%define first_variable_on_stack_offset \ - ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8) -%define second_variable_on_stack_offset \ - ((first_variable_on_stack_offset) + 8) - -%macro tdcall_regs_preamble 2 - mov rax, %1 - - xor rcx, rcx - mov ecx, %2 - - ; R10 =3D 0 (standard TDVMCALL) - - xor r10d, r10d - - ; Zero out unused (for standard TDVMCALL) registers to avoid leaking - ; secrets to the VMM. - - xor ebx, ebx - xor esi, esi - xor edi, edi - - xor edx, edx - xor ebp, ebp - xor r8d, r8d - xor r9d, r9d - xor r14, r14 - xor r15, r15 -%endmacro - -%macro tdcall_regs_postamble 0 - xor ebx, ebx - xor esi, esi - xor edi, edi - - xor ecx, ecx - xor edx, edx - xor r8d, r8d - xor r9d, r9d - xor r10d, r10d - xor r11d, r11d -%endmacro - -;-------------------------------------------------------------------------= ----- -; 0 =3D> RAX =3D TDCALL leaf / TDVMCALL -; M =3D> RCX =3D TDVMCALL register behavior -; 0xa =3D> R11 =3D TDVMCALL function / CPUID -; RCX =3D> R12 =3D p1 -; RDX =3D> R13 =3D p2 -; -; UINT64 -; EFIAPI -; TdVmCallCpuid ( -; UINT64 EaxIn, // Rcx -; UINT64 EcxIn, // Rdx -; UINT64 *Results // R8 -; ) -global ASM_PFX(TdVmCallCpuid) -ASM_PFX(TdVmCallCpuid): - tdcall_push_regs - - mov r11, EXIT_REASON_CPUID - mov r12, rcx - mov r13, rdx - - ; Save *results pointers - push r8 - - tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK - - tdcall - - ; ignore return data if TDCALL reports failure. - test rax, rax - jnz .no_return_data - - ; Propagate TDVMCALL success/failure to return value. - mov rax, r10 - test rax, rax - jnz .no_return_data - - ; Retrieve *Results - pop r8 - test r8, r8 - jz .no_return_data - ; Caller pass in buffer so store results r12-r15 contains eax-edx - mov [r8 + 0], r12 - mov [r8 + 8], r13 - mov [r8 + 16], r14 - mov [r8 + 24], r15 - -.no_return_data: - tdcall_regs_postamble - - tdcall_pop_regs - - ret --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#95921): https://edk2.groups.io/g/devel/message/95921 Mute This Topic: https://groups.io/mt/94795614/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-