[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.