OvmfPkg/XenBusDxe: Add support to make Xen Hypercalls.
Change in V4: - Replace the license by the commonly used file header text. - add file header to XenHypercall.h (license, copyright, brief desc) Change in V3: - adding IA32 support. (not reviewed yet) both XenBusDxe/Ia32/hypercall.{S,asm} file are new Change in V2: - file header, copyright - Add License - Add push/pop instruction. - fix types - Comment of exported functions - Improve coding style - Add error handling in the main init function (of the drivers) - Comment assembly Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16260 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
a154f42014
commit
abcbbb14a4
|
@ -0,0 +1,22 @@
|
||||||
|
# INTN
|
||||||
|
# EFIAPI
|
||||||
|
# XenHypercall2 (
|
||||||
|
# IN VOID *HypercallAddr,
|
||||||
|
# IN OUT INTN Arg1,
|
||||||
|
# IN OUT INTN Arg2
|
||||||
|
# );
|
||||||
|
ASM_GLOBAL ASM_PFX(XenHypercall2)
|
||||||
|
ASM_PFX(XenHypercall2):
|
||||||
|
# Save only ebx, ecx is supposed to be a scratch register and needs to be
|
||||||
|
# saved by the caller
|
||||||
|
push %ebx
|
||||||
|
# Copy HypercallAddr to eax
|
||||||
|
mov 8(%esp), %eax
|
||||||
|
# Copy Arg1 to the register expected by Xen
|
||||||
|
mov 12(%esp), %ebx
|
||||||
|
# Copy Arg2 to the register expected by Xen
|
||||||
|
mov 16(%esp), %ecx
|
||||||
|
# Call HypercallAddr
|
||||||
|
call *%eax
|
||||||
|
pop %ebx
|
||||||
|
ret
|
|
@ -0,0 +1,26 @@
|
||||||
|
.code
|
||||||
|
|
||||||
|
; INTN
|
||||||
|
; EFIAPI
|
||||||
|
; XenHypercall2 (
|
||||||
|
; IN VOID *HypercallAddr,
|
||||||
|
; IN OUT INTN Arg1,
|
||||||
|
; IN OUT INTN Arg2
|
||||||
|
; );
|
||||||
|
XenHypercall2 PROC
|
||||||
|
; Save only ebx, ecx is supposed to be a scratch register and needs to be
|
||||||
|
; saved by the caller
|
||||||
|
push ebx
|
||||||
|
; Copy HypercallAddr 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 HypercallAddr
|
||||||
|
call eax
|
||||||
|
pop ebx
|
||||||
|
ret
|
||||||
|
XenHypercall2 ENDP
|
||||||
|
|
||||||
|
END
|
|
@ -0,0 +1,22 @@
|
||||||
|
# INTN
|
||||||
|
# EFIAPI
|
||||||
|
# XenHypercall2 (
|
||||||
|
# IN VOID *HypercallAddr,
|
||||||
|
# IN OUT INTN Arg1,
|
||||||
|
# IN OUT INTN Arg2
|
||||||
|
# );
|
||||||
|
ASM_GLOBAL ASM_PFX(XenHypercall2)
|
||||||
|
ASM_PFX(XenHypercall2):
|
||||||
|
push %rdi
|
||||||
|
push %rsi
|
||||||
|
# Copy HypercallAddr to rax
|
||||||
|
movq %rcx, %rax
|
||||||
|
# Copy Arg1 to the register expected by Xen
|
||||||
|
movq %rdx, %rdi
|
||||||
|
# Copy Arg2 to the register expected by Xen
|
||||||
|
movq %r8, %rsi
|
||||||
|
# Call HypercallAddr
|
||||||
|
call *%rax
|
||||||
|
pop %rsi
|
||||||
|
pop %rdi
|
||||||
|
ret
|
|
@ -0,0 +1,26 @@
|
||||||
|
.code
|
||||||
|
|
||||||
|
; INTN
|
||||||
|
; EFIAPI
|
||||||
|
; XenHypercall2 (
|
||||||
|
; IN VOID *HypercallAddr,
|
||||||
|
; IN OUT INTN Arg1,
|
||||||
|
; IN OUT INTN Arg2
|
||||||
|
; );
|
||||||
|
XenHypercall2 PROC
|
||||||
|
push rdi
|
||||||
|
push rsi
|
||||||
|
; Copy HypercallAddr 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 HypercallAddr
|
||||||
|
call rax
|
||||||
|
pop rsi
|
||||||
|
pop rdi
|
||||||
|
ret
|
||||||
|
XenHypercall2 ENDP
|
||||||
|
|
||||||
|
END
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
#include "XenBusDxe.h"
|
#include "XenBusDxe.h"
|
||||||
|
|
||||||
|
#include "XenHypercall.h"
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Driver Binding Protocol instance
|
/// Driver Binding Protocol instance
|
||||||
|
@ -264,6 +266,8 @@ NotifyExitBoot (
|
||||||
@retval EFI_SUCCESS The device was started.
|
@retval EFI_SUCCESS The device was started.
|
||||||
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
|
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
|
||||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||||
|
@retval EFI_UNSUPPORTED Something is missing on the system that
|
||||||
|
prevent to start the edvice.
|
||||||
@retval Others The driver failded to start the device.
|
@retval Others The driver failded to start the device.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -295,6 +299,20 @@ XenBusDxeDriverBindingStart (
|
||||||
mMyDevice = Dev;
|
mMyDevice = Dev;
|
||||||
EfiReleaseLock (&mMyDeviceLock);
|
EfiReleaseLock (&mMyDeviceLock);
|
||||||
|
|
||||||
|
Status = XenHyperpageInit (Dev);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "XenBus: Unable to retrieve the hyperpage.\n"));
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
goto ErrorAllocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = XenGetSharedInfoPage (Dev);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "XenBus: Unable to get the shared info page.\n"));
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
goto ErrorAllocated;
|
||||||
|
}
|
||||||
|
|
||||||
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
|
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
|
||||||
NotifyExitBoot,
|
NotifyExitBoot,
|
||||||
(VOID*) Dev,
|
(VOID*) Dev,
|
||||||
|
|
|
@ -70,6 +70,8 @@ extern EFI_COMPONENT_NAME_PROTOCOL gXenBusDxeComponentName;
|
||||||
//
|
//
|
||||||
// Other stuff
|
// Other stuff
|
||||||
//
|
//
|
||||||
|
#include <IndustryStandard/Xen/xen.h>
|
||||||
|
|
||||||
#define PCI_VENDOR_ID_XEN 0x5853
|
#define PCI_VENDOR_ID_XEN 0x5853
|
||||||
#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001
|
#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001
|
||||||
|
|
||||||
|
@ -83,6 +85,9 @@ struct _XENBUS_DEVICE {
|
||||||
EFI_DRIVER_BINDING_PROTOCOL *This;
|
EFI_DRIVER_BINDING_PROTOCOL *This;
|
||||||
EFI_HANDLE ControllerHandle;
|
EFI_HANDLE ControllerHandle;
|
||||||
EFI_EVENT ExitBootEvent;
|
EFI_EVENT ExitBootEvent;
|
||||||
|
|
||||||
|
VOID *Hyperpage;
|
||||||
|
shared_info_t *SharedInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,6 +34,16 @@
|
||||||
DriverBinding.h
|
DriverBinding.h
|
||||||
ComponentName.c
|
ComponentName.c
|
||||||
ComponentName.h
|
ComponentName.h
|
||||||
|
XenHypercall.c
|
||||||
|
XenHypercall.h
|
||||||
|
|
||||||
|
[Sources.IA32]
|
||||||
|
Ia32/hypercall.S
|
||||||
|
Ia32/hypercall.asm
|
||||||
|
|
||||||
|
[Sources.X64]
|
||||||
|
X64/hypercall.S
|
||||||
|
X64/hypercall.asm
|
||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
UefiDriverEntryPoint
|
UefiDriverEntryPoint
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/** @file
|
||||||
|
Functions to make Xen hypercalls.
|
||||||
|
|
||||||
|
Copyright (C) 2014, Citrix Ltd.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
#include <Library/HobLib.h>
|
||||||
|
#include <Guid/XenInfo.h>
|
||||||
|
|
||||||
|
#include "XenBusDxe.h"
|
||||||
|
#include "XenHypercall.h"
|
||||||
|
|
||||||
|
#include <IndustryStandard/Xen/hvm/params.h>
|
||||||
|
#include <IndustryStandard/Xen/memory.h>
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
XenHyperpageInit (
|
||||||
|
IN OUT XENBUS_DEVICE *Dev
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_HOB_GUID_TYPE *GuidHob;
|
||||||
|
EFI_XEN_INFO *XenInfo;
|
||||||
|
|
||||||
|
GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);
|
||||||
|
if (GuidHob == NULL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
XenInfo = (EFI_XEN_INFO *) GET_GUID_HOB_DATA (GuidHob);
|
||||||
|
Dev->Hyperpage = XenInfo->HyperPages;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT64
|
||||||
|
XenHypercallHvmGetParam (
|
||||||
|
IN XENBUS_DEVICE *Dev,
|
||||||
|
IN INTN Index
|
||||||
|
)
|
||||||
|
{
|
||||||
|
xen_hvm_param_t Parameter;
|
||||||
|
INTN Error;
|
||||||
|
|
||||||
|
ASSERT (Dev->Hyperpage != NULL);
|
||||||
|
|
||||||
|
Parameter.domid = DOMID_SELF;
|
||||||
|
Parameter.index = Index;
|
||||||
|
Error = XenHypercall2 (Dev->Hyperpage + __HYPERVISOR_hvm_op * 32,
|
||||||
|
HVMOP_get_param, (INTN) &Parameter);
|
||||||
|
if (Error != 0) {
|
||||||
|
DEBUG ((EFI_D_ERROR,
|
||||||
|
"XenHypercall: Error %d trying to get HVM parameter %d\n",
|
||||||
|
Error, Index));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return Parameter.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTN
|
||||||
|
XenHypercallMemoryOp (
|
||||||
|
IN XENBUS_DEVICE *Dev,
|
||||||
|
IN UINTN Operation,
|
||||||
|
IN OUT VOID *Arguments
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT (Dev->Hyperpage != NULL);
|
||||||
|
return XenHypercall2 (Dev->Hyperpage + __HYPERVISOR_memory_op * 32,
|
||||||
|
Operation, (INTN) Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
INTN
|
||||||
|
XenHypercallEventChannelOp (
|
||||||
|
IN XENBUS_DEVICE *Dev,
|
||||||
|
IN INTN Operation,
|
||||||
|
IN OUT VOID *Arguments
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT (Dev->Hyperpage != NULL);
|
||||||
|
return XenHypercall2 (Dev->Hyperpage + __HYPERVISOR_event_channel_op * 32,
|
||||||
|
Operation, (INTN) Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
XenGetSharedInfoPage (
|
||||||
|
IN OUT XENBUS_DEVICE *Dev
|
||||||
|
)
|
||||||
|
{
|
||||||
|
xen_add_to_physmap_t Parameter;
|
||||||
|
|
||||||
|
ASSERT (Dev->SharedInfo == NULL);
|
||||||
|
|
||||||
|
Parameter.domid = DOMID_SELF;
|
||||||
|
Parameter.space = XENMAPSPACE_shared_info;
|
||||||
|
Parameter.idx = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// using reserved page because the page is not released when Linux is
|
||||||
|
// starting because of the add_to_physmap. QEMU might try to access the
|
||||||
|
// page, and fail because it have no right to do so (segv).
|
||||||
|
//
|
||||||
|
Dev->SharedInfo = AllocateReservedPages (1);
|
||||||
|
Parameter.gpfn = (UINTN) Dev->SharedInfo >> EFI_PAGE_SHIFT;
|
||||||
|
if (XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameter) != 0) {
|
||||||
|
FreePages (Dev->SharedInfo, 1);
|
||||||
|
Dev->SharedInfo = NULL;
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/** @file
|
||||||
|
Functions declarations to make Xen hypercalls.
|
||||||
|
|
||||||
|
Copyright (C) 2014, Citrix Ltd.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __XENBUS_DXE_HYPERCALL_H__
|
||||||
|
#define __XENBUS_DXE_HYPERCALL_H__
|
||||||
|
|
||||||
|
typedef struct _XENBUS_DEVICE XENBUS_DEVICE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will put the two arguments in the right place (registers) and
|
||||||
|
call HypercallAddr, which correspond to an entry in the hypercall pages.
|
||||||
|
|
||||||
|
@param HypercallAddr A memory address where the hypercall to call is.
|
||||||
|
@param Arg1 First argument.
|
||||||
|
@param Arg2 Second argument.
|
||||||
|
|
||||||
|
@return Return 0 if success otherwise it return an errno.
|
||||||
|
**/
|
||||||
|
INTN
|
||||||
|
EFIAPI
|
||||||
|
XenHypercall2 (
|
||||||
|
IN VOID *HypercallAddr,
|
||||||
|
IN OUT INTN Arg1,
|
||||||
|
IN OUT INTN Arg2
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the page where all hypercall are from the XenInfo hob.
|
||||||
|
|
||||||
|
@param Dev A XENBUS_DEVICE instance.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND hyperpage could not be found.
|
||||||
|
@retval EFI_SUCCESS Successfully retrieve the hyperpage pointer.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
XenHyperpageInit (
|
||||||
|
XENBUS_DEVICE *Dev
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the value of the HVM parameter Index.
|
||||||
|
|
||||||
|
@param Dev A XENBUS_DEVICE instance.
|
||||||
|
@param Index The parameter to get, e.g. HVM_PARAM_STORE_EVTCHN.
|
||||||
|
|
||||||
|
@return The value of the asked parameter or 0 in case of error.
|
||||||
|
**/
|
||||||
|
UINT64
|
||||||
|
XenHypercallHvmGetParam (
|
||||||
|
XENBUS_DEVICE *Dev,
|
||||||
|
INTN Index
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Hypercall to do different operation on the memory.
|
||||||
|
|
||||||
|
@param Dev A XENBUS_DEVICE instance.
|
||||||
|
@param Operation The operation number, e.g. XENMEM_add_to_physmap.
|
||||||
|
@param Arguments The arguments associated to the operation.
|
||||||
|
|
||||||
|
@return Return the return value from the hypercall, 0 in case of success
|
||||||
|
otherwise, an error code.
|
||||||
|
**/
|
||||||
|
INTN
|
||||||
|
XenHypercallMemoryOp (
|
||||||
|
IN XENBUS_DEVICE *Dev,
|
||||||
|
IN UINTN Operation,
|
||||||
|
IN OUT VOID *Arguments
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Do an operation on the event channels.
|
||||||
|
|
||||||
|
@param Dev A XENBUS_DEVICE instance.
|
||||||
|
@param Operation The operation number, e.g. EVTCHNOP_send.
|
||||||
|
@param Arguments The argument associated to the operation.
|
||||||
|
|
||||||
|
@return Return the return value from the hypercall, 0 in case of success
|
||||||
|
otherwise, an error code.
|
||||||
|
**/
|
||||||
|
INTN
|
||||||
|
XenHypercallEventChannelOp (
|
||||||
|
IN XENBUS_DEVICE *Dev,
|
||||||
|
IN INTN Operation,
|
||||||
|
IN OUT VOID *Arguments
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Map the shared_info_t page into memory.
|
||||||
|
|
||||||
|
@param Dev A XENBUS_DEVICE instance.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Dev->SharedInfo whill contain a pointer to
|
||||||
|
the shared info page
|
||||||
|
@retval EFI_LOAD_ERROR The shared info page could not be mapped. The
|
||||||
|
hypercall returned an error.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
XenGetSharedInfoPage (
|
||||||
|
IN OUT XENBUS_DEVICE *Dev
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue