diff options
author | Daniel De Graaf <dgdegra@tycho.nsa.gov> | 2011-10-06 19:38:01 +0100 |
---|---|---|
committer | Daniel De Graaf <dgdegra@tycho.nsa.gov> | 2011-10-06 19:38:01 +0100 |
commit | 399a74471de9f7525e84441c59aa9601133ba828 (patch) | |
tree | b62aa5d71814c09909c358c424ddb861c8f2db8e /tools/libxc/xc_linux_osdep.c | |
parent | 1f5552006de96f879ea0bcf342dcf4d9b3b06354 (diff) | |
download | xen-399a74471de9f7525e84441c59aa9601133ba828.tar.gz xen-399a74471de9f7525e84441c59aa9601133ba828.tar.bz2 xen-399a74471de9f7525e84441c59aa9601133ba828.zip |
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@tycho.nsa.gov>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
Diffstat (limited to 'tools/libxc/xc_linux_osdep.c')
-rw-r--r-- | tools/libxc/xc_linux_osdep.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c index f760421f9c..04059b8126 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" @@ -656,6 +657,105 @@ 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, + uint32_t notify_offset, + evtchn_port_t notify_port) +{ + struct ioctl_gntalloc_alloc_gref *gref_info = NULL; + struct ioctl_gntalloc_unmap_notify notify; + struct ioctl_gntalloc_dealloc_gref gref_drop; + int fd = (int)h; + 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(fd, 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, fd, gref_info->index); + + if (area == MAP_FAILED) { + area = NULL; + PERROR("linux_gntshr_share_pages: mmap failed"); + goto out_remove_fdmap; + } + + 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) + err = ioctl(fd, IOCTL_GNTALLOC_SET_UNMAP_NOTIFY, ¬ify); + if (err) { + PERROR("linux_gntshr_share_page_notify: ioctl SET_UNMAP_NOTIFY failed"); + munmap(area, count * XC_PAGE_SIZE); + area = NULL; + } + + memcpy(refs, gref_info->gref_ids, count * sizeof(uint32_t)); + + out_remove_fdmap: + /* Removing the mapping from the file descriptor does not cause the pages to + * be deallocated until the mapping is removed. + */ + gref_drop.index = gref_info->index; + gref_drop.count = count; + ioctl(fd, IOCTL_GNTALLOC_DEALLOC_GREF, &gref_drop); + out: + free(gref_info); + 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, + .munmap = &linux_gntshr_munmap, + }, +}; + + static struct xc_osdep_ops *linux_osdep_init(xc_interface *xch, enum xc_osdep_type type) { switch ( type ) @@ -666,6 +766,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; } |