@@ -147,4 +147,25 @@ struct ioctl_gntdev_unmap_notify {
/* Send an interrupt on the indicated event channel */
#define UNMAP_NOTIFY_SEND_EVENT 0x2
+struct ioctl_gntdev_grant_copy_segment {
+ union {
+ void *virt;
+ struct {
+ uint32_t ref;
+ uint16_t offset;
+ uint16_t domid;
+ } foreign;
+ } source, dest;
+ uint16_t len;
+ uint16_t flags;
+ int16_t status;
+};
+
+#define IOCTL_GNTDEV_GRANT_COPY \
+_IOC(_IOC_NONE, 'G', 8, sizeof(struct ioctl_gntdev_grant_copy))
+struct ioctl_gntdev_grant_copy {
+ unsigned int count;
+ struct ioctl_gntdev_grant_copy_segment *segments;
+};
+
#endif /* __LINUX_PUBLIC_GNTDEV_H__ */
@@ -113,6 +113,18 @@ int xengnttab_unmap(xengnttab_handle *xgt, void *start_address, uint32_t count)
return osdep_gnttab_unmap(xgt, start_address, count);
}
+int xengnttab_copy_grant(xengnttab_handle *xgt,
+ uint32_t count,
+ uint16_t *domids,
+ uint32_t *refs,
+ void **bufs,
+ uint32_t *offset,
+ uint32_t *len,
+ int type)
+{
+ return osdep_gnttab_grant_copy(xgt, count, domids, refs, bufs, offset, len,
+ type, -1, -1);
+}
/*
* Local variables:
* mode: C
@@ -258,6 +258,24 @@ int xengnttab_unmap(xengnttab_handle *xgt, void *start_address, uint32_t count);
int xengnttab_set_max_grants(xengnttab_handle *xgt,
uint32_t nr_grants);
+/**
+ * Copy memory from or to the domains defined in domids array.
+ * When @type is different then zero data is copied from grant pages addressed
+ * by @refs to @bufs, and contrarily for @type equal zero.
+ *
+ * @offset is the offset on the page
+ * @len is the amount of data to copy
+ * @offset[i] + @len[i] should not exceed XEN_PAGE_SIZE
+ */
+int xengnttab_copy_grant(xengnttab_handle *xgt,
+ uint32_t count,
+ uint16_t *domids,
+ uint32_t *refs,
+ void **bufs,
+ uint32_t *offset,
+ uint32_t *len,
+ int type);
+
/*
* Grant Sharing Interface (allocating and granting pages to others)
*/
@@ -12,6 +12,8 @@ VERS_1.0 {
xengnttab_unmap;
+ xengnttab_copy_grant;
+
xengntshr_open;
xengntshr_close;
@@ -235,6 +235,78 @@ int osdep_gnttab_unmap(xengnttab_handle *xgt,
return 0;
}
+int osdep_gnttab_grant_copy(xengnttab_handle *xgt,
+ uint32_t count,
+ uint16_t *domids, uint32_t *refs, void **bufs,
+ uint32_t *offset, uint32_t *len, int type,
+ uint32_t notify_offset, evtchn_port_t notify_port)
+{
+ int fd = xgt->fd;
+ struct ioctl_gntdev_grant_copy *copy = NULL;
+ struct ioctl_gntdev_grant_copy_segment *seg = NULL;
+ int i, r = 0;
+
+ copy = malloc(sizeof(struct ioctl_gntdev_grant_copy));
+ if(!copy) {
+ r = -1; goto out;
+ }
+
+ seg = calloc(count, sizeof(struct ioctl_gntdev_grant_copy_segment));
+ if(!seg) {
+ r = -1; goto out;
+ }
+
+ copy->segments = seg;
+ copy->count = count;
+
+ for (i = 0; i < count; i++)
+ {
+ seg[i].len = len[i];
+ seg[i].status = 0;
+
+ if(type)
+ {
+ seg[i].flags = GNTCOPY_source_gref;
+
+ seg[i].source.foreign.domid = domids[i];
+ seg[i].source.foreign.ref = refs[i];
+ seg[i].source.foreign.offset = offset[i];
+ seg[i].dest.virt = bufs[i];
+ }
+ else
+ {
+ seg[i].flags = GNTCOPY_dest_gref;
+
+ seg[i].dest.foreign.domid = domids[i];
+ seg[i].dest.foreign.ref = refs[i];
+ seg[i].dest.foreign.offset = offset[i];
+ seg[i].source.virt = bufs[i];
+ }
+ }
+
+ if (ioctl(fd, IOCTL_GNTDEV_GRANT_COPY, copy)) {
+ GTERROR(xgt->logger, "ioctl GRANT COPY failed %d ", errno);
+ r = -1; goto out;
+ }
+
+ for (i = 0; i < count; i++) {
+ if(seg[i].status != GNTST_okay) {
+ GTERROR(xgt->logger, "GRANT COPY failed for segment %d, "
+ "with status %d\n", i, seg[i].status);
+ }
+ }
+
+ r = 0;
+out:
+ if(seg)
+ free(seg);
+
+ if(copy)
+ free(copy);
+
+ return r;
+}
+
int osdep_gntshr_open(xengntshr_handle *xgs)
{
int fd = open(DEVXEN "gntalloc", O_RDWR);
@@ -106,6 +106,14 @@ int osdep_gnttab_set_max_grants(xengnttab_handle *xgt, uint32_t count)
return ret;
}
+int osdep_gnttab_grant_copy(xengnttab_handle *xgt,
+ uint32_t count,
+ uint16_t *domids, uint32_t *refs, void **bufs,
+ uint32_t *mem, uint32_t *len, int type,
+ uint32_t notify_offset, evtchn_port_t notify_port)
+{
+ return -1;
+}
/*
* Local variables:
* mode: C
@@ -23,6 +23,12 @@ void *osdep_gnttab_grant_map(xengnttab_handle *xgt,
int osdep_gnttab_unmap(xengnttab_handle *xgt,
void *start_address,
uint32_t count);
+int osdep_gnttab_grant_copy(xengnttab_handle *xgt,
+ uint32_t count,
+ uint16_t *domids, uint32_t *refs, void **bufs,
+ uint32_t *offset, uint32_t *len, int type,
+ uint32_t notify_offset, evtchn_port_t notify_port);
+
int osdep_gntshr_open(xengntshr_handle *xgs);
int osdep_gntshr_close(xengntshr_handle *xgs);
@@ -104,6 +104,14 @@ int xc_gnttab_munmap(xc_gnttab *xcg,
uint32_t count);
int xc_gnttab_set_max_grants(xc_gnttab *xcg,
uint32_t count);
+int xc_gnttab_copy_grant(xc_gnttab *xcg,
+ uint32_t count,
+ uint16_t *domids,
+ uint32_t *refs,
+ void **bufs,
+ uint32_t *mem,
+ uint32_t *len,
+ int type);
typedef struct xengntdev_handle xc_gntshr;
@@ -69,6 +69,18 @@ int xc_gnttab_set_max_grants(xc_gnttab *xcg,
return xengnttab_set_max_grants(xcg, count);
}
+int xc_gnttab_copy_grant(xc_gnttab *xcg,
+ uint32_t count,
+ uint16_t *domids,
+ uint32_t *refs,
+ void **bufs,
+ uint32_t *mem,
+ uint32_t *len,
+ int type)
+{
+ return xengnttab_copy_grant(xcg, count, domids, refs, bufs, mem, len, type);
+}
+
xc_gntshr *xc_gntshr_open(xentoollog_logger *logger,
unsigned open_flags)
{