Hi Ray, On 8/19/19 4:47 PM, Ni, Ray wrote: > Tom, > 1. It's not a common practice to have static inline functions defined in > header file. Who is going to call them?
The functions are called from two locations, so that's why I made them static inline. I'm new to EDK2 programming, so I'm sure there will be a number of things I do that will need to be changed. Should I make them non-inline and move them to the BaseLib in MdePkg or somewhere else? > 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? Ok, let me pull the latest tree and rebase. This patchset is currently based on a July 17th patch: cce01f538fb4 ("MdePkg/BaseLib: Base64Decode(): don't declare variables in nested blocks") so I'm probably behind the change that you made if it was recent. > 3. What happens if the "rep; vmmcall" is executed in Intel processor? Good question, I'm not sure. Is there a way that EDK2 has to prevent execution of unsupported instructions? Currently, this instruction will only be invoked when it is known that SEV-ES is active. Thanks, Tom > > 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 (#46094): https://edk2.groups.io/g/devel/message/46094 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] -=-=-=-=-=-=-=-=-=-=-=-