[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [RFC PATCH 01/60] hyper_dmabuf: initial working version of hyper_dmabuf drv



Abandoning this series as a new version was submitted for the review

"[RFC PATCH v2 0/9] hyper_dmabuf: Hyper_DMABUF driver"

On Tue, Dec 19, 2017 at 11:29:17AM -0800, Kim, Dongwon wrote:
> Upload of intial version of hyper_DMABUF driver enabling
> DMA_BUF exchange between two different VMs in virtualized
> platform based on hypervisor such as KVM or XEN.
> 
> Hyper_DMABUF drv's primary role is to import a DMA_BUF
> from originator then re-export it to another Linux VM
> so that it can be mapped and accessed by it.
> 
> The functionality of this driver highly depends on
> Hypervisor's native page sharing mechanism and inter-VM
> communication support.
> 
> This driver has two layers, one is main hyper_DMABUF
> framework for scatter-gather list management that handles
> actual import and export of DMA_BUF. Lower layer is about
> actual memory sharing and communication between two VMs,
> which is hypervisor-specific interface.
> 
> This driver is initially designed to enable DMA_BUF
> sharing across VMs in Xen environment, so currently working
> with Xen only.
> 
> This also adds Kernel configuration for hyper_DMABUF drv
> under Device Drivers->Xen driver support->hyper_dmabuf
> options.
> 
> To give some brief information about each source file,
> 
> hyper_dmabuf/hyper_dmabuf_conf.h
> : configuration info
> 
> hyper_dmabuf/hyper_dmabuf_drv.c
> : driver interface and initialization
> 
> hyper_dmabuf/hyper_dmabuf_imp.c
> : scatter-gather list generation and management. DMA_BUF
> ops for DMA_BUF reconstructed from hyper_DMABUF
> 
> hyper_dmabuf/hyper_dmabuf_ioctl.c
> : IOCTLs calls for export/import and comm channel creation
> unexport.
> 
> hyper_dmabuf/hyper_dmabuf_list.c
> : Database (linked-list) for exported and imported
> hyper_DMABUF
> 
> hyper_dmabuf/hyper_dmabuf_msg.c
> : creation and management of messages between exporter and
> importer
> 
> hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
> : comm ch management and ISRs for incoming messages.
> 
> hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c
> : Database (linked-list) for keeping information about
> existing comm channels among VMs
> 
> Signed-off-by: Dongwon Kim <dongwon.kim@xxxxxxxxx>
> Signed-off-by: Mateusz Polrola <mateuszx.potrola@xxxxxxxxx>
> ---
>  drivers/xen/Kconfig                                |   2 +
>  drivers/xen/Makefile                               |   1 +
>  drivers/xen/hyper_dmabuf/Kconfig                   |  14 +
>  drivers/xen/hyper_dmabuf/Makefile                  |  34 +
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h       |   2 +
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c        |  54 ++
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h        | 101 +++
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c        | 852 
> +++++++++++++++++++++
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h        |  31 +
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c      | 462 +++++++++++
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c       | 119 +++
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h       |  40 +
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c        | 212 +++++
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h        |  45 ++
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h      |  16 +
>  drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h     |  70 ++
>  .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c   | 328 ++++++++
>  .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h   |  62 ++
>  .../hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c  | 106 +++
>  .../hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h  |  35 +
>  20 files changed, 2586 insertions(+)
>  create mode 100644 drivers/xen/hyper_dmabuf/Kconfig
>  create mode 100644 drivers/xen/hyper_dmabuf/Makefile
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h
>  create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
>  create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
>  create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h
>  create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c
>  create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h
> 
> diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
> index d8dd546..b59b0e3 100644
> --- a/drivers/xen/Kconfig
> +++ b/drivers/xen/Kconfig
> @@ -321,4 +321,6 @@ config XEN_SYMS
>  config XEN_HAVE_VPMU
>         bool
>  
> +source "drivers/xen/hyper_dmabuf/Kconfig"
> +
>  endmenu
> diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
> index 451e833..a6e253a 100644
> --- a/drivers/xen/Makefile
> +++ b/drivers/xen/Makefile
> @@ -4,6 +4,7 @@ obj-$(CONFIG_X86)                     += fallback.o
>  obj-y        += grant-table.o features.o balloon.o manage.o preempt.o time.o
>  obj-y        += events/
>  obj-y        += xenbus/
> +obj-y        += hyper_dmabuf/
>  
>  nostackp := $(call cc-option, -fno-stack-protector)
>  CFLAGS_features.o                    := $(nostackp)
> diff --git a/drivers/xen/hyper_dmabuf/Kconfig 
> b/drivers/xen/hyper_dmabuf/Kconfig
> new file mode 100644
> index 0000000..75e1f96
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/Kconfig
> @@ -0,0 +1,14 @@
> +menu "hyper_dmabuf options"
> +
> +config HYPER_DMABUF
> +     tristate "Enables hyper dmabuf driver"
> +     default y
> +
> +config HYPER_DMABUF_XEN
> +     bool "Configure hyper_dmabuf for XEN hypervisor"
> +     default y
> +     depends on HYPER_DMABUF
> +     help
> +       Configuring hyper_dmabuf driver for XEN hypervisor
> +
> +endmenu
> diff --git a/drivers/xen/hyper_dmabuf/Makefile 
> b/drivers/xen/hyper_dmabuf/Makefile
> new file mode 100644
> index 0000000..0be7445
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/Makefile
> @@ -0,0 +1,34 @@
> +TARGET_MODULE:=hyper_dmabuf
> +
> +# If we running by kernel building system
> +ifneq ($(KERNELRELEASE),)
> +     $(TARGET_MODULE)-objs := hyper_dmabuf_drv.o \
> +                                 hyper_dmabuf_ioctl.o \
> +                                 hyper_dmabuf_list.o \
> +                              hyper_dmabuf_imp.o \
> +                              hyper_dmabuf_msg.o \
> +                              xen/hyper_dmabuf_xen_comm.o \
> +                              xen/hyper_dmabuf_xen_comm_list.o
> +
> +obj-$(CONFIG_HYPER_DMABUF) := $(TARGET_MODULE).o
> +
> +# If we are running without kernel build system
> +else
> +BUILDSYSTEM_DIR?=../../../
> +PWD:=$(shell pwd)
> +
> +all :
> +# run kernel build system to make module
> +$(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) modules
> +
> +clean:
> +# run kernel build system to cleanup in current directory
> +$(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) clean
> +
> +load:
> +     insmod ./$(TARGET_MODULE).ko
> +
> +unload:
> +     rmmod ./$(TARGET_MODULE).ko
> +
> +endif
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h
> new file mode 100644
> index 0000000..3d9b2d6
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h
> @@ -0,0 +1,2 @@
> +#define CURRENT_TARGET XEN
> +#define INTER_DOMAIN_DMABUF_SYNCHRONIZATION
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c
> new file mode 100644
> index 0000000..0698327
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c
> @@ -0,0 +1,54 @@
> +#include <linux/init.h>       /* module_init, module_exit */
> +#include <linux/module.h> /* version info, MODULE_LICENSE, MODULE_AUTHOR, 
> printk() */
> +#include "hyper_dmabuf_conf.h"
> +#include "hyper_dmabuf_list.h"
> +#include "xen/hyper_dmabuf_xen_comm_list.h"
> +
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_AUTHOR("IOTG-PED, INTEL");
> +
> +int register_device(void);
> +int unregister_device(void);
> +
> +/*===============================================================================================*/
> +static int hyper_dmabuf_drv_init(void)
> +{
> +     int ret = 0;
> +
> +     printk( KERN_NOTICE "hyper_dmabuf_starting: Initialization started" );
> +
> +     ret = register_device();
> +     if (ret < 0) {
> +             return -EINVAL;
> +     }
> +
> +     printk( KERN_NOTICE "initializing database for imported/exported 
> dmabufs\n");
> +
> +     ret = hyper_dmabuf_table_init();
> +     if (ret < 0) {
> +             return -EINVAL;
> +     }
> +
> +     ret = hyper_dmabuf_ring_table_init();
> +     if (ret < 0) {
> +             return -EINVAL;
> +     }
> +
> +     /* interrupt for comm should be registered here: */
> +     return ret;
> +}
> +
> +/*-----------------------------------------------------------------------------------------------*/
> +static void hyper_dmabuf_drv_exit(void)
> +{
> +     /* hash tables for export/import entries and ring_infos */
> +     hyper_dmabuf_table_destroy();
> +     hyper_dmabuf_ring_table_init();
> +
> +     printk( KERN_NOTICE "dma_buf-src_sink model: Exiting" );
> +     unregister_device();
> +}
> +/*===============================================================================================*/
> +
> +module_init(hyper_dmabuf_drv_init);
> +module_exit(hyper_dmabuf_drv_exit);
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
> new file mode 100644
> index 0000000..2dad9a6
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
> @@ -0,0 +1,101 @@
> +#ifndef __LINUX_PUBLIC_HYPER_DMABUF_DRV_H__
> +#define __LINUX_PUBLIC_HYPER_DMABUF_DRV_H__
> +
> +typedef int (*hyper_dmabuf_ioctl_t)(void *data);
> +
> +struct hyper_dmabuf_ioctl_desc {
> +     unsigned int cmd;
> +     int flags;
> +     hyper_dmabuf_ioctl_t func;
> +     const char *name;
> +};
> +
> +#define HYPER_DMABUF_IOCTL_DEF(ioctl, _func, _flags)         \
> +     [_IOC_NR(ioctl)] = {                            \
> +                     .cmd = ioctl,                   \
> +                     .func = _func,                  \
> +                     .flags = _flags,                \
> +                     .name = #ioctl                  \
> +     }
> +
> +#define IOCTL_HYPER_DMABUF_EXPORTER_RING_SETUP \
> +_IOC(_IOC_NONE, 'G', 0, sizeof(struct 
> ioctl_hyper_dmabuf_exporter_ring_setup))
> +struct ioctl_hyper_dmabuf_exporter_ring_setup {
> +     /* IN parameters */
> +     /* Remote domain id */
> +     uint32_t remote_domain;
> +     grant_ref_t ring_refid; /* assigned by driver, copied to userspace 
> after initialization */
> +     uint32_t port; /* assigned by driver, copied to userspace after 
> initialization */
> +};
> +
> +#define IOCTL_HYPER_DMABUF_IMPORTER_RING_SETUP \
> +_IOC(_IOC_NONE, 'G', 1, sizeof(struct 
> ioctl_hyper_dmabuf_importer_ring_setup))
> +struct ioctl_hyper_dmabuf_importer_ring_setup {
> +     /* IN parameters */
> +     /* Source domain id */
> +     uint32_t source_domain;
> +     /* Ring shared page refid */
> +     grant_ref_t ring_refid;
> +     /* Port number */
> +     uint32_t port;
> +};
> +
> +#define IOCTL_HYPER_DMABUF_EXPORT_REMOTE \
> +_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_hyper_dmabuf_export_remote))
> +struct ioctl_hyper_dmabuf_export_remote {
> +     /* IN parameters */
> +     /* DMA buf fd to be exported */
> +     uint32_t dmabuf_fd;
> +     /* Domain id to which buffer should be exported */
> +     uint32_t remote_domain;
> +     /* exported dma buf id */
> +     uint32_t hyper_dmabuf_id;
> +     uint32_t private[4];
> +};
> +
> +#define IOCTL_HYPER_DMABUF_EXPORT_FD \
> +_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_hyper_dmabuf_export_fd))
> +struct ioctl_hyper_dmabuf_export_fd {
> +     /* IN parameters */
> +     /* hyper dmabuf id to be imported */
> +     uint32_t hyper_dmabuf_id;
> +     /* flags */
> +     uint32_t flags;
> +     /* OUT parameters */
> +     /* exported dma buf fd */
> +     uint32_t fd;
> +};
> +
> +#define IOCTL_HYPER_DMABUF_DESTROY \
> +_IOC(_IOC_NONE, 'G', 4, sizeof(struct ioctl_hyper_dmabuf_destroy))
> +struct ioctl_hyper_dmabuf_destroy {
> +     /* IN parameters */
> +     /* hyper dmabuf id to be destroyed */
> +     uint32_t hyper_dmabuf_id;
> +     /* OUT parameters */
> +     /* Status of request */
> +     uint32_t status;
> +};
> +
> +#define IOCTL_HYPER_DMABUF_QUERY \
> +_IOC(_IOC_NONE, 'G', 5, sizeof(struct ioctl_hyper_dmabuf_query))
> +struct ioctl_hyper_dmabuf_query {
> +     /* in parameters */
> +     /* hyper dmabuf id to be queried */
> +     uint32_t hyper_dmabuf_id;
> +     /* item to be queried */
> +     uint32_t item;
> +     /* OUT parameters */
> +     /* Value of queried item */
> +     uint32_t info;
> +};
> +
> +#define IOCTL_HYPER_DMABUF_REMOTE_EXPORTER_RING_SETUP \
> +_IOC(_IOC_NONE, 'G', 6, sizeof(struct 
> ioctl_hyper_dmabuf_remote_exporter_ring_setup))
> +struct ioctl_hyper_dmabuf_remote_exporter_ring_setup {
> +     /* in parameters */
> +     uint32_t rdomain; /* id of remote domain where exporter's ring need to 
> be setup */
> +     uint32_t info;
> +};
> +
> +#endif //__LINUX_PUBLIC_HYPER_DMABUF_DRV_H__
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
> new file mode 100644
> index 0000000..faa5c1b
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
> @@ -0,0 +1,852 @@
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/dma-buf.h>
> +#include <xen/grant_table.h>
> +#include <asm/xen/page.h>
> +#include "hyper_dmabuf_struct.h"
> +#include "hyper_dmabuf_imp.h"
> +#include "xen/hyper_dmabuf_xen_comm.h"
> +#include "hyper_dmabuf_msg.h"
> +
> +#define REFS_PER_PAGE (PAGE_SIZE/sizeof(grant_ref_t))
> +
> +/* return total number of pages referecned by a sgt
> + * for pre-calculation of # of pages behind a given sgt
> + */
> +static int hyper_dmabuf_get_num_pgs(struct sg_table *sgt)
> +{
> +     struct scatterlist *sgl;
> +     int length, i;
> +     /* at least one page */
> +     int num_pages = 1;
> +
> +     sgl = sgt->sgl;
> +
> +     length = sgl->length - PAGE_SIZE + sgl->offset;
> +     num_pages += ((length + PAGE_SIZE - 1)/PAGE_SIZE); /* round-up */
> +
> +     for (i = 1; i < sgt->nents; i++) {
> +             sgl = sg_next(sgl);
> +             num_pages += ((sgl->length + PAGE_SIZE - 1) / PAGE_SIZE); /* 
> round-up */
> +     }
> +
> +     return num_pages;
> +}
> +
> +/* extract pages directly from struct sg_table */
> +struct hyper_dmabuf_pages_info *hyper_dmabuf_ext_pgs(struct sg_table *sgt)
> +{
> +     struct hyper_dmabuf_pages_info *pinfo;
> +     int i, j;
> +     int length;
> +     struct scatterlist *sgl;
> +
> +     pinfo = kmalloc(sizeof(*pinfo), GFP_KERNEL);
> +     if (pinfo == NULL)
> +             return NULL;
> +
> +     pinfo->pages = kmalloc(sizeof(struct page 
> *)*hyper_dmabuf_get_num_pgs(sgt), GFP_KERNEL);
> +     if (pinfo->pages == NULL)
> +             return NULL;
> +
> +     sgl = sgt->sgl;
> +
> +     pinfo->nents = 1;
> +     pinfo->frst_ofst = sgl->offset;
> +     pinfo->pages[0] = sg_page(sgl);
> +     length = sgl->length - PAGE_SIZE + sgl->offset;
> +     i=1;
> +
> +     while (length > 0) {
> +             pinfo->pages[i] = nth_page(sg_page(sgl), i);
> +             length -= PAGE_SIZE;
> +             pinfo->nents++;
> +             i++;
> +     }
> +
> +     for (j = 1; j < sgt->nents; j++) {
> +             sgl = sg_next(sgl);
> +             pinfo->pages[i++] = sg_page(sgl);
> +             length = sgl->length - PAGE_SIZE;
> +             pinfo->nents++;
> +
> +             while (length > 0) {
> +                     pinfo->pages[i] = nth_page(sg_page(sgl), i);
> +                     length -= PAGE_SIZE;
> +                     pinfo->nents++;
> +                     i++;
> +             }
> +     }
> +
> +     /*
> +      * lenght at that point will be 0 or negative,
> +      * so to calculate last page size just add it to PAGE_SIZE
> +      */
> +     pinfo->last_len = PAGE_SIZE + length;
> +
> +     return pinfo;
> +}
> +
> +/* create sg_table with given pages and other parameters */
> +struct sg_table* hyper_dmabuf_create_sgt(struct page **pages,
> +                             int frst_ofst, int last_len, int nents)
> +{
> +     struct sg_table *sgt;
> +     struct scatterlist *sgl;
> +     int i, ret;
> +
> +     sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
> +     if (sgt == NULL) {
> +             return NULL;
> +     }
> +
> +     ret = sg_alloc_table(sgt, nents, GFP_KERNEL);
> +     if (ret) {
> +             kfree(sgt);
> +             return NULL;
> +     }
> +
> +     sgl = sgt->sgl;
> +
> +     sg_set_page(sgl, pages[0], PAGE_SIZE-frst_ofst, frst_ofst);
> +
> +     for (i=1; i<nents-1; i++) {
> +             sgl = sg_next(sgl);
> +             sg_set_page(sgl, pages[i], PAGE_SIZE, 0);
> +     }
> +
> +     if (i > 1) /* more than one page */ {
> +             sgl = sg_next(sgl);
> +             sg_set_page(sgl, pages[i], last_len, 0);
> +     }
> +
> +     return sgt;
> +}
> +
> +/*
> + * Creates 2 level page directory structure for referencing shared pages.
> + * Top level page is a single page that contains up to 1024 refids that
> + * point to 2nd level pages.
> + * Each 2nd level page contains up to 1024 refids that point to shared
> + * data pages.
> + * There will always be one top level page and number of 2nd level pages
> + * depends on number of shared data pages.
> + *
> + *      Top level page                2nd level pages            Data pages
> + * +-------------------------+   ┌>+--------------------+ ┌--->+------------+
> + * |2nd level page 0 refid   |---┘ |Data page 0 refid   |-┘    |Data page 0 |
> + * |2nd level page 1 refid   |---┐ |Data page 1 refid   |-┐    +------------+
> + * |           ...           |   | |     ....           | |
> + * |2nd level page 1023 refid|-┐ | |Data page 1023 refid| └--->+------------+
> + * +-------------------------+ | | +--------------------+      |Data page 1 |
> + *                             | |                             +------------+
> + *                             | └>+--------------------+
> + *                             |   |Data page 1024 refid|
> + *                             |   |Data page 1025 refid|
> + *                             |   |       ...          |
> + *                             |   |Data page 2047 refid|
> + *                             |   +--------------------+
> + *                             |
> + *                             |        .....
> + *                             └-->+-----------------------+
> + *                                 |Data page 1047552 refid|
> + *                                 |Data page 1047553 refid|
> + *                                 |       ...             |
> + *                                 |Data page 1048575 
> refid|-->+------------------+
> + *                                 +-----------------------+   |Data page 
> 1048575 |
> + *                                                             
> +------------------+
> + *
> + * Using such 2 level structure it is possible to reference up to 4GB of
> + * shared data using single refid pointing to top level page.
> + *
> + * Returns refid of top level page.
> + */
> +grant_ref_t hyper_dmabuf_create_addressing_tables(grant_ref_t *data_refs, 
> int nents, int rdomain,
> +                                               struct 
> hyper_dmabuf_shared_pages_info *shared_pages_info)
> +{
> +     /*
> +      * Calculate number of pages needed for 2nd level addresing:
> +      */
> +     int n_2nd_level_pages = (nents/REFS_PER_PAGE + ((nents % REFS_PER_PAGE) 
> ? 1: 0));/* rounding */
> +     int i;
> +     unsigned long gref_page_start;
> +     grant_ref_t *tmp_page;
> +     grant_ref_t top_level_ref;
> +     grant_ref_t * addr_refs;
> +     addr_refs = kcalloc(sizeof(grant_ref_t), n_2nd_level_pages, GFP_KERNEL);
> +
> +     gref_page_start = __get_free_pages(GFP_KERNEL, n_2nd_level_pages);
> +     tmp_page = (grant_ref_t *)gref_page_start;
> +
> +     /* Store 2nd level pages to be freed later */
> +     shared_pages_info->addr_pages = tmp_page;
> +
> +     /*TODO: make sure that allocated memory is filled with 0*/
> +
> +     /* Share 2nd level addressing pages in readonly mode*/
> +     for (i=0; i< n_2nd_level_pages; i++) {
> +             addr_refs[i] = gnttab_grant_foreign_access(rdomain, 
> virt_to_mfn((unsigned long)tmp_page+i*PAGE_SIZE ), 1);
> +     }
> +
> +     /*
> +      * fill second level pages with data refs
> +      */
> +     for (i = 0; i < nents; i++) {
> +             tmp_page[i] = data_refs[i];
> +     }
> +
> +
> +     /* allocate top level page */
> +     gref_page_start = __get_free_pages(GFP_KERNEL, 1);
> +     tmp_page = (grant_ref_t *)gref_page_start;
> +
> +     /* Store top level page to be freed later */
> +     shared_pages_info->top_level_page = tmp_page;
> +
> +     /*
> +      * fill top level page with reference numbers of second level pages 
> refs.
> +      */
> +     for (i=0; i< n_2nd_level_pages; i++) {
> +             tmp_page[i] =  addr_refs[i];
> +     }
> +
> +     /* Share top level addressing page in readonly mode*/
> +     top_level_ref = gnttab_grant_foreign_access(rdomain, 
> virt_to_mfn((unsigned long)tmp_page), 1);
> +
> +     kfree(addr_refs);
> +
> +     return top_level_ref;
> +}
> +
> +/*
> + * Maps provided top level ref id and then return array of pages containing 
> data refs.
> + */
> +struct page** hyper_dmabuf_get_data_refs(grant_ref_t top_level_ref, int 
> domid, int nents,
> +                                      struct hyper_dmabuf_shared_pages_info 
> *shared_pages_info)
> +{
> +     struct page *top_level_page;
> +     struct page **level2_pages;
> +
> +     grant_ref_t *top_level_refs;
> +
> +     struct gnttab_map_grant_ref top_level_map_ops;
> +     struct gnttab_unmap_grant_ref top_level_unmap_ops;
> +
> +     struct gnttab_map_grant_ref *map_ops;
> +     struct gnttab_unmap_grant_ref *unmap_ops;
> +
> +     unsigned long addr;
> +     int n_level2_refs = 0;
> +     int i;
> +
> +     n_level2_refs = (nents / REFS_PER_PAGE) + ((nents % REFS_PER_PAGE) ? 1 
> : 0);
> +
> +     level2_pages = kcalloc(sizeof(struct page*), n_level2_refs, GFP_KERNEL);
> +
> +     map_ops = kcalloc(sizeof(map_ops[0]), REFS_PER_PAGE, GFP_KERNEL);
> +     unmap_ops = kcalloc(sizeof(unmap_ops[0]), REFS_PER_PAGE, GFP_KERNEL);
> +
> +     /* Map top level addressing page */
> +     if (gnttab_alloc_pages(1, &top_level_page)) {
> +             printk("Cannot allocate pages\n");
> +             return NULL;
> +     }
> +
> +     addr = (unsigned long)pfn_to_kaddr(page_to_pfn(top_level_page));
> +     gnttab_set_map_op(&top_level_map_ops, addr, GNTMAP_host_map | 
> GNTMAP_readonly, top_level_ref, domid);
> +     gnttab_set_unmap_op(&top_level_unmap_ops, addr, GNTMAP_host_map | 
> GNTMAP_readonly, -1);
> +
> +     if (gnttab_map_refs(&top_level_map_ops, NULL, &top_level_page, 1)) {
> +             printk("\nxen: dom0: HYPERVISOR map grant ref failed");
> +             return NULL;
> +     }
> +
> +     if (top_level_map_ops.status) {
> +             printk("\nxen: dom0: HYPERVISOR map grant ref failed status = 
> %d",
> +                             top_level_map_ops.status);
> +             return NULL;
> +     } else {
> +             top_level_unmap_ops.handle = top_level_map_ops.handle;
> +     }
> +
> +     /* Parse contents of top level addressing page to find how many second 
> level pages is there*/
> +     top_level_refs = pfn_to_kaddr(page_to_pfn(top_level_page));
> +
> +     /* Map all second level pages */
> +     if (gnttab_alloc_pages(n_level2_refs, level2_pages)) {
> +             printk("Cannot allocate pages\n");
> +             return NULL;
> +     }
> +
> +     for (i = 0; i < n_level2_refs; i++) {
> +             addr = (unsigned 
> long)pfn_to_kaddr(page_to_pfn(level2_pages[i]));
> +             gnttab_set_map_op(&map_ops[i], addr, GNTMAP_host_map | 
> GNTMAP_readonly, top_level_refs[i], domid);
> +             gnttab_set_unmap_op(&unmap_ops[i], addr, GNTMAP_host_map | 
> GNTMAP_readonly, -1);
> +     }
> +
> +     if (gnttab_map_refs(map_ops, NULL, level2_pages, n_level2_refs)) {
> +             printk("\nxen: dom0: HYPERVISOR map grant ref failed");
> +             return NULL;
> +     }
> +
> +     /* Checks if pages were mapped correctly and at the same time is 
> calculating total number of data refids*/
> +     for (i = 0; i < n_level2_refs; i++) {
> +             if (map_ops[i].status) {
> +                     printk("\nxen: dom0: HYPERVISOR map grant ref failed 
> status = %d",
> +                                     map_ops[i].status);
> +                     return NULL;
> +             } else {
> +                     unmap_ops[i].handle = map_ops[i].handle;
> +             }
> +     }
> +
> +     /* Unmap top level page, as it won't be needed any longer */
> +     if (gnttab_unmap_refs(&top_level_unmap_ops, NULL, &top_level_page, 1)) {
> +             printk("\xen: cannot unmap top level page\n");
> +             return NULL;
> +     }
> +
> +     gnttab_free_pages(1, &top_level_page);
> +     kfree(map_ops);
> +     shared_pages_info->unmap_ops = unmap_ops;
> +
> +     return level2_pages;
> +}
> +
> +
> +/* This collects all reference numbers for 2nd level shared pages and create 
> a table
> + * with those in 1st level shared pages then return reference numbers for 
> this top level
> + * table. */
> +grant_ref_t hyper_dmabuf_create_gref_table(struct page **pages, int rdomain, 
> int nents,
> +                                        struct 
> hyper_dmabuf_shared_pages_info *shared_pages_info)
> +{
> +     int i = 0;
> +     grant_ref_t *data_refs;
> +     grant_ref_t top_level_ref;
> +
> +     /* allocate temp array for refs of shared data pages */
> +     data_refs = kcalloc(nents, sizeof(grant_ref_t), GFP_KERNEL);
> +
> +     /* share data pages in rw mode*/
> +     for (i=0; i<nents; i++) {
> +             data_refs[i] = gnttab_grant_foreign_access(rdomain, 
> pfn_to_mfn(page_to_pfn(pages[i])), 0);
> +     }
> +
> +     /* create additional shared pages with 2 level addressing of data pages 
> */
> +     top_level_ref = hyper_dmabuf_create_addressing_tables(data_refs, nents, 
> rdomain,
> +                                                           
> shared_pages_info);
> +
> +     /* Store exported pages refid to be unshared later */
> +     shared_pages_info->data_refs = data_refs;
> +     shared_pages_info->top_level_ref = top_level_ref;
> +
> +     return top_level_ref;
> +}
> +
> +int hyper_dmabuf_cleanup_gref_table(struct hyper_dmabuf_sgt_info *sgt_info) {
> +     uint32_t i = 0;
> +     struct hyper_dmabuf_shared_pages_info *shared_pages_info = 
> &sgt_info->shared_pages_info;
> +
> +     grant_ref_t *ref = shared_pages_info->top_level_page;
> +     int n_2nd_level_pages = (sgt_info->sgt->nents/REFS_PER_PAGE + 
> ((sgt_info->sgt->nents % REFS_PER_PAGE) ? 1: 0));/* rounding */
> +
> +
> +     if (shared_pages_info->data_refs == NULL ||
> +         shared_pages_info->addr_pages ==  NULL ||
> +         shared_pages_info->top_level_page == NULL ||
> +         shared_pages_info->top_level_ref == -1) {
> +             printk("gref table for hyper_dmabuf already cleaned up\n");
> +             return 0;
> +     }
> +
> +     /* End foreign access for 2nd level addressing pages */
> +     while(ref[i] != 0 && i < n_2nd_level_pages) {
> +             if (gnttab_query_foreign_access(ref[i])) {
> +                     printk("refid not shared !!\n");
> +             }
> +             if (!gnttab_end_foreign_access_ref(ref[i], 1)) {
> +                     printk("refid still in use!!!\n");
> +             }
> +             i++;
> +     }
> +     free_pages((unsigned long)shared_pages_info->addr_pages, i);
> +
> +     /* End foreign access for top level addressing page */
> +     if (gnttab_query_foreign_access(shared_pages_info->top_level_ref)) {
> +             printk("refid not shared !!\n");
> +     }
> +     if (!gnttab_end_foreign_access_ref(shared_pages_info->top_level_ref, 
> 1)) {
> +             printk("refid still in use!!!\n");
> +     }
> +     gnttab_end_foreign_access_ref(shared_pages_info->top_level_ref, 1);
> +     free_pages((unsigned long)shared_pages_info->top_level_page, 1);
> +
> +     /* End foreign access for data pages, but do not free them */
> +     for (i = 0; i < sgt_info->sgt->nents; i++) {
> +             if 
> (gnttab_query_foreign_access(shared_pages_info->data_refs[i])) {
> +                     printk("refid not shared !!\n");
> +             }
> +             gnttab_end_foreign_access_ref(shared_pages_info->data_refs[i], 
> 0);
> +     }
> +
> +     kfree(shared_pages_info->data_refs);
> +
> +     shared_pages_info->data_refs = NULL;
> +     shared_pages_info->addr_pages = NULL;
> +     shared_pages_info->top_level_page = NULL;
> +     shared_pages_info->top_level_ref = -1;
> +
> +     return 0;
> +}
> +
> +int hyper_dmabuf_cleanup_imported_pages(struct 
> hyper_dmabuf_imported_sgt_info *sgt_info) {
> +     struct hyper_dmabuf_shared_pages_info *shared_pages_info = 
> &sgt_info->shared_pages_info;
> +
> +     if(shared_pages_info->unmap_ops == NULL || 
> shared_pages_info->data_pages == NULL) {
> +             printk("Imported pages already cleaned up or buffer was not 
> imported yet\n");
> +             return 0;
> +     }
> +
> +     if (gnttab_unmap_refs(shared_pages_info->unmap_ops, NULL, 
> shared_pages_info->data_pages, sgt_info->nents) ) {
> +             printk("Cannot unmap data pages\n");
> +             return -EINVAL;
> +     }
> +
> +     gnttab_free_pages(sgt_info->nents, shared_pages_info->data_pages);
> +     kfree(shared_pages_info->data_pages);
> +     kfree(shared_pages_info->unmap_ops);
> +     shared_pages_info->unmap_ops = NULL;
> +     shared_pages_info->data_pages = NULL;
> +
> +     return 0;
> +}
> +
> +/* map and construct sg_lists from reference numbers */
> +struct sg_table* hyper_dmabuf_map_pages(grant_ref_t top_level_gref, int 
> frst_ofst, int last_len, int nents, int sdomain,
> +                                     struct hyper_dmabuf_shared_pages_info 
> *shared_pages_info)
> +{
> +     struct sg_table *st;
> +     struct page **pages;
> +     struct gnttab_map_grant_ref *ops;
> +     struct gnttab_unmap_grant_ref *unmap_ops;
> +     unsigned long addr;
> +     grant_ref_t *refs;
> +     int i;
> +     int n_level2_refs = (nents / REFS_PER_PAGE) + ((nents % REFS_PER_PAGE) 
> ? 1 : 0);
> +
> +     /* Get data refids */
> +     struct page** refid_pages = hyper_dmabuf_get_data_refs(top_level_gref, 
> sdomain, nents,
> +                                                            
> shared_pages_info);
> +
> +     pages = kcalloc(sizeof(struct page*), nents, GFP_KERNEL);
> +     if (pages == NULL) {
> +             return NULL;
> +     }
> +
> +     /* allocate new pages that are mapped to shared pages via grant-table */
> +     if (gnttab_alloc_pages(nents, pages)) {
> +             printk("Cannot allocate pages\n");
> +             return NULL;
> +     }
> +
> +     ops = (struct gnttab_map_grant_ref *)kcalloc(nents, sizeof(struct 
> gnttab_map_grant_ref), GFP_KERNEL);
> +     unmap_ops = (struct gnttab_unmap_grant_ref *)kcalloc(nents, 
> sizeof(struct gnttab_unmap_grant_ref), GFP_KERNEL);
> +
> +     for (i=0; i<nents; i++) {
> +             addr = (unsigned long)pfn_to_kaddr(page_to_pfn(pages[i]));
> +             refs = pfn_to_kaddr(page_to_pfn(refid_pages[i / 
> REFS_PER_PAGE]));
> +             gnttab_set_map_op(&ops[i], addr, GNTMAP_host_map | 
> GNTMAP_readonly, refs[i % REFS_PER_PAGE], sdomain);
> +             gnttab_set_unmap_op(&unmap_ops[i], addr, GNTMAP_host_map | 
> GNTMAP_readonly, -1);
> +     }
> +
> +     if (gnttab_map_refs(ops, NULL, pages, nents)) {
> +             printk("\nxen: dom0: HYPERVISOR map grant ref failed\n");
> +             return NULL;
> +     }
> +
> +     for (i=0; i<nents; i++) {
> +             if (ops[i].status) {
> +                     printk("\nxen: dom0: HYPERVISOR map grant ref failed 
> status = %d\n",
> +                             ops[0].status);
> +                     return NULL;
> +             } else {
> +                     unmap_ops[i].handle = ops[i].handle;
> +             }
> +     }
> +
> +     st = hyper_dmabuf_create_sgt(pages, frst_ofst, last_len, nents);
> +
> +     if (gnttab_unmap_refs(shared_pages_info->unmap_ops, NULL, refid_pages, 
> n_level2_refs) ) {
> +             printk("Cannot unmap 2nd level refs\n");
> +             return NULL;
> +     }
> +
> +     gnttab_free_pages(n_level2_refs, refid_pages);
> +     kfree(refid_pages);
> +
> +     kfree(shared_pages_info->unmap_ops);
> +     shared_pages_info->unmap_ops = unmap_ops;
> +     shared_pages_info->data_pages = pages;
> +     kfree(ops);
> +
> +     return st;
> +}
> +
> +inline int hyper_dmabuf_sync_request_and_wait(int id, int ops)
> +{
> +     struct hyper_dmabuf_ring_rq *req;
> +     int operands[2];
> +     int ret;
> +
> +     operands[0] = id;
> +     operands[1] = ops;
> +
> +     req = kcalloc(1, sizeof(*req), GFP_KERNEL);
> +
> +     hyper_dmabuf_create_request(req, HYPER_DMABUF_OPS_TO_SOURCE, 
> &operands[0]);
> +
> +     /* send request */
> +     ret = hyper_dmabuf_send_request(id, req);
> +
> +     /* TODO: wait until it gets response.. or can we just move on? */
> +
> +     kfree(req);
> +
> +     return ret;
> +}
> +
> +static int hyper_dmabuf_ops_attach(struct dma_buf* dmabuf, struct device* 
> dev,
> +                     struct dma_buf_attachment *attach)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!attach->dmabuf->priv)
> +             return -EINVAL;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info 
> *)attach->dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_ATTACH);
> +
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +
> +     return ret;
> +}
> +
> +static void hyper_dmabuf_ops_detach(struct dma_buf* dmabuf, struct 
> dma_buf_attachment *attach)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!attach->dmabuf->priv)
> +             return;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info 
> *)attach->dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_DETACH);
> +
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +}
> +
> +static struct sg_table* hyper_dmabuf_ops_map(struct dma_buf_attachment 
> *attachment,
> +                                             enum dma_data_direction dir)
> +{
> +     struct sg_table *st;
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     struct hyper_dmabuf_pages_info *page_info;
> +     int ret;
> +
> +     if (!attachment->dmabuf->priv)
> +             return NULL;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info 
> *)attachment->dmabuf->priv;
> +
> +     /* extract pages from sgt */
> +     page_info = hyper_dmabuf_ext_pgs(sgt_info->sgt);
> +
> +     /* create a new sg_table with extracted pages */
> +     st = hyper_dmabuf_create_sgt(page_info->pages, page_info->frst_ofst,
> +                             page_info->last_len, page_info->nents);
> +     if (st == NULL)
> +             goto err_free_sg;
> +
> +        if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) {
> +                goto err_free_sg;
> +        }
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_MAP);
> +
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +
> +     return st;
> +
> +err_free_sg:
> +     sg_free_table(st);
> +     kfree(st);
> +     return NULL;
> +}
> +
> +static void hyper_dmabuf_ops_unmap(struct dma_buf_attachment *attachment,
> +                                             struct sg_table *sg,
> +                                             enum dma_data_direction dir)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!attachment->dmabuf->priv)
> +             return;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info 
> *)attachment->dmabuf->priv;
> +
> +     dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir);
> +
> +     sg_free_table(sg);
> +     kfree(sg);
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_UNMAP);
> +
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +}
> +
> +static void hyper_dmabuf_ops_release(struct dma_buf *dmabuf)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!dmabuf->priv)
> +             return;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_RELEASE);
> +
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +}
> +
> +static int hyper_dmabuf_ops_begin_cpu_access(struct dma_buf *dmabuf, enum 
> dma_data_direction dir)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!dmabuf->priv)
> +             return -EINVAL;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             
> HYPER_DMABUF_OPS_BEGIN_CPU_ACCESS);
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +
> +     return ret;
> +}
> +
> +static int hyper_dmabuf_ops_end_cpu_access(struct dma_buf *dmabuf, enum 
> dma_data_direction dir)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!dmabuf->priv)
> +             return -EINVAL;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             
> HYPER_DMABUF_OPS_END_CPU_ACCESS);
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +
> +     return 0;
> +}
> +
> +static void *hyper_dmabuf_ops_kmap_atomic(struct dma_buf *dmabuf, unsigned 
> long pgnum)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!dmabuf->priv)
> +             return NULL;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_KMAP_ATOMIC);
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +
> +     return NULL; /* for now NULL.. need to return the address of mapped 
> region */
> +}
> +
> +static void hyper_dmabuf_ops_kunmap_atomic(struct dma_buf *dmabuf, unsigned 
> long pgnum, void *vaddr)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!dmabuf->priv)
> +             return;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_KUNMAP_ATOMIC);
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +}
> +
> +static void *hyper_dmabuf_ops_kmap(struct dma_buf *dmabuf, unsigned long 
> pgnum)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!dmabuf->priv)
> +             return NULL;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_KMAP);
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +
> +     return NULL; /* for now NULL.. need to return the address of mapped 
> region */
> +}
> +
> +static void hyper_dmabuf_ops_kunmap(struct dma_buf *dmabuf, unsigned long 
> pgnum, void *vaddr)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!dmabuf->priv)
> +             return;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_KUNMAP);
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +}
> +
> +static int hyper_dmabuf_ops_mmap(struct dma_buf *dmabuf, struct 
> vm_area_struct *vma)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!dmabuf->priv)
> +             return -EINVAL;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_MMAP);
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +
> +     return ret;
> +}
> +
> +static void *hyper_dmabuf_ops_vmap(struct dma_buf *dmabuf)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!dmabuf->priv)
> +             return NULL;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_VMAP);
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +
> +     return NULL;
> +}
> +
> +static void hyper_dmabuf_ops_vunmap(struct dma_buf *dmabuf, void *vaddr)
> +{
> +     struct hyper_dmabuf_imported_sgt_info *sgt_info;
> +     int ret;
> +
> +     if (!dmabuf->priv)
> +             return;
> +
> +     sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv;
> +
> +     ret = 
> hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id),
> +                                             HYPER_DMABUF_OPS_VUNMAP);
> +     if (ret < 0) {
> +             printk("send dmabuf sync request failed\n");
> +     }
> +}
> +
> +static const struct dma_buf_ops hyper_dmabuf_ops = {
> +             .attach = hyper_dmabuf_ops_attach,
> +             .detach = hyper_dmabuf_ops_detach,
> +             .map_dma_buf = hyper_dmabuf_ops_map,
> +             .unmap_dma_buf = hyper_dmabuf_ops_unmap,
> +             .release = hyper_dmabuf_ops_release,
> +             .begin_cpu_access = (void*)hyper_dmabuf_ops_begin_cpu_access,
> +             .end_cpu_access = (void*)hyper_dmabuf_ops_end_cpu_access,
> +             .map_atomic = hyper_dmabuf_ops_kmap_atomic,
> +             .unmap_atomic = hyper_dmabuf_ops_kunmap_atomic,
> +             .map = hyper_dmabuf_ops_kmap,
> +             .unmap = hyper_dmabuf_ops_kunmap,
> +             .mmap = hyper_dmabuf_ops_mmap,
> +             .vmap = hyper_dmabuf_ops_vmap,
> +             .vunmap = hyper_dmabuf_ops_vunmap,
> +};
> +
> +/* exporting dmabuf as fd */
> +int hyper_dmabuf_export_fd(struct hyper_dmabuf_imported_sgt_info *dinfo, int 
> flags)
> +{
> +     int fd;
> +
> +     struct dma_buf* dmabuf;
> +
> +/* call hyper_dmabuf_export_dmabuf and create and bind a handle for it
> + * then release */
> +
> +     dmabuf = hyper_dmabuf_export_dma_buf(dinfo);
> +
> +     fd = dma_buf_fd(dmabuf, flags);
> +
> +     return fd;
> +}
> +
> +struct dma_buf* hyper_dmabuf_export_dma_buf(struct 
> hyper_dmabuf_imported_sgt_info *dinfo)
> +{
> +     DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
> +
> +     exp_info.ops = &hyper_dmabuf_ops;
> +     exp_info.size = dinfo->sgt->nents * PAGE_SIZE; /* multiple of 
> PAGE_SIZE, not considering offset */
> +     exp_info.flags = /* not sure about flag */0;
> +     exp_info.priv = dinfo;
> +
> +     return dma_buf_export(&exp_info);
> +};
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
> new file mode 100644
> index 0000000..003c158
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
> @@ -0,0 +1,31 @@
> +#ifndef __HYPER_DMABUF_IMP_H__
> +#define __HYPER_DMABUF_IMP_H__
> +
> +#include "hyper_dmabuf_struct.h"
> +
> +/* extract pages directly from struct sg_table */
> +struct hyper_dmabuf_pages_info *hyper_dmabuf_ext_pgs(struct sg_table *sgt);
> +
> +/* create sg_table with given pages and other parameters */
> +struct sg_table* hyper_dmabuf_create_sgt(struct page **pages,
> +                                int frst_ofst, int last_len, int nents);
> +
> +grant_ref_t hyper_dmabuf_create_gref_table(struct page **pages, int rdomain, 
> int nents,
> +                                        struct 
> hyper_dmabuf_shared_pages_info *shared_pages_info);
> +
> +int hyper_dmabuf_cleanup_gref_table(struct hyper_dmabuf_sgt_info *sgt_info);
> +
> +int hyper_dmabuf_cleanup_imported_pages(struct 
> hyper_dmabuf_imported_sgt_info *sgt_info);
> +
> +/* map first level tables that contains reference numbers for actual shared 
> pages */
> +grant_ref_t *hyper_dmabuf_map_gref_table(grant_ref_t *gref_table, int 
> n_pages_table);
> +
> +/* map and construct sg_lists from reference numbers */
> +struct sg_table* hyper_dmabuf_map_pages(grant_ref_t gref, int frst_ofst, int 
> last_len, int nents, int sdomain,
> +                                     struct hyper_dmabuf_shared_pages_info 
> *shared_pages_info);
> +
> +int hyper_dmabuf_export_fd(struct hyper_dmabuf_imported_sgt_info *dinfo, int 
> flags);
> +
> +struct dma_buf* hyper_dmabuf_export_dma_buf(struct 
> hyper_dmabuf_imported_sgt_info *dinfo);
> +
> +#endif /* __HYPER_DMABUF_IMP_H__ */
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
> new file mode 100644
> index 0000000..5e50908
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
> @@ -0,0 +1,462 @@
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/miscdevice.h>
> +#include <linux/uaccess.h>
> +#include <linux/dma-buf.h>
> +#include <linux/delay.h>
> +#include "hyper_dmabuf_struct.h"
> +#include "hyper_dmabuf_imp.h"
> +#include "hyper_dmabuf_list.h"
> +#include "hyper_dmabuf_drv.h"
> +#include "hyper_dmabuf_query.h"
> +#include "xen/hyper_dmabuf_xen_comm.h"
> +#include "hyper_dmabuf_msg.h"
> +
> +struct hyper_dmabuf_private {
> +     struct device *device;
> +} hyper_dmabuf_private;
> +
> +static uint32_t hyper_dmabuf_id_gen(void) {
> +     /* TODO: add proper implementation */
> +     static uint32_t id = 0;
> +     static int32_t domid = -1;
> +     if (domid == -1) {
> +             domid = hyper_dmabuf_get_domid();
> +     }
> +     return HYPER_DMABUF_ID_IMPORTER(domid, id++);
> +}
> +
> +static int hyper_dmabuf_exporter_ring_setup(void *data)
> +{
> +     struct ioctl_hyper_dmabuf_exporter_ring_setup *ring_attr;
> +     int ret = 0;
> +
> +     if (!data) {
> +             printk("user data is NULL\n");
> +             return -1;
> +     }
> +     ring_attr = (struct ioctl_hyper_dmabuf_exporter_ring_setup *)data;
> +
> +     ret = hyper_dmabuf_exporter_ringbuf_init(ring_attr->remote_domain,
> +                                             &ring_attr->ring_refid,
> +                                             &ring_attr->port);
> +
> +     return ret;
> +}
> +
> +static int hyper_dmabuf_importer_ring_setup(void *data)
> +{
> +     struct ioctl_hyper_dmabuf_importer_ring_setup *setup_imp_ring_attr;
> +     int ret = 0;
> +
> +     if (!data) {
> +             printk("user data is NULL\n");
> +             return -1;
> +     }
> +
> +     setup_imp_ring_attr = (struct ioctl_hyper_dmabuf_importer_ring_setup 
> *)data;
> +
> +     /* user need to provide a port number and ref # for the page used as 
> ring buffer */
> +     ret = 
> hyper_dmabuf_importer_ringbuf_init(setup_imp_ring_attr->source_domain,
> +                                              
> setup_imp_ring_attr->ring_refid,
> +                                              setup_imp_ring_attr->port);
> +
> +     return ret;
> +}
> +
> +static int hyper_dmabuf_export_remote(void *data)
> +{
> +     struct ioctl_hyper_dmabuf_export_remote *export_remote_attr;
> +     struct dma_buf *dma_buf;
> +     struct dma_buf_attachment *attachment;
> +     struct sg_table *sgt;
> +     struct hyper_dmabuf_pages_info *page_info;
> +     struct hyper_dmabuf_sgt_info *sgt_info;
> +     struct hyper_dmabuf_ring_rq *req;
> +     int operands[9];
> +     int ret = 0;
> +
> +     if (!data) {
> +             printk("user data is NULL\n");
> +             return -1;
> +     }
> +
> +     export_remote_attr = (struct ioctl_hyper_dmabuf_export_remote *)data;
> +
> +     dma_buf = dma_buf_get(export_remote_attr->dmabuf_fd);
> +     if (!dma_buf) {
> +             printk("Cannot get dma buf\n");
> +             return -1;
> +     }
> +
> +     attachment = dma_buf_attach(dma_buf, hyper_dmabuf_private.device);
> +     if (!attachment) {
> +             printk("Cannot get attachment\n");
> +             return -1;
> +     }
> +
> +     /* we check if this specific attachment was already exported
> +      * to the same domain and if yes, it returns hyper_dmabuf_id
> +      * of pre-exported sgt */
> +     ret = hyper_dmabuf_find_id(attachment, 
> export_remote_attr->remote_domain);
> +     if (ret != -1) {
> +             dma_buf_detach(dma_buf, attachment);
> +             dma_buf_put(dma_buf);
> +             export_remote_attr->hyper_dmabuf_id = ret;
> +             return 0;
> +     }
> +     /* Clear ret, as that will cause whole ioctl to return failure to 
> userspace, which is not true */
> +     ret = 0;
> +
> +     sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
> +
> +     sgt_info = kmalloc(sizeof(*sgt_info), GFP_KERNEL);
> +
> +     sgt_info->hyper_dmabuf_id = hyper_dmabuf_id_gen();
> +     /* TODO: We might need to consider using port number on event channel? 
> */
> +     sgt_info->hyper_dmabuf_rdomain = export_remote_attr->remote_domain;
> +     sgt_info->sgt = sgt;
> +     sgt_info->attachment = attachment;
> +     sgt_info->dma_buf = dma_buf;
> +
> +     page_info = hyper_dmabuf_ext_pgs(sgt);
> +     if (page_info == NULL)
> +             goto fail_export;
> +
> +     /* now register it to export list */
> +     hyper_dmabuf_register_exported(sgt_info);
> +
> +     page_info->hyper_dmabuf_rdomain = sgt_info->hyper_dmabuf_rdomain;
> +     page_info->hyper_dmabuf_id = sgt_info->hyper_dmabuf_id; /* may not be 
> needed */
> +
> +     export_remote_attr->hyper_dmabuf_id = sgt_info->hyper_dmabuf_id;
> +
> +     /* now create table of grefs for shared pages and */
> +
> +     /* now create request for importer via ring */
> +     operands[0] = page_info->hyper_dmabuf_id;
> +     operands[1] = page_info->nents;
> +     operands[2] = page_info->frst_ofst;
> +     operands[3] = page_info->last_len;
> +     operands[4] = hyper_dmabuf_create_gref_table(page_info->pages, 
> export_remote_attr->remote_domain,
> +                                             page_info->nents, 
> &sgt_info->shared_pages_info);
> +     /* driver/application specific private info, max 32 bytes */
> +     operands[5] = export_remote_attr->private[0];
> +     operands[6] = export_remote_attr->private[1];
> +     operands[7] = export_remote_attr->private[2];
> +     operands[8] = export_remote_attr->private[3];
> +
> +     req = kcalloc(1, sizeof(*req), GFP_KERNEL);
> +
> +     /* composing a message to the importer */
> +     hyper_dmabuf_create_request(req, HYPER_DMABUF_EXPORT, &operands[0]);
> +     if(hyper_dmabuf_send_request(export_remote_attr->remote_domain, req))
> +             goto fail_send_request;
> +
> +     /* free msg */
> +     kfree(req);
> +     /* free page_info */
> +     kfree(page_info);
> +
> +     return ret;
> +
> +fail_send_request:
> +     kfree(req);
> +     hyper_dmabuf_remove_exported(sgt_info->hyper_dmabuf_id);
> +
> +fail_export:
> +     dma_buf_unmap_attachment(sgt_info->attachment, sgt_info->sgt, 
> DMA_BIDIRECTIONAL);
> +     dma_buf_detach(sgt_info->dma_buf, sgt_info->attachment);
> +     dma_buf_put(sgt_info->dma_buf);
> +
> +     return -EINVAL;
> +}
> +
> +static int hyper_dmabuf_export_fd_ioctl(void *data)
> +{
> +     struct ioctl_hyper_dmabuf_export_fd *export_fd_attr;
> +     struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
> +     int ret = 0;
> +
> +     if (!data) {
> +             printk("user data is NULL\n");
> +             return -1;
> +     }
> +
> +     export_fd_attr = (struct ioctl_hyper_dmabuf_export_fd *)data;
> +
> +     /* look for dmabuf for the id */
> +     imported_sgt_info = 
> hyper_dmabuf_find_imported(export_fd_attr->hyper_dmabuf_id);
> +     if (imported_sgt_info == NULL) /* can't find sgt from the table */
> +             return -1;
> +
> +     printk("%s Found buffer gref %d  off %d last len %d nents %d domain 
> %d\n", __func__,
> +             imported_sgt_info->gref, imported_sgt_info->frst_ofst,
> +             imported_sgt_info->last_len, imported_sgt_info->nents,
> +             
> HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id));
> +
> +     imported_sgt_info->sgt = hyper_dmabuf_map_pages(imported_sgt_info->gref,
> +                                             imported_sgt_info->frst_ofst,
> +                                             imported_sgt_info->last_len,
> +                                             imported_sgt_info->nents,
> +                                             
> HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id),
> +                                             
> &imported_sgt_info->shared_pages_info);
> +
> +     if (!imported_sgt_info->sgt) {
> +             return -1;
> +     }
> +
> +     export_fd_attr->fd = hyper_dmabuf_export_fd(imported_sgt_info, 
> export_fd_attr->flags);
> +     if (export_fd_attr < 0) {
> +             ret = export_fd_attr->fd;
> +     }
> +
> +     return ret;
> +}
> +
> +/* removing dmabuf from the database and send int req to the source domain
> +* to unmap it. */
> +static int hyper_dmabuf_destroy(void *data)
> +{
> +     struct ioctl_hyper_dmabuf_destroy *destroy_attr;
> +     struct hyper_dmabuf_sgt_info *sgt_info;
> +     struct hyper_dmabuf_ring_rq *req;
> +     int ret;
> +
> +     if (!data) {
> +             printk("user data is NULL\n");
> +             return -EINVAL;
> +     }
> +
> +     destroy_attr = (struct ioctl_hyper_dmabuf_destroy *)data;
> +
> +     /* find dmabuf in export list */
> +     sgt_info = hyper_dmabuf_find_exported(destroy_attr->hyper_dmabuf_id);
> +     if (sgt_info == NULL) { /* failed to find corresponding entry in export 
> list */
> +             destroy_attr->status = -EINVAL;
> +             return -EFAULT;
> +     }
> +
> +     req = kcalloc(1, sizeof(*req), GFP_KERNEL);
> +
> +     hyper_dmabuf_create_request(req, HYPER_DMABUF_DESTROY, 
> &destroy_attr->hyper_dmabuf_id);
> +
> +     /* now send destroy request to remote domain
> +      * currently assuming there's only one importer exist */
> +     ret = hyper_dmabuf_send_request(sgt_info->hyper_dmabuf_rdomain, req);
> +     if (ret < 0) {
> +             kfree(req);
> +             return -EFAULT;
> +     }
> +
> +     /* free msg */
> +     kfree(req);
> +     destroy_attr->status = ret;
> +
> +     /* Rest of cleanup will follow when importer will free it's buffer,
> +      * current implementation assumes that there is only one importer
> +         */
> +
> +     return ret;
> +}
> +
> +static int hyper_dmabuf_query(void *data)
> +{
> +     struct ioctl_hyper_dmabuf_query *query_attr;
> +     struct hyper_dmabuf_sgt_info *sgt_info;
> +     struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
> +     int ret = 0;
> +
> +     if (!data) {
> +             printk("user data is NULL\n");
> +             return -EINVAL;
> +     }
> +
> +     query_attr = (struct ioctl_hyper_dmabuf_query *)data;
> +
> +     sgt_info = hyper_dmabuf_find_exported(query_attr->hyper_dmabuf_id);
> +     imported_sgt_info = 
> hyper_dmabuf_find_imported(query_attr->hyper_dmabuf_id);
> +
> +     /* if dmabuf can't be found in both lists, return */
> +     if (!(sgt_info && imported_sgt_info)) {
> +             printk("can't find entry anywhere\n");
> +             return -EINVAL;
> +     }
> +
> +     /* not considering the case where a dmabuf is found on both queues
> +      * in one domain */
> +     switch (query_attr->item)
> +     {
> +             case DMABUF_QUERY_TYPE_LIST:
> +                     if (sgt_info) {
> +                             query_attr->info = EXPORTED;
> +                     } else {
> +                             query_attr->info = IMPORTED;
> +                     }
> +                     break;
> +
> +             /* exporting domain of this specific dmabuf*/
> +             case DMABUF_QUERY_EXPORTER:
> +                     if (sgt_info) {
> +                             query_attr->info = 0xFFFFFFFF; /* myself */
> +                     } else {
> +                             query_attr->info = 
> (HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id));
> +                     }
> +                     break;
> +
> +             /* importing domain of this specific dmabuf */
> +             case DMABUF_QUERY_IMPORTER:
> +                     if (sgt_info) {
> +                             query_attr->info = 
> sgt_info->hyper_dmabuf_rdomain;
> +                     } else {
> +#if 0 /* TODO: a global variable, current_domain does not exist yet*/
> +                             query_attr->info = current_domain;
> +#endif
> +                     }
> +                     break;
> +
> +             /* size of dmabuf in byte */
> +             case DMABUF_QUERY_SIZE:
> +                     if (sgt_info) {
> +#if 0 /* TODO: hyper_dmabuf_buf_size is not implemented yet */
> +                             query_attr->info = 
> hyper_dmabuf_buf_size(sgt_info->sgt);
> +#endif
> +                     } else {
> +                             query_attr->info = imported_sgt_info->nents * 
> 4096 -
> +                                                imported_sgt_info->frst_ofst 
> - 4096 +
> +                                                imported_sgt_info->last_len;
> +                     }
> +                     break;
> +     }
> +
> +     return ret;
> +}
> +
> +static int hyper_dmabuf_remote_exporter_ring_setup(void *data)
> +{
> +     struct ioctl_hyper_dmabuf_remote_exporter_ring_setup 
> *remote_exporter_ring_setup;
> +     struct hyper_dmabuf_ring_rq *req;
> +
> +     remote_exporter_ring_setup = (struct 
> ioctl_hyper_dmabuf_remote_exporter_ring_setup *)data;
> +
> +     req = kcalloc(1, sizeof(*req), GFP_KERNEL);
> +     hyper_dmabuf_create_request(req, HYPER_DMABUF_EXPORTER_RING_SETUP, 
> NULL);
> +
> +     /* requesting remote domain to set-up exporter's ring */
> +     if(hyper_dmabuf_send_request(remote_exporter_ring_setup->rdomain, req) 
> < 0) {
> +             kfree(req);
> +             return -EINVAL;
> +     }
> +
> +     kfree(req);
> +     return 0;
> +}
> +
> +static const struct hyper_dmabuf_ioctl_desc hyper_dmabuf_ioctls[] = {
> +     HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_EXPORTER_RING_SETUP, 
> hyper_dmabuf_exporter_ring_setup, 0),
> +     HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_IMPORTER_RING_SETUP, 
> hyper_dmabuf_importer_ring_setup, 0),
> +     HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_EXPORT_REMOTE, 
> hyper_dmabuf_export_remote, 0),
> +     HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_EXPORT_FD, 
> hyper_dmabuf_export_fd_ioctl, 0),
> +     HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_DESTROY, 
> hyper_dmabuf_destroy, 0),
> +     HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_QUERY, hyper_dmabuf_query, 0),
> +     HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_REMOTE_EXPORTER_RING_SETUP, 
> hyper_dmabuf_remote_exporter_ring_setup, 0),
> +};
> +
> +static long hyper_dmabuf_ioctl(struct file *filp,
> +                     unsigned int cmd, unsigned long param)
> +{
> +     const struct hyper_dmabuf_ioctl_desc *ioctl = NULL;
> +     unsigned int nr = _IOC_NR(cmd);
> +     int ret = -EINVAL;
> +     hyper_dmabuf_ioctl_t func;
> +     char *kdata;
> +
> +     ioctl = &hyper_dmabuf_ioctls[nr];
> +
> +     func = ioctl->func;
> +
> +     if (unlikely(!func)) {
> +             printk("no function\n");
> +             return -EINVAL;
> +     }
> +
> +     kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
> +     if (!kdata) {
> +             printk("no memory\n");
> +             return -ENOMEM;
> +     }
> +
> +     if (copy_from_user(kdata, (void __user *)param, _IOC_SIZE(cmd)) != 0) {
> +             printk("failed to copy from user arguments\n");
> +             return -EFAULT;
> +     }
> +
> +     ret = func(kdata);
> +
> +     if (copy_to_user((void __user *)param, kdata, _IOC_SIZE(cmd)) != 0) {
> +             printk("failed to copy to user arguments\n");
> +             return -EFAULT;
> +     }
> +
> +     kfree(kdata);
> +
> +     return ret;
> +}
> +
> +struct device_info {
> +     int curr_domain;
> +};
> +
> +/*===============================================================================================*/
> +static struct file_operations hyper_dmabuf_driver_fops =
> +{
> +   .owner = THIS_MODULE,
> +   .unlocked_ioctl = hyper_dmabuf_ioctl,
> +};
> +
> +static struct miscdevice hyper_dmabuf_miscdev = {
> +     .minor = MISC_DYNAMIC_MINOR,
> +     .name = "xen/hyper_dmabuf",
> +     .fops = &hyper_dmabuf_driver_fops,
> +};
> +
> +static const char device_name[] = "hyper_dmabuf";
> +
> +/*===============================================================================================*/
> +int register_device(void)
> +{
> +     int result = 0;
> +
> +     result = misc_register(&hyper_dmabuf_miscdev);
> +
> +     if (result != 0) {
> +             printk(KERN_WARNING "hyper_dmabuf: driver can't be 
> registered\n");
> +             return result;
> +     }
> +
> +     hyper_dmabuf_private.device = hyper_dmabuf_miscdev.this_device;
> +
> +     /* TODO: Check if there is a different way to initialize dma mask 
> nicely */
> +     dma_coerce_mask_and_coherent(hyper_dmabuf_private.device, 0xFFFFFFFF);
> +
> +     /* TODO find a way to provide parameters for below function or move 
> that to ioctl */
> +/*   err = bind_interdomain_evtchn_to_irqhandler(rdomain, evtchn,
> +                             src_sink_isr, PORT_NUM, "remote_domain", &info);
> +     if (err < 0) {
> +             printk("hyper_dmabuf: can't register interrupt handlers\n");
> +             return -EFAULT;
> +     }
> +
> +     info.irq = err;
> +*/
> +     return result;
> +}
> +
> +/*-----------------------------------------------------------------------------------------------*/
> +void unregister_device(void)
> +{
> +     printk( KERN_NOTICE "hyper_dmabuf: unregister_device() is called" );
> +     misc_deregister(&hyper_dmabuf_miscdev);
> +}
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c
> new file mode 100644
> index 0000000..77a7e65
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c
> @@ -0,0 +1,119 @@
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/cdev.h>
> +#include <asm/uaccess.h>
> +#include <linux/hashtable.h>
> +#include <linux/dma-buf.h>
> +#include "hyper_dmabuf_list.h"
> +
> +DECLARE_HASHTABLE(hyper_dmabuf_hash_imported, MAX_ENTRY_IMPORTED);
> +DECLARE_HASHTABLE(hyper_dmabuf_hash_exported, MAX_ENTRY_EXPORTED);
> +
> +int hyper_dmabuf_table_init()
> +{
> +     hash_init(hyper_dmabuf_hash_imported);
> +     hash_init(hyper_dmabuf_hash_exported);
> +     return 0;
> +}
> +
> +int hyper_dmabuf_table_destroy()
> +{
> +     /* TODO: cleanup hyper_dmabuf_hash_imported and 
> hyper_dmabuf_hash_exported */
> +     return 0;
> +}
> +
> +int hyper_dmabuf_register_exported(struct hyper_dmabuf_sgt_info *info)
> +{
> +     struct hyper_dmabuf_info_entry_exported *info_entry;
> +
> +     info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL);
> +
> +     info_entry->info = info;
> +
> +     hash_add(hyper_dmabuf_hash_exported, &info_entry->node,
> +             info_entry->info->hyper_dmabuf_id);
> +
> +     return 0;
> +}
> +
> +int hyper_dmabuf_register_imported(struct hyper_dmabuf_imported_sgt_info* 
> info)
> +{
> +     struct hyper_dmabuf_info_entry_imported *info_entry;
> +
> +     info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL);
> +
> +     info_entry->info = info;
> +
> +     hash_add(hyper_dmabuf_hash_imported, &info_entry->node,
> +             info_entry->info->hyper_dmabuf_id);
> +
> +     return 0;
> +}
> +
> +struct hyper_dmabuf_sgt_info *hyper_dmabuf_find_exported(int id)
> +{
> +     struct hyper_dmabuf_info_entry_exported *info_entry;
> +     int bkt;
> +
> +     hash_for_each(hyper_dmabuf_hash_exported, bkt, info_entry, node)
> +             if(info_entry->info->hyper_dmabuf_id == id)
> +                     return info_entry->info;
> +
> +     return NULL;
> +}
> +
> +/* search for pre-exported sgt and return id of it if it exist */
> +int hyper_dmabuf_find_id(struct dma_buf_attachment *attach, int domid)
> +{
> +     struct hyper_dmabuf_info_entry_exported *info_entry;
> +     int bkt;
> +
> +     hash_for_each(hyper_dmabuf_hash_exported, bkt, info_entry, node)
> +             if(info_entry->info->attachment == attach &&
> +                     info_entry->info->hyper_dmabuf_rdomain == domid)
> +                     return info_entry->info->hyper_dmabuf_id;
> +
> +     return -1;
> +}
> +
> +struct hyper_dmabuf_imported_sgt_info *hyper_dmabuf_find_imported(int id)
> +{
> +     struct hyper_dmabuf_info_entry_imported *info_entry;
> +     int bkt;
> +
> +     hash_for_each(hyper_dmabuf_hash_imported, bkt, info_entry, node)
> +             if(info_entry->info->hyper_dmabuf_id == id)
> +                     return info_entry->info;
> +
> +     return NULL;
> +}
> +
> +int hyper_dmabuf_remove_exported(int id)
> +{
> +     struct hyper_dmabuf_info_entry_exported *info_entry;
> +     int bkt;
> +
> +     hash_for_each(hyper_dmabuf_hash_exported, bkt, info_entry, node)
> +             if(info_entry->info->hyper_dmabuf_id == id) {
> +                     hash_del(&info_entry->node);
> +                     return 0;
> +             }
> +
> +     return -1;
> +}
> +
> +int hyper_dmabuf_remove_imported(int id)
> +{
> +     struct hyper_dmabuf_info_entry_imported *info_entry;
> +     int bkt;
> +
> +     hash_for_each(hyper_dmabuf_hash_imported, bkt, info_entry, node)
> +             if(info_entry->info->hyper_dmabuf_id == id) {
> +                     hash_del(&info_entry->node);
> +                     return 0;
> +             }
> +
> +     return -1;
> +}
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h
> new file mode 100644
> index 0000000..869cd9a
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h
> @@ -0,0 +1,40 @@
> +#ifndef __HYPER_DMABUF_LIST_H__
> +#define __HYPER_DMABUF_LIST_H__
> +
> +#include "hyper_dmabuf_struct.h"
> +
> +/* number of bits to be used for exported dmabufs hash table */
> +#define MAX_ENTRY_EXPORTED 7
> +/* number of bits to be used for imported dmabufs hash table */
> +#define MAX_ENTRY_IMPORTED 7
> +
> +struct hyper_dmabuf_info_entry_exported {
> +        struct hyper_dmabuf_sgt_info *info;
> +        struct hlist_node node;
> +};
> +
> +struct hyper_dmabuf_info_entry_imported {
> +        struct hyper_dmabuf_imported_sgt_info *info;
> +        struct hlist_node node;
> +};
> +
> +int hyper_dmabuf_table_init(void);
> +
> +int hyper_dmabuf_table_destroy(void);
> +
> +int hyper_dmabuf_register_exported(struct hyper_dmabuf_sgt_info *info);
> +
> +/* search for pre-exported sgt and return id of it if it exist */
> +int hyper_dmabuf_find_id(struct dma_buf_attachment *attach, int domid);
> +
> +int hyper_dmabuf_register_imported(struct hyper_dmabuf_imported_sgt_info* 
> info);
> +
> +struct hyper_dmabuf_sgt_info *hyper_dmabuf_find_exported(int id);
> +
> +struct hyper_dmabuf_imported_sgt_info *hyper_dmabuf_find_imported(int id);
> +
> +int hyper_dmabuf_remove_exported(int id);
> +
> +int hyper_dmabuf_remove_imported(int id);
> +
> +#endif // __HYPER_DMABUF_LIST_H__
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
> new file mode 100644
> index 0000000..3237e50
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
> @@ -0,0 +1,212 @@
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/dma-buf.h>
> +#include "hyper_dmabuf_imp.h"
> +//#include "hyper_dmabuf_remote_sync.h"
> +#include "xen/hyper_dmabuf_xen_comm.h"
> +#include "hyper_dmabuf_msg.h"
> +#include "hyper_dmabuf_list.h"
> +
> +void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
> +                                     enum hyper_dmabuf_command command, int 
> *operands)
> +{
> +     int i;
> +
> +     request->request_id = hyper_dmabuf_next_req_id_export();
> +     request->status = HYPER_DMABUF_REQ_NOT_RESPONDED;
> +     request->command = command;
> +
> +     switch(command) {
> +     /* as exporter, commands to importer */
> +     case HYPER_DMABUF_EXPORT:
> +             /* exporting pages for dmabuf */
> +             /* command : HYPER_DMABUF_EXPORT,
> +              * operands0 : hyper_dmabuf_id
> +              * operands1 : number of pages to be shared
> +              * operands2 : offset of data in the first page
> +              * operands3 : length of data in the last page
> +              * operands4 : top-level reference number for shared pages
> +              * operands5~8 : Driver-specific private data (e.g. graphic 
> buffer's meta info)
> +              */
> +             for (i=0; i < 8; i++)
> +                     request->operands[i] = operands[i];
> +             break;
> +
> +     case HYPER_DMABUF_DESTROY:
> +             /* destroy sg_list for hyper_dmabuf_id on remote side */
> +             /* command : DMABUF_DESTROY,
> +              * operands0 : hyper_dmabuf_id
> +              */
> +             request->operands[0] = operands[0];
> +             break;
> +
> +     case HYPER_DMABUF_OPS_TO_REMOTE:
> +             /* notifying dmabuf map/unmap to importer (probably not needed) 
> */
> +             /* for dmabuf synchronization */
> +             break;
> +
> +     /* as importer, command to exporter */
> +     case HYPER_DMABUF_OPS_TO_SOURCE:
> +             /* notifying dmabuf map/unmap to exporter, map will make the 
> driver to do shadow mapping
> +             * or unmapping for synchronization with original exporter (e.g. 
> i915) */
> +             /* command : DMABUF_OPS_TO_SOURCE.
> +              * operands0 : hyper_dmabuf_id
> +              * operands1 : map(=1)/unmap(=2)/attach(=3)/detach(=4)
> +              */
> +             for (i=0; i<2; i++)
> +                     request->operands[i] = operands[i];
> +             break;
> +
> +     /* requesting the other side to setup another ring channel for reverse 
> direction */
> +     case HYPER_DMABUF_EXPORTER_RING_SETUP:
> +             /* command : HYPER_DMABUF_EXPORTER_RING_SETUP */
> +             /* no operands needed */
> +             break;
> +
> +     default:
> +             /* no command found */
> +             return;
> +     }
> +}
> +
> +int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_ring_rq *req)
> +{
> +     uint32_t i, ret;
> +     struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
> +     struct hyper_dmabuf_sgt_info *sgt_info;
> +
> +     /* make sure req is not NULL (may not be needed) */
> +     if (!req) {
> +             return -EINVAL;
> +     }
> +
> +     req->status = HYPER_DMABUF_REQ_PROCESSED;
> +
> +     switch (req->command) {
> +     case HYPER_DMABUF_EXPORT:
> +             /* exporting pages for dmabuf */
> +             /* command : HYPER_DMABUF_EXPORT,
> +              * operands0 : hyper_dmabuf_id
> +              * operands1 : number of pages to be shared
> +              * operands2 : offset of data in the first page
> +              * operands3 : length of data in the last page
> +              * operands4 : top-level reference number for shared pages
> +              * operands5~8 : Driver-specific private data (e.g. graphic 
> buffer's meta info)
> +              */
> +             imported_sgt_info = (struct 
> hyper_dmabuf_imported_sgt_info*)kcalloc(1, sizeof(*imported_sgt_info), 
> GFP_KERNEL);
> +             imported_sgt_info->hyper_dmabuf_id = req->operands[0];
> +             imported_sgt_info->frst_ofst = req->operands[2];
> +             imported_sgt_info->last_len = req->operands[3];
> +             imported_sgt_info->nents = req->operands[1];
> +             imported_sgt_info->gref = req->operands[4];
> +
> +             printk("DMABUF was exported\n");
> +             printk("\thyper_dmabuf_id %d\n", req->operands[0]);
> +             printk("\tnents %d\n", req->operands[1]);
> +             printk("\tfirst offset %d\n", req->operands[2]);
> +             printk("\tlast len %d\n", req->operands[3]);
> +             printk("\tgrefid %d\n", req->operands[4]);
> +
> +             for (i=0; i<4; i++)
> +                     imported_sgt_info->private[i] = req->operands[5+i];
> +
> +             hyper_dmabuf_register_imported(imported_sgt_info);
> +             break;
> +
> +     case HYPER_DMABUF_DESTROY:
> +             /* destroy sg_list for hyper_dmabuf_id on remote side */
> +             /* command : DMABUF_DESTROY,
> +              * operands0 : hyper_dmabuf_id
> +              */
> +
> +             imported_sgt_info =
> +                     hyper_dmabuf_find_imported(req->operands[0]);
> +
> +             if (imported_sgt_info) {
> +                     hyper_dmabuf_cleanup_imported_pages(imported_sgt_info);
> +
> +                     hyper_dmabuf_remove_imported(req->operands[0]);
> +
> +                     /* TODO: cleanup sgt on importer side etc */
> +             }
> +
> +             /* Notify exporter that buffer is freed and it can cleanup it */
> +             req->status = HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP;
> +             req->command = HYPER_DMABUF_DESTROY_FINISH;
> +
> +#if 0 /* function is not implemented yet */
> +
> +             ret = hyper_dmabuf_destroy_sgt(req->hyper_dmabuf_id);
> +#endif
> +             break;
> +
> +     case HYPER_DMABUF_DESTROY_FINISH:
> +             /* destroy sg_list for hyper_dmabuf_id on local side */
> +             /* command : DMABUF_DESTROY_FINISH,
> +              * operands0 : hyper_dmabuf_id
> +              */
> +
> +             /* TODO: that should be done on workqueue, when received ack 
> from all importers that buffer is no longer used */
> +             sgt_info =
> +                     hyper_dmabuf_find_exported(req->operands[0]);
> +
> +             if (sgt_info) {
> +                     hyper_dmabuf_cleanup_gref_table(sgt_info);
> +
> +                     /* unmap dmabuf */
> +                     dma_buf_unmap_attachment(sgt_info->attachment, 
> sgt_info->sgt, DMA_BIDIRECTIONAL);
> +                     dma_buf_detach(sgt_info->dma_buf, sgt_info->attachment);
> +                     dma_buf_put(sgt_info->dma_buf);
> +
> +                     /* TODO: Rest of cleanup, sgt cleanup etc */
> +             }
> +
> +             break;
> +
> +     case HYPER_DMABUF_OPS_TO_REMOTE:
> +             /* notifying dmabuf map/unmap to importer (probably not needed) 
> */
> +             /* for dmabuf synchronization */
> +             break;
> +
> +     /* as importer, command to exporter */
> +     case HYPER_DMABUF_OPS_TO_SOURCE:
> +             /* notifying dmabuf map/unmap to exporter, map will make the 
> driver to do shadow mapping
> +             * or unmapping for synchronization with original exporter (e.g. 
> i915) */
> +             /* command : DMABUF_OPS_TO_SOURCE.
> +              * operands0 : hyper_dmabuf_id
> +              * operands1 : map(=1)/unmap(=2)/attach(=3)/detach(=4)
> +              */
> +             break;
> +
> +     /* requesting the other side to setup another ring channel for reverse 
> direction */
> +     case HYPER_DMABUF_EXPORTER_RING_SETUP:
> +             /* command: HYPER_DMABUF_EXPORTER_RING_SETUP
> +              * no operands needed */
> +             ret = hyper_dmabuf_exporter_ringbuf_init(domid, 
> &req->operands[0], &req->operands[1]);
> +             if (ret < 0) {
> +                     req->status = HYPER_DMABUF_REQ_ERROR;
> +                     return -EINVAL;
> +             }
> +
> +             req->status = HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP;
> +             req->command = HYPER_DMABUF_IMPORTER_RING_SETUP;
> +             break;
> +
> +     case HYPER_DMABUF_IMPORTER_RING_SETUP:
> +             /* command: HYPER_DMABUF_IMPORTER_RING_SETUP */
> +             /* no operands needed */
> +             ret = hyper_dmabuf_importer_ringbuf_init(domid, 
> req->operands[0], req->operands[1]);
> +             if (ret < 0)
> +                     return -EINVAL;
> +
> +             break;
> +
> +     default:
> +             /* no matched command, nothing to do.. just return error */
> +             return -EINVAL;
> +     }
> +
> +     return req->command;
> +}
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
> new file mode 100644
> index 0000000..44bfb70
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
> @@ -0,0 +1,45 @@
> +#ifndef __HYPER_DMABUF_MSG_H__
> +#define __HYPER_DMABUF_MSG_H__
> +
> +enum hyper_dmabuf_command {
> +     HYPER_DMABUF_EXPORT = 0x10,
> +     HYPER_DMABUF_DESTROY,
> +     HYPER_DMABUF_DESTROY_FINISH,
> +     HYPER_DMABUF_OPS_TO_REMOTE,
> +     HYPER_DMABUF_OPS_TO_SOURCE,
> +     HYPER_DMABUF_EXPORTER_RING_SETUP, /* requesting remote domain to set up 
> exporter's ring */
> +     HYPER_DMABUF_IMPORTER_RING_SETUP, /* requesting remote domain to set up 
> importer's ring */
> +};
> +
> +enum hyper_dmabuf_ops {
> +     HYPER_DMABUF_OPS_ATTACH = 0x1000,
> +     HYPER_DMABUF_OPS_DETACH,
> +     HYPER_DMABUF_OPS_MAP,
> +     HYPER_DMABUF_OPS_UNMAP,
> +     HYPER_DMABUF_OPS_RELEASE,
> +     HYPER_DMABUF_OPS_BEGIN_CPU_ACCESS,
> +     HYPER_DMABUF_OPS_END_CPU_ACCESS,
> +     HYPER_DMABUF_OPS_KMAP_ATOMIC,
> +     HYPER_DMABUF_OPS_KUNMAP_ATOMIC,
> +     HYPER_DMABUF_OPS_KMAP,
> +     HYPER_DMABUF_OPS_KUNMAP,
> +     HYPER_DMABUF_OPS_MMAP,
> +     HYPER_DMABUF_OPS_VMAP,
> +     HYPER_DMABUF_OPS_VUNMAP,
> +};
> +
> +enum hyper_dmabuf_req_feedback {
> +     HYPER_DMABUF_REQ_PROCESSED = 0x100,
> +     HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP,
> +     HYPER_DMABUF_REQ_ERROR,
> +     HYPER_DMABUF_REQ_NOT_RESPONDED
> +};
> +
> +/* create a request packet with given command and operands */
> +void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
> +                                        enum hyper_dmabuf_command command, 
> int *operands);
> +
> +/* parse incoming request packet (or response) and take appropriate actions 
> for those */
> +int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_ring_rq *req);
> +
> +#endif // __HYPER_DMABUF_MSG_H__
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h
> new file mode 100644
> index 0000000..a577167
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h
> @@ -0,0 +1,16 @@
> +#ifndef __HYPER_DMABUF_QUERY_H__
> +#define __HYPER_DMABUF_QUERY_H__
> +
> +enum hyper_dmabuf_query {
> +     DMABUF_QUERY_TYPE_LIST = 0x10,
> +     DMABUF_QUERY_EXPORTER,
> +     DMABUF_QUERY_IMPORTER,
> +     DMABUF_QUERY_SIZE
> +};
> +
> +enum hyper_dmabuf_status {
> +     EXPORTED = 0x01,
> +     IMPORTED
> +};
> +
> +#endif /* __HYPER_DMABUF_QUERY_H__ */
> diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h 
> b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
> new file mode 100644
> index 0000000..c8a2f4d
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
> @@ -0,0 +1,70 @@
> +#ifndef __HYPER_DMABUF_STRUCT_H__
> +#define __HYPER_DMABUF_STRUCT_H__
> +
> +#include <xen/interface/grant_table.h>
> +
> +/* Importer combine source domain id with given hyper_dmabuf_id
> + * to make it unique in case there are multiple exporters */
> +
> +#define HYPER_DMABUF_ID_IMPORTER(sdomain, id) \
> +     ((((sdomain) & 0xFF) << 24) | ((id) & 0xFFFFFF))
> +
> +#define HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(id) \
> +     (((id) >> 24) & 0xFF)
> +
> +/* each grant_ref_t is 4 bytes, so total 4096 grant_ref_t can be
> + * in this block meaning we can share 4KB*4096 = 16MB of buffer
> + * (needs to be increased for large buffer use-cases such as 4K
> + * frame buffer) */
> +#define MAX_ALLOWED_NUM_PAGES_FOR_GREF_NUM_ARRAYS 4
> +
> +struct hyper_dmabuf_shared_pages_info {
> +     grant_ref_t *data_refs; /* table with shared buffer pages refid */
> +     grant_ref_t *addr_pages; /* pages of 2nd level addressing */
> +     grant_ref_t *top_level_page; /* page of top level addressing, it 
> contains refids of 2nd level pages */
> +     grant_ref_t top_level_ref; /* top level refid */
> +     struct gnttab_unmap_grant_ref* unmap_ops; /* unmap ops for mapped pages 
> */
> +     struct page **data_pages; /* data pages to be unmapped */
> +};
> +
> +/* Exporter builds pages_info before sharing pages */
> +struct hyper_dmabuf_pages_info {
> +        int hyper_dmabuf_id; /* unique id to reference dmabuf in source 
> domain */
> +        int hyper_dmabuf_rdomain; /* currenting considering just one remote 
> domain access it */
> +        int frst_ofst; /* offset of data in the first page */
> +        int last_len; /* length of data in the last page */
> +        int nents; /* # of pages */
> +        struct page **pages; /* pages that contains reference numbers of 
> shared pages*/
> +};
> +
> +/* Both importer and exporter use this structure to point to sg lists
> + *
> + * Exporter stores references to sgt in a hash table
> + * Exporter keeps these references for synchronization and tracking purposes
> + *
> + * Importer use this structure exporting to other drivers in the same domain 
> */
> +struct hyper_dmabuf_sgt_info {
> +        int hyper_dmabuf_id; /* unique id to reference dmabuf in remote 
> domain */
> +     int hyper_dmabuf_rdomain; /* domain importing this sgt */
> +        struct sg_table *sgt; /* pointer to sgt */
> +     struct dma_buf *dma_buf; /* needed to store this for freeing it later */
> +     struct dma_buf_attachment *attachment; /* needed to store this for 
> freeing this later */
> +     struct hyper_dmabuf_shared_pages_info shared_pages_info;
> +     int private[4]; /* device specific info (e.g. image's meta info?) */
> +};
> +
> +/* Importer store references (before mapping) on shared pages
> + * Importer store these references in the table and map it in
> + * its own memory map once userspace asks for reference for the buffer */
> +struct hyper_dmabuf_imported_sgt_info {
> +     int hyper_dmabuf_id; /* unique id to reference dmabuf 
> (HYPER_DMABUF_ID_IMPORTER(source domain id, exporter's hyper_dmabuf_id */
> +     int frst_ofst;  /* start offset in shared page #1 */
> +     int last_len;   /* length of data in the last shared page */
> +     int nents;      /* number of pages to be shared */
> +     grant_ref_t gref; /* reference number of top level addressing page of 
> shared pages */
> +     struct sg_table *sgt; /* sgt pointer after importing buffer */
> +     struct hyper_dmabuf_shared_pages_info shared_pages_info;
> +     int private[4]; /* device specific info (e.g. image's meta info?) */
> +};
> +
> +#endif /* __HYPER_DMABUF_STRUCT_H__ */
> diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c 
> b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
> new file mode 100644
> index 0000000..22f2ef0
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
> @@ -0,0 +1,328 @@
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/workqueue.h>
> +#include <xen/grant_table.h>
> +#include <xen/events.h>
> +#include <xen/xenbus.h>
> +#include <asm/xen/page.h>
> +#include "hyper_dmabuf_xen_comm.h"
> +#include "hyper_dmabuf_xen_comm_list.h"
> +#include "../hyper_dmabuf_imp.h"
> +#include "../hyper_dmabuf_list.h"
> +#include "../hyper_dmabuf_msg.h"
> +
> +static int export_req_id = 0;
> +static int import_req_id = 0;
> +
> +int32_t hyper_dmabuf_get_domid(void)
> +{
> +     struct xenbus_transaction xbt;
> +     int32_t domid;
> +
> +        xenbus_transaction_start(&xbt);
> +
> +        if (!xenbus_scanf(xbt, "domid","", "%d", &domid)) {
> +             domid = -1;
> +        }
> +        xenbus_transaction_end(xbt, 0);
> +
> +     return domid;
> +}
> +
> +int hyper_dmabuf_next_req_id_export(void)
> +{
> +        export_req_id++;
> +        return export_req_id;
> +}
> +
> +int hyper_dmabuf_next_req_id_import(void)
> +{
> +        import_req_id++;
> +        return import_req_id;
> +}
> +
> +/* For now cache latast rings as global variables TODO: keep them in list*/
> +static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, void *dev_id);
> +static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *dev_id);
> +
> +/* exporter needs to generated info for page sharing */
> +int hyper_dmabuf_exporter_ringbuf_init(int rdomain, grant_ref_t *refid, int 
> *port)
> +{
> +     struct hyper_dmabuf_ring_info_export *ring_info;
> +     struct hyper_dmabuf_sring *sring;
> +     struct evtchn_alloc_unbound alloc_unbound;
> +     struct evtchn_close close;
> +
> +     void *shared_ring;
> +     int ret;
> +
> +     ring_info = (struct hyper_dmabuf_ring_info_export*)
> +                             kmalloc(sizeof(*ring_info), GFP_KERNEL);
> +
> +     /* from exporter to importer */
> +     shared_ring = (void *)__get_free_pages(GFP_KERNEL, 1);
> +     if (shared_ring == 0) {
> +             return -EINVAL;
> +     }
> +
> +     sring = (struct hyper_dmabuf_sring *) shared_ring;
> +
> +     SHARED_RING_INIT(sring);
> +
> +     FRONT_RING_INIT(&(ring_info->ring_front), sring, PAGE_SIZE);
> +
> +     ring_info->gref_ring = gnttab_grant_foreign_access(rdomain,
> +                                                     
> virt_to_mfn(shared_ring), 0);
> +     if (ring_info->gref_ring < 0) {
> +             return -EINVAL; /* fail to get gref */
> +     }
> +
> +     alloc_unbound.dom = DOMID_SELF;
> +     alloc_unbound.remote_dom = rdomain;
> +     ret = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, 
> &alloc_unbound);
> +     if (ret != 0) {
> +             printk("Cannot allocate event channel\n");
> +             return -EINVAL;
> +     }
> +
> +     /* setting up interrupt */
> +     ret = bind_evtchn_to_irqhandler(alloc_unbound.port,
> +                                     hyper_dmabuf_front_ring_isr, 0,
> +                                     NULL, (void*) ring_info);
> +
> +     if (ret < 0) {
> +             printk("Failed to setup event channel\n");
> +             close.port = alloc_unbound.port;
> +             HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
> +             gnttab_end_foreign_access(ring_info->gref_ring, 0, 
> virt_to_mfn(shared_ring));
> +             return -EINVAL;
> +     }
> +
> +     ring_info->rdomain = rdomain;
> +     ring_info->irq = ret;
> +     ring_info->port = alloc_unbound.port;
> +
> +     /* store refid and port numbers for userspace's use */
> +     *refid = ring_info->gref_ring;
> +     *port = ring_info->port;
> +
> +     printk("%s: allocated eventchannel gref %d  port: %d  irq: %d\n", 
> __func__,
> +             ring_info->gref_ring,
> +             ring_info->port,
> +             ring_info->irq);
> +
> +     /* register ring info */
> +     ret = hyper_dmabuf_register_exporter_ring(ring_info);
> +
> +     return ret;
> +}
> +
> +/* importer needs to know about shared page and port numbers for ring buffer 
> and event channel */
> +int hyper_dmabuf_importer_ringbuf_init(int sdomain, grant_ref_t gref, int 
> port)
> +{
> +     struct hyper_dmabuf_ring_info_import *ring_info;
> +     struct hyper_dmabuf_sring *sring;
> +
> +     struct page *shared_ring;
> +
> +     struct gnttab_map_grant_ref *ops;
> +     struct gnttab_unmap_grant_ref *unmap_ops;
> +     int ret;
> +
> +     ring_info = (struct hyper_dmabuf_ring_info_import *)
> +                     kmalloc(sizeof(*ring_info), GFP_KERNEL);
> +
> +     ring_info->sdomain = sdomain;
> +     ring_info->evtchn = port;
> +
> +     ops = (struct gnttab_map_grant_ref*)kmalloc(sizeof(*ops), GFP_KERNEL);
> +     unmap_ops = (struct gnttab_unmap_grant_ref*)kmalloc(sizeof(*unmap_ops), 
> GFP_KERNEL);
> +
> +     if (gnttab_alloc_pages(1, &shared_ring)) {
> +             return -EINVAL;
> +     }
> +
> +     gnttab_set_map_op(&ops[0], (unsigned 
> long)pfn_to_kaddr(page_to_pfn(shared_ring)),
> +                     GNTMAP_host_map, gref, sdomain);
> +
> +     ret = gnttab_map_refs(ops, NULL, &shared_ring, 1);
> +     if (ret < 0) {
> +             printk("Cannot map ring\n");
> +             return -EINVAL;
> +     }
> +
> +     if (ops[0].status) {
> +             printk("Ring mapping failed\n");
> +             return -EINVAL;
> +     }
> +
> +     sring = (struct hyper_dmabuf_sring*) 
> pfn_to_kaddr(page_to_pfn(shared_ring));
> +
> +     BACK_RING_INIT(&ring_info->ring_back, sring, PAGE_SIZE);
> +
> +     ret = bind_interdomain_evtchn_to_irqhandler(sdomain, port, 
> hyper_dmabuf_back_ring_isr, 0,
> +                                                 NULL, (void*)ring_info);
> +     if (ret < 0) {
> +             return -EINVAL;
> +     }
> +
> +     ring_info->irq = ret;
> +
> +     printk("%s: bound to eventchannel port: %d  irq: %d\n", __func__,
> +             port,
> +             ring_info->irq);
> +
> +     ret = hyper_dmabuf_register_importer_ring(ring_info);
> +
> +     return ret;
> +}
> +
> +int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req)
> +{
> +     struct hyper_dmabuf_front_ring *ring;
> +     struct hyper_dmabuf_ring_rq *new_req;
> +     struct hyper_dmabuf_ring_info_export *ring_info;
> +     int notify;
> +
> +     /* find a ring info for the channel */
> +     ring_info = hyper_dmabuf_find_exporter_ring(domain);
> +     if (!ring_info) {
> +             printk("Can't find ring info for the channel\n");
> +             return -EINVAL;
> +     }
> +
> +     ring = &ring_info->ring_front;
> +
> +     if (RING_FULL(ring))
> +             return -EBUSY;
> +
> +     new_req = RING_GET_REQUEST(ring, ring->req_prod_pvt);
> +     if (!new_req) {
> +             printk("NULL REQUEST\n");
> +             return -EIO;
> +     }
> +
> +     memcpy(new_req, req, sizeof(*new_req));
> +
> +     ring->req_prod_pvt++;
> +
> +     RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(ring, notify);
> +     if (notify) {
> +             notify_remote_via_irq(ring_info->irq);
> +     }
> +
> +     return 0;
> +}
> +
> +/* called by interrupt (WORKQUEUE) */
> +int hyper_dmabuf_send_response(struct hyper_dmabuf_ring_rp* response, int 
> domain)
> +{
> +     /* as a importer and as a exporter */
> +     return 0;
> +}
> +
> +/* ISR for request from exporter (as an importer) */
> +static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *dev_id)
> +{
> +     RING_IDX rc, rp;
> +     struct hyper_dmabuf_ring_rq request;
> +     struct hyper_dmabuf_ring_rp response;
> +     int notify, more_to_do;
> +     int ret;
> +//   struct hyper_dmabuf_work *work;
> +
> +     struct hyper_dmabuf_ring_info_import *ring_info = (struct 
> hyper_dmabuf_ring_info_import *)dev_id;
> +     struct hyper_dmabuf_back_ring *ring;
> +
> +     ring = &ring_info->ring_back;
> +
> +     do {
> +             rc = ring->req_cons;
> +             rp = ring->sring->req_prod;
> +
> +             while (rc != rp) {
> +                     if (RING_REQUEST_CONS_OVERFLOW(ring, rc))
> +                             break;
> +
> +                     memcpy(&request, RING_GET_REQUEST(ring, rc), 
> sizeof(request));
> +                     printk("Got request\n");
> +                     ring->req_cons = ++rc;
> +
> +                     /* TODO: probably using linked list for multiple 
> requests then let
> +                      * a task in a workqueue to process those is better 
> idea becuase
> +                      * we do not want to stay in ISR for long.
> +                      */
> +                     ret = hyper_dmabuf_msg_parse(ring_info->sdomain, 
> &request);
> +
> +                     if (ret > 0) {
> +                             /* build response */
> +                             memcpy(&response, &request, sizeof(response));
> +
> +                             /* we sent back modified request as a 
> response.. we might just need to have request only..*/
> +                             memcpy(RING_GET_RESPONSE(ring, 
> ring->rsp_prod_pvt), &response, sizeof(response));
> +                             ring->rsp_prod_pvt++;
> +
> +                             RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(ring, 
> notify);
> +
> +                             if (notify) {
> +                                     printk("Notyfing\n");
> +                                     notify_remote_via_irq(ring_info->irq);
> +                             }
> +                     }
> +
> +                     RING_FINAL_CHECK_FOR_REQUESTS(ring, more_to_do);
> +                     printk("Final check for requests %d\n", more_to_do);
> +             }
> +     } while (more_to_do);
> +
> +     return IRQ_HANDLED;
> +}
> +
> +/* ISR for responses from importer */
> +static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, void *dev_id)
> +{
> +     /* front ring only care about response from back */
> +     struct hyper_dmabuf_ring_rp *response;
> +     RING_IDX i, rp;
> +     int more_to_do, ret;
> +
> +     struct hyper_dmabuf_ring_info_export *ring_info = (struct 
> hyper_dmabuf_ring_info_export *)dev_id;
> +     struct hyper_dmabuf_front_ring *ring;
> +     ring = &ring_info->ring_front;
> +
> +     do {
> +             more_to_do = 0;
> +             rp = ring->sring->rsp_prod;
> +             for (i = ring->rsp_cons; i != rp; i++) {
> +                     unsigned long id;
> +
> +                     response = RING_GET_RESPONSE(ring, i);
> +                     id = response->response_id;
> +
> +                     if (response->status == 
> HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP) {
> +                             /* parsing response */
> +                             ret = 
> hyper_dmabuf_msg_parse(ring_info->rdomain, (struct 
> hyper_dmabuf_ring_rq*)response);
> +
> +                             if (ret < 0) {
> +                                     printk("getting error while parsing 
> response\n");
> +                             }
> +                     } else if (response->status == HYPER_DMABUF_REQ_ERROR) {
> +                             printk("remote domain %d couldn't process 
> request %d\n", ring_info->rdomain, response->command);
> +                     }
> +
> +             }
> +
> +             ring->rsp_cons = i;
> +
> +             if (i != ring->req_prod_pvt) {
> +                     RING_FINAL_CHECK_FOR_RESPONSES(ring, more_to_do);
> +                     printk("more to do %d\n", more_to_do);
> +             } else {
> +                     ring->sring->rsp_event = i+1;
> +             }
> +     } while (more_to_do);
> +
> +     return IRQ_HANDLED;
> +}
> diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h 
> b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h
> new file mode 100644
> index 0000000..2754917
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h
> @@ -0,0 +1,62 @@
> +#ifndef __HYPER_DMABUF_XEN_COMM_H__
> +#define __HYPER_DMABUF_XEN_COMM_H__
> +
> +#include "xen/interface/io/ring.h"
> +
> +#define MAX_NUMBER_OF_OPERANDS 9
> +
> +struct hyper_dmabuf_ring_rq {
> +        unsigned int request_id;
> +        unsigned int status;
> +        unsigned int command;
> +        unsigned int operands[MAX_NUMBER_OF_OPERANDS];
> +};
> +
> +struct hyper_dmabuf_ring_rp {
> +        unsigned int response_id;
> +        unsigned int status;
> +        unsigned int command;
> +        unsigned int operands[MAX_NUMBER_OF_OPERANDS];
> +};
> +
> +DEFINE_RING_TYPES(hyper_dmabuf, struct hyper_dmabuf_ring_rq, struct 
> hyper_dmabuf_ring_rp);
> +
> +struct hyper_dmabuf_ring_info_export {
> +        struct hyper_dmabuf_front_ring ring_front;
> +     int rdomain;
> +        int gref_ring;
> +        int irq;
> +        int port;
> +};
> +
> +struct hyper_dmabuf_ring_info_import {
> +        int sdomain;
> +        int irq;
> +        int evtchn;
> +        struct hyper_dmabuf_back_ring ring_back;
> +};
> +
> +//struct hyper_dmabuf_work {
> +//   hyper_dmabuf_ring_rq requrest;
> +//   struct work_struct msg_parse;
> +//};
> +
> +int32_t hyper_dmabuf_get_domid(void);
> +
> +int hyper_dmabuf_next_req_id_export(void);
> +
> +int hyper_dmabuf_next_req_id_import(void);
> +
> +/* exporter needs to generated info for page sharing */
> +int hyper_dmabuf_exporter_ringbuf_init(int rdomain, grant_ref_t *gref, int 
> *port);
> +
> +/* importer needs to know about shared page and port numbers for ring buffer 
> and event channel */
> +int hyper_dmabuf_importer_ringbuf_init(int sdomain, grant_ref_t gref, int 
> port);
> +
> +/* send request to the remote domain */
> +int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req);
> +
> +/* called by interrupt (WORKQUEUE) */
> +int hyper_dmabuf_send_response(struct hyper_dmabuf_ring_rp* response, int 
> domain);
> +
> +#endif // __HYPER_DMABUF_XEN_COMM_H__
> diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c 
> b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c
> new file mode 100644
> index 0000000..15c9d29
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c
> @@ -0,0 +1,106 @@
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/cdev.h>
> +#include <asm/uaccess.h>
> +#include <linux/hashtable.h>
> +#include <xen/grant_table.h>
> +#include "hyper_dmabuf_xen_comm.h"
> +#include "hyper_dmabuf_xen_comm_list.h"
> +
> +DECLARE_HASHTABLE(hyper_dmabuf_hash_importer_ring, MAX_ENTRY_IMPORT_RING);
> +DECLARE_HASHTABLE(hyper_dmabuf_hash_exporter_ring, MAX_ENTRY_EXPORT_RING);
> +
> +int hyper_dmabuf_ring_table_init()
> +{
> +     hash_init(hyper_dmabuf_hash_importer_ring);
> +     hash_init(hyper_dmabuf_hash_exporter_ring);
> +     return 0;
> +}
> +
> +int hyper_dmabuf_ring_table_destroy()
> +{
> +     /* TODO: cleanup tables*/
> +     return 0;
> +}
> +
> +int hyper_dmabuf_register_exporter_ring(struct hyper_dmabuf_ring_info_export 
> *ring_info)
> +{
> +     struct hyper_dmabuf_exporter_ring_info *info_entry;
> +
> +     info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL);
> +
> +     info_entry->info = ring_info;
> +
> +     hash_add(hyper_dmabuf_hash_exporter_ring, &info_entry->node,
> +             info_entry->info->rdomain);
> +
> +     return 0;
> +}
> +
> +int hyper_dmabuf_register_importer_ring(struct hyper_dmabuf_ring_info_import 
> *ring_info)
> +{
> +     struct hyper_dmabuf_importer_ring_info *info_entry;
> +
> +     info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL);
> +
> +     info_entry->info = ring_info;
> +
> +     hash_add(hyper_dmabuf_hash_importer_ring, &info_entry->node,
> +             info_entry->info->sdomain);
> +
> +     return 0;
> +}
> +
> +struct hyper_dmabuf_ring_info_export *hyper_dmabuf_find_exporter_ring(int 
> domid)
> +{
> +     struct hyper_dmabuf_exporter_ring_info *info_entry;
> +     int bkt;
> +
> +     hash_for_each(hyper_dmabuf_hash_exporter_ring, bkt, info_entry, node)
> +             if(info_entry->info->rdomain == domid)
> +                     return info_entry->info;
> +
> +     return NULL;
> +}
> +
> +struct hyper_dmabuf_ring_info_import *hyper_dmabuf_find_importer_ring(int 
> domid)
> +{
> +     struct hyper_dmabuf_importer_ring_info *info_entry;
> +     int bkt;
> +
> +     hash_for_each(hyper_dmabuf_hash_importer_ring, bkt, info_entry, node)
> +             if(info_entry->info->sdomain == domid)
> +                     return info_entry->info;
> +
> +     return NULL;
> +}
> +
> +int hyper_dmabuf_remove_exporter_ring(int domid)
> +{
> +     struct hyper_dmabuf_exporter_ring_info *info_entry;
> +     int bkt;
> +
> +     hash_for_each(hyper_dmabuf_hash_exporter_ring, bkt, info_entry, node)
> +             if(info_entry->info->rdomain == domid) {
> +                     hash_del(&info_entry->node);
> +                     return 0;
> +             }
> +
> +     return -1;
> +}
> +
> +int hyper_dmabuf_remove_importer_ring(int domid)
> +{
> +     struct hyper_dmabuf_importer_ring_info *info_entry;
> +     int bkt;
> +
> +     hash_for_each(hyper_dmabuf_hash_importer_ring, bkt, info_entry, node)
> +             if(info_entry->info->sdomain == domid) {
> +                     hash_del(&info_entry->node);
> +                     return 0;
> +             }
> +
> +     return -1;
> +}
> diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h 
> b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h
> new file mode 100644
> index 0000000..5929f99
> --- /dev/null
> +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h
> @@ -0,0 +1,35 @@
> +#ifndef __HYPER_DMABUF_XEN_COMM_LIST_H__
> +#define __HYPER_DMABUF_XEN_COMM_LIST_H__
> +
> +/* number of bits to be used for exported dmabufs hash table */
> +#define MAX_ENTRY_EXPORT_RING 7
> +/* number of bits to be used for imported dmabufs hash table */
> +#define MAX_ENTRY_IMPORT_RING 7
> +
> +struct hyper_dmabuf_exporter_ring_info {
> +        struct hyper_dmabuf_ring_info_export *info;
> +        struct hlist_node node;
> +};
> +
> +struct hyper_dmabuf_importer_ring_info {
> +        struct hyper_dmabuf_ring_info_import *info;
> +        struct hlist_node node;
> +};
> +
> +int hyper_dmabuf_ring_table_init(void);
> +
> +int hyper_dmabuf_ring_table_destroy(void);
> +
> +int hyper_dmabuf_register_exporter_ring(struct hyper_dmabuf_ring_info_export 
> *ring_info);
> +
> +int hyper_dmabuf_register_importer_ring(struct hyper_dmabuf_ring_info_import 
> *ring_info);
> +
> +struct hyper_dmabuf_ring_info_export *hyper_dmabuf_find_exporter_ring(int 
> domid);
> +
> +struct hyper_dmabuf_ring_info_import *hyper_dmabuf_find_importer_ring(int 
> domid);
> +
> +int hyper_dmabuf_remove_exporter_ring(int domid);
> +
> +int hyper_dmabuf_remove_importer_ring(int domid);
> +
> +#endif // __HYPER_DMABUF_XEN_COMM_LIST_H__
> -- 
> 2.7.4
> 
> 

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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.