]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/XenBusDxe/XenHypercall.c
OvmfPkg/XenBusDxe: Add support to make Xen Hypercalls.
[mirror_edk2.git] / OvmfPkg / XenBusDxe / XenHypercall.c
diff --git a/OvmfPkg/XenBusDxe/XenHypercall.c b/OvmfPkg/XenBusDxe/XenHypercall.c
new file mode 100644 (file)
index 0000000..0f2ba5d
--- /dev/null
@@ -0,0 +1,118 @@
+/** @file\r
+  Functions to make Xen hypercalls.\r
+\r
+  Copyright (C) 2014, Citrix Ltd.\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/HobLib.h>\r
+#include <Guid/XenInfo.h>\r
+\r
+#include "XenBusDxe.h"\r
+#include "XenHypercall.h"\r
+\r
+#include <IndustryStandard/Xen/hvm/params.h>\r
+#include <IndustryStandard/Xen/memory.h>\r
+\r
+EFI_STATUS\r
+XenHyperpageInit (\r
+  IN OUT XENBUS_DEVICE *Dev\r
+  )\r
+{\r
+  EFI_HOB_GUID_TYPE   *GuidHob;\r
+  EFI_XEN_INFO        *XenInfo;\r
+\r
+  GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);\r
+  if (GuidHob == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  XenInfo = (EFI_XEN_INFO *) GET_GUID_HOB_DATA (GuidHob);\r
+  Dev->Hyperpage = XenInfo->HyperPages;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+UINT64\r
+XenHypercallHvmGetParam (\r
+  IN XENBUS_DEVICE *Dev,\r
+  IN INTN          Index\r
+  )\r
+{\r
+  xen_hvm_param_t     Parameter;\r
+  INTN                Error;\r
+\r
+  ASSERT (Dev->Hyperpage != NULL);\r
+\r
+  Parameter.domid = DOMID_SELF;\r
+  Parameter.index = Index;\r
+  Error = XenHypercall2 (Dev->Hyperpage + __HYPERVISOR_hvm_op * 32,\r
+                         HVMOP_get_param, (INTN) &Parameter);\r
+  if (Error != 0) {\r
+    DEBUG ((EFI_D_ERROR,\r
+            "XenHypercall: Error %d trying to get HVM parameter %d\n",\r
+            Error, Index));\r
+    return 0;\r
+  }\r
+  return Parameter.value;\r
+}\r
+\r
+INTN\r
+XenHypercallMemoryOp (\r
+  IN     XENBUS_DEVICE *Dev,\r
+  IN     UINTN Operation,\r
+  IN OUT VOID *Arguments\r
+  )\r
+{\r
+  ASSERT (Dev->Hyperpage != NULL);\r
+  return XenHypercall2 (Dev->Hyperpage + __HYPERVISOR_memory_op * 32,\r
+                        Operation, (INTN) Arguments);\r
+}\r
+\r
+INTN\r
+XenHypercallEventChannelOp (\r
+  IN     XENBUS_DEVICE *Dev,\r
+  IN     INTN Operation,\r
+  IN OUT VOID *Arguments\r
+  )\r
+{\r
+  ASSERT (Dev->Hyperpage != NULL);\r
+  return XenHypercall2 (Dev->Hyperpage + __HYPERVISOR_event_channel_op * 32,\r
+                        Operation, (INTN) Arguments);\r
+}\r
+\r
+EFI_STATUS\r
+XenGetSharedInfoPage (\r
+  IN OUT XENBUS_DEVICE *Dev\r
+  )\r
+{\r
+  xen_add_to_physmap_t Parameter;\r
+\r
+  ASSERT (Dev->SharedInfo == NULL);\r
+\r
+  Parameter.domid = DOMID_SELF;\r
+  Parameter.space = XENMAPSPACE_shared_info;\r
+  Parameter.idx = 0;\r
+\r
+  //\r
+  // using reserved page because the page is not released when Linux is\r
+  // starting because of the add_to_physmap. QEMU might try to access the\r
+  // page, and fail because it have no right to do so (segv).\r
+  //\r
+  Dev->SharedInfo = AllocateReservedPages (1);\r
+  Parameter.gpfn = (UINTN) Dev->SharedInfo >> EFI_PAGE_SHIFT;\r
+  if (XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameter) != 0) {\r
+    FreePages (Dev->SharedInfo, 1);\r
+    Dev->SharedInfo = NULL;\r
+    return EFI_LOAD_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r