diff mbox

[RESEND,1/4] libs, gnttab, libxc: Interface for grant copy operation

Message ID 1464669898-28495-2-git-send-email-paulinaszubarczyk@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paulina Szubarczyk May 31, 2016, 4:44 a.m. UTC
Implentation of interface to grant copy operation called through
libxc. An ioctl(gntdev, IOCTL_GNTDEV_GRANT_COPY, ..) system call is
invoked for linux. In the mini-os the operation is yet not
implemented.

* In the file "tools/include/xen-sys/Linux/gntdev.h" added
  - 'struct ioctl_gntdev_grant_copy_segment'
    The structure is analogous to 'struct gntdev_grant_copy_segment'
    defined in linux code include/uapi/xen/gntdev.h. Typdefs are
    replaced by they original types:
      typedef uint16_t domid_t;
      typedef uint32_t grant_ref_t;
    That leads to defining domids array with type uint16_t in libs,
    differently then in other functions concerning grant table
    operations in that library.

` - macro #define IOCTL_GNTDEV_GRANT_COPY

  - 'struct ioctl_gntdev_grant_copy'
    taken from linux code as higher. Structure aggregating
    'struct gntdev_grant_copy_segment'

* In the file libs/gnttab/linux.c
  - function 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)

    It is a function used to perform grant copy opertion. It allocats
    'ioctl_gntdev_grant_copy' and 'ioctl_gntdev_grant_copy_segment'.
    Segments are filled from the passed values.

    When @type is different then zero the source to copy from are guest
    domain grant pages addressed by @refs and the destination is local
    memory accessed from @bufs, the operation flag is then set to
    'GNTCOPY_source_gref', 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
        - the condition is checked in gntdev device.

    Notification is yet not implemented.
---
 tools/include/xen-sys/Linux/gntdev.h  | 21 ++++++++++
 tools/libs/gnttab/gnttab_core.c       | 12 ++++++
 tools/libs/gnttab/include/xengnttab.h | 18 +++++++++
 tools/libs/gnttab/libxengnttab.map    |  2 +
 tools/libs/gnttab/linux.c             | 72 +++++++++++++++++++++++++++++++++++
 tools/libs/gnttab/minios.c            |  8 ++++
 tools/libs/gnttab/private.h           |  6 +++
 tools/libxc/include/xenctrl_compat.h  |  8 ++++
 tools/libxc/xc_gnttab_compat.c        | 12 ++++++
 9 files changed, 159 insertions(+)

Comments

David Vrabel May 31, 2016, 9:25 a.m. UTC | #1
On 31/05/2016 05:44, Paulina Szubarczyk wrote:
> Implentation of interface to grant copy operation called through
> libxc. An ioctl(gntdev, IOCTL_GNTDEV_GRANT_COPY, ..) system call is
> invoked for linux. In the mini-os the operation is yet not
> implemented.
> 
> * In the file "tools/include/xen-sys/Linux/gntdev.h" added
>   - 'struct ioctl_gntdev_grant_copy_segment'
>     The structure is analogous to 'struct gntdev_grant_copy_segment'
>     defined in linux code include/uapi/xen/gntdev.h. Typdefs are
>     replaced by they original types:
>       typedef uint16_t domid_t;
>       typedef uint32_t grant_ref_t;
>     That leads to defining domids array with type uint16_t in libs,
>     differently then in other functions concerning grant table
>     operations in that library.
> 
> ` - macro #define IOCTL_GNTDEV_GRANT_COPY
> 
>   - 'struct ioctl_gntdev_grant_copy'
>     taken from linux code as higher. Structure aggregating
>     'struct gntdev_grant_copy_segment'
> 
> * In the file libs/gnttab/linux.c
>   - function 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)
> 
>     It is a function used to perform grant copy opertion. It allocats
>     'ioctl_gntdev_grant_copy' and 'ioctl_gntdev_grant_copy_segment'.
>     Segments are filled from the passed values.
> 
>     When @type is different then zero the source to copy from are guest
>     domain grant pages addressed by @refs and the destination is local
>     memory accessed from @bufs, the operation flag is then set to
>     'GNTCOPY_source_gref', 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
>         - the condition is checked in gntdev device.
> 
>     Notification is yet not implemented.

