mirror of https://github.com/acidanthera/audk.git
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 "XenHypercall.h"
|
||||
|
||||
|
||||
///
|
||||
/// Driver Binding Protocol instance
|
||||
|
@ -264,6 +266,8 @@ NotifyExitBoot (
|
|||
@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_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.
|
||||
|
||||
**/
|
||||
|
@ -295,6 +299,20 @@ XenBusDxeDriverBindingStart (
|
|||
mMyDevice = Dev;
|
||||
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,
|
||||
NotifyExitBoot,
|
||||
(VOID*) Dev,
|
||||
|
|
|
@ -70,6 +70,8 @@ extern EFI_COMPONENT_NAME_PROTOCOL gXenBusDxeComponentName;
|
|||
//
|
||||
// Other stuff
|
||||
//
|
||||
#include <IndustryStandard/Xen/xen.h>
|
||||
|
||||
#define PCI_VENDOR_ID_XEN 0x5853
|
||||
#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001
|
||||
|
||||
|
@ -83,6 +85,9 @@ struct _XENBUS_DEVICE {
|
|||
EFI_DRIVER_BINDING_PROTOCOL *This;
|
||||
EFI_HANDLE ControllerHandle;
|
||||
EFI_EVENT ExitBootEvent;
|
||||
|
||||
VOID *Hyperpage;
|
||||
shared_info_t *SharedInfo;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,16 @@
|
|||
DriverBinding.h
|
||||
ComponentName.c
|
||||
ComponentName.h
|
||||
XenHypercall.c
|
||||
XenHypercall.h
|
||||
|
||||
[Sources.IA32]
|
||||
Ia32/hypercall.S
|
||||
Ia32/hypercall.asm
|
||||
|
||||
[Sources.X64]
|
||||
X64/hypercall.S
|
||||
X64/hypercall.asm
|
||||
|
||||
[LibraryClasses]
|
||||
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