mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-27 15:44:04 +02:00
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:
parent
9d5a9940e4
commit
0e6f6c715c
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user