[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH RFC 04/18] OvmfPkg/XenbusDxe: Add support to make Xen Hypercalls.



Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
---
 OvmfPkg/XenbusDxe/X64/hypercall.S   |  16 ++++++
 OvmfPkg/XenbusDxe/X64/hypercall.asm |  19 +++++++
 OvmfPkg/XenbusDxe/XenHypercall.c    | 101 ++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenbusDxe/XenHypercall.h    |  44 ++++++++++++++++
 OvmfPkg/XenbusDxe/XenbusDxe.c       |   8 +++
 OvmfPkg/XenbusDxe/XenbusDxe.h       |   5 ++
 OvmfPkg/XenbusDxe/XenbusDxe.inf     |   6 +++
 7 files changed, 199 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..80982e3
--- /dev/null
+++ b/OvmfPkg/XenbusDxe/X64/hypercall.S
@@ -0,0 +1,16 @@
+# Hypercall with 2 arguments
+# INTN
+# EFIAPI
+# XenHypercall2 (
+#   IN     VOID *hypercall_addr,
+#   IN OUT INTN arg1,
+#   IN OUT INTN arg2
+#   );
+# XXX push and pop ?
+ASM_GLOBAL ASM_PFX(XenHypercall2)
+ASM_PFX(XenHypercall2):
+  movq %rcx, %rax
+  movq %rdx, %rdi
+  movq %r8, %rsi
+  call *%rax
+  ret
diff --git a/OvmfPkg/XenbusDxe/X64/hypercall.asm 
b/OvmfPkg/XenbusDxe/X64/hypercall.asm
new file mode 100644
index 0000000..8bc41a2
--- /dev/null
+++ b/OvmfPkg/XenbusDxe/X64/hypercall.asm
@@ -0,0 +1,19 @@
+.code
+
+; Hypercall with 2 arguments
+; INTN
+; EFIAPI
+; XenHypercall2 (
+;   IN     VOID *hypercall_addr,
+;   IN OUT INTN arg1,
+;   IN OUT INTN arg2
+;   );
+XenHypercall2 PROC
+  mov rax, rcx
+  mov rdi, rdx
+  mov rsi, r8
+  call rax
+  ret
+XenHypercall2 ENDP
+
+END
diff --git a/OvmfPkg/XenbusDxe/XenHypercall.c b/OvmfPkg/XenbusDxe/XenHypercall.c
new file mode 100644
index 0000000..5e98dd5
--- /dev/null
+++ b/OvmfPkg/XenbusDxe/XenHypercall.c
@@ -0,0 +1,101 @@
+#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 (
+  XENBUS_DEVICE *Dev
+  )
+{
+  EFI_HOB_GUID_TYPE   *GuidHob;
+  EFI_XEN_INFO        *XenInfo;
+
+  GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);
+  if (GuidHob == NULL) {
+    DEBUG ((EFI_D_INFO, "XenbusInit: No xeninfo ?\n"));
+    return EFI_NOT_FOUND;
+  }
+  XenInfo = (EFI_XEN_INFO*)GET_GUID_HOB_DATA (GuidHob);
+  Dev->Hyperpage = XenInfo->HyperPages;
+  return EFI_SUCCESS;
+}
+
+UINTN
+XenHypercallHvmGetParam (
+  XENBUS_DEVICE *Dev,
+  INTN Index
+  )
+{
+  xen_hvm_param_t     xhv;
+  INTN                error;
+
+  ASSERT (Dev->Hyperpage != NULL);
+
+  xhv.domid = DOMID_SELF;
+  xhv.index = Index;
+  error = XenHypercall2(Dev->Hyperpage + __HYPERVISOR_hvm_op * 32,
+                        HVMOP_get_param, (INTN)&xhv);
+  if (error) {
+    DEBUG ((EFI_D_ERROR, "%a: error %d trying to get %d\n", __func__,
+            error, Index));
+    return (0);
+  }
+  return (xhv.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
+  )
+{
+  struct xen_add_to_physmap xatp;
+
+  ASSERT (Dev->SharedInfo == NULL);
+
+  xatp.domid = DOMID_SELF;
+  xatp.space = XENMAPSPACE_shared_info;
+  xatp.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);
+  xatp.gpfn = (UINTN)Dev->SharedInfo >> EFI_PAGE_SHIFT;
+  if (XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &xatp) != 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..1afaf73
--- /dev/null
+++ b/OvmfPkg/XenbusDxe/XenHypercall.h
@@ -0,0 +1,44 @@
+#ifndef __XENBUS_DXE_HYPERCALL_H__
+#define __XENBUS_DXE_HYPERCALL_H__
+
+typedef struct _XENBUS_DEVICE XENBUS_DEVICE;
+
+INTN
+EFIAPI
+XenHypercall2 (
+  IN     VOID *hypercall_addr,
+  IN OUT INTN arg1,
+  IN OUT INTN arg2
+  );
+
+EFI_STATUS
+XenHyperpageInit (
+  XENBUS_DEVICE *Dev
+  );
+
+UINTN
+XenHypercallHvmGetParam (
+  XENBUS_DEVICE *Dev,
+  INTN Index
+  );
+
+INTN
+XenHypercallMemoryOp (
+  IN     XENBUS_DEVICE *Dev,
+  IN     UINTN Operation,
+  IN OUT VOID *Arguments
+  );
+
+INTN
+XenHypercallEventChannelOp (
+  IN     XENBUS_DEVICE *Dev,
+  IN     INTN Operation,
+  IN OUT VOID *Arguments
+  );
+
+EFI_STATUS
+XenGetSharedInfoPage (
+  IN OUT XENBUS_DEVICE *Dev
+  );
+
+#endif
diff --git a/OvmfPkg/XenbusDxe/XenbusDxe.c b/OvmfPkg/XenbusDxe/XenbusDxe.c
index 2c3d9b8..63ea31b 100644
--- a/OvmfPkg/XenbusDxe/XenbusDxe.c
+++ b/OvmfPkg/XenbusDxe/XenbusDxe.c
@@ -16,6 +16,8 @@
 
 #include "XenbusDxe.h"
 
+#include "XenHypercall.h"
+
 ///
 /// Driver Binding Protocol instance
 ///
@@ -294,6 +296,12 @@ XenbusDxeDriverBindingStart (
   Dev->This = This;
   Dev->ControllerHandle = ControllerHandle;
 
+  Status = XenHyperpageInit (Dev);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = XenGetSharedInfoPage (Dev);
+  ASSERT_EFI_ERROR (Status);
+
   Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
                              NotifyExitBoot,
                              (VOID*) Dev,
diff --git a/OvmfPkg/XenbusDxe/XenbusDxe.h b/OvmfPkg/XenbusDxe/XenbusDxe.h
index c1ca87a..6140f94 100644
--- a/OvmfPkg/XenbusDxe/XenbusDxe.h
+++ b/OvmfPkg/XenbusDxe/XenbusDxe.h
@@ -71,6 +71,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
diff --git a/OvmfPkg/XenbusDxe/XenbusDxe.inf b/OvmfPkg/XenbusDxe/XenbusDxe.inf
index d6685b3..8b69f93 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
-- 
Anthony PERARD


_______________________________________________
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®.