WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 2/3] libxc: add xc_gntshr_* functions

These functions and the xc_gntshr device (/dev/xen/gntalloc on linux)
allow applications to create pages shared with other domains.

Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
---
 tools/libxc/xc_gnttab.c      |   27 +++++++++
 tools/libxc/xc_linux_osdep.c |  121 ++++++++++++++++++++++++++++++++++++++++++
 tools/libxc/xc_private.c     |   13 +++++
 tools/libxc/xenctrl.h        |   48 +++++++++++++++++
 tools/libxc/xenctrlosdep.h   |   13 +++++
 5 files changed, 222 insertions(+), 0 deletions(-)

diff --git a/tools/libxc/xc_gnttab.c b/tools/libxc/xc_gnttab.c
index dc7aa0c..ffa3550 100644
--- a/tools/libxc/xc_gnttab.c
+++ b/tools/libxc/xc_gnttab.c
@@ -204,6 +204,33 @@ int xc_gnttab_set_max_grants(xc_gnttab *xcg, uint32_t 
count)
        return xcg->ops->u.gnttab.set_max_grants(xcg, xcg->ops_handle, count);
 }
 
+void *xc_gntshr_share_pages(xc_gntshr *xcg, uint32_t domid,
+                            int count, uint32_t *refs, int writable)
+{
+       return xcg->ops->u.gntshr.share_pages(xcg, xcg->ops_handle, domid,
+                                             count, refs, writable);
+}
+
+void *xc_gntshr_share_page_notify(xc_gntshr *xcg, uint32_t domid,
+                                  uint32_t *ref, int writable,
+                                  uint32_t notify_offset,
+                                  evtchn_port_t notify_port)
+{
+       return xcg->ops->u.gntshr.share_page_notify(xcg, xcg->ops_handle,
+                       domid, ref, writable, notify_offset, notify_port);
+}
+
+/*
+ * Unmaps the @count pages starting at @start_address, which were mapped by a
+ * call to xc_gntshr_share_*. Never logs.
+ */
+int xc_gntshr_munmap(xc_gntshr *xcg, void *start_address, uint32_t count)
+{
+       return xcg->ops->u.gntshr.munmap(xcg, xcg->ops_handle,
+                                        start_address, count);
+}
+
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index 8f7718f..871d37c 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -34,6 +34,7 @@
 #include <xen/memory.h>
 #include <xen/sys/evtchn.h>
 #include <xen/sys/gntdev.h>
+#include <xen/sys/gntalloc.h>
 
 #include "xenctrl.h"
 #include "xenctrlosdep.h"
@@ -718,6 +719,124 @@ static struct xc_osdep_ops linux_gnttab_ops = {
     },
 };
 
