All of lore.kernel.org
 help / color / mirror / Atom feed
From: Petre Pircalabu <ppircalabu@bitdefender.com>
To: xen-devel@lists.xenproject.org
Cc: Petre Pircalabu <ppircalabu@bitdefender.com>,
	Tamas K Lengyel <tamas@tklengyel.com>,
	Razvan Cojocaru <rcojocaru@bitdefender.com>, Wei Liu <wl@xen.org>,
	Ian Jackson <ian.jackson@eu.citrix.com>,
	Alexandru Isaila <aisaila@bitdefender.com>
Subject: [Xen-devel] [PATCH v2 10/10] xen-access: Add support for vm_event_ng interface
Date: Tue, 16 Jul 2019 20:06:24 +0300	[thread overview]
Message-ID: <fa78b1f1a9b046f52a017afcb73c6ef57d018d82.1563293545.git.ppircalabu@bitdefender.com> (raw)
In-Reply-To: <cover.1563293545.git.ppircalabu@bitdefender.com>
In-Reply-To: <cover.1563293545.git.ppircalabu@bitdefender.com>

Split xen-access in order to accommodate both vm_event interfaces
(legacy and NG). By default, the legacy vm_event is selected but
this can be changed by adding the '-n' flag in the command line.

Signed-off-by: Petre Pircalabu <ppircalabu@bitdefender.com>
---
 tools/tests/xen-access/Makefile      |   7 +-
 tools/tests/xen-access/vm-event-ng.c | 183 ++++++++++++++++++
 tools/tests/xen-access/vm-event.c    | 194 +++++++++++++++++++
 tools/tests/xen-access/xen-access.c  | 348 +++++++++++------------------------
 tools/tests/xen-access/xen-access.h  |  91 +++++++++
 5 files changed, 582 insertions(+), 241 deletions(-)
 create mode 100644 tools/tests/xen-access/vm-event-ng.c
 create mode 100644 tools/tests/xen-access/vm-event.c
 create mode 100644 tools/tests/xen-access/xen-access.h

diff --git a/tools/tests/xen-access/Makefile b/tools/tests/xen-access/Makefile
index 131c9f3..17760d8 100644
--- a/tools/tests/xen-access/Makefile
+++ b/tools/tests/xen-access/Makefile
@@ -7,6 +7,7 @@ CFLAGS += -DXC_WANT_COMPAT_DEVICEMODEL_API
 CFLAGS += $(CFLAGS_libxenctrl)
 CFLAGS += $(CFLAGS_libxenguest)
 CFLAGS += $(CFLAGS_libxenevtchn)
+CFLAGS += $(CFLAGS_libxenforeignmemory)
 CFLAGS += $(CFLAGS_xeninclude)
 
 TARGETS-y := xen-access
@@ -25,8 +26,10 @@ clean:
 .PHONY: distclean
 distclean: clean
 
-xen-access: xen-access.o Makefile
-	$(CC) -o $@ $< $(LDFLAGS) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenevtchn)
+OBJS = xen-access.o vm-event.o vm-event-ng.o
+
+xen-access: $(OBJS) Makefile
+	$(CC) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenevtchn) $(LDLIBS_libxenforeignmemory)
 
 install uninstall:
 
diff --git a/tools/tests/xen-access/vm-event-ng.c b/tools/tests/xen-access/vm-event-ng.c
new file mode 100644
index 0000000..2c79f61
--- /dev/null
+++ b/tools/tests/xen-access/vm-event-ng.c
@@ -0,0 +1,183 @@
+/*
+ * vm-event-ng.c
+ *
+ * Copyright (c) 2019 Bitdefender S.R.L.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <xenforeignmemory.h>
+#include "xen-access.h"
+
+#ifndef PFN_UP
+#define PFN_UP(x)     (((x) + XC_PAGE_SIZE-1) >> XC_PAGE_SHIFT)
+#endif /* PFN_UP */
+
+typedef struct vm_event_channels
+{
+    vm_event_t vme;
+    int num_channels;
+    xenforeignmemory_resource_handle *fres;
+    struct vm_event_slot *slots;
+    int *ports;
+} vm_event_channels_t;
+
+#define to_channels(_vme) container_of((_vme), vm_event_channels_t, vme)
+
+static int vm_event_channels_init(xc_interface *xch, xenevtchn_handle *xce,
+                                  domid_t domain_id, vm_event_ops_t *ops,
+                                  vm_event_t **vm_event)
+{
+    vm_event_channels_t *impl = NULL;
+    int rc, i;
+
+    impl = (vm_event_channels_t *)calloc(1, sizeof(vm_event_channels_t));
+    if ( impl == NULL )
+        return -ENOMEM;
+
+    rc = xc_monitor_ng_enable(xch, domain_id, &impl->fres, &impl->num_channels, (void**)&impl->slots);
+    if ( rc )
+    {
+        ERROR("Failed to enable monitor");
+        return rc;
+    }
+
+    impl->ports = calloc(impl->num_channels, sizeof(int));
+    if ( impl->ports == NULL )
+    {
+        rc = -ENOMEM;
+        goto err;
+    }
+
+    for ( i = 0; i < impl->num_channels; i++)
+    {
+        rc = xenevtchn_bind_interdomain(xce, domain_id, impl->slots[i].port);
+        if (  rc < 0 )
+        {
+            ERROR("Failed to bind vm_event_slot port for vcpu %d", i);
+            rc = -errno;
+            goto err;
+        }
+
+        impl->ports[i] = rc;
+    }
+
+    *vm_event = (vm_event_t*) impl;
+    return 0;
+
+err:
+    while ( --i >= 0 )
+        xenevtchn_unbind(xce, impl->ports[i]);
+    free(impl->ports);
+    xc_monitor_ng_disable(xch, domain_id, &impl->fres);
+    free(impl);
+    return rc;
+}
+
+static int vcpu_id_by_port(vm_event_channels_t *impl, int port, int *vcpu_id)
+{
+    int i;
+
+    for ( i = 0; i < impl->num_channels; i++ )
+    {
+        if ( port == impl->ports[i] )
+        {
+            *vcpu_id = i;
+            return 0;
+        }
+    }
+
+    return -EINVAL;
+}
+
+static int vm_event_channels_teardown(vm_event_t *vm_event)
+{
+    vm_event_channels_t *impl = to_channels(vm_event);
+    int rc, i;
+
+    if ( impl == NULL || impl->ports == NULL )
+        return -EINVAL;
+
+    for ( i = 0; i < impl->num_channels; i++ )
+    {
+        rc = xenevtchn_unbind(vm_event->xce, impl->ports[i]);
+        if ( rc != 0 )
+        {
+            ERROR("Error unbinding event port");
+            return rc;
+        }
+    }
+
+    return xc_monitor_ng_disable(impl->vme.xch, impl->vme.domain_id, &impl->fres);
+}
+
+static bool vm_event_channels_get_request(vm_event_t *vm_event, vm_event_request_t *req, int *port)
+{
+    int vcpu_id;
+    vm_event_channels_t *impl = to_channels(vm_event);
+
+    if ( vcpu_id_by_port(impl, *port, &vcpu_id) != 0 )
+        return false;
+
+    if ( impl->slots[vcpu_id].state != STATE_VM_EVENT_SLOT_SUBMIT )
+        return false;
+
+    memcpy(req, &impl->slots[vcpu_id].u.req, sizeof(*req));
+
+    return true;
+}
+
+static void vm_event_channels_put_response(vm_event_t *vm_event, vm_event_response_t *rsp, int port)
+{
+    int vcpu_id;
+    vm_event_channels_t *impl = to_channels(vm_event);
+
+    if ( vcpu_id_by_port(impl, port, &vcpu_id) != 0 )
+        return;
+
+    memcpy(&impl->slots[vcpu_id].u.rsp, rsp, sizeof(*rsp));
+    impl->slots[vcpu_id].state = STATE_VM_EVENT_SLOT_FINISH;
+}
+
+static int vm_event_channels_notify_port(vm_event_t *vm_event, int port)
+{
+    return xenevtchn_notify(vm_event->xce, port);
+}
+
+vm_event_ops_t channel_ops = {
+    .get_request = vm_event_channels_get_request,
+    .put_response = vm_event_channels_put_response,
+    .notify_port = vm_event_channels_notify_port,
+    .init = vm_event_channels_init,
+    .teardown = vm_event_channels_teardown,
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/tests/xen-access/vm-event.c b/tools/tests/xen-access/vm-event.c
new file mode 100644
index 0000000..e6b20ce
--- /dev/null
+++ b/tools/tests/xen-access/vm-event.c
@@ -0,0 +1,194 @@
+/*
+ * vm-event.c
+ *
+ * Copyright (c) 2019 Bitdefender S.R.L.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include "xen-access.h"
+
+typedef struct vm_event_ring {
+    vm_event_t vme;
+    int port;
+    vm_event_back_ring_t back_ring;
+    uint32_t evtchn_port;
+    void *ring_page;
+} vm_event_ring_t;
+
+#define to_ring(_vme) container_of((_vme), vm_event_ring_t, vme)
+
+static int vm_event_ring_init(xc_interface *xch, xenevtchn_handle *xce,
+                              domid_t domain_id, vm_event_ops_t *ops,
+                              vm_event_t **vm_event)
+{
+    vm_event_ring_t *impl;
+    int rc;
+
+    impl = (vm_event_ring_t*) calloc (1, sizeof(vm_event_ring_t));
+    if ( impl == NULL )
+        return -ENOMEM;
+
+    /* Enable mem_access */
+    impl->ring_page = xc_monitor_enable(xch, domain_id, &impl->evtchn_port);
+    if ( impl->ring_page == NULL )
+    {
+        switch ( errno )
+        {
+        case EBUSY:
+            ERROR("xenaccess is (or was) active on this domain");
+            break;
+        case ENODEV:
+            ERROR("EPT not supported for this guest");
+            break;
+        default:
+            perror("Error enabling mem_access");
+            break;
+        }
+        rc = -errno;
+        goto err;
+    }
+
+    /* Bind event notification */
+    rc = xenevtchn_bind_interdomain(xce, domain_id, impl->evtchn_port);
+    if ( rc < 0 )
+    {
+        ERROR("Failed to bind event channel");
+        munmap(impl->ring_page, XC_PAGE_SIZE);
+        xc_monitor_disable(xch, domain_id);
+        goto err;
+    }
+
+    impl->port = rc;
+
+    /* Initialise ring */
+    SHARED_RING_INIT((vm_event_sring_t *)impl->ring_page);
+    BACK_RING_INIT(&impl->back_ring, (vm_event_sring_t *)impl->ring_page,
+                   XC_PAGE_SIZE);
+
+    *vm_event = (vm_event_t*) impl;
+    return 0;
+
+err:
+    free(impl);
+    return rc;
+}
+
+static int vm_event_ring_teardown(vm_event_t *vm_event)
+{
+    vm_event_ring_t *impl = to_ring(vm_event);
+    int rc;
+
+    if ( impl->ring_page != NULL )
+        munmap(impl->ring_page, XC_PAGE_SIZE);
+
+    /* Tear down domain xenaccess in Xen */
+    rc = xc_monitor_disable(vm_event->xch, vm_event->domain_id);
+    if ( rc != 0 )
+    {
+        ERROR("Error tearing down domain xenaccess in xen");
+        return rc;
+    }
+
+    /* Unbind VIRQ */
+    rc = xenevtchn_unbind(vm_event->xce, impl->port);
+    if ( rc != 0 )
+    {
+        ERROR("Error unbinding event port");
+        return rc;
+    }
+
+    return 0;
+}
+
+/*
+ * Note that this function is not thread safe.
+ */
+static bool vm_event_ring_get_request(vm_event_t *vm_event, vm_event_request_t *req, int *port)
+{
+    vm_event_back_ring_t *back_ring;
+    RING_IDX req_cons;
+    vm_event_ring_t *impl = to_ring(vm_event);
+
+    if ( !RING_HAS_UNCONSUMED_REQUESTS(&impl->back_ring) )
+        return false;
+
+    back_ring = &impl->back_ring;
+    req_cons = back_ring->req_cons;
+
+    /* Copy request */
+    memcpy(req, RING_GET_REQUEST(back_ring, req_cons), sizeof(*req));
+    req_cons++;
+
+    /* Update ring */
+    back_ring->req_cons = req_cons;
+    back_ring->sring->req_event = req_cons + 1;
+
+    *port = impl->port;
+
+    return true;
+}
+
+/*
+ * Note that this function is not thread safe.
+ */
+static void vm_event_ring_put_response(vm_event_t *vm_event, vm_event_response_t *rsp, int port)
+{
+    vm_event_back_ring_t *back_ring;
+    RING_IDX rsp_prod;
+    vm_event_ring_t *impl = to_ring(vm_event);
+
+    back_ring = &impl->back_ring;
+    rsp_prod = back_ring->rsp_prod_pvt;
+
+    /* Copy response */
+    memcpy(RING_GET_RESPONSE(back_ring, rsp_prod), rsp, sizeof(*rsp));
+    rsp_prod++;
+
+    /* Update ring */
+    back_ring->rsp_prod_pvt = rsp_prod;
+    RING_PUSH_RESPONSES(back_ring);
+}
+
+static int vm_event_ring_notify_port(vm_event_t *vm_event, int port)
+{
+    return xenevtchn_notify(vm_event->xce, port);
+}
+
+vm_event_ops_t ring_ops = {
+    .get_request = vm_event_ring_get_request,
+    .put_response = vm_event_ring_put_response,
+    .notify_port = vm_event_ring_notify_port,
+    .init = vm_event_ring_init,
+    .teardown = vm_event_ring_teardown,
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c
index abf17a2..9157f23 100644
--- a/tools/tests/xen-access/xen-access.c
+++ b/tools/tests/xen-access/xen-access.c
@@ -35,14 +35,9 @@
 #include <time.h>
 #include <signal.h>
 #include <unistd.h>
-#include <sys/mman.h>
 #include <poll.h>
 #include <getopt.h>
 
-#include <xenctrl.h>
-#include <xenevtchn.h>
-#include <xen/vm_event.h>
-
 #include <xen-tools/libs.h>
 
 #if defined(__arm__) || defined(__aarch64__)
@@ -52,9 +47,7 @@
 #define START_PFN 0ULL
 #endif
 
-#define DPRINTF(a, b...) fprintf(stderr, a, ## b)
-#define ERROR(a, b...) fprintf(stderr, a "\n", ## b)
-#define PERROR(a, b...) fprintf(stderr, a ": %s\n", ## b, strerror(errno))
+#include "xen-access.h"
 
 /* From xen/include/asm-x86/processor.h */
 #define X86_TRAP_DEBUG  1
@@ -63,32 +56,14 @@
 /* From xen/include/asm-x86/x86-defns.h */
 #define X86_CR4_PGE        0x00000080 /* enable global pages */
 
-typedef struct vm_event {
-    domid_t domain_id;
-    xenevtchn_handle *xce_handle;
-    int port;
-    vm_event_back_ring_t back_ring;
-    uint32_t evtchn_port;
-    void *ring_page;
-} vm_event_t;
-
-typedef struct xenaccess {
-    xc_interface *xc_handle;
-
-    xen_pfn_t max_gpfn;
-
-    vm_event_t vm_event;
-} xenaccess_t;
-
 static int interrupted;
-bool evtchn_bind = 0, evtchn_open = 0, mem_access_enable = 0;
 
 static void close_handler(int sig)
 {
     interrupted = sig;
 }
 
-int xc_wait_for_event_or_timeout(xc_interface *xch, xenevtchn_handle *xce, unsigned long ms)
+static int xc_wait_for_event_or_timeout(xc_interface *xch, xenevtchn_handle *xce, unsigned long ms)
 {
     struct pollfd fd = { .fd = xenevtchn_fd(xce), .events = POLLIN | POLLERR };
     int port;
@@ -129,161 +104,85 @@ int xc_wait_for_event_or_timeout(xc_interface *xch, xenevtchn_handle *xce, unsig
     return -errno;
 }
 
-int xenaccess_teardown(xc_interface *xch, xenaccess_t *xenaccess)
+static int vm_event_teardown(vm_event_t *vm_event)
 {
     int rc;
 
-    if ( xenaccess == NULL )
+    if ( vm_event == NULL )
         return 0;
 
-    /* Tear down domain xenaccess in Xen */
-    if ( xenaccess->vm_event.ring_page != NULL )
-        munmap(xenaccess->vm_event.ring_page, XC_PAGE_SIZE);
-
-    if ( mem_access_enable )
-    {
-        rc = xc_monitor_disable(xenaccess->xc_handle,
-                                xenaccess->vm_event.domain_id);
-        if ( rc != 0 )
-        {
-            ERROR("Error tearing down domain xenaccess in xen");
-            return rc;
-        }
-    }
-
-    /* Unbind VIRQ */
-    if ( evtchn_bind )
-    {
-        rc = xenevtchn_unbind(xenaccess->vm_event.xce_handle,
-                              xenaccess->vm_event.port);
-        if ( rc != 0 )
-        {
-            ERROR("Error unbinding event port");
-            return rc;
-        }
-    }
+    rc = vm_event->ops->teardown(vm_event);
+    if ( rc != 0 )
+        return rc;
 
     /* Close event channel */
-    if ( evtchn_open )
+    rc = xenevtchn_close(vm_event->xce);
+    if ( rc != 0 )
     {
-        rc = xenevtchn_close(xenaccess->vm_event.xce_handle);
-        if ( rc != 0 )
-        {
-            ERROR("Error closing event channel");
-            return rc;
-        }
+        ERROR("Error closing event channel");
+        return rc;
     }
 
     /* Close connection to Xen */
-    rc = xc_interface_close(xenaccess->xc_handle);
+    rc = xc_interface_close(vm_event->xch);
     if ( rc != 0 )
     {
         ERROR("Error closing connection to xen");
         return rc;
     }
-    xenaccess->xc_handle = NULL;
-
-    free(xenaccess);
 
     return 0;
 }
 
-xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t domain_id)
+static vm_event_t *vm_event_init(domid_t domain_id, vm_event_ops_t *ops)
 {
-    xenaccess_t *xenaccess = 0;
+    vm_event_t *vm_event;
     xc_interface *xch;
+    xenevtchn_handle *xce;
+    xen_pfn_t max_gpfn;
     int rc;
 
+    if ( ops == NULL )
+        return NULL;
+
     xch = xc_interface_open(NULL, NULL, 0);
     if ( xch == NULL )
-        goto err_iface;
+        goto err;
 
     DPRINTF("xenaccess init\n");
-    *xch_r = xch;
-
-    /* Allocate memory */
-    xenaccess = malloc(sizeof(xenaccess_t));
-    memset(xenaccess, 0, sizeof(xenaccess_t));
-
-    /* Open connection to xen */
-    xenaccess->xc_handle = xch;
-
-    /* Set domain id */
-    xenaccess->vm_event.domain_id = domain_id;
-
-    /* Enable mem_access */
-    xenaccess->vm_event.ring_page =
-            xc_monitor_enable(xenaccess->xc_handle,
-                              xenaccess->vm_event.domain_id,
-                              &xenaccess->vm_event.evtchn_port);
-    if ( xenaccess->vm_event.ring_page == NULL )
-    {
-        switch ( errno )
-        {
-        case EBUSY:
-            ERROR("xenaccess is (or was) active on this domain");
-            break;
-        case ENODEV:
-            ERROR("EPT not supported for this guest");
-            break;
-        default:
-            perror("Error enabling mem_access");
-            break;
-        }
-        goto err;
-    }
-    mem_access_enable = 1;
 
     /* Open event channel */
-    xenaccess->vm_event.xce_handle = xenevtchn_open(NULL, 0);
-    if ( xenaccess->vm_event.xce_handle == NULL )
+    xce = xenevtchn_open(NULL, 0);
+    if ( xce == NULL )
     {
         ERROR("Failed to open event channel");
         goto err;
     }
-    evtchn_open = 1;
-
-    /* Bind event notification */
-    rc = xenevtchn_bind_interdomain(xenaccess->vm_event.xce_handle,
-                                    xenaccess->vm_event.domain_id,
-                                    xenaccess->vm_event.evtchn_port);
-    if ( rc < 0 )
-    {
-        ERROR("Failed to bind event channel");
-        goto err;
-    }
-    evtchn_bind = 1;
-    xenaccess->vm_event.port = rc;
-
-    /* Initialise ring */
-    SHARED_RING_INIT((vm_event_sring_t *)xenaccess->vm_event.ring_page);
-    BACK_RING_INIT(&xenaccess->vm_event.back_ring,
-                   (vm_event_sring_t *)xenaccess->vm_event.ring_page,
-                   XC_PAGE_SIZE);
 
     /* Get max_gpfn */
-    rc = xc_domain_maximum_gpfn(xenaccess->xc_handle,
-                                xenaccess->vm_event.domain_id,
-                                &xenaccess->max_gpfn);
-
+    rc = xc_domain_maximum_gpfn(xch, domain_id, &max_gpfn);
     if ( rc )
     {
         ERROR("Failed to get max gpfn");
         goto err;
     }
+    DPRINTF("max_gpfn = %"PRI_xen_pfn"\n", max_gpfn);
 
-    DPRINTF("max_gpfn = %"PRI_xen_pfn"\n", xenaccess->max_gpfn);
+    rc = ops->init(xch, xce, domain_id, ops, &vm_event);
+    if ( rc < 0 )
+        goto err;
 
-    return xenaccess;
+    vm_event->xch = xch;
+    vm_event->xce = xce;
+    vm_event->domain_id = domain_id;
+    vm_event->ops = ops;
+    vm_event->max_gpfn = max_gpfn;
 
- err:
-    rc = xenaccess_teardown(xch, xenaccess);
-    if ( rc )
-    {
-        ERROR("Failed to teardown xenaccess structure!\n");
-    }
+    return vm_event;
 
- err_iface:
+ err:
+    xenevtchn_close(xce);
+    xc_interface_close(xch);
 
     return NULL;
 }
@@ -298,26 +197,6 @@ static inline int control_singlestep(xc_interface *xch, domid_t domain_id,
 }
 
 /*
- * Note that this function is not thread safe.
- */
-static void get_request(vm_event_t *vm_event, vm_event_request_t *req)
-{
-    vm_event_back_ring_t *back_ring;
-    RING_IDX req_cons;
-
-    back_ring = &vm_event->back_ring;
-    req_cons = back_ring->req_cons;
-
-    /* Copy request */
-    memcpy(req, RING_GET_REQUEST(back_ring, req_cons), sizeof(*req));
-    req_cons++;
-
-    /* Update ring */
-    back_ring->req_cons = req_cons;
-    back_ring->sring->req_event = req_cons + 1;
-}
-
-/*
  * X86 control register names
  */
 static const char* get_x86_ctrl_reg_name(uint32_t index)
@@ -335,29 +214,9 @@ static const char* get_x86_ctrl_reg_name(uint32_t index)
     return names[index];
 }
 
-/*
- * Note that this function is not thread safe.
- */
-static void put_response(vm_event_t *vm_event, vm_event_response_t *rsp)
-{
-    vm_event_back_ring_t *back_ring;
-    RING_IDX rsp_prod;
-
-    back_ring = &vm_event->back_ring;
-    rsp_prod = back_ring->rsp_prod_pvt;
-
-    /* Copy response */
-    memcpy(RING_GET_RESPONSE(back_ring, rsp_prod), rsp, sizeof(*rsp));
-    rsp_prod++;
-
-    /* Update ring */
-    back_ring->rsp_prod_pvt = rsp_prod;
-    RING_PUSH_RESPONSES(back_ring);
-}
-
 void usage(char* progname)
 {
-    fprintf(stderr, "Usage: %s [-m] <domain_id> write|exec", progname);
+    fprintf(stderr, "Usage: %s [-m] [-n] <domain_id> write|exec", progname);
 #if defined(__i386__) || defined(__x86_64__)
     fprintf(stderr, "|breakpoint|altp2m_write|altp2m_exec|debug|cpuid|desc_access|write_ctrlreg_cr4|altp2m_write_no_gpt");
 #elif defined(__arm__) || defined(__aarch64__)
@@ -367,19 +226,22 @@ void usage(char* progname)
             "\n"
             "Logs first page writes, execs, or breakpoint traps that occur on the domain.\n"
             "\n"
-            "-m requires this program to run, or else the domain may pause\n");
+            "-m requires this program to run, or else the domain may pause\n"
+            "-n uses the per-vcpu channels vm_event interface\n");
 }
 
