diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
index 868488906643..c690f1481093 100644
--- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
@@ -30,6 +30,12 @@
 [Includes.common]
   Include                        # Root include for the package
 
+[LibraryClasses]
+  #
+  # library to create handles containing the XENIO_PROTOCOL I/O protocol
+  #
+  XenIoMmioLib|Include/Library/XenIoMmioLib.h
+
 [Guids.common]
   gArmVirtualizationTokenSpaceGuid = { 0x0B6F5CA7, 0x4F53, 0x445A, { 0xB7, 0x6E, 0x2E, 0x36, 0x5B, 0x80, 0x63, 0x66 } }
   gEarlyPL011BaseAddressGuid       = { 0xB199DEA9, 0xFD5C, 0x4A84, { 0x80, 0x82, 0x2F, 0x41, 0x70, 0x78, 0x03, 0x05 } }
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Include/Library/XenIoMmioLib.h b/ArmPlatformPkg/ArmVirtualizationPkg/Include/Library/XenIoMmioLib.h
new file mode 100644
index 000000000000..faeabe5affe0
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Include/Library/XenIoMmioLib.h
@@ -0,0 +1,20 @@
+/** @file
+*  Library to install the XENIO_PROTOCOL on a handle
+*
+*  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
+*
+*  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.
+*
+**/
+
+EFI_STATUS
+XenIoMmioInstall (
+  IN  EFI_HANDLE  *Handle,
+  IN  UINT64      GrantTableAddress
+  );
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenIoMmioLib/XenIoMmioLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenIoMmioLib/XenIoMmioLib.c
new file mode 100644
index 000000000000..2d8413638680
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenIoMmioLib/XenIoMmioLib.c
@@ -0,0 +1,91 @@
+/** @file
+*  Library to install the XENIO_PROTOCOL on a handle
+*
+*  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
+*
+*  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 <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/XenIoMmioLib.h>
+
+#include <Protocol/XenIo.h>
+#include <Guid/XenBusRootDevice.h>
+
+#pragma pack (1)
+typedef struct {
+  VENDOR_DEVICE_PATH                  Vendor;
+  EFI_DEVICE_PATH_PROTOCOL            End;
+} XENBUS_ROOT_DEVICE_PATH;
+#pragma pack ()
+
+EFI_STATUS
+XenIoMmioInstall (
+  IN  EFI_HANDLE  *Handle,
+  IN  UINT64      GrantTableAddress
+  )
+{
+  EFI_STATUS                     Status;
+  XENIO_PROTOCOL                 *XenIo;
+  XENBUS_ROOT_DEVICE_PATH        *XenBusDevicePath;
+
+  ASSERT (Handle != NULL);
+
+  XenIo = AllocateZeroPool (sizeof *XenIo);
+  ASSERT (XenIo != NULL);
+  XenIo->GrantTableAddress = GrantTableAddress;
+
+  XenBusDevicePath = (XENBUS_ROOT_DEVICE_PATH *)CreateDeviceNode (
+                                HARDWARE_DEVICE_PATH,
+                                HW_VENDOR_DP,
+                                sizeof (XENBUS_ROOT_DEVICE_PATH));
+  if (XenBusDevicePath == NULL) {
+    DEBUG ((EFI_D_ERROR, "%a: Out of memory\n", __FUNCTION__));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CopyMem (&XenBusDevicePath->Vendor.Guid, &gXenBusRootDeviceGuid,
+    sizeof (EFI_GUID));
+  SetDevicePathNodeLength (&XenBusDevicePath->Vendor,
+    sizeof (*XenBusDevicePath) - sizeof (XenBusDevicePath->End));
+  SetDevicePathEndNode (&XenBusDevicePath->End);
+
+  Status = gBS->InstallProtocolInterface (Handle,
+                 &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
+                 XenBusDevicePath);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: Failed to install the EFI_DEVICE_PATH "
+      "protocol on handle 0x%p (Status == %r)\n",
+      __FUNCTION__, *Handle, Status));
+    FreePool (XenBusDevicePath);
+    return Status;
+  }
+
+  Status = gBS->InstallProtocolInterface (Handle,
+                 &gXenIoProtocolGuid, EFI_NATIVE_INTERFACE,
+                 XenIo);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: Failed to install XENIO_PROTOCOL on handle 0x%p "
+      "(Status == %r)\n", __FUNCTION__, *Handle, Status));
+
+    Status = gBS->UninstallProtocolInterface (*Handle,
+                    &gEfiDevicePathProtocolGuid, XenBusDevicePath);
+    ASSERT_EFI_ERROR (Status);
+    FreePool (XenBusDevicePath);
+    FreePool (XenIo);
+  }
+  return Status;
+}
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenIoMmioLib/XenIoMmioLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenIoMmioLib/XenIoMmioLib.inf
new file mode 100644
index 000000000000..14f24ff7fd2c
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/XenIoMmioLib/XenIoMmioLib.inf
@@ -0,0 +1,38 @@
+## @file
+# Library to install the XENIO_PROTOCOL on a handle
+#
+# Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
+#
+#  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.
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = XenIoMmioLib
+  FILE_GUID                      = 3CD90EEC-EBF3-425D-AAE8-B16215AC4F50
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = XenIoMmioLib
+
+[Sources]
+  XenIoMmioLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+
+[Guids]
+  gXenBusRootDeviceGuid
+
+[Protocols]
+  gEfiDevicePathProtocolGuid
