OvmfPkg/XenHypercallLib: Use direct hypercalls

This removes the need to allocate memory for the hypercall page,
particularly for use during runtime.  This also makes the library usable
in all phases, so LIBRARY_CLASS can remove the restrictions.

The processor vendor is used to select vmmcall or vmcall instructions.
The listed vendors are those in the Xen tree.

Signed-off-by: Jason Andryuk <jason.andryuk@amd.com>
This commit is contained in:
Jason Andryuk 2024-04-11 15:43:56 -04:00 committed by mergify[bot]
parent 9d5a9940e4
commit 0e6f6c715c
4 changed files with 148 additions and 44 deletions

View File

@ -2,24 +2,47 @@ SECTION .text
; INTN ; INTN
; EFIAPI ; EFIAPI
; __XenHypercall2 ( ; __XenVmmcall2 (
; IN VOID *HypercallAddr, ; IN INTN HypercallNum,
; IN OUT INTN Arg1, ; IN OUT INTN Arg1,
; IN OUT INTN Arg2 ; IN OUT INTN Arg2
; ); ; );
global ASM_PFX(__XenHypercall2) global ASM_PFX(__XenVmmcall2)
ASM_PFX(__XenHypercall2): ASM_PFX(__XenVmmcall2):
; Save only ebx, ecx is supposed to be a scratch register and needs to be ; Save only ebx, ecx is supposed to be a scratch register and needs to be
; saved by the caller ; saved by the caller
push ebx push ebx
; Copy HypercallAddr to eax ; Copy HypercallNum to eax
mov eax, [esp + 8] mov eax, [esp + 8]
; Copy Arg1 to the register expected by Xen ; Copy Arg1 to the register expected by Xen
mov ebx, [esp + 12] mov ebx, [esp + 12]
; Copy Arg2 to the register expected by Xen ; Copy Arg2 to the register expected by Xen
mov ecx, [esp + 16] mov ecx, [esp + 16]
; Call HypercallAddr ; Call Hypercall
call eax vmmcall
pop ebx
ret
; INTN
; EFIAPI
; __XenVmcall2 (
; IN INTN HypercallNum,
; IN OUT INTN Arg1,
; IN OUT INTN Arg2
; );
global ASM_PFX(__XenVmcall2)
ASM_PFX(__XenVmcall2):
; Save only ebx, ecx is supposed to be a scratch register and needs to be
; saved by the caller
push ebx
; Copy HypercallNum to eax
mov eax, [esp + 8]
; Copy Arg1 to the register expected by Xen
mov ebx, [esp + 12]
; Copy Arg2 to the register expected by Xen
mov ecx, [esp + 16]
; Call Hypercall
vmcall
pop ebx pop ebx
ret ret

View File

@ -3,23 +3,46 @@ SECTION .text
; INTN ; INTN
; EFIAPI ; EFIAPI
; __XenHypercall2 ( ; __XenVmmcall2 (
; IN VOID *HypercallAddr, ; IN INTN HypercallNum,
; IN OUT INTN Arg1, ; IN OUT INTN Arg1,
; IN OUT INTN Arg2 ; IN OUT INTN Arg2
; ); ; );
global ASM_PFX(__XenHypercall2) global ASM_PFX(__XenVmmcall2)
ASM_PFX(__XenHypercall2): ASM_PFX(__XenVmmcall2):
push rdi push rdi
push rsi push rsi
; Copy HypercallAddr to rax ; Copy HypercallNum to rax
mov rax, rcx mov rax, rcx
; Copy Arg1 to the register expected by Xen ; Copy Arg1 to the register expected by Xen
mov rdi, rdx mov rdi, rdx
; Copy Arg2 to the register expected by Xen ; Copy Arg2 to the register expected by Xen
mov rsi, r8 mov rsi, r8
; Call HypercallAddr ; Call HypercallNum
call rax vmmcall
pop rsi
pop rdi
ret
; INTN
; EFIAPI
; __XenVmcall2 (
; IN INTN HypercallNum,
; IN OUT INTN Arg1,
; IN OUT INTN Arg2
; );
global ASM_PFX(__XenVmcall2)
ASM_PFX(__XenVmcall2):
push rdi
push rsi
; Copy HypercallNum to rax
mov rax, rcx
; Copy Arg1 to the register expected by Xen
mov rdi, rdx
; Copy Arg2 to the register expected by Xen
mov rsi, r8
; Call HypercallNum
vmcall
pop rsi pop rsi
pop rdi pop rdi
ret ret

View File