+static xc_osdep_handle linux_gntshr_open(xc_gntshr *xcg)
+{
+    int fd = open(DEVXEN "gntalloc", O_RDWR);
+
+    if ( fd == -1 )
+        return XC_OSDEP_OPEN_ERROR;
+
+    return (xc_osdep_handle)fd;
+}
+
+static int linux_gntshr_close(xc_gntshr *xcg, xc_osdep_handle h)
+{
+    int fd = (int)h;
+    return close(fd);
+}
+
+static void *linux_gntshr_share_pages(xc_gntshr *xch, xc_osdep_handle h,
+                                      uint32_t domid, int count,
+                                      uint32_t *refs, int writable)
+{
+       struct ioctl_gntalloc_alloc_gref *gref_info = NULL;
+       int err;
+       void *area = NULL;
+       gref_info = malloc(sizeof(*gref_info) + count * sizeof(uint32_t));
+       if (!gref_info)
+               return NULL;
+       gref_info->domid = domid;
+       gref_info->flags = writable ? GNTALLOC_FLAG_WRITABLE : 0;
+       gref_info->count = count;
+
+       err = ioctl((int)h, IOCTL_GNTALLOC_ALLOC_GREF, gref_info);
+       if (err) {
+               PERROR("linux_gntshr_share_pages: ioctl failed");
+               goto out;
+       }
+
+       area = mmap(NULL, count * XC_PAGE_SIZE, PROT_READ | PROT_WRITE,
+               MAP_SHARED, (int)h, gref_info->index);
+
+       if (area == MAP_FAILED) {
+               area = NULL;
+               PERROR("linux_gntshr_share_pages: mmap failed");
+               goto out;
+       }
+
+       memcpy(refs, gref_info->gref_ids, count * sizeof(uint32_t));
+ out:
+       free(gref_info);
+       return area;
+}
+
+static void *linux_gntshr_share_page_notify(xc_gntshr *xch, xc_osdep_handle h,
+                                            uint32_t domid, uint32_t *ref,
+                                            int writable, uint32_t 
notify_offset,
+                                            evtchn_port_t notify_port)
+{
+       struct ioctl_gntalloc_alloc_gref gref_info;
+       struct ioctl_gntalloc_unmap_notify notify;
+       int err;
+       int fd = (int)h;
+       void *area = NULL;
+       gref_info.domid = domid;
+       gref_info.flags = writable ? GNTALLOC_FLAG_WRITABLE : 0;
+       gref_info.count = 1;
+
+       err = ioctl(fd, IOCTL_GNTALLOC_ALLOC_GREF, &gref_info);
+       if (err) {
+               PERROR("linux_gntshr_share_page_notify: ioctl failed");
+               goto out;
+       }
+
+       area = mmap(NULL, XC_PAGE_SIZE, PROT_READ | PROT_WRITE,
+               MAP_SHARED, fd, gref_info.index);
+
+       if (area == MAP_FAILED) {
+               PERROR("linux_gntshr_share_page_notify: mmap failed");
+               area = NULL;
+               goto out;
+       }
+
+       notify.index = gref_info.index;
+       notify.action = 0;
+       if (notify_offset >= 0) {
+               notify.index += notify_offset;
+               notify.action |= UNMAP_NOTIFY_CLEAR_BYTE;
+       }
+       if (notify_port >= 0) {
+               notify.event_channel_port = notify_port;
+               notify.action |= UNMAP_NOTIFY_SEND_EVENT;
+       }
+       if (notify.action && ioctl(fd, IOCTL_GNTALLOC_SET_UNMAP_NOTIFY, 
&notify)) {
+               PERROR("linux_gntshr_share_page_notify: ioctl SET_UNMAP_NOTIFY 
failed");
+       }
+
+       *ref = gref_info.gref_ids[0];
+ out:
+       return area;
+}
+
+
+static int linux_gntshr_munmap(xc_gntshr *xcg, xc_osdep_handle h,
+                               void *start_address, uint32_t count)
+{
+       return munmap(start_address, count);
+}
+
+static struct xc_osdep_ops linux_gntshr_ops = {
+    .open = &linux_gntshr_open,
+    .close = &linux_gntshr_close,
+
+    .u.gntshr = {
+        .share_pages = &linux_gntshr_share_pages,
+        .share_page_notify = &linux_gntshr_share_page_notify,
+        .munmap = &linux_gntshr_munmap,
+    },
+};
+
+
 static struct xc_osdep_ops *linux_osdep_init(xc_interface *xch, enum 
xc_osdep_type type)
 {
     switch ( type )
@@ -728,6 +847,8 @@ static struct xc_osdep_ops *linux_osdep_init(xc_interface 
*xch, enum xc_osdep_ty
         return &linux_evtchn_ops;
     case XC_OSDEP_GNTTAB:
         return &linux_gnttab_ops;
+    case XC_OSDEP_GNTSHR:
+        return &linux_gntshr_ops;
     default:
         return NULL;
     }
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index 09c8f23..09a91e7 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -258,6 +258,19 @@ int xc_gnttab_close(xc_gnttab *xcg)
     return xc_interface_close_common(xcg);
 }
 
+xc_gntshr *xc_gntshr_open(xentoollog_logger *logger,
+                             unsigned open_flags)
+{
+    return xc_interface_open_common(logger, NULL, open_flags,
+                                    XC_OSDEP_GNTSHR);
+}
+
+int xc_gntshr_close(xc_gntshr *xcg)
+{
+    return xc_interface_close_common(xcg);
+}
+
+
 static pthread_key_t errbuf_pkey;
 static pthread_once_t errbuf_pkey_once = PTHREAD_ONCE_INIT;
 
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 7859571..374c705 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -115,6 +115,7 @@
 typedef struct xc_interface_core xc_interface;
 typedef struct xc_interface_core xc_evtchn;
 typedef struct xc_interface_core xc_gnttab;
+typedef struct xc_interface_core xc_gntshr;
 typedef enum xc_error_code xc_error_code;
 
 
@@ -1400,6 +1401,53 @@ grant_entry_v1_t *xc_gnttab_map_table_v1(xc_interface 
*xch, int domid, int *gnt_
 grant_entry_v2_t *xc_gnttab_map_table_v2(xc_interface *xch, int domid, int 
*gnt_num);
 /* Sometimes these don't set errno [fixme], and sometimes they don't log. */
 
+/*
+ * Return an fd onto the grant sharing driver.  Logs errors.
+ */
+xc_gntshr *xc_gntshr_open(xentoollog_logger *logger,
+                         unsigned open_flags);
+
+/*
+ * Close a handle previously allocated with xc_gntshr_open().
+ * Never logs errors.
+ */
+int xc_gntshr_close(xc_gntshr *xcg);
+
+/*
+ * Creates and shares pages with another domain.
+ * 
+ * @parm xcg a handle to an open grant sharing instance
+ * @parm domid the domain to share memory with
+ * @parm count the number of pages to share
+ * @parm refs the grant references of the pages (output)
+ * @parm writable true if the other domain can write to the pages
+ * @return local mapping of the pages
+ */
+void *xc_gntshr_share_pages(xc_gntshr *xcg, uint32_t domid,
+                            int count, uint32_t *refs, int writable);
+
+/*
+ * Creates and shares a page with another domain, with unmap notification.
+ * 
+ * @parm xcg a handle to an open grant sharing instance
+ * @parm domid the domain to share memory with
+ * @parm refs the grant reference of the pages (output)
+ * @parm writable true if the other domain can write to the page
+ * @parm notify_offset The byte offset in the page to use for unmap
+ *                     notification; -1 for none.
+ * @parm notify_port The event channel port to use for unmap notify, or -1
+ * @return local mapping of the page
+ */
+void *xc_gntshr_share_page_notify(xc_gntshr *xcg, uint32_t domid,
+                                  uint32_t *ref, int writable,
+                                  uint32_t notify_offset,
+                                  evtchn_port_t notify_port);
+/*
+ * Unmaps the @count pages starting at @start_address, which were mapped by a
+ * call to xc_gntshr_share_*. Never logs.
+ */
+int xc_gntshr_munmap(xc_gntshr *xcg, void *start_address, uint32_t count);
+
 int xc_physdev_map_pirq(xc_interface *xch,
                         int domid,
                         int index,
diff --git a/tools/libxc/xenctrlosdep.h b/tools/libxc/xenctrlosdep.h
index 01969c5..e1c1ba5 100644
--- a/tools/libxc/xenctrlosdep.h
+++ b/tools/libxc/xenctrlosdep.h
@@ -54,6 +54,7 @@ enum xc_osdep_type {
     XC_OSDEP_PRIVCMD,
     XC_OSDEP_EVTCHN,
     XC_OSDEP_GNTTAB,
+    XC_OSDEP_GNTSHR,
 };
 
 /* Opaque handle internal to the backend */
@@ -129,6 +130,18 @@ struct xc_osdep_ops
                           uint32_t count);
             int (*set_max_grants)(xc_gnttab *xcg, xc_osdep_handle h, uint32_t 
count);
         } gnttab;
+        struct {
+            void *(*share_pages)(xc_gntshr *xcg, xc_osdep_handle h,
+                                 uint32_t domid, int count,
+                                 uint32_t *refs, int writable);
+            void *(*share_page_notify)(xc_gntshr *xcg, xc_osdep_handle h,
+                                       uint32_t domid,
+                                       uint32_t *ref, int writable,
+                                       uint32_t notify_offset,
+                                       evtchn_port_t notify_port);
+            int (*munmap)(xc_gntshr *xcg, xc_osdep_handle h,
+                          void *start_address, uint32_t count);
+        } gntshr;
     } u;
 };
 typedef struct xc_osdep_ops xc_osdep_ops;
-- 
1.7.6


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel