Tom, 1. It's not a common practice to have static inline functions defined in header file. Who is going to call them? 2. Recently I made a change to move the AMD registers definitions to MdePkg/Include/Register/Amd from UefiCpuPkg. Do you think that's a good idea and can you please put your new register definitions to MdePkg as well? 3. What happens if the "rep; vmmcall" is executed in Intel processor?
Thanks, Ray > -----Original Message----- > From: Lendacky, Thomas <thomas.lenda...@amd.com> > Sent: Monday, August 19, 2019 2:36 PM > To: devel@edk2.groups.io > Cc: Justen, Jordan L <jordan.l.jus...@intel.com>; Laszlo Ersek > <ler...@redhat.com>; Ard Biesheuvel > <ard.biesheu...@linaro.org>; Kinney, Michael D <michael.d.kin...@intel.com>; > Gao, Liming <liming....@intel.com>; Dong, > Eric <eric.d...@intel.com>; Ni, Ray <ray...@intel.com>; Singh, Brijesh > <brijesh.si...@amd.com> > Subject: [RFC PATCH 08/28] MdePkg/BaseLib: Implement the VMGEXIT support > > From: Tom Lendacky <thomas.lenda...@amd.com> > > VMGEXIT is a new instruction used for Hypervisor/Guest communication when > running as an SEV-ES guest. A VMGEXIT will cause an automatic exit (AE) > to occur, resulting in a #VMEXIT with an exit code value of 0x403. > > To support VMGEXIT, define the VMGEXIT assember routine to issue the > instruction (rep; vmmcall), the GHCB structure and some helper functions > for communicating register information to and from the hypervisor and the > guest. > > Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com> > --- > MdePkg/Library/BaseLib/BaseLib.inf | 1 + > MdePkg/Include/Library/BaseLib.h | 14 ++ > UefiCpuPkg/Include/Register/Amd/Ghcb.h | 197 ++++++++++++++++++++++++ > MdePkg/Library/BaseLib/X64/GccInline.c | 17 ++ > MdePkg/Library/BaseLib/X64/VmgExit.nasm | 38 +++++ > 5 files changed, 267 insertions(+) > create mode 100644 UefiCpuPkg/Include/Register/Amd/Ghcb.h > create mode 100644 MdePkg/Library/BaseLib/X64/VmgExit.nasm > > diff --git a/MdePkg/Library/BaseLib/BaseLib.inf > b/MdePkg/Library/BaseLib/BaseLib.inf > index 3586beb0ab5c..a41401340f95 100644 > --- a/MdePkg/Library/BaseLib/BaseLib.inf > +++ b/MdePkg/Library/BaseLib/BaseLib.inf > @@ -286,6 +286,7 @@ [Sources.X64] > X64/ReadCr2.nasm| MSFT > X64/ReadCr0.nasm| MSFT > X64/ReadEflags.nasm| MSFT > + X64/VmgExit.nasm | MSFT > > > X64/Non-existing.c > diff --git a/MdePkg/Include/Library/BaseLib.h > b/MdePkg/Include/Library/BaseLib.h > index 2a75bc023f56..80bd5cf57a72 100644 > --- a/MdePkg/Include/Library/BaseLib.h > +++ b/MdePkg/Include/Library/BaseLib.h > @@ -7880,6 +7880,20 @@ AsmLfence ( > VOID > ); > > +/** > + Executes a VMGEXIT instruction (VMMCALL with a REP prefix) > + > + Executes a VMGEXIT instruction. This function is only available on IA-32 > and > + x64. > + > +**/ > +VOID > +EFIAPI > +AsmVmgExit ( > + VOID > + ); > + > + > /** > Patch the immediate operand of an IA32 or X64 instruction such that the > byte, > word, dword or qword operand is encoded at the end of the instruction's > diff --git a/UefiCpuPkg/Include/Register/Amd/Ghcb.h > b/UefiCpuPkg/Include/Register/Amd/Ghcb.h > new file mode 100644 > index 000000000000..e9fd116fac25 > --- /dev/null > +++ b/UefiCpuPkg/Include/Register/Amd/Ghcb.h > @@ -0,0 +1,197 @@ > + > +#ifndef __GHCB_H__ > +#define __GHCB_H__ > + > +#include <Protocol/DebugSupport.h> > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > + > +#define UD_EXCEPTION 6 > +#define GP_EXCEPTION 13 > + > +#define GHCB_VERSION_MIN 1 > +#define GHCB_VERSION_MAX 1 > + > +#define GHCB_STANDARD_USAGE 0 > + > +typedef enum { > + SvmExitDr7Read = 0x27, > + SvmExitDr7Write = 0x37, > + SvmExitRdtsc = 0x6E, > + SvmExitRdpmc, > + SvmExitCpuid = 0x72, > + SvmExitInvd = 0x76, > + SvmExitIoioProt = 0x7B, > + SvmExitMsr, > + SvmExitVmmCall = 0x81, > + SvmExitRdtscp = 0x87, > + SvmExitWbinvd = 0x89, > + SvmExitMonitor, > + SvmExitMwait, > + SvmExitNpf = 0x400, > + > + // VMG special exits > + SvmExitMmioRead = 0x80000001, > + SvmExitMmioWrite, > + SvmExitNmiComplete, > + SvmExitApResetHold, > + > + SvmExitUnsupported = 0x8000FFFF, > +} SVM_EXITCODE; > + > +typedef enum { > + GhcbCpl = 25, > + GhcbRflags = 46, > + GhcbRip, > + GhcbRsp = 59, > + GhcbRax = 63, > + GhcbRcx = 97, > + GhcbRdx, > + GhcbRbx, > + GhcbRbp = 101, > + GhcbRsi, > + GhcbRdi, > + GhcbR8, > + GhcbR9, > + GhcbR10, > + GhcbR11, > + GhcbR12, > + GhcbR13, > + GhcbR14, > + GhcbR15, > + GhcbXCr0 = 125, > +} GHCB_REGISTER; > + > +typedef struct { > + UINT8 Reserved1[203]; > + UINT8 Cpl; > + UINT8 Reserved2[148]; > + UINT64 Dr7; > + UINT8 Reserved3[144]; > + UINT64 Rax; > + UINT8 Reserved4[264]; > + UINT64 Rcx; > + UINT64 Rdx; > + UINT64 Rbx; > + UINT8 Reserved5[112]; > + UINT64 SwExitCode; > + UINT64 SwExitInfo1; > + UINT64 SwExitInfo2; > + UINT64 SwScratch; > + UINT8 Reserved6[56]; > + UINT64 XCr0; > + UINT8 ValidBitmap[16]; > + UINT64 X87StateGpa; > + UINT8 Reserved7[1016]; > +} __attribute__ ((__packed__)) GHCB_SAVE_AREA; > + > +typedef struct { > + GHCB_SAVE_AREA SaveArea; > + UINT8 SharedBuffer[2032]; > + UINT8 Reserved1[10]; > + UINT16 ProtocolVersion; > + UINT32 GhcbUsage; > +} __attribute__ ((__packed__)) __attribute__ ((aligned(SIZE_4KB))) GHCB; > + > +typedef union { > + struct { > + UINT32 Lower32Bits; > + UINT32 Upper32Bits; > + } Elements; > + > + UINT64 Uint64; > +} GHCB_EXIT_INFO; > + > +static inline > +BOOLEAN > +GhcbIsRegValid( > + GHCB *Ghcb, > + GHCB_REGISTER Reg > + ) > +{ > + UINT32 RegIndex = Reg / 8; > + UINT32 RegBit = Reg & 0x07; > + > + return (Ghcb->SaveArea.ValidBitmap[RegIndex] & (1 << RegBit)); > +} > + > +static inline > +VOID > +GhcbSetRegValid( > + GHCB *Ghcb, > + GHCB_REGISTER Reg > + ) > +{ > + UINT32 RegIndex = Reg / 8; > + UINT32 RegBit = Reg & 0x07; > + > + Ghcb->SaveArea.ValidBitmap[RegIndex] |= (1 << RegBit); > +} > + > +static inline > +VOID > +VmgException( > + UINTN Exception > + ) > +{ > + switch (Exception) { > + case UD_EXCEPTION: > + case GP_EXCEPTION: > + break; > + default: > + ASSERT (0); > + } > +} > + > +static inline > +UINTN > +VmgExit( > + GHCB *Ghcb, > + UINT64 ExitCode, > + UINT64 ExitInfo1, > + UINT64 ExitInfo2 > + ) > +{ > + GHCB_EXIT_INFO ExitInfo; > + UINTN Reason, Action; > + > + Ghcb->SaveArea.SwExitCode = ExitCode; > + Ghcb->SaveArea.SwExitInfo1 = ExitInfo1; > + Ghcb->SaveArea.SwExitInfo2 = ExitInfo2; > + AsmVmgExit (); > + > + if (!Ghcb->SaveArea.SwExitInfo1) { > + return 0; > + } > + > + ExitInfo.Uint64 = Ghcb->SaveArea.SwExitInfo1; > + Reason = ExitInfo.Elements.Upper32Bits; > + Action = ExitInfo.Elements.Lower32Bits; > + switch (Action) { > + case 1: > + VmgException (Reason); > + break; > + default: > + ASSERT (0); > + } > + > + return Reason; > +} > + > +static inline > +VOID > +VmgInit( > + GHCB *Ghcb > + ) > +{ > + SetMem (&Ghcb->SaveArea, sizeof (Ghcb->SaveArea), 0); > +} > + > +static inline > +VOID > +VmgDone( > + GHCB *Ghcb > + ) > +{ > +} > +#endif > diff --git a/MdePkg/Library/BaseLib/X64/GccInline.c > b/MdePkg/Library/BaseLib/X64/GccInline.c > index 154ce1f57e92..17539caa0798 100644 > --- a/MdePkg/Library/BaseLib/X64/GccInline.c > +++ b/MdePkg/Library/BaseLib/X64/GccInline.c > @@ -1798,3 +1798,20 @@ AsmFlushCacheLine ( > } > > > +/** > + Executes a VMGEXIT instruction. > + > + Executes a VMGEXIT instruction. This function is only available on IA-32 > and > + X64. > + > +**/ > +VOID > +EFIAPI > +AsmVmgExit ( > + VOID > + ) > +{ > + __asm__ __volatile__ ("rep; vmmcall":::"memory"); > +} > + > + > diff --git a/MdePkg/Library/BaseLib/X64/VmgExit.nasm > b/MdePkg/Library/BaseLib/X64/VmgExit.nasm > new file mode 100644 > index 000000000000..b673bb94b60d > --- /dev/null > +++ b/MdePkg/Library/BaseLib/X64/VmgExit.nasm > @@ -0,0 +1,38 @@ > +;------------------------------------------------------------------------------ > +; > +; Copyright (c) 2019, Advanced Micro Device, Inc. All rights reserved.<BR> > +; This program and the accompanying materials > +; are licensed and made available under the terms and conditions of the BSD > License > +; which accompanies this distribution. The full text of the license may be > found at > +; http://opensource.org/licenses/bsd-license.php. > +; > +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR > IMPLIED. > +; > +; Module Name: > +; > +; VmgExit.Asm > +; > +; Abstract: > +; > +; AsmVmgExit function > +; > +; Notes: > +; > +;------------------------------------------------------------------------------ > + > + DEFAULT REL > + SECTION .text > + > +;------------------------------------------------------------------------------ > +; VOID > +; EFIAPI > +; AsmVmgExit ( > +; VOID > +; ); > +;------------------------------------------------------------------------------ > +global ASM_PFX(AsmVmgExit) > +ASM_PFX(AsmVmgExit): > + rep; vmmcall > + ret > + > -- > 2.17.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#46052): https://edk2.groups.io/g/devel/message/46052 Mute This Topic: https://groups.io/mt/32960649/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-