@ -7,11 +7,31 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
#include <PiDxe.h> #include <PiDxe.h>
#include <Library/HobLib.h> #include <Library/BaseLib.h>
#include <Library/DebugLib.h> #include <Library/DebugLib.h>
#include <Guid/XenInfo.h> #include <Library/CpuLib.h>
STATIC VOID *HyperPage; static INTN mUseVmmCall = -1;
static BOOLEAN mHypercallAvail;
//
// Interface exposed by the ASM implementation of the core hypercall
//
INTN
EFIAPI
__XenVmmcall2 (
IN INTN HypercallNum,
IN OUT INTN Arg1,
IN OUT INTN Arg2
);
INTN
EFIAPI
__XenVmcall2 (
IN INTN HypercallNum,
IN OUT INTN Arg1,
IN OUT INTN Arg2
);
/** /**
Check if the Xen Hypercall library is able to make calls to the Xen Check if the Xen Hypercall library is able to make calls to the Xen
@ -29,23 +49,38 @@ XenHypercallIsAvailable (
VOID VOID
) )
{ {
return HyperPage != NULL; return mHypercallAvail;
} }
// STATIC
// Interface exposed by the ASM implementation of the core hypercall UINT32
// XenCpuidLeaf (
INTN VOID
EFIAPI )
__XenHypercall2 ( {
IN VOID *HypercallAddr, UINT8 Signature[13];
IN OUT INTN Arg1, UINT32 XenLeaf;
IN OUT INTN Arg2
); Signature[12] = '\0';
for (XenLeaf = 0x40000000; XenLeaf < 0x40010000; XenLeaf += 0x100) {
AsmCpuid (
XenLeaf,
NULL,
(UINT32 *)&Signature[0],
(UINT32 *)&Signature[4],
(UINT32 *)&Signature[8]
);
if (!AsciiStrCmp ((CHAR8 *)Signature, "XenVMMXenVMM")) {
return XenLeaf;
}
}
return 0;
}
/** /**
Library constructor: retrieves the Hyperpage address Library constructor: Check for Xen leaf in CPUID
from the gEfiXenInfoGuid HOB
**/ **/
RETURN_STATUS RETURN_STATUS
EFIAPI EFIAPI
@ -53,16 +88,41 @@ XenHypercallLibInit (
VOID VOID
) )
{ {
EFI_HOB_GUID_TYPE *GuidHob; UINT32 XenLeaf;
EFI_XEN_INFO *XenInfo; CHAR8 sig[13];
GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid); XenLeaf = XenCpuidLeaf ();
if (GuidHob == NULL) { if (XenLeaf == 0) {
return RETURN_NOT_FOUND; return RETURN_NOT_FOUND;
} }
XenInfo = (EFI_XEN_INFO *)GET_GUID_HOB_DATA (GuidHob); sig[12] = '\0';
HyperPage = XenInfo->HyperPages; AsmCpuid (
0,
NULL,
(UINT32 *)&sig[0],
(UINT32 *)&sig[8],
(UINT32 *)&sig[4]
);
DEBUG ((DEBUG_INFO, "Detected CPU \"%12a\"\n", sig));
if ((AsciiStrCmp ("AuthenticAMD", sig) == 0) ||
(AsciiStrCmp ("HygonGenuine", sig) == 0))
{
mUseVmmCall = TRUE;
} else if ((AsciiStrCmp ("GenuineIntel", sig) == 0) ||
(AsciiStrCmp ("CentaurHauls", sig) == 0) ||
(AsciiStrCmp (" Shanghai ", sig) == 0))
{
mUseVmmCall = FALSE;
} else {
DEBUG ((DEBUG_ERROR, "Unsupported CPU vendor\n"));
return RETURN_NOT_FOUND;
}
mHypercallAvail = TRUE;
return RETURN_SUCCESS; return RETURN_SUCCESS;
} }
@ -84,7 +144,9 @@ XenHypercall2 (
IN OUT INTN Arg2 IN OUT INTN Arg2
) )
{ {
ASSERT (HyperPage != NULL); if (mUseVmmCall) {
return __XenVmmcall2 (HypercallID, Arg1, Arg2);
return __XenHypercall2 ((UINT8 *)HyperPage + HypercallID * 32, Arg1, Arg2); } else {
return __XenVmcall2 (HypercallID, Arg1, Arg2);
}
} }

View File

@ -13,11 +13,6 @@
MODULE_TYPE = BASE MODULE_TYPE = BASE
VERSION_STRING = 1.0 VERSION_STRING = 1.0
CONSTRUCTOR = XenHypercallLibConstruct CONSTRUCTOR = XenHypercallLibConstruct
[Defines.IA32, Defines.X64]
LIBRARY_CLASS = XenHypercallLib|PEIM DXE_DRIVER UEFI_DRIVER
[Defines.ARM, Defines.AARCH64]
LIBRARY_CLASS = XenHypercallLib LIBRARY_CLASS = XenHypercallLib
# #
@ -52,6 +47,7 @@
OvmfPkg/OvmfPkg.dec OvmfPkg/OvmfPkg.dec
[LibraryClasses.IA32, LibraryClasses.X64] [LibraryClasses.IA32, LibraryClasses.X64]
CpuLib
BaseLib BaseLib
HobLib HobLib
DebugLib DebugLib