+extern vm_event_ops_t ring_ops;
+extern vm_event_ops_t channel_ops;
+
 int main(int argc, char *argv[])
 {
     struct sigaction act;
     domid_t domain_id;
-    xenaccess_t *xenaccess;
+    vm_event_t *vm_event;
     vm_event_request_t req;
     vm_event_response_t rsp;
     int rc = -1;
     int rc1;
-    xc_interface *xch;
     xenmem_access_t default_access = XENMEM_access_rwx;
     xenmem_access_t after_first_access = XENMEM_access_rwx;
     int memaccess = 0;
@@ -394,6 +256,7 @@ int main(int argc, char *argv[])
     int write_ctrlreg_cr4 = 0;
     int altp2m_write_no_gpt = 0;
     uint16_t altp2m_view_id = 0;
+    int new_interface = 0;
 
     char* progname = argv[0];
     char* command;
@@ -402,11 +265,12 @@ int main(int argc, char *argv[])
     struct option long_options[] =
     {
         { "mem-access-listener", no_argument, 0, 'm' },
+        { "new-interface", no_argument, 0, 'n' },
     };
 
     while ( 1 )
     {
-        c = getopt_long(argc, argv, "m", long_options, &option_index);
+        c = getopt_long(argc, argv, "mn", long_options, &option_index);
         if ( c == -1 )
             break;
 
@@ -416,6 +280,10 @@ int main(int argc, char *argv[])
             required = 1;
             break;
 
+        case 'n':
+            new_interface = 1;
+            break;
+
         default:
             usage(progname);
             return -1;
@@ -495,10 +363,11 @@ int main(int argc, char *argv[])
         return -1;
     }
 
-    xenaccess = xenaccess_init(&xch, domain_id);
-    if ( xenaccess == NULL )
+    vm_event = vm_event_init(domain_id,
+                             (new_interface) ? &channel_ops : &ring_ops);
+    if ( vm_event == NULL )
     {
-        ERROR("Error initialising xenaccess");
+        ERROR("Error initialising vm_event");
         return 1;
     }
 
@@ -514,7 +383,7 @@ int main(int argc, char *argv[])
     sigaction(SIGALRM, &act, NULL);
 
     /* Set whether the access listener is required */
-    rc = xc_domain_set_access_required(xch, domain_id, required);
+    rc = xc_domain_set_access_required(vm_event->xch, domain_id, required);
     if ( rc < 0 )
     {
         ERROR("Error %d setting mem_access listener required\n", rc);
@@ -529,13 +398,13 @@ int main(int argc, char *argv[])
 
         if( altp2m_write_no_gpt )
         {
-            rc = xc_monitor_inguest_pagefault(xch, domain_id, 1);
+            rc = xc_monitor_inguest_pagefault(vm_event->xch, domain_id, 1);
             if ( rc < 0 )
             {
                 ERROR("Error %d setting inguest pagefault\n", rc);
                 goto exit;
             }
-            rc = xc_monitor_emul_unimplemented(xch, domain_id, 1);
+            rc = xc_monitor_emul_unimplemented(vm_event->xch, domain_id, 1);
             if ( rc < 0 )
             {
                 ERROR("Error %d failed to enable emul unimplemented\n", rc);
@@ -543,14 +412,15 @@ int main(int argc, char *argv[])
             }
         }
 
-        rc = xc_altp2m_set_domain_state( xch, domain_id, 1 );
+        rc = xc_altp2m_set_domain_state( vm_event->xch, domain_id, 1 );
         if ( rc < 0 )
         {
             ERROR("Error %d enabling altp2m on domain!\n", rc);
             goto exit;
         }
 
-        rc = xc_altp2m_create_view( xch, domain_id, default_access, &altp2m_view_id );
+        rc = xc_altp2m_create_view( vm_event->xch, domain_id, default_access,
+                                    &altp2m_view_id );
         if ( rc < 0 )
         {
             ERROR("Error %d creating altp2m view!\n", rc);
@@ -560,24 +430,24 @@ int main(int argc, char *argv[])
         DPRINTF("altp2m view created with id %u\n", altp2m_view_id);
         DPRINTF("Setting altp2m mem_access permissions.. ");
 
-        for( ; gfn < xenaccess->max_gpfn; ++gfn )
+        for( ; gfn < vm_event->max_gpfn; ++gfn )
         {
-            rc = xc_altp2m_set_mem_access( xch, domain_id, altp2m_view_id, gfn,
-                                           default_access);
+            rc = xc_altp2m_set_mem_access( vm_event->xch, domain_id,
+                                           altp2m_view_id, gfn, default_access);
             if ( !rc )
                 perm_set++;
         }
 
         DPRINTF("done! Permissions set on %lu pages.\n", perm_set);
 
-        rc = xc_altp2m_switch_to_view( xch, domain_id, altp2m_view_id );
+        rc = xc_altp2m_switch_to_view( vm_event->xch, domain_id, altp2m_view_id );
         if ( rc < 0 )
         {
             ERROR("Error %d switching to altp2m view!\n", rc);
             goto exit;
         }
 
-        rc = xc_monitor_singlestep( xch, domain_id, 1 );
+        rc = xc_monitor_singlestep( vm_event->xch, domain_id, 1 );
         if ( rc < 0 )
         {
             ERROR("Error %d failed to enable singlestep monitoring!\n", rc);
@@ -588,15 +458,15 @@ int main(int argc, char *argv[])
     if ( memaccess && !altp2m )
     {
         /* Set the default access type and convert all pages to it */
-        rc = xc_set_mem_access(xch, domain_id, default_access, ~0ull, 0);
+        rc = xc_set_mem_access(vm_event->xch, domain_id, default_access, ~0ull, 0);
         if ( rc < 0 )
         {
             ERROR("Error %d setting default mem access type\n", rc);
             goto exit;
         }
 
-        rc = xc_set_mem_access(xch, domain_id, default_access, START_PFN,
-                               (xenaccess->max_gpfn - START_PFN) );
+        rc = xc_set_mem_access(vm_event->xch, domain_id, default_access, START_PFN,
+                               (vm_event->max_gpfn - START_PFN) );
 
         if ( rc < 0 )
         {
@@ -608,7 +478,7 @@ int main(int argc, char *argv[])
 
     if ( breakpoint )
     {
-        rc = xc_monitor_software_breakpoint(xch, domain_id, 1);
+        rc = xc_monitor_software_breakpoint(vm_event->xch, domain_id, 1);
         if ( rc < 0 )
         {
             ERROR("Error %d setting breakpoint trapping with vm_event\n", rc);
@@ -618,7 +488,7 @@ int main(int argc, char *argv[])
 
     if ( debug )
     {
-        rc = xc_monitor_debug_exceptions(xch, domain_id, 1, 1);
+        rc = xc_monitor_debug_exceptions(vm_event->xch, domain_id, 1, 1);
         if ( rc < 0 )
         {
             ERROR("Error %d setting debug exception listener with vm_event\n", rc);
@@ -628,7 +498,7 @@ int main(int argc, char *argv[])
 
     if ( cpuid )
     {
-        rc = xc_monitor_cpuid(xch, domain_id, 1);
+        rc = xc_monitor_cpuid(vm_event->xch, domain_id, 1);
         if ( rc < 0 )
         {
             ERROR("Error %d setting cpuid listener with vm_event\n", rc);
@@ -638,7 +508,7 @@ int main(int argc, char *argv[])
 
     if ( desc_access )
     {
-        rc = xc_monitor_descriptor_access(xch, domain_id, 1);
+        rc = xc_monitor_descriptor_access(vm_event->xch, domain_id, 1);
         if ( rc < 0 )
         {
             ERROR("Error %d setting descriptor access listener with vm_event\n", rc);
@@ -648,7 +518,7 @@ int main(int argc, char *argv[])
 
     if ( privcall )
     {
-        rc = xc_monitor_privileged_call(xch, domain_id, 1);
+        rc = xc_monitor_privileged_call(vm_event->xch, domain_id, 1);
         if ( rc < 0 )
         {
             ERROR("Error %d setting privileged call trapping with vm_event\n", rc);
@@ -659,7 +529,7 @@ int main(int argc, char *argv[])
     if ( write_ctrlreg_cr4 )
     {
         /* Mask the CR4.PGE bit so no events will be generated for global TLB flushes. */
-        rc = xc_monitor_write_ctrlreg(xch, domain_id, VM_EVENT_X86_CR4, 1, 1,
+        rc = xc_monitor_write_ctrlreg(vm_event->xch, domain_id, VM_EVENT_X86_CR4, 1, 1,
                                       X86_CR4_PGE, 1);
         if ( rc < 0 )
         {
@@ -671,41 +541,43 @@ int main(int argc, char *argv[])
     /* Wait for access */
     for ( ; ; )
     {
+        int port = 0;
+
         if ( interrupted )
         {
             /* Unregister for every event */
             DPRINTF("xenaccess shutting down on signal %d\n", interrupted);
 
             if ( breakpoint )
-                rc = xc_monitor_software_breakpoint(xch, domain_id, 0);
+                rc = xc_monitor_software_breakpoint(vm_event->xch, domain_id, 0);
             if ( debug )
-                rc = xc_monitor_debug_exceptions(xch, domain_id, 0, 0);
+                rc = xc_monitor_debug_exceptions(vm_event->xch, domain_id, 0, 0);
             if ( cpuid )
-                rc = xc_monitor_cpuid(xch, domain_id, 0);
+                rc = xc_monitor_cpuid(vm_event->xch, domain_id, 0);
             if ( desc_access )
-                rc = xc_monitor_descriptor_access(xch, domain_id, 0);
+                rc = xc_monitor_descriptor_access(vm_event->xch, domain_id, 0);
             if ( write_ctrlreg_cr4 )
-                rc = xc_monitor_write_ctrlreg(xch, domain_id, VM_EVENT_X86_CR4, 0, 0, 0, 0);
+                rc = xc_monitor_write_ctrlreg(vm_event->xch, domain_id, VM_EVENT_X86_CR4, 0, 0, 0, 0);
 
             if ( privcall )
-                rc = xc_monitor_privileged_call(xch, domain_id, 0);
+                rc = xc_monitor_privileged_call(vm_event->xch, domain_id, 0);
 
             if ( altp2m )
             {
-                rc = xc_altp2m_switch_to_view( xch, domain_id, 0 );
-                rc = xc_altp2m_destroy_view(xch, domain_id, altp2m_view_id);
-                rc = xc_altp2m_set_domain_state(xch, domain_id, 0);
-                rc = xc_monitor_singlestep(xch, domain_id, 0);
+                rc = xc_altp2m_switch_to_view( vm_event->xch, domain_id, 0 );
+                rc = xc_altp2m_destroy_view(vm_event->xch, domain_id, altp2m_view_id);
+                rc = xc_altp2m_set_domain_state(vm_event->xch, domain_id, 0);
+                rc = xc_monitor_singlestep(vm_event->xch, domain_id, 0);
             } else {
-                rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, ~0ull, 0);
-                rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, START_PFN,
-                                       (xenaccess->max_gpfn - START_PFN) );
+                rc = xc_set_mem_access(vm_event->xch, domain_id, XENMEM_access_rwx, ~0ull, 0);
+                rc = xc_set_mem_access(vm_event->xch, domain_id, XENMEM_access_rwx, START_PFN,
+                                       (vm_event->max_gpfn - START_PFN) );
             }
 
             shutting_down = 1;
         }
 
-        rc = xc_wait_for_event_or_timeout(xch, xenaccess->vm_event.xce_handle, 100);
+        rc = xc_wait_for_event_or_timeout(vm_event->xch, vm_event->xce, 100);
         if ( rc < -1 )
         {
             ERROR("Error getting event");
@@ -717,10 +589,10 @@ int main(int argc, char *argv[])
             DPRINTF("Got event from Xen\n");
         }
 
-        while ( RING_HAS_UNCONSUMED_REQUESTS(&xenaccess->vm_event.back_ring) )
-        {
-            get_request(&xenaccess->vm_event, &req);
+        port = rc;
 
+        while ( vm_event->ops->get_request(vm_event, &req, &port) )
+        {
             if ( req.version != VM_EVENT_INTERFACE_VERSION )
             {
                 ERROR("Error: vm_event interface version mismatch!\n");
@@ -744,7 +616,7 @@ int main(int argc, char *argv[])
                      * At shutdown we have already reset all the permissions so really no use getting it again.
                      */
                     xenmem_access_t access;
-                    rc = xc_get_mem_access(xch, domain_id, req.u.mem_access.gfn, &access);
+                    rc = xc_get_mem_access(vm_event->xch, domain_id, req.u.mem_access.gfn, &access);
                     if (rc < 0)
                     {
                         ERROR("Error %d getting mem_access event\n", rc);
@@ -777,7 +649,7 @@ int main(int argc, char *argv[])
                 }
                 else if ( default_access != after_first_access )
                 {
-                    rc = xc_set_mem_access(xch, domain_id, after_first_access,
+                    rc = xc_set_mem_access(vm_event->xch, domain_id, after_first_access,
                                            req.u.mem_access.gfn, 1);
                     if (rc < 0)
                     {
@@ -798,7 +670,7 @@ int main(int argc, char *argv[])
                        req.vcpu_id);
 
                 /* Reinject */
-                rc = xc_hvm_inject_trap(xch, domain_id, req.vcpu_id,
+                rc = xc_hvm_inject_trap(vm_event->xch, domain_id, req.vcpu_id,
                                         X86_TRAP_INT3,
                                         req.u.software_breakpoint.type, -1,
                                         req.u.software_breakpoint.insn_length, 0);
@@ -846,7 +718,7 @@ int main(int argc, char *argv[])
                        req.u.debug_exception.insn_length);
 
                 /* Reinject */
-                rc = xc_hvm_inject_trap(xch, domain_id, req.vcpu_id,
+                rc = xc_hvm_inject_trap(vm_event->xch, domain_id, req.vcpu_id,
                                         X86_TRAP_DEBUG,
                                         req.u.debug_exception.type, -1,
                                         req.u.debug_exception.insn_length,
@@ -914,17 +786,15 @@ int main(int argc, char *argv[])
             }
 
             /* Put the response on the ring */
-            put_response(&xenaccess->vm_event, &rsp);
-        }
-
-        /* Tell Xen page is ready */
-        rc = xenevtchn_notify(xenaccess->vm_event.xce_handle,
-                              xenaccess->vm_event.port);
+            put_response(vm_event, &rsp, port);
 
-        if ( rc != 0 )
-        {
-            ERROR("Error resuming page");
-            interrupted = -1;
+            /* Tell Xen page is ready */
+            rc = notify_port(vm_event, port);
+            if ( rc != 0 )
+            {
+                ERROR("Error resuming page");
+                interrupted = -1;
+            }
         }
 
         if ( shutting_down )
@@ -937,13 +807,13 @@ exit:
     {
         uint32_t vcpu_id;
         for ( vcpu_id = 0; vcpu_id<XEN_LEGACY_MAX_VCPUS; vcpu_id++)
-            rc = control_singlestep(xch, domain_id, vcpu_id, 0);
+            rc = control_singlestep(vm_event->xch, domain_id, vcpu_id, 0);
     }
 
-    /* Tear down domain xenaccess */
-    rc1 = xenaccess_teardown(xch, xenaccess);
+    /* Tear down domain */
+    rc1 = vm_event_teardown(vm_event);
     if ( rc1 != 0 )
-        ERROR("Error tearing down xenaccess");
+        ERROR("Error tearing down vm_event");
 
     if ( rc == 0 )
         rc = rc1;
diff --git a/tools/tests/xen-access/xen-access.h b/tools/tests/xen-access/xen-access.h
new file mode 100644
index 0000000..9fc640c
--- /dev/null
+++ b/tools/tests/xen-access/xen-access.h
@@ -0,0 +1,91 @@
+/*
+ * xen-access.h
+ *
+ * Copyright (c) 2019 Bitdefender S.R.L.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef XEN_ACCESS_H
+#define XEN_ACCESS_H
+
+#include <xenctrl.h>
+#include <xenevtchn.h>
+#include <xen/vm_event.h>
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+                const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+                (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif /* container_of */
+
+#define DPRINTF(a, b...) fprintf(stderr, a, ## b)
+#define ERROR(a, b...) fprintf(stderr, a "\n", ## b)
+#define PERROR(a, b...) fprintf(stderr, a ": %s\n", ## b, strerror(errno))
+
+struct vm_event_ops;
+
+typedef struct vm_event {
+    xc_interface *xch;
+    domid_t domain_id;
+    xenevtchn_handle *xce;
+    xen_pfn_t max_gpfn;
+    struct vm_event_ops *ops;
+} vm_event_t;
+
+typedef struct vm_event_ops {
+    int (*init)(xc_interface *, xenevtchn_handle *, domid_t,
+                struct vm_event_ops *, vm_event_t **);
+    int (*teardown)(vm_event_t *);
+    bool (*get_request)(vm_event_t *, vm_event_request_t *, int *);
+    void (*put_response)(vm_event_t *, vm_event_response_t *, int);
+    int (*notify_port)(vm_event_t *, int port);
+} vm_event_ops_t;
+
+static inline bool get_request(vm_event_t *vm_event, vm_event_request_t *req,
+                               int *port)
+{
+    return ( vm_event ) ? vm_event->ops->get_request(vm_event, req, port) :
+                          false;
+}
+
+static inline void put_response(vm_event_t *vm_event, vm_event_response_t *rsp, int port)
+{
+    if (  vm_event )
+        vm_event->ops->put_response(vm_event, rsp, port);
+}
+
+static inline int notify_port(vm_event_t *vm_event, int port)
+{
+    if ( !vm_event )
+        return -EINVAL;
+
+    return vm_event->ops->notify_port(vm_event, port);
+}
+
+#endif /* XEN_ACCESS_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2019-07-16 17:07 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-16 17:06 [Xen-devel] [PATCH v2 00/10] Per vcpu vm_event channels Petre Pircalabu
2019-07-16 17:06 ` [Xen-devel] [PATCH v2 01/10] vm_event: Define VM_EVENT type Petre Pircalabu
2019-07-16 20:59   ` Tamas K Lengyel
2019-07-17  7:59     ` Petre Ovidiu PIRCALABU
2019-07-17  8:49   ` Alexandru Stefan ISAILA
2019-07-17  9:57     ` Petre Ovidiu PIRCALABU
2019-07-16 17:06 ` [Xen-devel] [PATCH v2 02/10] vm_event: Remove "ring" suffix from vm_event_check_ring Petre Pircalabu
2019-07-17  9:11   ` Alexandru Stefan ISAILA
2019-07-16 17:06 ` [Xen-devel] [PATCH v2 03/10] vm_event: Add 'struct domain' backpointer to vm_event_domain Petre Pircalabu
2019-07-16 21:02   ` Tamas K Lengyel
2019-07-17  9:28   ` Jan Beulich
2019-07-16 17:06 ` [Xen-devel] [PATCH v2 04/10] vm_event: Simplify vm_event interface Petre Pircalabu
2019-07-16 21:04   ` Tamas K Lengyel
2019-07-17 11:13   ` Alexandru Stefan ISAILA
2019-07-16 17:06 ` [Xen-devel] [PATCH v2 05/10] vm_event: Move struct vm_event_domain to vm_event.c Petre Pircalabu
2019-07-17  9:31   ` Jan Beulich
2019-07-17 12:26     ` Petre Ovidiu PIRCALABU
2019-07-16 17:06 ` [Xen-devel] [PATCH v2 06/10] vm_event: Decouple implementation details from interface Petre Pircalabu
2019-07-16 17:06 ` [Xen-devel] [PATCH v2 07/10] vm_event: Add vm_event_ng interface Petre Pircalabu
2019-07-16 21:13   ` Tamas K Lengyel
2019-07-17 12:13     ` Petre Ovidiu PIRCALABU
2019-07-17 10:06   ` Jan Beulich
2019-07-17 12:38     ` Tamas K Lengyel
2019-07-17 13:12       ` Jan Beulich
2019-07-17 14:41     ` Petre Ovidiu PIRCALABU
2019-07-17 16:32       ` Jan Beulich
2019-07-17 18:42         ` Paul Durrant
2019-07-18 13:59         ` Petre Ovidiu PIRCALABU
2019-07-18 14:44           ` Jan Beulich
2019-07-18 14:55             ` Petre Ovidiu PIRCALABU
2019-07-31 12:53             ` Petre Ovidiu PIRCALABU
2019-07-31 13:09               ` Jan Beulich
2019-07-19  7:56           ` Paul Durrant
2019-07-19  8:22             ` Jan Beulich
2019-07-19  8:26               ` Paul Durrant
2019-07-19 11:23                 ` Petre Ovidiu PIRCALABU
2019-07-19 12:11                   ` Paul Durrant
2019-07-19 12:32                     ` Jan Beulich
2019-07-19 12:37                       ` Paul Durrant
2019-07-19 12:59                         ` Jan Beulich
2019-07-19 17:40                           ` Petre Ovidiu PIRCALABU
2019-07-22  7:58                             ` Paul Durrant
2019-07-22  7:59                             ` Jan Beulich
2019-07-22 10:44                               ` Petre Ovidiu PIRCALABU
2019-07-17 13:42   ` Alexandru Stefan ISAILA
2019-07-17 14:46     ` Petre Ovidiu PIRCALABU
2019-07-16 17:06 ` [Xen-devel] [PATCH v2 08/10] xen-access: Use getopt_long for cmdline parsing Petre Pircalabu
2019-07-16 21:09   ` Tamas K Lengyel
2019-07-17 11:16   ` Alexandru Stefan ISAILA
2019-07-16 17:06 ` [Xen-devel] [PATCH v2 09/10] xen-access: Code cleanup Petre Pircalabu
2019-07-16 21:07   ` Tamas K Lengyel
2019-07-17 11:18   ` Alexandru Stefan ISAILA
2019-07-16 17:06 ` Petre Pircalabu [this message]
2019-07-16 20:45 ` [Xen-devel] [PATCH v2 00/10] Per vcpu vm_event channels Tamas K Lengyel
2019-07-17  9:14   ` Petre Ovidiu PIRCALABU

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=fa78b1f1a9b046f52a017afcb73c6ef57d018d82.1563293545.git.ppircalabu@bitdefender.com \
    --to=ppircalabu@bitdefender.com \
    --cc=aisaila@bitdefender.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=rcojocaru@bitdefender.com \
    --cc=tamas@tklengyel.com \
    --cc=wl@xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.