I'm not sure what you mean by "notifcation" here.

> index caf6fb4..0ca07c9 100644
> --- a/tools/include/xen-sys/Linux/gntdev.h
> +++ b/tools/include/xen-sys/Linux/gntdev.h
> @@ -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__ */
> diff --git a/tools/libs/gnttab/gnttab_core.c b/tools/libs/gnttab/gnttab_core.c
> index 5d0474d..1e014f8 100644
> --- a/tools/libs/gnttab/gnttab_core.c
> +++ b/tools/libs/gnttab/gnttab_core.c
> @@ -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)

This interface should match the ioctl which matches the hypercall.  In
particular the ioctl (and hypercall) allows copies to and from grant
references in the same call and returns a per-op status.

Using the same structure in libxc would also allow you to a) remove the
memory allocations; and b) avoid having to fill in a different structure.

I would suggest:

int xengnttab_copy_grant(xengnttab_handle *xgt,
	unsigned int count,
	xengnttab_copy_segment_t *segs);

With:

typedef struct ioctl_gntdev_copy_segment xengnttab_copy_segment_t;

You should put the required struct ioctl_gntdev_grant_copy on the stack
since it is small.

David
Paulina Szubarczyk June 1, 2016, 7:45 a.m. UTC | #2
On Tue, 2016-05-31 at 10:25 +0100, David Vrabel wrote:
> 
> On 31/05/2016 05:44, Paulina Szubarczyk wrote:
> > Implentation of interface to grant copy operation called through
> > libxc. An ioctl(gntdev, IOCTL_GNTDEV_GRANT_COPY, ..) system call is
> > invoked for linux. In the mini-os the operation is yet not
> > implemented.
> > 
> > * In the file "tools/include/xen-sys/Linux/gntdev.h" added
> >   - 'struct ioctl_gntdev_grant_copy_segment'
> >     The structure is analogous to 'struct gntdev_grant_copy_segment'
> >     defined in linux code include/uapi/xen/gntdev.h. Typdefs are
> >     replaced by they original types:
> >       typedef uint16_t domid_t;
> >       typedef uint32_t grant_ref_t;
> >     That leads to defining domids array with type uint16_t in libs,
> >     differently then in other functions concerning grant table
> >     operations in that library.
> > 
> > ` - macro #define IOCTL_GNTDEV_GRANT_COPY
> > 
> >   - 'struct ioctl_gntdev_grant_copy'
> >     taken from linux code as higher. Structure aggregating
> >     'struct gntdev_grant_copy_segment'
> > 
> > * In the file libs/gnttab/linux.c
> >   - function 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)
> > 
> >     It is a function used to perform grant copy opertion. It allocats
> >     'ioctl_gntdev_grant_copy' and 'ioctl_gntdev_grant_copy_segment'.
> >     Segments are filled from the passed values.
> > 
> >     When @type is different then zero the source to copy from are guest
> >     domain grant pages addressed by @refs and the destination is local
> >     memory accessed from @bufs, the operation flag is then set to
> >     'GNTCOPY_source_gref', 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
> >         - the condition is checked in gntdev device.
> > 
> >     Notification is yet not implemented.
> 
> I'm not sure what you mean by "notifcation" here.
There is notify interface for grant map operations to communicate a
failure to the peer in case of teardown if the notify_port is given
to allow it to take care of resources. I have not checked yet how is it
used.
> 
> > index caf6fb4..0ca07c9 100644
> > --- a/tools/include/xen-sys/Linux/gntdev.h
> > +++ b/tools/include/xen-sys/Linux/gntdev.h
> > @@ -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__ */
> > diff --git a/tools/libs/gnttab/gnttab_core.c b/tools/libs/gnttab/gnttab_core.c
> > index 5d0474d..1e014f8 100644
> > --- a/tools/libs/gnttab/gnttab_core.c
> > +++ b/tools/libs/gnttab/gnttab_core.c
> > @@ -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)
> 
> This interface should match the ioctl which matches the hypercall.  In
> particular the ioctl (and hypercall) allows copies to and from grant
> references in the same call and returns a per-op status.
> 
I followed the pattern of declaration for the grant map in this file
which as I believe is generic due to the use of it by both linux and
mini-os. 

The header with 'struct ioctl_gntdev_copy_segment' is linked only to the
linux part which issues the hypercall by gntdev, whereas mini-os does
not use gntdev it is not accessible at the higher level.

> Using the same structure in libxc would also allow you to a) remove the
> memory allocations; and b) avoid having to fill in a different structure.
> 
> I would suggest:
> 
> int xengnttab_copy_grant(xengnttab_handle *xgt,
> 	unsigned int count,
> 	xengnttab_copy_segment_t *segs);
> 
> With:
> 
> typedef struct ioctl_gntdev_copy_segment xengnttab_copy_segment_t;
> 
> You should put the required struct ioctl_gntdev_grant_copy on the stack
> since it is small.
> 
> David

Paulina
David Vrabel June 1, 2016, 11:22 a.m. UTC | #3
On 01/06/16 08:45, Paulina Szubarczyk wrote:
> On Tue, 2016-05-31 at 10:25 +0100, David Vrabel wrote:
>>
>> On 31/05/2016 05:44, Paulina Szubarczyk wrote:
>>>
>>>     Notification is yet not implemented.
>>
>> I'm not sure what you mean by "notifcation" here.
> There is notify interface for grant map operations to communicate a
> failure to the peer in case of teardown if the notify_port is given
> to allow it to take care of resources. I have not checked yet how is it
> used.

This is not relevant for grant copy, since there's no mapping that
persists after the grant copy call.

>>> --- a/tools/libs/gnttab/gnttab_core.c
>>> +++ b/tools/libs/gnttab/gnttab_core.c
>>> @@ -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)
>>
>> This interface should match the ioctl which matches the hypercall.  In
>> particular the ioctl (and hypercall) allows copies to and from grant
>> references in the same call and returns a per-op status.
>>
> I followed the pattern of declaration for the grant map in this file
> which as I believe is generic due to the use of it by both linux and
> mini-os.

The library needs to expose all the functionality of the grant copy
hypercall which includes having different ops in the call copying in
different directions.

> The header with 'struct ioctl_gntdev_copy_segment' is linked only to the
> linux part which issues the hypercall by gntdev, whereas mini-os does
> not use gntdev it is not accessible at the higher level.

The library should provide its own structure that happens to look like
the structure for the Linux ioctl.

The (future) minios implementation can use the same structure.

I think you will also find that the user of this API would prefer to
deal with a single array of xengnttab_copy_segment_t's instead of the 5
different arrays currently needed.

>> Using the same structure in libxc would also allow you to a) remove the
>> memory allocations; and b) avoid having to fill in a different structure.
>>
>> I would suggest:
>>
>> int xengnttab_copy_grant(xengnttab_handle *xgt,
>> 	unsigned int count,
>> 	xengnttab_copy_segment_t *segs);
>>
>> With:
>>
>> typedef struct ioctl_gntdev_copy_segment xengnttab_copy_segment_t;
>>
>> You should put the required struct ioctl_gntdev_grant_copy on the stack
>> since it is small.

David
Paulina Szubarczyk June 1, 2016, 11:42 a.m. UTC | #4
On Wed, 2016-06-01 at 12:22 +0100, David Vrabel wrote:
> On 01/06/16 08:45, Paulina Szubarczyk wrote:
> > On Tue, 2016-05-31 at 10:25 +0100, David Vrabel wrote:
> >>
> >> On 31/05/2016 05:44, Paulina Szubarczyk wrote:
> >>>
> >>>     Notification is yet not implemented.
> >>
> >> I'm not sure what you mean by "notifcation" here.
> > There is notify interface for grant map operations to communicate a
> > failure to the peer in case of teardown if the notify_port is given
> > to allow it to take care of resources. I have not checked yet how is it
> > used.
> 
> This is not relevant for grant copy, since there's no mapping that
> persists after the grant copy call.
> 
> >>> --- a/tools/libs/gnttab/gnttab_core.c
> >>> +++ b/tools/libs/gnttab/gnttab_core.c
> >>> @@ -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)
> >>
> >> This interface should match the ioctl which matches the hypercall.  In
> >> particular the ioctl (and hypercall) allows copies to and from grant
> >> references in the same call and returns a per-op status.
> >>
> > I followed the pattern of declaration for the grant map in this file
> > which as I believe is generic due to the use of it by both linux and
> > mini-os.
> 
> The library needs to expose all the functionality of the grant copy
> hypercall which includes having different ops in the call copying in
> different directions.
> 
> > The header with 'struct ioctl_gntdev_copy_segment' is linked only to the
> > linux part which issues the hypercall by gntdev, whereas mini-os does
> > not use gntdev it is not accessible at the higher level.
> 
> The library should provide its own structure that happens to look like
> the structure for the Linux ioctl.
> 
> The (future) minios implementation can use the same structure.
> 
> I think you will also find that the user of this API would prefer to
> deal with a single array of xengnttab_copy_segment_t's instead of the 5
> different arrays currently needed.

Ok, it will be changed.

> >> Using the same structure in libxc would also allow you to a) remove the
> >> memory allocations; and b) avoid having to fill in a different structure.
> >>
> >> I would suggest:
> >>
> >> int xengnttab_copy_grant(xengnttab_handle *xgt,
> >> 	unsigned int count,
> >> 	xengnttab_copy_segment_t *segs);
> >>
> >> With:
> >>
> >> typedef struct ioctl_gntdev_copy_segment xengnttab_copy_segment_t;
> >>
> >> You should put the required struct ioctl_gntdev_grant_copy on the stack
> >> since it is small.
> 
> David
> 
Paulina
Roger Pau Monne June 2, 2016, 9:37 a.m. UTC | #5
On Tue, May 31, 2016 at 06:44:55AM +0200, Paulina Szubarczyk wrote:
> Implentation of interface to grant copy operation called through
> libxc. An ioctl(gntdev, IOCTL_GNTDEV_GRANT_COPY, ..) system call is
> invoked for linux. In the mini-os the operation is yet not
> implemented.

Thanks for the patch! This (and other patches) seem to be missing a 
Signed-off-by tag. See:
 
http://wiki.xenproject.org/wiki/Submitting_Xen_Project_Patches#Signing_off_a_patch

> ---
>  tools/include/xen-sys/Linux/gntdev.h  | 21 ++++++++++
>  tools/libs/gnttab/gnttab_core.c       | 12 ++++++
>  tools/libs/gnttab/include/xengnttab.h | 18 +++++++++
>  tools/libs/gnttab/libxengnttab.map    |  2 +
>  tools/libs/gnttab/linux.c             | 72 +++++++++++++++++++++++++++++++++++
>  tools/libs/gnttab/minios.c            |  8 ++++
>  tools/libs/gnttab/private.h           |  6 +++
>  tools/libxc/include/xenctrl_compat.h  |  8 ++++
>  tools/libxc/xc_gnttab_compat.c        | 12 ++++++
>  9 files changed, 159 insertions(+)
> 
[...]
> index 7e04174..8c90227 100644
> --- a/tools/libs/gnttab/minios.c
> +++ b/tools/libs/gnttab/minios.c
> @@ -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;
> +}

You should add some dummy helpers to tools/libs/gnttab/gnttab_unimp.c or 
else you will break the build for OSes that don't have a gnttab device.

Roger.
Wei Liu June 6, 2016, 2:47 p.m. UTC | #6
On Tue, May 31, 2016 at 06:44:55AM +0200, Paulina Szubarczyk wrote:
[...]
>  /*
>   * Grant Sharing Interface (allocating and granting pages to others)
>   */
> diff --git a/tools/libs/gnttab/libxengnttab.map b/tools/libs/gnttab/libxengnttab.map
> index dc737ac..6a94102 100644
> --- a/tools/libs/gnttab/libxengnttab.map
> +++ b/tools/libs/gnttab/libxengnttab.map
> @@ -12,6 +12,8 @@ VERS_1.0 {
>  
>  		xengnttab_unmap;
>  
> +		xengnttab_copy_grant;
> +		
>  		xengntshr_open;
>  		xengntshr_close;
>  

This is not correct. We probably need to use a new version here.

I would think we need to make the version 1.1 now because we add a new
function to it.

Anyway, this is not hard to fix, don't let this block you. If you're
interested in knowing the details:

https://www.gnu.org/software/gnulib/manual/html_node/LD-Version-Scripts.html

I'm expecting you to post another version.

Wei.
diff mbox

Patch

diff --git a/tools/include/xen-sys/Linux/gntdev.h b/tools/include/xen-sys/Linux/gntdev.h
index caf6fb4..0ca07c9 100644
--- a/tools/include/xen-sys/Linux/gntdev.h
+++ b/tools/include/xen-sys/Linux/gntdev.h
@@ -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__ */
diff --git a/tools/libs/gnttab/gnttab_core.c b/tools/libs/gnttab/gnttab_core.c
index 5d0474d..1e014f8 100644
--- a/tools/libs/gnttab/gnttab_core.c
+++ b/tools/libs/gnttab/gnttab_core.c
@@ -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
diff --git a/tools/libs/gnttab/include/xengnttab.h b/tools/libs/gnttab/include/xengnttab.h
index 0431dcf..923e022 100644
--- a/tools/libs/gnttab/include/xengnttab.h
+++ b/tools/libs/gnttab/include/xengnttab.h
@@ -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)
  */
diff --git a/tools/libs/gnttab/libxengnttab.map b/tools/libs/gnttab/libxengnttab.map
index dc737ac..6a94102 100644
--- a/tools/libs/gnttab/libxengnttab.map
+++ b/tools/libs/gnttab/libxengnttab.map
@@ -12,6 +12,8 @@  VERS_1.0 {
 
 		xengnttab_unmap;
 
+		xengnttab_copy_grant;
+		
 		xengntshr_open;
 		xengntshr_close;
 
diff --git a/tools/libs/gnttab/linux.c b/tools/libs/gnttab/linux.c
index 7b0fba4..2b21a9f 100644
--- a/tools/libs/gnttab/linux.c
+++ b/tools/libs/gnttab/linux.c
@@ -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);
diff --git a/tools/libs/gnttab/minios.c b/tools/libs/gnttab/minios.c
index 7e04174..8c90227 100644
--- a/tools/libs/gnttab/minios.c
+++ b/tools/libs/gnttab/minios.c
@@ -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
diff --git a/tools/libs/gnttab/private.h b/tools/libs/gnttab/private.h
index d286c86..098de8b 100644
--- a/tools/libs/gnttab/private.h
+++ b/tools/libs/gnttab/private.h
@@ -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);
 
diff --git a/tools/libxc/include/xenctrl_compat.h b/tools/libxc/include/xenctrl_compat.h
index 93ccadb..871d48d 100644
--- a/tools/libxc/include/xenctrl_compat.h
+++ b/tools/libxc/include/xenctrl_compat.h
@@ -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;
 
diff --git a/tools/libxc/xc_gnttab_compat.c b/tools/libxc/xc_gnttab_compat.c
index 6f036d8..888cfc3 100644
--- a/tools/libxc/xc_gnttab_compat.c
+++ b/tools/libxc/xc_gnttab_compat.c
@@ -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)
 {