--- /dev/null
+diff -durN -x '*~' -x '*.orig' -x '*.rej' xen-4.4.0.orig/tools/libxc/xc_mem_access.c xen-4.4.0/tools/libxc/xc_mem_access.c
+--- xen-4.4.0.orig/tools/libxc/xc_mem_access.c 2014-03-10 11:43:57.000000000 +0100
++++ xen-4.4.0/tools/libxc/xc_mem_access.c 2014-06-18 10:19:54.000000000 +0200
+@@ -24,19 +24,9 @@
+ #include "xc_private.h"
+
+
+-int xc_mem_access_enable(xc_interface *xch, domid_t domain_id,
+- uint32_t *port)
++void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t *port)
+ {
+- if ( !port )
+- {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- return xc_mem_event_control(xch, domain_id,
+- XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE,
+- XEN_DOMCTL_MEM_EVENT_OP_ACCESS,
+- port);
++ return xc_mem_event_enable(xch, domain_id, HVM_PARAM_ACCESS_RING_PFN, port);
+ }
+
+ int xc_mem_access_disable(xc_interface *xch, domid_t domain_id)
+diff -durN -x '*~' -x '*.orig' -x '*.rej' xen-4.4.0.orig/tools/libxc/xc_mem_event.c xen-4.4.0/tools/libxc/xc_mem_event.c
+--- xen-4.4.0.orig/tools/libxc/xc_mem_event.c 2014-03-10 11:43:57.000000000 +0100
++++ xen-4.4.0/tools/libxc/xc_mem_event.c 2014-06-18 10:19:54.000000000 +0200
+@@ -56,3 +56,118 @@
+ return do_memory_op(xch, mode, &meo, sizeof(meo));
+ }
+
++void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int param,
++ uint32_t *port)
++{
++ void *ring_page = NULL;
++ unsigned long ring_pfn, mmap_pfn;
++ unsigned int op, mode;
++ int rc1, rc2, saved_errno;
++
++ if ( !port )
++ {
++ errno = EINVAL;
++ return NULL;
++ }
++
++ /* Pause the domain for ring page setup */
++ rc1 = xc_domain_pause(xch, domain_id);
++ if ( rc1 != 0 )
++ {
++ PERROR("Unable to pause domain\n");
++ return NULL;
++ }
++
++ /* Get the pfn of the ring page */
++ rc1 = xc_get_hvm_param(xch, domain_id, param, &ring_pfn);
++ if ( rc1 != 0 )
++ {
++ PERROR("Failed to get pfn of ring page\n");
++ goto out;
++ }
++
++ mmap_pfn = ring_pfn;
++ ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
++ &mmap_pfn, 1);
++ if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
++ {
++ /* Map failed, populate ring page */
++ rc1 = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0,
++ &ring_pfn);
++ if ( rc1 != 0 )
++ {
++ PERROR("Failed to populate ring pfn\n");
++ goto out;
++ }
++
++ mmap_pfn = ring_pfn;
++ ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
++ &mmap_pfn, 1);
++ if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
++ {
++ PERROR("Could not map the ring page\n");
++ goto out;
++ }
++ }
++
++ switch ( param )
++ {
++ case HVM_PARAM_PAGING_RING_PFN:
++ op = XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE;
++ mode = XEN_DOMCTL_MEM_EVENT_OP_PAGING;
++ break;
++
++ case HVM_PARAM_ACCESS_RING_PFN:
++ op = XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE;
++ mode = XEN_DOMCTL_MEM_EVENT_OP_ACCESS;
++ break;
++
++ case HVM_PARAM_SHARING_RING_PFN:
++ op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_ENABLE;
++ mode = XEN_DOMCTL_MEM_EVENT_OP_SHARING;
++ break;
++
++ /*
++ * This is for the outside chance that the HVM_PARAM is valid but is invalid
++ * as far as mem_event goes.
++ */
++ default:
++ errno = EINVAL;
++ rc1 = -1;
++ goto out;
++ }
++
++ rc1 = xc_mem_event_control(xch, domain_id, op, mode, port);
++ if ( rc1 != 0 )
++ {
++ PERROR("Failed to enable mem_event\n");
++ goto out;
++ }
++
++ /* Remove the ring_pfn from the guest's physmap */
++ rc1 = xc_domain_decrease_reservation_exact(xch, domain_id, 1, 0, &ring_pfn);
++ if ( rc1 != 0 )
++ PERROR("Failed to remove ring page from guest physmap");
++
++ out:
++ saved_errno = errno;
++
++ rc2 = xc_domain_unpause(xch, domain_id);
++ if ( rc1 != 0 || rc2 != 0 )
++ {
++ if ( rc2 != 0 )
++ {
++ if ( rc1 == 0 )
++ saved_errno = errno;
++ PERROR("Unable to unpause domain");
++ }
++
++ if ( ring_page )
++ munmap(ring_page, XC_PAGE_SIZE);
++ ring_page = NULL;
++
++ errno = saved_errno;
++ }
++
++ return ring_page;
++}
+diff -durN -x '*~' -x '*.orig' -x '*.rej' xen-4.4.0.orig/tools/libxc/xenctrl.h xen-4.4.0/tools/libxc/xenctrl.h
+--- xen-4.4.0.orig/tools/libxc/xenctrl.h 2014-03-10 11:43:57.000000000 +0100
++++ xen-4.4.0/tools/libxc/xenctrl.h 2014-06-18 10:19:54.000000000 +0200
+@@ -2040,6 +2040,12 @@
+ int xc_mem_event_memop(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int mode,
+ uint64_t gfn, void *buffer);
++/*
++ * Enables mem_event and returns the mapped ring page indicated by param.
++ * param can be HVM_PARAM_PAGING/ACCESS/SHARING_RING_PFN
++ */
++void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int param,
++ uint32_t *port);
+
+ /**
+ * Mem paging operations.
+@@ -2060,7 +2066,13 @@
+ * Access tracking operations.
+ * Supported only on Intel EPT 64 bit processors.
+ */
+-int xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t *port);
++
++/*
++ * Enables mem_access and returns the mapped ring page.
++ * Will return NULL on error.
++ * Caller has to unmap this page when done.
++ */
++void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, uint32_t *port);
+ int xc_mem_access_disable(xc_interface *xch, domid_t domain_id);
+ int xc_mem_access_resume(xc_interface *xch, domid_t domain_id,
+ unsigned long gfn);
+diff -durN -x '*~' -x '*.orig' -x '*.rej' xen-4.4.0.orig/tools/tests/xen-access/xen-access.c xen-4.4.0/tools/tests/xen-access/xen-access.c
+--- xen-4.4.0.orig/tools/tests/xen-access/xen-access.c 2014-03-10 11:43:57.000000000 +0100
++++ xen-4.4.0/tools/tests/xen-access/xen-access.c 2014-06-18 10:20:55.000000000 +0200
+@@ -231,7 +231,6 @@
+ xenaccess_t *xenaccess = 0;
+ xc_interface *xch;
+ int rc;
+- unsigned long ring_pfn, mmap_pfn;
+
+ xch = xc_interface_open(NULL, NULL, 0);
+ if ( !xch )
+@@ -253,40 +252,12 @@
+ /* Initialise lock */
+ mem_event_ring_lock_init(&xenaccess->mem_event);
+
+- /* Map the ring page */
+- xc_get_hvm_param(xch, xenaccess->mem_event.domain_id,
+- HVM_PARAM_ACCESS_RING_PFN, &ring_pfn);
+- mmap_pfn = ring_pfn;
+- xenaccess->mem_event.ring_page =
+- xc_map_foreign_batch(xch, xenaccess->mem_event.domain_id,
+- PROT_READ | PROT_WRITE, &mmap_pfn, 1);
+- if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
+- {
+- /* Map failed, populate ring page */
+- rc = xc_domain_populate_physmap_exact(xenaccess->xc_handle,
+- xenaccess->mem_event.domain_id,
+- 1, 0, 0, &ring_pfn);
+- if ( rc != 0 )
+- {
+- PERROR("Failed to populate ring gfn\n");
+- goto err;
+- }
+-
+- mmap_pfn = ring_pfn;
+- xenaccess->mem_event.ring_page =
+- xc_map_foreign_batch(xch, xenaccess->mem_event.domain_id,
+- PROT_READ | PROT_WRITE, &mmap_pfn, 1);
+- if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
+- {
+- PERROR("Could not map the ring page\n");
+- goto err;
+- }
+- }
+-
+- /* Initialise Xen */
+- rc = xc_mem_access_enable(xenaccess->xc_handle, xenaccess->mem_event.domain_id,
+- &xenaccess->mem_event.evtchn_port);
+- if ( rc != 0 )
++ /* Enable mem_access */
++ xenaccess->mem_event.ring_page =
++ xc_mem_access_enable(xenaccess->xc_handle,
++ xenaccess->mem_event.domain_id,
++ &xenaccess->mem_event.evtchn_port);
++ if ( xenaccess->mem_event.ring_page == NULL )
+ {
+ switch ( errno ) {
+ case EBUSY:
+@@ -296,7 +267,7 @@
+ ERROR("EPT not supported for this guest");
+ break;
+ default:
+- perror("Error initialising shared page");
++ perror("Error enabling mem_access");
+ break;
+ }
+ goto err;
+@@ -330,11 +301,6 @@
+ (mem_event_sring_t *)xenaccess->mem_event.ring_page,
+ PAGE_SIZE);
+
+- /* Now that the ring is set, remove it from the guest's physmap */
+- if ( xc_domain_decrease_reservation_exact(xch,
+- xenaccess->mem_event.domain_id, 1, 0, &ring_pfn) )
+- PERROR("Failed to remove ring from guest physmap");
+-
+ /* Get platform info */
+ xenaccess->platform_info = malloc(sizeof(xc_platform_info_t));
+ if ( xenaccess->platform_info == NULL )