[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 04/18] OvmfPkg/XenBusDxe: Add support to make Xen Hypercalls.
On Thu, Sep 04, 2014 at 05:50:59PM +0100, Anthony PERARD wrote: > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx> One comment below, otherwise Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> > > --- > 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 > --- > OvmfPkg/XenBusDxe/X64/hypercall.S | 23 +++++++ > OvmfPkg/XenBusDxe/X64/hypercall.asm | 27 ++++++++ > OvmfPkg/XenBusDxe/XenBusDxe.c | 22 ++++++ > OvmfPkg/XenBusDxe/XenBusDxe.h | 5 ++ > OvmfPkg/XenBusDxe/XenBusDxe.inf | 6 ++ > OvmfPkg/XenBusDxe/XenHypercall.c | 134 > ++++++++++++++++++++++++++++++++++++ > OvmfPkg/XenBusDxe/XenHypercall.h | 100 +++++++++++++++++++++++++++ > 7 files changed, 317 insertions(+) > create mode 100644 OvmfPkg/XenBusDxe/X64/hypercall.S > create mode 100644 OvmfPkg/XenBusDxe/X64/hypercall.asm > create mode 100644 OvmfPkg/XenBusDxe/XenHypercall.c > create mode 100644 OvmfPkg/XenBusDxe/XenHypercall.h > > diff --git a/OvmfPkg/XenBusDxe/X64/hypercall.S > b/OvmfPkg/XenBusDxe/X64/hypercall.S > new file mode 100644 > index 0000000..3b18e48 > --- /dev/null > +++ b/OvmfPkg/XenBusDxe/X64/hypercall.S > @@ -0,0 +1,23 @@ > +# Hypercall with 2 arguments > +# 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 > diff --git a/OvmfPkg/XenBusDxe/X64/hypercall.asm > b/OvmfPkg/XenBusDxe/X64/hypercall.asm > new file mode 100644 > index 0000000..a39f240 > --- /dev/null > +++ b/OvmfPkg/XenBusDxe/X64/hypercall.asm > @@ -0,0 +1,27 @@ > +.code > + > +; Hypercall with 2 arguments > +; 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 > diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c > index e125ed7..db88cb4 100644 > --- a/OvmfPkg/XenBusDxe/XenBusDxe.c > +++ b/OvmfPkg/XenBusDxe/XenBusDxe.c > @@ -45,6 +45,8 @@ > > #include "XenBusDxe.h" > > +#include "XenHypercall.h" > + > > /// > /// Driver Binding Protocol instance > @@ -279,6 +281,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. > > **/ > @@ -298,6 +302,20 @@ XenBusDxeDriverBindingStart ( > Dev->This = This; > Dev->ControllerHandle = ControllerHandle; > > + Status = XenHyperpageInit (Dev); > + if (EFI_ERROR (Status)) { > + DEBUG ((EFI_D_ERROR, "XenBus: Unable to retrieve the hyperpage.")); > + Status = EFI_UNSUPPORTED; > + goto ErrorNoHyperpage; > + } > + > + Status = XenGetSharedInfoPage (Dev); > + if (EFI_ERROR (Status)) { > + DEBUG ((EFI_D_ERROR, "XenBus: Unable to get the shared info page.")); > + Status = EFI_UNSUPPORTED; > + goto ErrorNoHyperpage; > + } > + > Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, > NotifyExitBoot, > (VOID*) Dev, > @@ -306,6 +324,10 @@ XenBusDxeDriverBindingStart ( > > mMyDevice = Dev; > return EFI_SUCCESS; > + > +ErrorNoHyperpage: > + FreePool (Dev); > + return Status; > } > > /** > diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h > index 9e4860a..af0510a 100644 > --- a/OvmfPkg/XenBusDxe/XenBusDxe.h > +++ b/OvmfPkg/XenBusDxe/XenBusDxe.h > @@ -86,6 +86,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 > > @@ -99,6 +101,9 @@ struct _XENBUS_DEVICE { > EFI_DRIVER_BINDING_PROTOCOL *This; > EFI_HANDLE ControllerHandle; > EFI_EVENT ExitBootEvent; > + > + VOID *Hyperpage; > + shared_info_t *SharedInfo; > }; > > #endif > diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf > index b4d7551..edc3e51 100644 > --- a/OvmfPkg/XenBusDxe/XenBusDxe.inf > +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf > @@ -31,6 +31,12 @@ > DriverBinding.h > ComponentName.c > ComponentName.h > + XenHypercall.c > + XenHypercall.h > + > +[Sources.X64] > + X64/hypercall.S > + X64/hypercall.asm > > [LibraryClasses] > UefiDriverEntryPoint > diff --git a/OvmfPkg/XenBusDxe/XenHypercall.c > b/OvmfPkg/XenBusDxe/XenHypercall.c > new file mode 100644 > index 0000000..2e1f361 > --- /dev/null > +++ b/OvmfPkg/XenBusDxe/XenHypercall.c > @@ -0,0 +1,134 @@ > +/** @file > + Functions to make Xen hypercalls. > + > + Copyright (C) 2014, Citrix Ltd. > + > + Redistribution and use in source and binary forms, with or without > + modification, are permitted provided that the following conditions > + are met: > + > + * Redistributions of source code must retain the above copyright > + notice, this list of conditions and the following disclaimer. > + * Redistributions in binary form must reproduce the above copyright > + notice, this list of conditions and the following disclaimer in > + the documentation and/or other materials provided with the > + distribution. > + > + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS > + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; > + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER > + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN > + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE > + POSSIBILITY OF SUCH DAMAGE. > + > +**/ > + > +#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 s/linux/Linux > + // 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; > +} > diff --git a/OvmfPkg/XenBusDxe/XenHypercall.h > b/OvmfPkg/XenBusDxe/XenHypercall.h > new file mode 100644 > index 0000000..29eaf9f > --- /dev/null > +++ b/OvmfPkg/XenBusDxe/XenHypercall.h > @@ -0,0 +1,100 @@ > +#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 > -- > Anthony PERARD > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxx > http://lists.xen.org/xen-devel _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |