All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dongwon Kim <dongwon.kim@intel.com>
To: linux-kernel@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org, xen-devel@lists.xenproject.org,
	mateuszx.potrola@intel.com, dongwon.kim@intel.com
Subject: [RFC PATCH 16/60] hyper_dmabuf: define hypervisor specific backend API
Date: Tue, 19 Dec 2017 11:29:32 -0800	[thread overview]
Message-ID: <1513711816-2618-16-git-send-email-dongwon.kim@intel.com> (raw)
In-Reply-To: <1513711816-2618-1-git-send-email-dongwon.kim@intel.com>

For adoption of hyper_dmabuf driver to various hypervisors
other than Xen, a "backend" layer is defined and separated out
from existing one-body structure.

"Backend" is basically a list of entry points of function calls
that provides method to do Kernel's page-level sharing and inter
VMs communication using hypervisor's native mechanism (hypercall).

All backend APIs are listed up in "struct hyper_dmabuf_backend_ops"
as shown below.

struct hyper_dmabuf_backend_ops {
        /* retreiving id of current virtual machine */
        int (*get_vm_id)(void);

        /* get pages shared via hypervisor-specific method */
        int (*share_pages)(struct page **, int, int, void **);

        /* make shared pages unshared via hypervisor specific method */
        int (*unshare_pages)(void **, int);

        /* map remotely shared pages on importer's side via
         * hypervisor-specific method
         */
        struct page ** (*map_shared_pages)(int, int, int, void **);

        /* unmap and free shared pages on importer's side via
         * hypervisor-specific method
         */
        int (*unmap_shared_pages)(void **, int);

        /* initialize communication environment */
        int (*init_comm_env)(void);

        void (*destroy_comm)(void);

        /* upstream ch setup (receiving and responding) */
        int (*init_rx_ch)(int);

        /* downstream ch setup (transmitting and parsing responses) */
        int (*init_tx_ch)(int);

        int (*send_req)(int, struct hyper_dmabuf_req *, int);
};

Within this new structure, only backend APIs need to be re-designed or
replaced with new ones when porting this sharing model to a different
hypervisor environment, which is a lot simpler than completely redesiging
whole driver for a new hypervisor.

Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
---
 drivers/xen/hyper_dmabuf/Makefile                  |  11 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h       |   1 -
 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c        |  33 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h        | 112 ++----
 drivers/xen/hyper_dmabuf/hyper_dmabuf_id.c         |   6 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c        | 426 ++-------------------
 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h        |  14 -
 drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c      | 134 +++----
 drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.h      |  87 +++++
 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c        |  52 ++-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h        |  23 +-
 .../xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c    |   4 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h     |  26 +-
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c   | 303 +++++++++------
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h   |  51 +--
 .../hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c  |  67 ++--
 .../hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h  |  32 +-
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.c    |  22 ++
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.h    |  20 +
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c    | 356 +++++++++++++++++
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.h    |  19 +
 21 files changed, 949 insertions(+), 850 deletions(-)
 create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.h
 create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.c
 create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.h
 create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c
 create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.h

diff --git a/drivers/xen/hyper_dmabuf/Makefile b/drivers/xen/hyper_dmabuf/Makefile
index c9b8b7f..d90cfc3 100644
--- a/drivers/xen/hyper_dmabuf/Makefile
+++ b/drivers/xen/hyper_dmabuf/Makefile
@@ -1,5 +1,7 @@
 TARGET_MODULE:=hyper_dmabuf
 
+PLATFORM:=XEN
+
 # If we running by kernel building system
 ifneq ($(KERNELRELEASE),)
 	$(TARGET_MODULE)-objs := hyper_dmabuf_drv.o \
@@ -9,8 +11,13 @@ ifneq ($(KERNELRELEASE),)
 				 hyper_dmabuf_msg.o \
 				 hyper_dmabuf_id.o \
 				 hyper_dmabuf_remote_sync.o \
-				 xen/hyper_dmabuf_xen_comm.o \
-				 xen/hyper_dmabuf_xen_comm_list.o
+
+ifeq ($(CONFIG_XEN), y)
+	$(TARGET_MODULE)-objs += xen/hyper_dmabuf_xen_comm.o \
+				 xen/hyper_dmabuf_xen_comm_list.o \
+				 xen/hyper_dmabuf_xen_shm.o \
+				 xen/hyper_dmabuf_xen_drv.o
+endif
 
 obj-$(CONFIG_HYPER_DMABUF) := $(TARGET_MODULE).o
 
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h
index 3d9b2d6..d012b05 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h
@@ -1,2 +1 @@
 #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
index 66d6cb9..ddcc955 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c
@@ -1,15 +1,18 @@
-#include <linux/init.h>       /* module_init, module_exit */
-#include <linux/module.h> /* version info, MODULE_LICENSE, MODULE_AUTHOR, printk() */
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/workqueue.h>
-#include <xen/grant_table.h>
-#include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_conf.h"
+#include "hyper_dmabuf_msg.h"
+#include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_list.h"
 #include "hyper_dmabuf_id.h"
-#include "xen/hyper_dmabuf_xen_comm_list.h"
-#include "xen/hyper_dmabuf_xen_comm.h"
 
-MODULE_LICENSE("Dual BSD/GPL");
+#ifdef CONFIG_XEN
+#include "xen/hyper_dmabuf_xen_drv.h"
+extern struct hyper_dmabuf_backend_ops xen_backend_ops;
+#endif
+
+MODULE_LICENSE("GPL");
 MODULE_AUTHOR("IOTG-PED, INTEL");
 
 int register_device(void);
@@ -29,24 +32,24 @@ static int hyper_dmabuf_drv_init(void)
 		return -EINVAL;
 	}
 
+#ifdef CONFIG_XEN
+	hyper_dmabuf_private.backend_ops = &xen_backend_ops;
+#endif
+
 	printk( KERN_NOTICE "initializing database for imported/exported dmabufs\n");
 
 	/* device structure initialization */
 	/* currently only does work-queue initialization */
 	hyper_dmabuf_private.work_queue = create_workqueue("hyper_dmabuf_wqueue");
-	hyper_dmabuf_private.domid = hyper_dmabuf_get_domid();
+	hyper_dmabuf_private.domid = hyper_dmabuf_private.backend_ops->get_vm_id();
 
 	ret = hyper_dmabuf_table_init();
 	if (ret < 0) {
 		return -EINVAL;
 	}
 
-	ret = hyper_dmabuf_ring_table_init();
-	if (ret < 0) {
-		return -EINVAL;
-	}
+	ret = hyper_dmabuf_private.backend_ops->init_comm_env();
 
-	ret = hyper_dmabuf_setup_data_dir();
 	if (ret < 0) {
 		return -EINVAL;
 	}
@@ -61,8 +64,7 @@ static void hyper_dmabuf_drv_exit(void)
 	/* hash tables for export/import entries and ring_infos */
 	hyper_dmabuf_table_destroy();
 
-	hyper_dmabuf_cleanup_ringbufs();
-	hyper_dmabuf_ring_table_destroy();
+	hyper_dmabuf_private.backend_ops->destroy_comm();
 
 	/* destroy workqueue */
 	if (hyper_dmabuf_private.work_queue)
@@ -72,7 +74,6 @@ static void hyper_dmabuf_drv_exit(void)
 	if (hyper_dmabuf_private.id_queue)
 		destroy_reusable_list();
 
-	hyper_dmabuf_destroy_data_dir();
 	printk( KERN_NOTICE "dma_buf-src_sink model: Exiting" );
 	unregister_device();
 }
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
index 37b0cc1..03d77d7 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
@@ -6,94 +6,48 @@ struct list_reusable_id {
 	struct list_head list;
 };
 
-struct hyper_dmabuf_private {
-        struct device *device;
-	int domid;
-	struct workqueue_struct *work_queue;
-	struct list_reusable_id *id_queue;
-};
+struct hyper_dmabuf_backend_ops {
+	/* retreiving id of current virtual machine */
+	int (*get_vm_id)(void);
 
-typedef int (*hyper_dmabuf_ioctl_t)(void *data);
+	/* get pages shared via hypervisor-specific method */
+	int (*share_pages)(struct page **, int, int, void **);
 
-struct hyper_dmabuf_ioctl_desc {
-	unsigned int cmd;
-	int flags;
-	hyper_dmabuf_ioctl_t func;
-	const char *name;
-};
+	/* make shared pages unshared via hypervisor specific method */
+	int (*unshare_pages)(void **, int);
 
-#define HYPER_DMABUF_IOCTL_DEF(ioctl, _func, _flags) 	\
-	[_IOC_NR(ioctl)] = {				\
-			.cmd = ioctl,			\
-			.func = _func,			\
-			.flags = _flags,		\
-			.name = #ioctl			\
-	}
+	/* map remotely shared pages on importer's side via
+	 * hypervisor-specific method
+	 */
+	struct page ** (*map_shared_pages)(int, int, int, void **);
 
-#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;
-};
+	/* unmap and free shared pages on importer's side via
+	 * hypervisor-specific method
+	 */
+	int (*unmap_shared_pages)(void **, int);
 
-#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;
-};
+	/* initialize communication environment */
+	int (*init_comm_env)(void);
 
-#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];
-};
+	void (*destroy_comm)(void);
 
-#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;
-};
+	/* upstream ch setup (receiving and responding) */
+	int (*init_rx_ch)(int);
+
+	/* downstream ch setup (transmitting and parsing responses) */
+	int (*init_tx_ch)(int);
 
-#define IOCTL_HYPER_DMABUF_UNEXPORT \
-_IOC(_IOC_NONE, 'G', 4, sizeof(struct ioctl_hyper_dmabuf_unexport))
-struct ioctl_hyper_dmabuf_unexport {
-	/* IN parameters */
-	/* hyper dmabuf id to be unexported */
-	uint32_t hyper_dmabuf_id;
-	/* OUT parameters */
-	/* Status of request */
-	uint32_t status;
+	int (*send_req)(int, struct hyper_dmabuf_req *, int);
 };
 
-#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;
+struct hyper_dmabuf_private {
+        struct device *device;
+	int domid;
+	struct workqueue_struct *work_queue;
+	struct list_reusable_id *id_queue;
+
+	/* backend ops - hypervisor specific */
+	struct hyper_dmabuf_backend_ops *backend_ops;
 };
 
-#endif //__LINUX_PUBLIC_HYPER_DMABUF_DRV_H__
+#endif /* __LINUX_PUBLIC_HYPER_DMABUF_DRV_H__ */
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_id.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_id.c
index 7bbb179..b58a111 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_id.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_id.c
@@ -1,5 +1,6 @@
 #include <linux/list.h>
 #include <linux/slab.h>
+#include "hyper_dmabuf_msg.h"
 #include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_id.h"
 
@@ -19,6 +20,7 @@ void store_reusable_id(int id)
 static int retrieve_reusable_id(void)
 {
 	struct list_reusable_id *reusable_head = hyper_dmabuf_private.id_queue;
+	int id;
 
 	/* check there is reusable id */
 	if (!list_empty(&reusable_head->list)) {
@@ -27,7 +29,9 @@ static int retrieve_reusable_id(void)
 						 list);
 
 		list_del(&reusable_head->list);
-		return reusable_head->id;
+		id = reusable_head->id;
+		kfree(reusable_head);
+		return id;
 	}
 
 	return -1;
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
index b109138..0f104b9 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
@@ -8,10 +8,12 @@
 #include "hyper_dmabuf_struct.h"
 #include "hyper_dmabuf_imp.h"
 #include "hyper_dmabuf_id.h"
-#include "xen/hyper_dmabuf_xen_comm.h"
 #include "hyper_dmabuf_msg.h"
+#include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_list.h"
 
+extern struct hyper_dmabuf_private hyper_dmabuf_private;
+
 #define REFS_PER_PAGE (PAGE_SIZE/sizeof(grant_ref_t))
 
 int dmabuf_refcount(struct dma_buf *dma_buf)
@@ -138,397 +140,10 @@ struct sg_table* hyper_dmabuf_create_sgt(struct page **pages,
 /* free sg_table */
 void hyper_dmabuf_free_sgt(struct sg_table* sgt)
 {
-	sg_free_table(sgt);
-	kfree(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));
-	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->nents/REFS_PER_PAGE +
-				((sgt_info->nents % REFS_PER_PAGE) ? 1: 0));
-
-
-	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");
-		}
-		gnttab_free_grant_reference(ref[i]);
-		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");
-	}
-	gnttab_end_foreign_access_ref(shared_pages_info->top_level_ref, 1);
-	gnttab_free_grant_reference(shared_pages_info->top_level_ref);
-
-	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->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);
-		gnttab_free_grant_reference(shared_pages_info->data_refs[i]);
-	}
-
-	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 = kcalloc(nents, sizeof(struct gnttab_map_grant_ref),
-		      GFP_KERNEL);
-	unmap_ops = 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;
-		}
+	if (sgt) {
+		sg_free_table(sgt);
+		kfree(sgt);
 	}
-
-	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;
 }
 
 int hyper_dmabuf_cleanup_sgt_info(struct hyper_dmabuf_sgt_info *sgt_info, int force)
@@ -537,6 +152,7 @@ int hyper_dmabuf_cleanup_sgt_info(struct hyper_dmabuf_sgt_info *sgt_info, int fo
 	struct attachment_list *attachl;
 	struct kmap_vaddr_list *va_kmapl;
 	struct vmap_vaddr_list *va_vmapl;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 
 	if (!sgt_info) {
 		printk("invalid hyper_dmabuf_id\n");
@@ -598,7 +214,7 @@ int hyper_dmabuf_cleanup_sgt_info(struct hyper_dmabuf_sgt_info *sgt_info, int fo
 	}
 
 	/* Start cleanup of buffer in reverse order to exporting */
-	hyper_dmabuf_cleanup_gref_table(sgt_info);
+	ops->unshare_pages(&sgt_info->refs_info, sgt_info->nents);
 
 	/* unmap dma-buf */
 	dma_buf_unmap_attachment(sgt_info->active_attached->attach,
@@ -620,21 +236,22 @@ int hyper_dmabuf_cleanup_sgt_info(struct hyper_dmabuf_sgt_info *sgt_info, int fo
 	return 0;
 }
 
-inline int hyper_dmabuf_sync_request_and_wait(int id, int ops)
+inline int hyper_dmabuf_sync_request_and_wait(int id, int dmabuf_ops)
 {
-	struct hyper_dmabuf_ring_rq *req;
+	struct hyper_dmabuf_req *req;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	int operands[2];
 	int ret;
 
 	operands[0] = id;
-	operands[1] = ops;
+	operands[1] = dmabuf_ops;
 
 	req = kcalloc(1, sizeof(*req), GFP_KERNEL);
 
 	hyper_dmabuf_create_request(req, HYPER_DMABUF_OPS_TO_SOURCE, &operands[0]);
 
 	/* send request and wait for a response */
-	ret = hyper_dmabuf_send_request(HYPER_DMABUF_DOM_ID(id), req, true);
+	ret = ops->send_req(HYPER_DMABUF_DOM_ID(id), req, true);
 
 	kfree(req);
 
@@ -753,6 +370,7 @@ static void hyper_dmabuf_ops_unmap(struct dma_buf_attachment *attachment,
 static void hyper_dmabuf_ops_release(struct dma_buf *dma_buf)
 {
 	struct hyper_dmabuf_imported_sgt_info *sgt_info;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	int ret;
 	int final_release;
 
@@ -761,16 +379,22 @@ static void hyper_dmabuf_ops_release(struct dma_buf *dma_buf)
 
 	sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dma_buf->priv;
 
-	final_release = sgt_info && !sgt_info->valid &&
-		       !dmabuf_refcount(sgt_info->dma_buf);
-
 	if (!dmabuf_refcount(sgt_info->dma_buf)) {
 		sgt_info->dma_buf = NULL;
 	}
 
-	if (final_release) {
-		hyper_dmabuf_cleanup_imported_pages(sgt_info);
+	sgt_info->num_importers--;
+
+	if (sgt_info->num_importers == 0) {
+		ops->unmap_shared_pages(&sgt_info->refs_info, sgt_info->nents);
 		hyper_dmabuf_free_sgt(sgt_info->sgt);
+		sgt_info->sgt = NULL;
+	}
+
+	final_release = sgt_info && !sgt_info->valid &&
+		        !sgt_info->num_importers;
+
+	if (final_release) {
 		ret = hyper_dmabuf_sync_request_and_wait(sgt_info->hyper_dmabuf_id,
 							HYPER_DMABUF_OPS_RELEASE_FINAL);
 	} else {
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
index 1b0801f..a4a6d63 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
@@ -11,20 +11,6 @@ struct hyper_dmabuf_pages_info *hyper_dmabuf_ext_pgs(struct sg_table *sgt);
 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_cleanup_sgt_info(struct hyper_dmabuf_sgt_info *sgt_info, int force);
 
 void hyper_dmabuf_free_sgt(struct sg_table *sgt);
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
index 5c6d9c8..70107bb 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
@@ -8,47 +8,37 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include "hyper_dmabuf_struct.h"
-#include "hyper_dmabuf_imp.h"
+#include "hyper_dmabuf_ioctl.h"
 #include "hyper_dmabuf_list.h"
+#include "hyper_dmabuf_msg.h"
 #include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_id.h"
+#include "hyper_dmabuf_imp.h"
 #include "hyper_dmabuf_query.h"
-#include "xen/hyper_dmabuf_xen_comm.h"
-#include "xen/hyper_dmabuf_xen_comm_list.h"
-#include "hyper_dmabuf_msg.h"
 
 extern struct hyper_dmabuf_private hyper_dmabuf_private;
 
-static int hyper_dmabuf_exporter_ring_setup(void *data)
+static int hyper_dmabuf_tx_ch_setup(void *data)
 {
-	struct ioctl_hyper_dmabuf_exporter_ring_setup *ring_attr;
-	struct hyper_dmabuf_ring_info_export *ring_info;
+	struct ioctl_hyper_dmabuf_tx_ch_setup *tx_ch_attr;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	int ret = 0;
 
 	if (!data) {
 		printk("user data is NULL\n");
 		return -1;
 	}
-	ring_attr = (struct ioctl_hyper_dmabuf_exporter_ring_setup *)data;
-
-	/* check if the ring ch already exists */
-	ring_info = hyper_dmabuf_find_exporter_ring(ring_attr->remote_domain);
-
-	if (ring_info) {
-		printk("(exporter's) ring ch to domid = %d already exist\ngref = %d, port = %d\n",
-			ring_info->rdomain, ring_info->gref_ring, ring_info->port);
-		return 0;
-	}
+	tx_ch_attr = (struct ioctl_hyper_dmabuf_tx_ch_setup *)data;
 
-	ret = hyper_dmabuf_exporter_ringbuf_init(ring_attr->remote_domain);
+	ret = ops->init_tx_ch(tx_ch_attr->remote_domain);
 
 	return ret;
 }
 
-static int hyper_dmabuf_importer_ring_setup(void *data)
+static int hyper_dmabuf_rx_ch_setup(void *data)
 {
-	struct ioctl_hyper_dmabuf_importer_ring_setup *setup_imp_ring_attr;
-	struct hyper_dmabuf_ring_info_import *ring_info;
+	struct ioctl_hyper_dmabuf_rx_ch_setup *rx_ch_attr;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	int ret = 0;
 
 	if (!data) {
@@ -56,17 +46,9 @@ static int hyper_dmabuf_importer_ring_setup(void *data)
 		return -1;
 	}
 
-	setup_imp_ring_attr = (struct ioctl_hyper_dmabuf_importer_ring_setup *)data;
-
-	/* check if the ring ch already exist */
-	ring_info = hyper_dmabuf_find_importer_ring(setup_imp_ring_attr->source_domain);
+	rx_ch_attr = (struct ioctl_hyper_dmabuf_rx_ch_setup *)data;
 
-	if (ring_info) {
-		printk("(importer's) ring ch to domid = %d already exist\n", ring_info->sdomain);
-		return 0;
-	}
-
-	ret = hyper_dmabuf_importer_ringbuf_init(setup_imp_ring_attr->source_domain);
+	ret = ops->init_rx_ch(rx_ch_attr->source_domain);
 
 	return ret;
 }
@@ -74,13 +56,14 @@ static int hyper_dmabuf_importer_ring_setup(void *data)
 static int hyper_dmabuf_export_remote(void *data)
 {
 	struct ioctl_hyper_dmabuf_export_remote *export_remote_attr;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	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];
+	struct hyper_dmabuf_req *req;
+	int operands[MAX_NUMBER_OF_OPERANDS];
 	int ret = 0;
 
 	if (!data) {
@@ -125,6 +108,7 @@ static int hyper_dmabuf_export_remote(void *data)
 	sgt_info = kmalloc(sizeof(*sgt_info), GFP_KERNEL);
 
 	sgt_info->hyper_dmabuf_id = hyper_dmabuf_get_id();
+
 	/* TODO: We might need to consider using port number on event channel? */
 	sgt_info->hyper_dmabuf_rdomain = export_remote_attr->remote_domain;
 	sgt_info->dma_buf = dma_buf;
@@ -163,15 +147,14 @@ static int hyper_dmabuf_export_remote(void *data)
 
 	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);
+	operands[4] = ops->share_pages (page_info->pages, export_remote_attr->remote_domain,
+					page_info->nents, &sgt_info->refs_info);
+
 	/* driver/application specific private info, max 32 bytes */
 	operands[5] = export_remote_attr->private[0];
 	operands[6] = export_remote_attr->private[1];
@@ -182,7 +165,8 @@ static int hyper_dmabuf_export_remote(void *data)
 
 	/* 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, false))
+
+	if(ops->send_req(export_remote_attr->remote_domain, req, false))
 		goto fail_send_request;
 
 	/* free msg */
@@ -215,8 +199,10 @@ static int hyper_dmabuf_export_remote(void *data)
 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;
-	struct hyper_dmabuf_ring_rq *req;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
+	struct hyper_dmabuf_imported_sgt_info *sgt_info;
+	struct hyper_dmabuf_req *req;
+	struct page **data_pages;
 	int operand;
 	int ret = 0;
 
@@ -228,43 +214,48 @@ static int hyper_dmabuf_export_fd_ioctl(void *data)
 	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 */
+	sgt_info = hyper_dmabuf_find_imported(export_fd_attr->hyper_dmabuf_id);
+	if (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_DOM_ID(imported_sgt_info->hyper_dmabuf_id));
-
-	if (!imported_sgt_info->sgt) {
-		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_DOM_ID(imported_sgt_info->hyper_dmabuf_id),
-							&imported_sgt_info->shared_pages_info);
-
-		/* send notifiticatio for first export_fd to exporter */
-		operand = imported_sgt_info->hyper_dmabuf_id;
-		req = kcalloc(1, sizeof(*req), GFP_KERNEL);
-		hyper_dmabuf_create_request(req, HYPER_DMABUF_FIRST_EXPORT, &operand);
-
-		ret = hyper_dmabuf_send_request(HYPER_DMABUF_DOM_ID(operand), req, false);
-
-		if (!imported_sgt_info->sgt || ret) {
-			kfree(req);
-			printk("Failed to create sgt or notify exporter\n");
-			return -EINVAL;
-		}
+		sgt_info->ref_handle, sgt_info->frst_ofst,
+		sgt_info->last_len, sgt_info->nents,
+		HYPER_DMABUF_DOM_ID(sgt_info->hyper_dmabuf_id));
+
+	if (!sgt_info->sgt) {
+		data_pages = ops->map_shared_pages(sgt_info->ref_handle,
+						   HYPER_DMABUF_DOM_ID(sgt_info->hyper_dmabuf_id),
+						   sgt_info->nents,
+						   &sgt_info->refs_info);
+
+		sgt_info->sgt = hyper_dmabuf_create_sgt(data_pages, sgt_info->frst_ofst,
+							sgt_info->last_len, sgt_info->nents);
+
+	}
+
+	/* send notification for export_fd to exporter */
+	operand = sgt_info->hyper_dmabuf_id;
+
+	req = kcalloc(1, sizeof(*req), GFP_KERNEL);
+	hyper_dmabuf_create_request(req, HYPER_DMABUF_FIRST_EXPORT, &operand);
+
+	ret = ops->send_req(HYPER_DMABUF_DOM_ID(operand), req, false);
+
+	if (!sgt_info->sgt || ret) {
 		kfree(req);
+		printk("Failed to create sgt or notify exporter\n");
+		return -EINVAL;
 	}
+	kfree(req);
 
-	export_fd_attr->fd = hyper_dmabuf_export_fd(imported_sgt_info, export_fd_attr->flags);
+	export_fd_attr->fd = hyper_dmabuf_export_fd(sgt_info, export_fd_attr->flags);
 
 	if (export_fd_attr->fd < 0) {
 		/* fail to get fd */
 		ret = export_fd_attr->fd;
+	} else {
+		sgt_info->num_importers++;
 	}
 
 	return ret;
@@ -276,8 +267,9 @@ static int hyper_dmabuf_export_fd_ioctl(void *data)
 static int hyper_dmabuf_unexport(void *data)
 {
 	struct ioctl_hyper_dmabuf_unexport *unexport_attr;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	struct hyper_dmabuf_sgt_info *sgt_info;
-	struct hyper_dmabuf_ring_rq *req;
+	struct hyper_dmabuf_req *req;
 	int ret;
 
 	if (!data) {
@@ -301,7 +293,7 @@ static int hyper_dmabuf_unexport(void *data)
 	hyper_dmabuf_create_request(req, HYPER_DMABUF_NOTIFY_UNEXPORT, &unexport_attr->hyper_dmabuf_id);
 
 	/* Now send unexport request to remote domain, marking that buffer should not be used anymore */
-	ret = hyper_dmabuf_send_request(sgt_info->hyper_dmabuf_rdomain, req, true);
+	ret = ops->send_req(sgt_info->hyper_dmabuf_rdomain, req, true);
 	if (ret < 0) {
 		kfree(req);
 		return -EFAULT;
@@ -405,8 +397,8 @@ static int hyper_dmabuf_query(void *data)
 }
 
 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_TX_CH_SETUP, hyper_dmabuf_tx_ch_setup, 0),
+	HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_RX_CH_SETUP, hyper_dmabuf_rx_ch_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_UNEXPORT, hyper_dmabuf_unexport, 0),
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.h
new file mode 100644
index 0000000..de216d3
--- /dev/null
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.h
@@ -0,0 +1,87 @@
+#ifndef __LINUX_PUBLIC_HYPER_DMABUF_IOCTL_H__
+#define __LINUX_PUBLIC_HYPER_DMABUF_IOCTL_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_TX_CH_SETUP \
+_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_hyper_dmabuf_tx_ch_setup))
+struct ioctl_hyper_dmabuf_tx_ch_setup {
+	/* IN parameters */
+	/* Remote domain id */
+	int remote_domain;
+};
+
+#define IOCTL_HYPER_DMABUF_RX_CH_SETUP \
+_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_hyper_dmabuf_rx_ch_setup))
+struct ioctl_hyper_dmabuf_rx_ch_setup {
+	/* IN parameters */
+	/* Source domain id */
+	int source_domain;
+};
+
+#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 */
+	int dmabuf_fd;
+	/* Domain id to which buffer should be exported */
+	int remote_domain;
+	/* exported dma buf id */
+	int hyper_dmabuf_id;
+	int 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 */
+	int hyper_dmabuf_id;
+	/* flags */
+	int flags;
+	/* OUT parameters */
+	/* exported dma buf fd */
+	int fd;
+};
+
+#define IOCTL_HYPER_DMABUF_UNEXPORT \
+_IOC(_IOC_NONE, 'G', 4, sizeof(struct ioctl_hyper_dmabuf_unexport))
+struct ioctl_hyper_dmabuf_unexport {
+	/* IN parameters */
+	/* hyper dmabuf id to be unexported */
+	int hyper_dmabuf_id;
+	/* OUT parameters */
+	/* Status of request */
+	int 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 */
+	int hyper_dmabuf_id;
+	/* item to be queried */
+	int item;
+	/* OUT parameters */
+	/* Value of queried item */
+	int info;
+};
+
+#endif //__LINUX_PUBLIC_HYPER_DMABUF_DRV_H__
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
index a2d687f..4647115 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
@@ -5,11 +5,10 @@
 #include <linux/dma-buf.h>
 #include <xen/grant_table.h>
 #include <linux/workqueue.h>
+#include "hyper_dmabuf_msg.h"
 #include "hyper_dmabuf_drv.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"
 
 #define FORCED_UNEXPORTING 0
@@ -18,18 +17,17 @@ extern struct hyper_dmabuf_private hyper_dmabuf_private;
 
 struct cmd_process {
 	struct work_struct work;
-	struct hyper_dmabuf_ring_rq *rq;
+	struct hyper_dmabuf_req *rq;
 	int domid;
 };
 
-void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
-				        enum hyper_dmabuf_command command, int *operands)
+void hyper_dmabuf_create_request(struct hyper_dmabuf_req *req,
+				 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;
+	req->status = HYPER_DMABUF_REQ_NOT_RESPONDED;
+	req->command = command;
 
 	switch(command) {
 	/* as exporter, commands to importer */
@@ -44,7 +42,7 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
 		 * operands5~8 : Driver-specific private data (e.g. graphic buffer's meta info)
 		 */
 		for (i=0; i < 8; i++)
-			request->operands[i] = operands[i];
+			req->operands[i] = operands[i];
 		break;
 
 	case HYPER_DMABUF_NOTIFY_UNEXPORT:
@@ -52,7 +50,7 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
 		/* command : DMABUF_DESTROY,
 		 * operands0 : hyper_dmabuf_id
 		 */
-		request->operands[0] = operands[0];
+		req->operands[0] = operands[0];
 		break;
 
 	case HYPER_DMABUF_FIRST_EXPORT:
@@ -60,7 +58,7 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
 		/* command : HYPER_DMABUF_FIRST_EXPORT,
 		 * operands0 : hyper_dmabuf_id
 		 */
-		request->operands[0] = operands[0];
+		req->operands[0] = operands[0];
 		break;
 
 	case HYPER_DMABUF_OPS_TO_REMOTE:
@@ -77,7 +75,7 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
 		 * operands1 : map(=1)/unmap(=2)/attach(=3)/detach(=4)
 		 */
 		for (i=0; i<2; i++)
-			request->operands[i] = operands[i];
+			req->operands[i] = operands[i];
 		break;
 
 	default:
@@ -88,10 +86,10 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
 
 void cmd_process_work(struct work_struct *work)
 {
-	struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
 	struct hyper_dmabuf_sgt_info *sgt_info;
+	struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
 	struct cmd_process *proc = container_of(work, struct cmd_process, work);
-	struct hyper_dmabuf_ring_rq *req;
+	struct hyper_dmabuf_req *req;
 	int domid;
 	int i;
 
@@ -114,7 +112,7 @@ void cmd_process_work(struct work_struct *work)
 		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];
+		imported_sgt_info->ref_handle = req->operands[4];
 
 		printk("DMABUF was exported\n");
 		printk("\thyper_dmabuf_id %d\n", req->operands[0]);
@@ -139,10 +137,7 @@ void cmd_process_work(struct work_struct *work)
 			break;
 		}
 
-		if (sgt_info->importer_exported)
-			printk("warning: exported flag is not supposed to be 1 already\n");
-
-		sgt_info->importer_exported = 1;
+		sgt_info->importer_exported++;
 		break;
 
 	case HYPER_DMABUF_OPS_TO_REMOTE:
@@ -160,11 +155,11 @@ void cmd_process_work(struct work_struct *work)
 	kfree(proc);
 }
 
-int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_ring_rq *req)
+int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_req *req)
 {
 	struct cmd_process *proc;
-	struct hyper_dmabuf_ring_rq *temp_req;
-	struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
+	struct hyper_dmabuf_req *temp_req;
+	struct hyper_dmabuf_imported_sgt_info *sgt_info;
 	int ret;
 
 	if (!req) {
@@ -189,22 +184,21 @@ int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_ring_rq *req)
 		 * operands0 : hyper_dmabuf_id
 		 */
 
-		imported_sgt_info =
-			hyper_dmabuf_find_imported(req->operands[0]);
+		sgt_info = hyper_dmabuf_find_imported(req->operands[0]);
 
-		if (imported_sgt_info) {
+		if (sgt_info) {
 			/* if anything is still using dma_buf */
-			if (imported_sgt_info->dma_buf &&
-			    dmabuf_refcount(imported_sgt_info->dma_buf) > 0) {
+			if (sgt_info->dma_buf &&
+			    dmabuf_refcount(sgt_info->dma_buf) > 0) {
 				/*
 				 * Buffer is still in  use, just mark that it should
 				 * not be allowed to export its fd anymore.
 				 */
-				imported_sgt_info->valid = 0;
+				sgt_info->valid = 0;
 			} else {
 				/* No one is using buffer, remove it from imported list */
 				hyper_dmabuf_remove_imported(req->operands[0]);
-				kfree(imported_sgt_info);
+				kfree(sgt_info);
 			}
 		} else {
 			req->status = HYPER_DMABUF_REQ_ERROR;
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
index 1e9d827..ac4caeb 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
@@ -1,6 +1,22 @@
 #ifndef __HYPER_DMABUF_MSG_H__
 #define __HYPER_DMABUF_MSG_H__
 
+#define MAX_NUMBER_OF_OPERANDS 9
+
+struct hyper_dmabuf_req {
+	unsigned int request_id;
+	unsigned int status;
+	unsigned int command;
+	unsigned int operands[MAX_NUMBER_OF_OPERANDS];
+};
+
+struct hyper_dmabuf_resp {
+	unsigned int response_id;
+	unsigned int status;
+	unsigned int command;
+	unsigned int operands[MAX_NUMBER_OF_OPERANDS];
+};
+
 enum hyper_dmabuf_command {
 	HYPER_DMABUF_EXPORT = 0x10,
 	HYPER_DMABUF_FIRST_EXPORT,
@@ -35,10 +51,11 @@ enum hyper_dmabuf_req_feedback {
 };
 
 /* 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);
+void hyper_dmabuf_create_request(struct hyper_dmabuf_req *req,
+				 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);
+int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_req *req);
 
 #endif // __HYPER_DMABUF_MSG_H__
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c
index c5950e0..0f4735c 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c
@@ -5,9 +5,9 @@
 #include <linux/dma-buf.h>
 #include "hyper_dmabuf_struct.h"
 #include "hyper_dmabuf_list.h"
+#include "hyper_dmabuf_msg.h"
 #include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_id.h"
-#include "xen/hyper_dmabuf_xen_comm.h"
 #include "hyper_dmabuf_msg.h"
 #include "hyper_dmabuf_imp.h"
 
@@ -133,6 +133,8 @@ int hyper_dmabuf_remote_sync(int id, int ops)
 
 	case HYPER_DMABUF_OPS_RELEASE:
 		/* place holder */
+                sgt_info->importer_exported--;
+
 		break;
 
 	case HYPER_DMABUF_OPS_BEGIN_CPU_ACCESS:
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
index b52f958..f053dd10 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
@@ -1,14 +1,6 @@
 #ifndef __HYPER_DMABUF_STRUCT_H__
 #define __HYPER_DMABUF_STRUCT_H__
 
-#include <xen/interface/grant_table.h>
-
-/* 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
-
 /* stack of mapped sgts */
 struct sgt_list {
 	struct sg_table *sgt;
@@ -33,15 +25,6 @@ struct vmap_vaddr_list {
 	struct list_head list;
 };
 
-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 */
@@ -69,8 +52,8 @@ struct hyper_dmabuf_sgt_info {
 	struct kmap_vaddr_list *va_kmapped;
 	struct vmap_vaddr_list *va_vmapped;
 	bool valid;
-	bool importer_exported; /* exported locally on importer's side */
-	struct hyper_dmabuf_shared_pages_info shared_pages_info;
+	int importer_exported; /* exported locally on importer's side */
+	void *refs_info; /* hypervisor-specific info for the references */
 	int private[4]; /* device specific info (e.g. image's meta info?) */
 };
 
@@ -79,14 +62,15 @@ struct hyper_dmabuf_sgt_info {
  * 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 ref_handle; /* reference number of top level addressing page of shared pages */
 	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 dma_buf *dma_buf;
 	struct sg_table *sgt; /* sgt pointer after importing buffer */
-	struct hyper_dmabuf_shared_pages_info shared_pages_info;
+	void *refs_info;
 	bool valid;
+	int num_importers;
 	int private[4]; /* device specific info (e.g. image's meta info?) */
 };
 
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
index f9e0df3..bd37ec2 100644
--- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
@@ -10,16 +10,15 @@
 #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;
 
-struct hyper_dmabuf_ring_rq req_pending = {0};
+struct hyper_dmabuf_req req_pending = {0};
 
-/* Creates entry in xen store that will keep details of all exporter rings created by this domain */
-int32_t hyper_dmabuf_setup_data_dir()
+/* Creates entry in xen store that will keep details of all
+ * exporter rings created by this domain
+ */
+static int xen_comm_setup_data_dir(void)
 {
 	char buf[255];
 
@@ -27,13 +26,13 @@ int32_t hyper_dmabuf_setup_data_dir()
 	return xenbus_mkdir(XBT_NIL, buf, "");
 }
 
-
 /* Removes entry from xenstore with exporter ring details.
- * Other domains that has connected to any of exporter rings created by this domain,
- * will be notified about removal of this entry and will treat that as signal to
- * cleanup importer rings created for this domain
+ * Other domains that has connected to any of exporter rings
+ * created by this domain, will be notified about removal of
+ * this entry and will treat that as signal to cleanup importer
+ * rings created for this domain
  */
-int32_t hyper_dmabuf_destroy_data_dir()
+static int xen_comm_destroy_data_dir(void)
 {
 	char buf[255];
 
@@ -41,18 +40,19 @@ int32_t hyper_dmabuf_destroy_data_dir()
 	return xenbus_rm(XBT_NIL, buf, "");
 }
 
-/*
- * Adds xenstore entries with details of exporter ring created for given remote domain.
- * It requires special daemon running in dom0 to make sure that given remote domain will
- * have right permissions to access that data.
+/* Adds xenstore entries with details of exporter ring created
+ * for given remote domain. It requires special daemon running
+ * in dom0 to make sure that given remote domain will have right
+ * permissions to access that data.
  */
-static int32_t hyper_dmabuf_expose_ring_details(uint32_t domid, uint32_t rdomid, uint32_t grefid, uint32_t port)
+static int xen_comm_expose_ring_details(int domid, int rdomid,
+					int gref, int port)
 {
 	char buf[255];
 	int ret;
 
 	sprintf(buf, "/local/domain/%d/data/hyper_dmabuf/%d", domid, rdomid);
-	ret = xenbus_printf(XBT_NIL, buf, "grefid", "%d", grefid);
+	ret = xenbus_printf(XBT_NIL, buf, "grefid", "%d", gref);
 
 	if (ret) {
 		printk("Failed to write xenbus entry %s: %d\n", buf, ret);
@@ -72,7 +72,7 @@ static int32_t hyper_dmabuf_expose_ring_details(uint32_t domid, uint32_t rdomid,
 /*
  * Queries details of ring exposed by remote domain.
  */
-static int32_t hyper_dmabuf_get_ring_details(uint32_t domid, uint32_t rdomid, uint32_t *grefid, uint32_t *port)
+static int xen_comm_get_ring_details(int domid, int rdomid, int *grefid, int *port)
 {
 	char buf[255];
 	int ret;
@@ -95,10 +95,10 @@ static int32_t hyper_dmabuf_get_ring_details(uint32_t domid, uint32_t rdomid, ui
 	return (ret <= 0 ? 1 : 0);
 }
 
-int32_t hyper_dmabuf_get_domid(void)
+int hyper_dmabuf_get_domid(void)
 {
 	struct xenbus_transaction xbt;
-	int32_t domid;
+	int domid;
 
         xenbus_transaction_start(&xbt);
 
@@ -110,29 +110,35 @@ int32_t hyper_dmabuf_get_domid(void)
 	return domid;
 }
 
-int hyper_dmabuf_next_req_id_export(void)
+static int xen_comm_next_req_id(void)
 {
         export_req_id++;
         return export_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 *info);
-static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *info);
-
-/*
- * Callback function that will be called on any change of xenbus path being watched.
- * Used for detecting creation/destruction of remote domain exporter ring.
- * When remote domain's exporter ring will be detected, importer ring on this domain will be created.
- * When remote domain's exporter ring destruction will be detected it will celanup this domain importer ring.
- * Destruction can be caused by unloading module by remote domain or it's crash/force shutdown.
+static irqreturn_t front_ring_isr(int irq, void *info);
+static irqreturn_t back_ring_isr(int irq, void *info);
+
+/* Callback function that will be called on any change of xenbus path
+ * being watched. Used for detecting creation/destruction of remote
+ * domain exporter ring.
+ *
+ * When remote domain's exporter ring will be detected, importer ring
+ * on this domain will be created.
+ *
+ * When remote domain's exporter ring destruction will be detected it
+ * will celanup this domain importer ring.
+ *
+ * Destruction can be caused by unloading module by remote domain or
+ * it's crash/force shutdown.
  */
-static void remote_domain_exporter_watch_cb(struct xenbus_watch *watch,
-				   const char *path, const char *token)
+static void remote_dom_exporter_watch_cb(struct xenbus_watch *watch,
+					 const char *path, const char *token)
 {
 	int rdom,ret;
 	uint32_t grefid, port;
-	struct hyper_dmabuf_ring_info_import *ring_info;
+	struct xen_comm_rx_ring_info *ring_info;
 
 	/* Check which domain has changed its exporter rings */
 	ret = sscanf(watch->node, "/local/domain/%d/", &rdom);
@@ -141,39 +147,49 @@ static void remote_domain_exporter_watch_cb(struct xenbus_watch *watch,
 	}
 
 	/* Check if we have importer ring for given remote domain alrady created */
-	ring_info = hyper_dmabuf_find_importer_ring(rdom);
-
-	/*
-	 * Try to query remote domain exporter ring details - if that will fail and we have
-	 * importer ring that means remote domains has cleanup its exporter ring, so our
-	 * importer ring is no longer useful.
-	 * If querying details will succeed and we don't have importer ring, it means that
-	 * remote domain has setup it for us and we should connect to it.
+	ring_info = xen_comm_find_rx_ring(rdom);
+
+	/* Try to query remote domain exporter ring details - if that will
+	 * fail and we have importer ring that means remote domains has cleanup
+	 * its exporter ring, so our importer ring is no longer useful.
+	 *
+	 * If querying details will succeed and we don't have importer ring,
+	 * it means that remote domain has setup it for us and we should connect
+	 * to it.
 	 */
-	ret = hyper_dmabuf_get_ring_details(hyper_dmabuf_get_domid(), rdom, &grefid, &port);
+	ret = xen_comm_get_ring_details(hyper_dmabuf_get_domid(), rdom,
+					&grefid, &port);
 
 	if (ring_info && ret != 0) {
 		printk("Remote exporter closed, cleaninup importer\n");
-		hyper_dmabuf_importer_ringbuf_cleanup(rdom);
+		hyper_dmabuf_xen_cleanup_rx_rbuf(rdom);
 	} else if (!ring_info && ret == 0) {
 		printk("Registering importer\n");
-		hyper_dmabuf_importer_ringbuf_init(rdom);
+		hyper_dmabuf_xen_init_rx_rbuf(rdom);
 	}
 }
 
 /* exporter needs to generated info for page sharing */
-int hyper_dmabuf_exporter_ringbuf_init(int rdomain)
+int hyper_dmabuf_xen_init_tx_rbuf(int domid)
 {
-	struct hyper_dmabuf_ring_info_export *ring_info;
-	struct hyper_dmabuf_sring *sring;
+	struct xen_comm_tx_ring_info *ring_info;
+	struct xen_comm_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);
+	/* check if there's any existing tx channel in the table */
+	ring_info = xen_comm_find_tx_ring(domid);
+
+	if (ring_info) {
+		printk("tx ring ch to domid = %d already exist\ngref = %d, port = %d\n",
+		ring_info->rdomain, ring_info->gref_ring, ring_info->port);
+		return 0;
+	}
+
+	ring_info = kmalloc(sizeof(*ring_info), GFP_KERNEL);
 
 	/* from exporter to importer */
 	shared_ring = (void *)__get_free_pages(GFP_KERNEL, 1);
@@ -181,20 +197,22 @@ int hyper_dmabuf_exporter_ringbuf_init(int rdomain)
 		return -EINVAL;
 	}
 
-	sring = (struct hyper_dmabuf_sring *) shared_ring;
+	sring = (struct xen_comm_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);
+	ring_info->gref_ring = gnttab_grant_foreign_access(domid,
+							   virt_to_mfn(shared_ring),
+							   0);
 	if (ring_info->gref_ring < 0) {
-		return -EINVAL; /* fail to get gref */
+		/* fail to get gref */
+		return -EINVAL;
 	}
 
 	alloc_unbound.dom = DOMID_SELF;
-	alloc_unbound.remote_dom = rdomain;
+	alloc_unbound.remote_dom = domid;
 	ret = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
 					&alloc_unbound);
 	if (ret != 0) {
@@ -204,7 +222,7 @@ int hyper_dmabuf_exporter_ringbuf_init(int rdomain)
 
 	/* setting up interrupt */
 	ret = bind_evtchn_to_irqhandler(alloc_unbound.port,
-					hyper_dmabuf_front_ring_isr, 0,
+					front_ring_isr, 0,
 					NULL, (void*) ring_info);
 
 	if (ret < 0) {
@@ -216,7 +234,7 @@ int hyper_dmabuf_exporter_ringbuf_init(int rdomain)
 		return -EINVAL;
 	}
 
-	ring_info->rdomain = rdomain;
+	ring_info->rdomain = domid;
 	ring_info->irq = ret;
 	ring_info->port = alloc_unbound.port;
 
@@ -226,109 +244,128 @@ int hyper_dmabuf_exporter_ringbuf_init(int rdomain)
 		ring_info->port,
 		ring_info->irq);
 
-	ret = hyper_dmabuf_register_exporter_ring(ring_info);
+	ret = xen_comm_add_tx_ring(ring_info);
 
-	ret = hyper_dmabuf_expose_ring_details(hyper_dmabuf_get_domid(), rdomain,
-                                               ring_info->gref_ring, ring_info->port);
+	ret = xen_comm_expose_ring_details(hyper_dmabuf_get_domid(), domid,
+					   ring_info->gref_ring, ring_info->port);
 
 	/*
 	 * Register watch for remote domain exporter ring.
-	 * When remote domain will setup its exporter ring, we will automatically connect our importer ring to it.
+	 * When remote domain will setup its exporter ring,
+	 * we will automatically connect our importer ring to it.
 	 */
-	ring_info->watch.callback = remote_domain_exporter_watch_cb;
+	ring_info->watch.callback = remote_dom_exporter_watch_cb;
 	ring_info->watch.node = (const char*) kmalloc(sizeof(char) * 255, GFP_KERNEL);
-	sprintf((char*)ring_info->watch.node, "/local/domain/%d/data/hyper_dmabuf/%d/port", rdomain, hyper_dmabuf_get_domid());
+	sprintf((char*)ring_info->watch.node,
+		"/local/domain/%d/data/hyper_dmabuf/%d/port",
+		domid, hyper_dmabuf_get_domid());
+
 	register_xenbus_watch(&ring_info->watch);
 
 	return ret;
 }
 
 /* cleans up exporter ring created for given remote domain */
-void hyper_dmabuf_exporter_ringbuf_cleanup(int rdomain)
+void hyper_dmabuf_xen_cleanup_tx_rbuf(int domid)
 {
-	struct hyper_dmabuf_ring_info_export *ring_info;
+	struct xen_comm_tx_ring_info *ring_info;
 
 	/* check if we at all have exporter ring for given rdomain */
-	ring_info = hyper_dmabuf_find_exporter_ring(rdomain);
+	ring_info = xen_comm_find_tx_ring(domid);
 
 	if (!ring_info) {
 		return;
 	}
 
-	hyper_dmabuf_remove_exporter_ring(rdomain);
+	xen_comm_remove_tx_ring(domid);
 
 	unregister_xenbus_watch(&ring_info->watch);
 	kfree(ring_info->watch.node);
 
-	/* No need to close communication channel, will be done by this function */
-	unbind_from_irqhandler(ring_info->irq,	(void*) ring_info);
+	/* No need to close communication channel, will be done by
+	 * this function
+	 */
+	unbind_from_irqhandler(ring_info->irq, (void*) ring_info);
 
-	/* No need to free sring page, will be freed by this function when other side will end its access */
+	/* No need to free sring page, will be freed by this function
+	 * when other side will end its access
+	 */
 	gnttab_end_foreign_access(ring_info->gref_ring, 0,
 				  (unsigned long) ring_info->ring_front.sring);
 
 	kfree(ring_info);
 }
 
-/* importer needs to know about shared page and port numbers for ring buffer and event channel */
-int hyper_dmabuf_importer_ringbuf_init(int sdomain)
+/* importer needs to know about shared page and port numbers for
+ * ring buffer and event channel
+ */
+int hyper_dmabuf_xen_init_rx_rbuf(int domid)
 {
-	struct hyper_dmabuf_ring_info_import *ring_info;
-	struct hyper_dmabuf_sring *sring;
+	struct xen_comm_rx_ring_info *ring_info;
+	struct xen_comm_sring *sring;
 
 	struct page *shared_ring;
 
-	struct gnttab_map_grant_ref *ops;
+	struct gnttab_map_grant_ref *map_ops;
+
 	int ret;
-	int importer_gref, importer_port;
+	int rx_gref, rx_port;
 
-	ret = hyper_dmabuf_get_ring_details(hyper_dmabuf_get_domid(), sdomain,
-					    &importer_gref, &importer_port);
+	/* check if there's existing rx ring channel */
+	ring_info = xen_comm_find_rx_ring(domid);
+
+	if (ring_info) {
+		printk("rx ring ch from domid = %d already exist\n", ring_info->sdomain);
+		return 0;
+	}
+
+	ret = xen_comm_get_ring_details(hyper_dmabuf_get_domid(), domid,
+					&rx_gref, &rx_port);
 
 	if (ret) {
-		printk("Domain %d has not created exporter ring for current domain\n", sdomain);
+		printk("Domain %d has not created exporter ring for current domain\n", domid);
 		return ret;
 	}
 
-	ring_info = (struct hyper_dmabuf_ring_info_import *)
-			kmalloc(sizeof(*ring_info), GFP_KERNEL);
+	ring_info = kmalloc(sizeof(*ring_info), GFP_KERNEL);
 
-	ring_info->sdomain = sdomain;
-	ring_info->evtchn = importer_port;
+	ring_info->sdomain = domid;
+	ring_info->evtchn = rx_port;
 
-	ops = (struct gnttab_map_grant_ref*)kmalloc(sizeof(*ops), GFP_KERNEL);
+	map_ops = kmalloc(sizeof(*map_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, importer_gref, sdomain);
+	gnttab_set_map_op(&map_ops[0], (unsigned long)pfn_to_kaddr(page_to_pfn(shared_ring)),
+			  GNTMAP_host_map, rx_gref, domid);
+
 	gnttab_set_unmap_op(&ring_info->unmap_op, (unsigned long)pfn_to_kaddr(page_to_pfn(shared_ring)),
-			GNTMAP_host_map, -1);
+			    GNTMAP_host_map, -1);
 
-	ret = gnttab_map_refs(ops, NULL, &shared_ring, 1);
+	ret = gnttab_map_refs(map_ops, NULL, &shared_ring, 1);
 	if (ret < 0) {
 		printk("Cannot map ring\n");
 		return -EINVAL;
 	}
 
-	if (ops[0].status) {
+	if (map_ops[0].status) {
 		printk("Ring mapping failed\n");
 		return -EINVAL;
 	} else {
-		ring_info->unmap_op.handle = ops[0].handle;
+		ring_info->unmap_op.handle = map_ops[0].handle;
 	}
 
-	kfree(ops);
+	kfree(map_ops);
 
-	sring = (struct hyper_dmabuf_sring*) pfn_to_kaddr(page_to_pfn(shared_ring));
+	sring = (struct xen_comm_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, importer_port,
-						hyper_dmabuf_back_ring_isr, 0,
-						NULL, (void*)ring_info);
+	ret = bind_interdomain_evtchn_to_irqhandler(domid, rx_port,
+						    back_ring_isr, 0,
+						    NULL, (void*)ring_info);
 	if (ret < 0) {
 		return -EINVAL;
 	}
@@ -336,35 +373,35 @@ int hyper_dmabuf_importer_ringbuf_init(int sdomain)
 	ring_info->irq = ret;
 
 	printk("%s: bound to eventchannel port: %d  irq: %d\n", __func__,
-		importer_port,
+		rx_port,
 		ring_info->irq);
 
-	ret = hyper_dmabuf_register_importer_ring(ring_info);
+	ret = xen_comm_add_rx_ring(ring_info);
 
 	/* Setup communcation channel in opposite direction */
-	if (!hyper_dmabuf_find_exporter_ring(sdomain)) {
-		ret = hyper_dmabuf_exporter_ringbuf_init(sdomain);
+	if (!xen_comm_find_tx_ring(domid)) {
+		ret = hyper_dmabuf_xen_init_tx_rbuf(domid);
 	}
 
 	return ret;
 }
 
 /* clenas up importer ring create for given source domain */
-void hyper_dmabuf_importer_ringbuf_cleanup(int sdomain)
+void hyper_dmabuf_xen_cleanup_rx_rbuf(int domid)
 {
-	struct hyper_dmabuf_ring_info_import *ring_info;
+	struct xen_comm_rx_ring_info *ring_info;
 	struct page *shared_ring;
 
 	/* check if we have importer ring created for given sdomain */
-	ring_info = hyper_dmabuf_find_importer_ring(sdomain);
+	ring_info = xen_comm_find_rx_ring(domid);
 
 	if (!ring_info)
 		return;
 
-	hyper_dmabuf_remove_importer_ring(sdomain);
+	xen_comm_remove_rx_ring(domid);
 
 	/* no need to close event channel, will be done by that function */
-	unbind_from_irqhandler(ring_info->irq,	(void*) ring_info);
+	unbind_from_irqhandler(ring_info->irq, (void*)ring_info);
 
 	/* unmapping shared ring page */
 	shared_ring = virt_to_page(ring_info->ring_back.sring);
@@ -374,23 +411,39 @@ void hyper_dmabuf_importer_ringbuf_cleanup(int sdomain)
 	kfree(ring_info);
 }
 
-/* cleans up all exporter/importer rings */
-void hyper_dmabuf_cleanup_ringbufs(void)
+int hyper_dmabuf_xen_init_comm_env(void)
 {
-	hyper_dmabuf_foreach_exporter_ring(hyper_dmabuf_exporter_ringbuf_cleanup);
-	hyper_dmabuf_foreach_importer_ring(hyper_dmabuf_importer_ringbuf_cleanup);
+	int ret;
+
+	xen_comm_ring_table_init();
+	ret = xen_comm_setup_data_dir();
+
+	return ret;
 }
 
-int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req, int wait)
+/* cleans up all tx/rx rings */
+static void hyper_dmabuf_xen_cleanup_all_rbufs(void)
 {
-	struct hyper_dmabuf_front_ring *ring;
-	struct hyper_dmabuf_ring_rq *new_req;
-	struct hyper_dmabuf_ring_info_export *ring_info;
+	xen_comm_foreach_tx_ring(hyper_dmabuf_xen_cleanup_tx_rbuf);
+	xen_comm_foreach_rx_ring(hyper_dmabuf_xen_cleanup_rx_rbuf);
+}
+
+void hyper_dmabuf_xen_destroy_comm(void)
+{
+	hyper_dmabuf_xen_cleanup_all_rbufs();
+	xen_comm_destroy_data_dir();
+}
+
+int hyper_dmabuf_xen_send_req(int domid, struct hyper_dmabuf_req *req, int wait)
+{
+	struct xen_comm_front_ring *ring;
+	struct hyper_dmabuf_req *new_req;
+	struct xen_comm_tx_ring_info *ring_info;
 	int notify;
 	int timeout = 1000;
 
 	/* find a ring info for the channel */
-	ring_info = hyper_dmabuf_find_exporter_ring(domain);
+	ring_info = xen_comm_find_tx_ring(domid);
 	if (!ring_info) {
 		printk("Can't find ring info for the channel\n");
 		return -EINVAL;
@@ -407,6 +460,8 @@ int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req, int
 		return -EIO;
 	}
 
+	req->request_id = xen_comm_next_req_id();
+
 	/* update req_pending with current request */
 	memcpy(&req_pending, req, sizeof(req_pending));
 
@@ -438,19 +493,19 @@ int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req, int
 }
 
 /* ISR for handling request */
-static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *info)
+static irqreturn_t back_ring_isr(int irq, void *info)
 {
 	RING_IDX rc, rp;
-	struct hyper_dmabuf_ring_rq req;
-	struct hyper_dmabuf_ring_rp resp;
+	struct hyper_dmabuf_req req;
+	struct hyper_dmabuf_resp resp;
 
 	int notify, more_to_do;
 	int ret;
 
-	struct hyper_dmabuf_ring_info_import *ring_info;
-	struct hyper_dmabuf_back_ring *ring;
+	struct xen_comm_rx_ring_info *ring_info;
+	struct xen_comm_back_ring *ring;
 
-	ring_info = (struct hyper_dmabuf_ring_info_import *)info;
+	ring_info = (struct xen_comm_rx_ring_info *)info;
 	ring = &ring_info->ring_back;
 
 	do {
@@ -490,17 +545,17 @@ static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *info)
 }
 
 /* ISR for handling responses */
-static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, void *info)
+static irqreturn_t front_ring_isr(int irq, void *info)
 {
 	/* front ring only care about response from back */
-	struct hyper_dmabuf_ring_rp *resp;
+	struct hyper_dmabuf_resp *resp;
 	RING_IDX i, rp;
 	int more_to_do, ret;
 
-	struct hyper_dmabuf_ring_info_export *ring_info;
-	struct hyper_dmabuf_front_ring *ring;
+	struct xen_comm_tx_ring_info *ring_info;
+	struct xen_comm_front_ring *ring;
 
-	ring_info = (struct hyper_dmabuf_ring_info_export *)info;
+	ring_info = (struct xen_comm_tx_ring_info *)info;
 	ring = &ring_info->ring_front;
 
 	do {
@@ -518,7 +573,7 @@ static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, void *info)
 			if (resp->status == HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP) {
 				/* parsing response */
 				ret = hyper_dmabuf_msg_parse(ring_info->rdomain,
-							(struct hyper_dmabuf_ring_rq *)resp);
+							(struct hyper_dmabuf_req *)resp);
 
 				if (ret < 0) {
 					printk("getting error while parsing response\n");
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h
index 4ab031a..ba41e9d 100644
--- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h
@@ -3,27 +3,14 @@
 
 #include "xen/interface/io/ring.h"
 #include "xen/xenbus.h"
+#include "../hyper_dmabuf_msg.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(xen_comm, struct hyper_dmabuf_req, struct hyper_dmabuf_resp);
 
-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;
+struct xen_comm_tx_ring_info {
+        struct xen_comm_front_ring ring_front;
 	int rdomain;
         int gref_ring;
         int irq;
@@ -31,39 +18,35 @@ struct hyper_dmabuf_ring_info_export {
 	struct xenbus_watch watch;
 };
 
-struct hyper_dmabuf_ring_info_import {
+struct xen_comm_rx_ring_info {
         int sdomain;
         int irq;
         int evtchn;
-        struct hyper_dmabuf_back_ring ring_back;
+        struct xen_comm_back_ring ring_back;
 	struct gnttab_unmap_grant_ref unmap_op;
 };
 
-int32_t hyper_dmabuf_get_domid(void);
-int32_t hyper_dmabuf_setup_data_dir(void);
-int32_t hyper_dmabuf_destroy_data_dir(void);
+int hyper_dmabuf_get_domid(void);
 
-int hyper_dmabuf_next_req_id_export(void);
+int hyper_dmabuf_xen_init_comm_env(void);
 
 /* exporter needs to generated info for page sharing */
-int hyper_dmabuf_exporter_ringbuf_init(int rdomain);
+int hyper_dmabuf_xen_init_tx_rbuf(int domid);
 
-/* importer needs to know about shared page and port numbers for ring buffer and event channel */
-int hyper_dmabuf_importer_ringbuf_init(int sdomain);
+/* importer needs to know about shared page and port numbers
+ * for ring buffer and event channel
+ */
+int hyper_dmabuf_xen_init_rx_rbuf(int domid);
 
 /* cleans up exporter ring created for given domain */
-void hyper_dmabuf_exporter_ringbuf_cleanup(int rdomain);
+void hyper_dmabuf_xen_cleanup_tx_rbuf(int domid);
 
 /* cleans up importer ring created for given domain */
-void hyper_dmabuf_importer_ringbuf_cleanup(int sdomain);
+void hyper_dmabuf_xen_cleanup_rx_rbuf(int domid);
 
-/* cleans up all exporter/importer rings */
-void hyper_dmabuf_cleanup_ringbufs(void);
+void hyper_dmabuf_xen_destroy_comm(void);
 
 /* send request to the remote domain */
-int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req, int wait);
-
-/* called by interrupt (WORKQUEUE) */
-int hyper_dmabuf_send_response(struct hyper_dmabuf_ring_rp* response, int domain);
+int hyper_dmabuf_xen_send_req(int domid, struct hyper_dmabuf_req *req, int wait);
 
 #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
index a068276..2a1f45b 100644
--- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c
@@ -9,80 +9,73 @@
 #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);
+DECLARE_HASHTABLE(xen_comm_tx_ring_hash, MAX_ENTRY_TX_RING);
+DECLARE_HASHTABLE(xen_comm_rx_ring_hash, MAX_ENTRY_RX_RING);
 
-int hyper_dmabuf_ring_table_init()
+void xen_comm_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;
+	hash_init(xen_comm_rx_ring_hash);
+	hash_init(xen_comm_tx_ring_hash);
 }
 
-int hyper_dmabuf_register_exporter_ring(struct hyper_dmabuf_ring_info_export *ring_info)
+int xen_comm_add_tx_ring(struct xen_comm_tx_ring_info *ring_info)
 {
-	struct hyper_dmabuf_exporter_ring_info *info_entry;
+	struct xen_comm_tx_ring_info_entry *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,
+	hash_add(xen_comm_tx_ring_hash, &info_entry->node,
 		info_entry->info->rdomain);
 
 	return 0;
 }
 
-int hyper_dmabuf_register_importer_ring(struct hyper_dmabuf_ring_info_import *ring_info)
+int xen_comm_add_rx_ring(struct xen_comm_rx_ring_info *ring_info)
 {
-	struct hyper_dmabuf_importer_ring_info *info_entry;
+	struct xen_comm_rx_ring_info_entry *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,
+	hash_add(xen_comm_rx_ring_hash, &info_entry->node,
 		info_entry->info->sdomain);
 
 	return 0;
 }
 
-struct hyper_dmabuf_ring_info_export *hyper_dmabuf_find_exporter_ring(int domid)
+struct xen_comm_tx_ring_info *xen_comm_find_tx_ring(int domid)
 {
-	struct hyper_dmabuf_exporter_ring_info *info_entry;
+	struct xen_comm_tx_ring_info_entry *info_entry;
 	int bkt;
 
-	hash_for_each(hyper_dmabuf_hash_exporter_ring, bkt, info_entry, node)
+	hash_for_each(xen_comm_tx_ring_hash, 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 xen_comm_rx_ring_info *xen_comm_find_rx_ring(int domid)
 {
-	struct hyper_dmabuf_importer_ring_info *info_entry;
+	struct xen_comm_rx_ring_info_entry *info_entry;
 	int bkt;
 
-	hash_for_each(hyper_dmabuf_hash_importer_ring, bkt, info_entry, node)
+	hash_for_each(xen_comm_rx_ring_hash, bkt, info_entry, node)
 		if(info_entry->info->sdomain == domid)
 			return info_entry->info;
 
 	return NULL;
 }
 
-int hyper_dmabuf_remove_exporter_ring(int domid)
+int xen_comm_remove_tx_ring(int domid)
 {
-	struct hyper_dmabuf_exporter_ring_info *info_entry;
+	struct xen_comm_tx_ring_info_entry *info_entry;
 	int bkt;
 
-	hash_for_each(hyper_dmabuf_hash_exporter_ring, bkt, info_entry, node)
+	hash_for_each(xen_comm_tx_ring_hash, bkt, info_entry, node)
 		if(info_entry->info->rdomain == domid) {
 			hash_del(&info_entry->node);
 			kfree(info_entry);
@@ -92,12 +85,12 @@ int hyper_dmabuf_remove_exporter_ring(int domid)
 	return -1;
 }
 
-int hyper_dmabuf_remove_importer_ring(int domid)
+int xen_comm_remove_rx_ring(int domid)
 {
-	struct hyper_dmabuf_importer_ring_info *info_entry;
+	struct xen_comm_rx_ring_info_entry *info_entry;
 	int bkt;
 
-	hash_for_each(hyper_dmabuf_hash_importer_ring, bkt, info_entry, node)
+	hash_for_each(xen_comm_rx_ring_hash, bkt, info_entry, node)
 		if(info_entry->info->sdomain == domid) {
 			hash_del(&info_entry->node);
 			kfree(info_entry);
@@ -107,24 +100,26 @@ int hyper_dmabuf_remove_importer_ring(int domid)
 	return -1;
 }
 
-void hyper_dmabuf_foreach_exporter_ring(void (*func)(int rdom))
+void xen_comm_foreach_tx_ring(void (*func)(int domid))
 {
-	struct hyper_dmabuf_exporter_ring_info *info_entry;
+	struct xen_comm_tx_ring_info_entry *info_entry;
 	struct hlist_node *tmp;
 	int bkt;
 
-	hash_for_each_safe(hyper_dmabuf_hash_exporter_ring, bkt, tmp, info_entry, node) {
+	hash_for_each_safe(xen_comm_tx_ring_hash, bkt, tmp,
+			   info_entry, node) {
 		func(info_entry->info->rdomain);
 	}
 }
 
-void hyper_dmabuf_foreach_importer_ring(void (*func)(int sdom))
+void xen_comm_foreach_rx_ring(void (*func)(int domid))
 {
-	struct hyper_dmabuf_importer_ring_info *info_entry;
+	struct xen_comm_rx_ring_info_entry *info_entry;
 	struct hlist_node *tmp;
 	int bkt;
 
-	hash_for_each_safe(hyper_dmabuf_hash_importer_ring, bkt, tmp, info_entry, node) {
+	hash_for_each_safe(xen_comm_rx_ring_hash, bkt, tmp,
+			   info_entry, node) {
 		func(info_entry->info->sdomain);
 	}
 }
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
index fd1958c..18b3afd 100644
--- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h
@@ -2,40 +2,38 @@
 #define __HYPER_DMABUF_XEN_COMM_LIST_H__
 
 /* number of bits to be used for exported dmabufs hash table */
-#define MAX_ENTRY_EXPORT_RING 7
+#define MAX_ENTRY_TX_RING 7
 /* number of bits to be used for imported dmabufs hash table */
-#define MAX_ENTRY_IMPORT_RING 7
+#define MAX_ENTRY_RX_RING 7
 
-struct hyper_dmabuf_exporter_ring_info {
-        struct hyper_dmabuf_ring_info_export *info;
+struct xen_comm_tx_ring_info_entry {
+        struct xen_comm_tx_ring_info *info;
         struct hlist_node node;
 };
 
-struct hyper_dmabuf_importer_ring_info {
-        struct hyper_dmabuf_ring_info_import *info;
+struct xen_comm_rx_ring_info_entry {
+        struct xen_comm_rx_ring_info *info;
         struct hlist_node node;
 };
 
-int hyper_dmabuf_ring_table_init(void);
+void xen_comm_ring_table_init(void);
 
-int hyper_dmabuf_ring_table_destroy(void);
+int xen_comm_add_tx_ring(struct xen_comm_tx_ring_info *ring_info);
 
-int hyper_dmabuf_register_exporter_ring(struct hyper_dmabuf_ring_info_export *ring_info);
+int xen_comm_add_rx_ring(struct xen_comm_rx_ring_info *ring_info);
 
-int hyper_dmabuf_register_importer_ring(struct hyper_dmabuf_ring_info_import *ring_info);
+int xen_comm_remove_tx_ring(int domid);
 
-struct hyper_dmabuf_ring_info_export *hyper_dmabuf_find_exporter_ring(int domid);
+int xen_comm_remove_rx_ring(int domid);
 
-struct hyper_dmabuf_ring_info_import *hyper_dmabuf_find_importer_ring(int domid);
+struct xen_comm_tx_ring_info *xen_comm_find_tx_ring(int domid);
 
-int hyper_dmabuf_remove_exporter_ring(int domid);
-
-int hyper_dmabuf_remove_importer_ring(int domid);
+struct xen_comm_rx_ring_info *xen_comm_find_rx_ring(int domid);
 
 /* iterates over all exporter rings and calls provided function for each of them */
-void hyper_dmabuf_foreach_exporter_ring(void (*func)(int rdom));
+void xen_comm_foreach_tx_ring(void (*func)(int domid));
 
 /* iterates over all importer rings and calls provided function for each of them */
-void hyper_dmabuf_foreach_importer_ring(void (*func)(int sdom));
+void xen_comm_foreach_rx_ring(void (*func)(int domid));
 
 #endif // __HYPER_DMABUF_XEN_COMM_LIST_H__
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.c
new file mode 100644
index 0000000..e7b871a
--- /dev/null
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.c
@@ -0,0 +1,22 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <xen/grant_table.h>
+#include "../hyper_dmabuf_msg.h"
+#include "../hyper_dmabuf_drv.h"
+#include "hyper_dmabuf_xen_drv.h"
+#include "hyper_dmabuf_xen_comm.h"
+#include "hyper_dmabuf_xen_shm.h"
+
+struct hyper_dmabuf_backend_ops xen_backend_ops = {
+	.get_vm_id = hyper_dmabuf_get_domid,
+	.share_pages = hyper_dmabuf_xen_share_pages,
+	.unshare_pages = hyper_dmabuf_xen_unshare_pages,
+	.map_shared_pages = (void *)hyper_dmabuf_xen_map_shared_pages,
+	.unmap_shared_pages = hyper_dmabuf_xen_unmap_shared_pages,
+	.init_comm_env = hyper_dmabuf_xen_init_comm_env,
+	.destroy_comm = hyper_dmabuf_xen_destroy_comm,
+	.init_rx_ch = hyper_dmabuf_xen_init_rx_rbuf,
+	.init_tx_ch = hyper_dmabuf_xen_init_tx_rbuf,
+	.send_req = hyper_dmabuf_xen_send_req,
+};
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.h b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.h
new file mode 100644
index 0000000..e351c08
--- /dev/null
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.h
@@ -0,0 +1,20 @@
+#ifndef __HYPER_DMABUF_XEN_DRV_H__
+#define __HYPER_DMABUF_XEN_DRV_H__
+#include <xen/interface/grant_table.h>
+
+extern struct hyper_dmabuf_backend_ops xen_backend_ops;
+
+/* Main purpose of this structure is to keep
+ * all references created or acquired for sharing
+ * pages with another domain for freeing those later
+ * when unsharing.
+ */
+struct xen_shared_pages_info {
+        grant_ref_t lvl3_gref; /* top level refid */
+        grant_ref_t *lvl3_table; /* page of top level addressing, it contains refids of 2nd level pages */
+        grant_ref_t *lvl2_table; /* table of 2nd level pages, that contains refids to data pages */
+        struct gnttab_unmap_grant_ref* unmap_ops; /* unmap ops for mapped pages */
+        struct page **data_pages; /* data pages to be unmapped */
+};
+
+#endif // __HYPER_DMABUF_XEN_COMM_H__
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c
new file mode 100644
index 0000000..c0045d4
--- /dev/null
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c
@@ -0,0 +1,356 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <xen/grant_table.h>
+#include <asm/xen/page.h>
+#include "hyper_dmabuf_xen_drv.h"
+
+#define REFS_PER_PAGE (PAGE_SIZE/sizeof(grant_ref_t))
+
+/*
+ * 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.
+ *
+ *      3rd 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.
+ */
+int hyper_dmabuf_xen_share_pages(struct page **pages, int domid, int nents,
+				 void **refs_info)
+{
+	grant_ref_t lvl3_gref;
+	grant_ref_t *lvl2_table;
+	grant_ref_t *lvl3_table;
+
+	/*
+	 * Calculate number of pages needed for 2nd level addresing:
+	 */
+	int n_lvl2_grefs = (nents/REFS_PER_PAGE +
+			   ((nents % REFS_PER_PAGE) ? 1: 0));
+
+	struct xen_shared_pages_info *sh_pages_info;
+	int i;
+
+	lvl3_table = (grant_ref_t *)__get_free_pages(GFP_KERNEL, 1);
+	lvl2_table = (grant_ref_t *)__get_free_pages(GFP_KERNEL, n_lvl2_grefs);
+
+	sh_pages_info = kmalloc(sizeof(*sh_pages_info), GFP_KERNEL);
+	*refs_info = (void *)sh_pages_info;
+
+	/* share data pages in rw mode*/
+	for (i=0; i<nents; i++) {
+		lvl2_table[i] = gnttab_grant_foreign_access(domid,
+							    pfn_to_mfn(page_to_pfn(pages[i])),
+							    0);
+	}
+
+	/* Share 2nd level addressing pages in readonly mode*/
+	for (i=0; i< n_lvl2_grefs; i++) {
+		lvl3_table[i] = gnttab_grant_foreign_access(domid,
+							   virt_to_mfn((unsigned long)lvl2_table+i*PAGE_SIZE ),
+							   1);
+	}
+
+	/* Share lvl3_table in readonly mode*/
+	lvl3_gref = gnttab_grant_foreign_access(domid,
+						virt_to_mfn((unsigned long)lvl3_table),
+						1);
+
+
+	/* Store lvl3_table page to be freed later */
+	sh_pages_info->lvl3_table = lvl3_table;
+
+	/* Store lvl2_table pages to be freed later */
+	sh_pages_info->lvl2_table = lvl2_table;
+
+	/* Store exported pages refid to be unshared later */
+	sh_pages_info->lvl3_gref = lvl3_gref;
+
+	return lvl3_gref;
+}
+
+int hyper_dmabuf_xen_unshare_pages(void **refs_info, int nents) {
+	struct xen_shared_pages_info *sh_pages_info;
+	int n_lvl2_grefs = (nents/REFS_PER_PAGE + ((nents % REFS_PER_PAGE) ? 1: 0));
+	int i;
+
+	sh_pages_info = (struct xen_shared_pages_info *)(*refs_info);
+
+	if (sh_pages_info->lvl3_table == NULL ||
+	    sh_pages_info->lvl2_table ==  NULL ||
+	    sh_pages_info->lvl3_gref == -1) {
+		printk("gref table for hyper_dmabuf already cleaned up\n");
+		return 0;
+	}
+
+	/* End foreign access for data pages, but do not free them */
+	for (i = 0; i < nents; i++) {
+		if (gnttab_query_foreign_access(sh_pages_info->lvl2_table[i])) {
+			printk("refid not shared !!\n");
+		}
+		gnttab_end_foreign_access_ref(sh_pages_info->lvl2_table[i], 0);
+		gnttab_free_grant_reference(sh_pages_info->lvl2_table[i]);
+	}
+
+	/* End foreign access for 2nd level addressing pages */
+	for (i = 0; i < n_lvl2_grefs; i++) {
+		if (gnttab_query_foreign_access(sh_pages_info->lvl3_table[i])) {
+			printk("refid not shared !!\n");
+		}
+		if (!gnttab_end_foreign_access_ref(sh_pages_info->lvl3_table[i], 1)) {
+			printk("refid still in use!!!\n");
+		}
+		gnttab_free_grant_reference(sh_pages_info->lvl3_table[i]);
+	}
+
+	/* End foreign access for top level addressing page */
+	if (gnttab_query_foreign_access(sh_pages_info->lvl3_gref)) {
+		printk("gref not shared !!\n");
+	}
+
+	gnttab_end_foreign_access_ref(sh_pages_info->lvl3_gref, 1);
+	gnttab_free_grant_reference(sh_pages_info->lvl3_gref);
+
+	/* freeing all pages used for 2 level addressing */
+	free_pages((unsigned long)sh_pages_info->lvl2_table, n_lvl2_grefs);
+	free_pages((unsigned long)sh_pages_info->lvl3_table, 1);
+
+	sh_pages_info->lvl3_gref = -1;
+	sh_pages_info->lvl2_table = NULL;
+	sh_pages_info->lvl3_table = NULL;
+	kfree(sh_pages_info);
+	sh_pages_info = NULL;
+
+	return 0;
+}
+
+/*
+ * Maps provided top level ref id and then return array of pages containing data refs.
+ */
+struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int nents, void **refs_info)
+{
+	struct page *lvl3_table_page;
+	struct page **lvl2_table_pages;
+	struct page **data_pages;
+	struct xen_shared_pages_info *sh_pages_info;
+
+	grant_ref_t *lvl3_table;
+	grant_ref_t *lvl2_table;
+
+	struct gnttab_map_grant_ref lvl3_map_ops;
+	struct gnttab_unmap_grant_ref lvl3_unmap_ops;
+
+	struct gnttab_map_grant_ref *lvl2_map_ops;
+	struct gnttab_unmap_grant_ref *lvl2_unmap_ops;
+
+	struct gnttab_map_grant_ref *data_map_ops;
+	struct gnttab_unmap_grant_ref *data_unmap_ops;
+
+	int nents_last = nents % REFS_PER_PAGE;
+	int n_lvl2_grefs = (nents / REFS_PER_PAGE) + ((nents_last > 0) ? 1 : 0);
+	int i, j, k;
+
+	sh_pages_info = kmalloc(sizeof(*sh_pages_info), GFP_KERNEL);
+	*refs_info = (void *) sh_pages_info;
+
+	lvl2_table_pages = kcalloc(sizeof(struct page*), n_lvl2_grefs, GFP_KERNEL);
+	data_pages = kcalloc(sizeof(struct page*), nents, GFP_KERNEL);
+
+	lvl2_map_ops = kcalloc(sizeof(*lvl2_map_ops), n_lvl2_grefs, GFP_KERNEL);
+	lvl2_unmap_ops = kcalloc(sizeof(*lvl2_unmap_ops), n_lvl2_grefs, GFP_KERNEL);
+
+	data_map_ops = kcalloc(sizeof(*data_map_ops), nents, GFP_KERNEL);
+	data_unmap_ops = kcalloc(sizeof(*data_unmap_ops), nents, GFP_KERNEL);
+
+	/* Map top level addressing page */
+	if (gnttab_alloc_pages(1, &lvl3_table_page)) {
+		printk("Cannot allocate pages\n");
+		return NULL;
+	}
+
+	lvl3_table = (grant_ref_t *)pfn_to_kaddr(page_to_pfn(lvl3_table_page));
+
+	gnttab_set_map_op(&lvl3_map_ops, (unsigned long)lvl3_table, GNTMAP_host_map | GNTMAP_readonly,
+			  (grant_ref_t)lvl3_gref, domid);
+
+	gnttab_set_unmap_op(&lvl3_unmap_ops, (unsigned long)lvl3_table, GNTMAP_host_map | GNTMAP_readonly, -1);
+
+	if (gnttab_map_refs(&lvl3_map_ops, NULL, &lvl3_table_page, 1)) {
+		printk("\nxen: dom0: HYPERVISOR map grant ref failed");
+		return NULL;
+	}
+
+	if (lvl3_map_ops.status) {
+		printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d",
+			lvl3_map_ops.status);
+		return NULL;
+	} else {
+		lvl3_unmap_ops.handle = lvl3_map_ops.handle;
+	}
+
+	/* Map all second level pages */
+	if (gnttab_alloc_pages(n_lvl2_grefs, lvl2_table_pages)) {
+		printk("Cannot allocate pages\n");
+		return NULL;
+	}
+
+	for (i = 0; i < n_lvl2_grefs; i++) {
+		lvl2_table = (grant_ref_t *)pfn_to_kaddr(page_to_pfn(lvl2_table_pages[i]));
+		gnttab_set_map_op(&lvl2_map_ops[i], (unsigned long)lvl2_table, GNTMAP_host_map | GNTMAP_readonly,
+				  lvl3_table[i], domid);
+		gnttab_set_unmap_op(&lvl2_unmap_ops[i], (unsigned long)lvl2_table, GNTMAP_host_map | GNTMAP_readonly, -1);
+	}
+
+	/* Unmap top level page, as it won't be needed any longer */
+	if (gnttab_unmap_refs(&lvl3_unmap_ops, NULL, &lvl3_table_page, 1)) {
+		printk("\xen: cannot unmap top level page\n");
+		return NULL;
+	}
+
+	if (gnttab_map_refs(lvl2_map_ops, NULL, lvl2_table_pages, n_lvl2_grefs)) {
+		printk("\nxen: dom0: HYPERVISOR map grant ref failed");
+		return NULL;
+	}
+
+	/* Checks if pages were mapped correctly */
+	for (i = 0; i < n_lvl2_grefs; i++) {
+		if (lvl2_map_ops[i].status) {
+			printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d",
+			       lvl2_map_ops[i].status);
+			return NULL;
+		} else {
+			lvl2_unmap_ops[i].handle = lvl2_map_ops[i].handle;
+		}
+	}
+
+	if (gnttab_alloc_pages(nents, data_pages)) {
+		printk("Cannot allocate pages\n");
+		return NULL;
+	}
+
+	k = 0;
+
+	for (i = 0; i < (nents_last ? n_lvl2_grefs - 1 : n_lvl2_grefs); i++) {
+		lvl2_table = pfn_to_kaddr(page_to_pfn(lvl2_table_pages[i]));
+		for (j = 0; j < REFS_PER_PAGE; j++) {
+			gnttab_set_map_op(&data_map_ops[k],
+					  (unsigned long)pfn_to_kaddr(page_to_pfn(data_pages[k])),
+					  GNTMAP_host_map,
+					  lvl2_table[j], domid);
+
+			gnttab_set_unmap_op(&data_unmap_ops[k],
+					    (unsigned long)pfn_to_kaddr(page_to_pfn(data_pages[k])),
+					    GNTMAP_host_map, -1);
+			k++;
+		}
+	}
+
+	/* for grefs in the last lvl2 table page */
+	lvl2_table = pfn_to_kaddr(page_to_pfn(lvl2_table_pages[n_lvl2_grefs - 1]));
+
+	for (j = 0; j < nents_last; j++) {
+		gnttab_set_map_op(&data_map_ops[k],
+				  (unsigned long)pfn_to_kaddr(page_to_pfn(data_pages[k])),
+				  GNTMAP_host_map,
+				  lvl2_table[j], domid);
+
+		gnttab_set_unmap_op(&data_unmap_ops[k],
+				    (unsigned long)pfn_to_kaddr(page_to_pfn(data_pages[k])),
+				    GNTMAP_host_map, -1);
+		k++;
+	}
+
+	if (gnttab_map_refs(data_map_ops, NULL, data_pages, nents)) {
+		printk("\nxen: dom0: HYPERVISOR map grant ref failed\n");
+		return NULL;
+	}
+
+	/* unmapping lvl2 table pages */
+	if (gnttab_unmap_refs(lvl2_unmap_ops, NULL, lvl2_table_pages,
+			      n_lvl2_grefs)) {
+		printk("Cannot unmap 2nd level refs\n");
+		return NULL;
+	}
+
+	for (i = 0; i < nents; i++) {
+		if (data_map_ops[i].status) {
+			printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d\n",
+				data_map_ops[i].status);
+			return NULL;
+		} else {
+			data_unmap_ops[i].handle = data_map_ops[i].handle;
+		}
+	}
+
+	/* store these references for unmapping in the future */
+	sh_pages_info->unmap_ops = data_unmap_ops;
+	sh_pages_info->data_pages = data_pages;
+
+	gnttab_free_pages(1, &lvl3_table_page);
+	gnttab_free_pages(n_lvl2_grefs, lvl2_table_pages);
+	kfree(lvl2_table_pages);
+	kfree(lvl2_map_ops);
+	kfree(lvl2_unmap_ops);
+	kfree(data_map_ops);
+
+	return data_pages;
+}
+
+int hyper_dmabuf_xen_unmap_shared_pages(void **refs_info, int nents) {
+	struct xen_shared_pages_info *sh_pages_info;
+
+	sh_pages_info = (struct xen_shared_pages_info *)(*refs_info);
+
+	if (sh_pages_info->unmap_ops == NULL ||
+	    sh_pages_info->data_pages == NULL) {
+		printk("Imported pages already cleaned up or buffer was not imported yet\n");
+		return 0;
+	}
+
+	if (gnttab_unmap_refs(sh_pages_info->unmap_ops, NULL,
+			      sh_pages_info->data_pages, nents) ) {
+		printk("Cannot unmap data pages\n");
+		return -EINVAL;
+	}
+
+	gnttab_free_pages(nents, sh_pages_info->data_pages);
+
+	kfree(sh_pages_info->data_pages);
+	kfree(sh_pages_info->unmap_ops);
+	sh_pages_info->unmap_ops = NULL;
+	sh_pages_info->data_pages = NULL;
+	kfree(sh_pages_info);
+	sh_pages_info = NULL;
+
+	return 0;
+}
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.h b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.h
new file mode 100644
index 0000000..2287804
--- /dev/null
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.h
@@ -0,0 +1,19 @@
+#ifndef __HYPER_DMABUF_XEN_SHM_H__
+#define __HYPER_DMABUF_XEN_SHM_H__
+
+/* 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. */
+int hyper_dmabuf_xen_share_pages(struct page **pages, int domid, int nents,
+				 void **refs_info);
+
+int hyper_dmabuf_xen_unshare_pages(void **refs_info, int nents);
+
+/* Maps provided top level ref id and then return array of pages containing data refs.
+ */
+struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int nents,
+						void **refs_info);
+
+int hyper_dmabuf_xen_unmap_shared_pages(void **refs_info, int nents);
+
+#endif /* __HYPER_DMABUF_XEN_SHM_H__ */
-- 
2.7.4

WARNING: multiple messages have this Message-ID (diff)
From: Dongwon Kim <dongwon.kim@intel.com>
To: linux-kernel@vger.kernel.org
Cc: xen-devel@lists.xenproject.org, mateuszx.potrola@intel.com,
	dri-devel@lists.freedesktop.org, dongwon.kim@intel.com
Subject: [RFC PATCH 16/60] hyper_dmabuf: define hypervisor specific backend API
Date: Tue, 19 Dec 2017 11:29:32 -0800	[thread overview]
Message-ID: <1513711816-2618-16-git-send-email-dongwon.kim@intel.com> (raw)
In-Reply-To: <1513711816-2618-1-git-send-email-dongwon.kim@intel.com>

For adoption of hyper_dmabuf driver to various hypervisors
other than Xen, a "backend" layer is defined and separated out
from existing one-body structure.

"Backend" is basically a list of entry points of function calls
that provides method to do Kernel's page-level sharing and inter
VMs communication using hypervisor's native mechanism (hypercall).

All backend APIs are listed up in "struct hyper_dmabuf_backend_ops"
as shown below.

struct hyper_dmabuf_backend_ops {
        /* retreiving id of current virtual machine */
        int (*get_vm_id)(void);

        /* get pages shared via hypervisor-specific method */
        int (*share_pages)(struct page **, int, int, void **);

        /* make shared pages unshared via hypervisor specific method */
        int (*unshare_pages)(void **, int);

        /* map remotely shared pages on importer's side via
         * hypervisor-specific method
         */
        struct page ** (*map_shared_pages)(int, int, int, void **);

        /* unmap and free shared pages on importer's side via
         * hypervisor-specific method
         */
        int (*unmap_shared_pages)(void **, int);

        /* initialize communication environment */
        int (*init_comm_env)(void);

        void (*destroy_comm)(void);

        /* upstream ch setup (receiving and responding) */
        int (*init_rx_ch)(int);

        /* downstream ch setup (transmitting and parsing responses) */
        int (*init_tx_ch)(int);

        int (*send_req)(int, struct hyper_dmabuf_req *, int);
};

Within this new structure, only backend APIs need to be re-designed or
replaced with new ones when porting this sharing model to a different
hypervisor environment, which is a lot simpler than completely redesiging
whole driver for a new hypervisor.

Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
---
 drivers/xen/hyper_dmabuf/Makefile                  |  11 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h       |   1 -
 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c        |  33 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h        | 112 ++----
 drivers/xen/hyper_dmabuf/hyper_dmabuf_id.c         |   6 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c        | 426 ++-------------------
 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h        |  14 -
 drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c      | 134 +++----
 drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.h      |  87 +++++
 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c        |  52 ++-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h        |  23 +-
 .../xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c    |   4 +-
 drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h     |  26 +-
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c   | 303 +++++++++------
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h   |  51 +--
 .../hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c  |  67 ++--
 .../hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h  |  32 +-
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.c    |  22 ++
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.h    |  20 +
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c    | 356 +++++++++++++++++
 .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.h    |  19 +
 21 files changed, 949 insertions(+), 850 deletions(-)
 create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.h
 create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.c
 create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.h
 create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c
 create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.h

diff --git a/drivers/xen/hyper_dmabuf/Makefile b/drivers/xen/hyper_dmabuf/Makefile
index c9b8b7f..d90cfc3 100644
--- a/drivers/xen/hyper_dmabuf/Makefile
+++ b/drivers/xen/hyper_dmabuf/Makefile
@@ -1,5 +1,7 @@
 TARGET_MODULE:=hyper_dmabuf
 
+PLATFORM:=XEN
+
 # If we running by kernel building system
 ifneq ($(KERNELRELEASE),)
 	$(TARGET_MODULE)-objs := hyper_dmabuf_drv.o \
@@ -9,8 +11,13 @@ ifneq ($(KERNELRELEASE),)
 				 hyper_dmabuf_msg.o \
 				 hyper_dmabuf_id.o \
 				 hyper_dmabuf_remote_sync.o \
-				 xen/hyper_dmabuf_xen_comm.o \
-				 xen/hyper_dmabuf_xen_comm_list.o
+
+ifeq ($(CONFIG_XEN), y)
+	$(TARGET_MODULE)-objs += xen/hyper_dmabuf_xen_comm.o \
+				 xen/hyper_dmabuf_xen_comm_list.o \
+				 xen/hyper_dmabuf_xen_shm.o \
+				 xen/hyper_dmabuf_xen_drv.o
+endif
 
 obj-$(CONFIG_HYPER_DMABUF) := $(TARGET_MODULE).o
 
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h
index 3d9b2d6..d012b05 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h
@@ -1,2 +1 @@
 #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
index 66d6cb9..ddcc955 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c
@@ -1,15 +1,18 @@
-#include <linux/init.h>       /* module_init, module_exit */
-#include <linux/module.h> /* version info, MODULE_LICENSE, MODULE_AUTHOR, printk() */
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/workqueue.h>
-#include <xen/grant_table.h>
-#include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_conf.h"
+#include "hyper_dmabuf_msg.h"
+#include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_list.h"
 #include "hyper_dmabuf_id.h"
-#include "xen/hyper_dmabuf_xen_comm_list.h"
-#include "xen/hyper_dmabuf_xen_comm.h"
 
-MODULE_LICENSE("Dual BSD/GPL");
+#ifdef CONFIG_XEN
+#include "xen/hyper_dmabuf_xen_drv.h"
+extern struct hyper_dmabuf_backend_ops xen_backend_ops;
+#endif
+
+MODULE_LICENSE("GPL");
 MODULE_AUTHOR("IOTG-PED, INTEL");
 
 int register_device(void);
@@ -29,24 +32,24 @@ static int hyper_dmabuf_drv_init(void)
 		return -EINVAL;
 	}
 
+#ifdef CONFIG_XEN
+	hyper_dmabuf_private.backend_ops = &xen_backend_ops;
+#endif
+
 	printk( KERN_NOTICE "initializing database for imported/exported dmabufs\n");
 
 	/* device structure initialization */
 	/* currently only does work-queue initialization */
 	hyper_dmabuf_private.work_queue = create_workqueue("hyper_dmabuf_wqueue");
-	hyper_dmabuf_private.domid = hyper_dmabuf_get_domid();
+	hyper_dmabuf_private.domid = hyper_dmabuf_private.backend_ops->get_vm_id();
 
 	ret = hyper_dmabuf_table_init();
 	if (ret < 0) {
 		return -EINVAL;
 	}
 
-	ret = hyper_dmabuf_ring_table_init();
-	if (ret < 0) {
-		return -EINVAL;
-	}
+	ret = hyper_dmabuf_private.backend_ops->init_comm_env();
 
-	ret = hyper_dmabuf_setup_data_dir();
 	if (ret < 0) {
 		return -EINVAL;
 	}
@@ -61,8 +64,7 @@ static void hyper_dmabuf_drv_exit(void)
 	/* hash tables for export/import entries and ring_infos */
 	hyper_dmabuf_table_destroy();
 
-	hyper_dmabuf_cleanup_ringbufs();
-	hyper_dmabuf_ring_table_destroy();
+	hyper_dmabuf_private.backend_ops->destroy_comm();
 
 	/* destroy workqueue */
 	if (hyper_dmabuf_private.work_queue)
@@ -72,7 +74,6 @@ static void hyper_dmabuf_drv_exit(void)
 	if (hyper_dmabuf_private.id_queue)
 		destroy_reusable_list();
 
-	hyper_dmabuf_destroy_data_dir();
 	printk( KERN_NOTICE "dma_buf-src_sink model: Exiting" );
 	unregister_device();
 }
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
index 37b0cc1..03d77d7 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h
@@ -6,94 +6,48 @@ struct list_reusable_id {
 	struct list_head list;
 };
 
-struct hyper_dmabuf_private {
-        struct device *device;
-	int domid;
-	struct workqueue_struct *work_queue;
-	struct list_reusable_id *id_queue;
-};
+struct hyper_dmabuf_backend_ops {
+	/* retreiving id of current virtual machine */
+	int (*get_vm_id)(void);
 
-typedef int (*hyper_dmabuf_ioctl_t)(void *data);
+	/* get pages shared via hypervisor-specific method */
+	int (*share_pages)(struct page **, int, int, void **);
 
-struct hyper_dmabuf_ioctl_desc {
-	unsigned int cmd;
-	int flags;
-	hyper_dmabuf_ioctl_t func;
-	const char *name;
-};
+	/* make shared pages unshared via hypervisor specific method */
+	int (*unshare_pages)(void **, int);
 
-#define HYPER_DMABUF_IOCTL_DEF(ioctl, _func, _flags) 	\
-	[_IOC_NR(ioctl)] = {				\
-			.cmd = ioctl,			\
-			.func = _func,			\
-			.flags = _flags,		\
-			.name = #ioctl			\
-	}
+	/* map remotely shared pages on importer's side via
+	 * hypervisor-specific method
+	 */
+	struct page ** (*map_shared_pages)(int, int, int, void **);
 
-#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;
-};
+	/* unmap and free shared pages on importer's side via
+	 * hypervisor-specific method
+	 */
+	int (*unmap_shared_pages)(void **, int);
 
-#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;
-};
+	/* initialize communication environment */
+	int (*init_comm_env)(void);
 
-#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];
-};
+	void (*destroy_comm)(void);
 
-#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;
-};
+	/* upstream ch setup (receiving and responding) */
+	int (*init_rx_ch)(int);
+
+	/* downstream ch setup (transmitting and parsing responses) */
+	int (*init_tx_ch)(int);
 
-#define IOCTL_HYPER_DMABUF_UNEXPORT \
-_IOC(_IOC_NONE, 'G', 4, sizeof(struct ioctl_hyper_dmabuf_unexport))
-struct ioctl_hyper_dmabuf_unexport {
-	/* IN parameters */
-	/* hyper dmabuf id to be unexported */
-	uint32_t hyper_dmabuf_id;
-	/* OUT parameters */
-	/* Status of request */
-	uint32_t status;
+	int (*send_req)(int, struct hyper_dmabuf_req *, int);
 };
 
-#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;
+struct hyper_dmabuf_private {
+        struct device *device;
+	int domid;
+	struct workqueue_struct *work_queue;
+	struct list_reusable_id *id_queue;
+
+	/* backend ops - hypervisor specific */
+	struct hyper_dmabuf_backend_ops *backend_ops;
 };
 
-#endif //__LINUX_PUBLIC_HYPER_DMABUF_DRV_H__
+#endif /* __LINUX_PUBLIC_HYPER_DMABUF_DRV_H__ */
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_id.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_id.c
index 7bbb179..b58a111 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_id.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_id.c
@@ -1,5 +1,6 @@
 #include <linux/list.h>
 #include <linux/slab.h>
+#include "hyper_dmabuf_msg.h"
 #include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_id.h"
 
@@ -19,6 +20,7 @@ void store_reusable_id(int id)
 static int retrieve_reusable_id(void)
 {
 	struct list_reusable_id *reusable_head = hyper_dmabuf_private.id_queue;
+	int id;
 
 	/* check there is reusable id */
 	if (!list_empty(&reusable_head->list)) {
@@ -27,7 +29,9 @@ static int retrieve_reusable_id(void)
 						 list);
 
 		list_del(&reusable_head->list);
-		return reusable_head->id;
+		id = reusable_head->id;
+		kfree(reusable_head);
+		return id;
 	}
 
 	return -1;
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
index b109138..0f104b9 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c
@@ -8,10 +8,12 @@
 #include "hyper_dmabuf_struct.h"
 #include "hyper_dmabuf_imp.h"
 #include "hyper_dmabuf_id.h"
-#include "xen/hyper_dmabuf_xen_comm.h"
 #include "hyper_dmabuf_msg.h"
+#include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_list.h"
 
+extern struct hyper_dmabuf_private hyper_dmabuf_private;
+
 #define REFS_PER_PAGE (PAGE_SIZE/sizeof(grant_ref_t))
 
 int dmabuf_refcount(struct dma_buf *dma_buf)
@@ -138,397 +140,10 @@ struct sg_table* hyper_dmabuf_create_sgt(struct page **pages,
 /* free sg_table */
 void hyper_dmabuf_free_sgt(struct sg_table* sgt)
 {
-	sg_free_table(sgt);
-	kfree(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));
-	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->nents/REFS_PER_PAGE +
-				((sgt_info->nents % REFS_PER_PAGE) ? 1: 0));
-
-
-	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");
-		}
-		gnttab_free_grant_reference(ref[i]);
-		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");
-	}
-	gnttab_end_foreign_access_ref(shared_pages_info->top_level_ref, 1);
-	gnttab_free_grant_reference(shared_pages_info->top_level_ref);
-
-	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->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);
-		gnttab_free_grant_reference(shared_pages_info->data_refs[i]);
-	}
-
-	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 = kcalloc(nents, sizeof(struct gnttab_map_grant_ref),
-		      GFP_KERNEL);
-	unmap_ops = 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;
-		}
+	if (sgt) {
+		sg_free_table(sgt);
+		kfree(sgt);
 	}
-
-	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;
 }
 
 int hyper_dmabuf_cleanup_sgt_info(struct hyper_dmabuf_sgt_info *sgt_info, int force)
@@ -537,6 +152,7 @@ int hyper_dmabuf_cleanup_sgt_info(struct hyper_dmabuf_sgt_info *sgt_info, int fo
 	struct attachment_list *attachl;
 	struct kmap_vaddr_list *va_kmapl;
 	struct vmap_vaddr_list *va_vmapl;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 
 	if (!sgt_info) {
 		printk("invalid hyper_dmabuf_id\n");
@@ -598,7 +214,7 @@ int hyper_dmabuf_cleanup_sgt_info(struct hyper_dmabuf_sgt_info *sgt_info, int fo
 	}
 
 	/* Start cleanup of buffer in reverse order to exporting */
-	hyper_dmabuf_cleanup_gref_table(sgt_info);
+	ops->unshare_pages(&sgt_info->refs_info, sgt_info->nents);
 
 	/* unmap dma-buf */
 	dma_buf_unmap_attachment(sgt_info->active_attached->attach,
@@ -620,21 +236,22 @@ int hyper_dmabuf_cleanup_sgt_info(struct hyper_dmabuf_sgt_info *sgt_info, int fo
 	return 0;
 }
 
-inline int hyper_dmabuf_sync_request_and_wait(int id, int ops)
+inline int hyper_dmabuf_sync_request_and_wait(int id, int dmabuf_ops)
 {
-	struct hyper_dmabuf_ring_rq *req;
+	struct hyper_dmabuf_req *req;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	int operands[2];
 	int ret;
 
 	operands[0] = id;
-	operands[1] = ops;
+	operands[1] = dmabuf_ops;
 
 	req = kcalloc(1, sizeof(*req), GFP_KERNEL);
 
 	hyper_dmabuf_create_request(req, HYPER_DMABUF_OPS_TO_SOURCE, &operands[0]);
 
 	/* send request and wait for a response */
-	ret = hyper_dmabuf_send_request(HYPER_DMABUF_DOM_ID(id), req, true);
+	ret = ops->send_req(HYPER_DMABUF_DOM_ID(id), req, true);
 
 	kfree(req);
 
@@ -753,6 +370,7 @@ static void hyper_dmabuf_ops_unmap(struct dma_buf_attachment *attachment,
 static void hyper_dmabuf_ops_release(struct dma_buf *dma_buf)
 {
 	struct hyper_dmabuf_imported_sgt_info *sgt_info;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	int ret;
 	int final_release;
 
@@ -761,16 +379,22 @@ static void hyper_dmabuf_ops_release(struct dma_buf *dma_buf)
 
 	sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dma_buf->priv;
 
-	final_release = sgt_info && !sgt_info->valid &&
-		       !dmabuf_refcount(sgt_info->dma_buf);
-
 	if (!dmabuf_refcount(sgt_info->dma_buf)) {
 		sgt_info->dma_buf = NULL;
 	}
 
-	if (final_release) {
-		hyper_dmabuf_cleanup_imported_pages(sgt_info);
+	sgt_info->num_importers--;
+
+	if (sgt_info->num_importers == 0) {
+		ops->unmap_shared_pages(&sgt_info->refs_info, sgt_info->nents);
 		hyper_dmabuf_free_sgt(sgt_info->sgt);
+		sgt_info->sgt = NULL;
+	}
+
+	final_release = sgt_info && !sgt_info->valid &&
+		        !sgt_info->num_importers;
+
+	if (final_release) {
 		ret = hyper_dmabuf_sync_request_and_wait(sgt_info->hyper_dmabuf_id,
 							HYPER_DMABUF_OPS_RELEASE_FINAL);
 	} else {
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
index 1b0801f..a4a6d63 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h
@@ -11,20 +11,6 @@ struct hyper_dmabuf_pages_info *hyper_dmabuf_ext_pgs(struct sg_table *sgt);
 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_cleanup_sgt_info(struct hyper_dmabuf_sgt_info *sgt_info, int force);
 
 void hyper_dmabuf_free_sgt(struct sg_table *sgt);
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
index 5c6d9c8..70107bb 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c
@@ -8,47 +8,37 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include "hyper_dmabuf_struct.h"
-#include "hyper_dmabuf_imp.h"
+#include "hyper_dmabuf_ioctl.h"
 #include "hyper_dmabuf_list.h"
+#include "hyper_dmabuf_msg.h"
 #include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_id.h"
+#include "hyper_dmabuf_imp.h"
 #include "hyper_dmabuf_query.h"
-#include "xen/hyper_dmabuf_xen_comm.h"
-#include "xen/hyper_dmabuf_xen_comm_list.h"
-#include "hyper_dmabuf_msg.h"
 
 extern struct hyper_dmabuf_private hyper_dmabuf_private;
 
-static int hyper_dmabuf_exporter_ring_setup(void *data)
+static int hyper_dmabuf_tx_ch_setup(void *data)
 {
-	struct ioctl_hyper_dmabuf_exporter_ring_setup *ring_attr;
-	struct hyper_dmabuf_ring_info_export *ring_info;
+	struct ioctl_hyper_dmabuf_tx_ch_setup *tx_ch_attr;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	int ret = 0;
 
 	if (!data) {
 		printk("user data is NULL\n");
 		return -1;
 	}
-	ring_attr = (struct ioctl_hyper_dmabuf_exporter_ring_setup *)data;
-
-	/* check if the ring ch already exists */
-	ring_info = hyper_dmabuf_find_exporter_ring(ring_attr->remote_domain);
-
-	if (ring_info) {
-		printk("(exporter's) ring ch to domid = %d already exist\ngref = %d, port = %d\n",
-			ring_info->rdomain, ring_info->gref_ring, ring_info->port);
-		return 0;
-	}
+	tx_ch_attr = (struct ioctl_hyper_dmabuf_tx_ch_setup *)data;
 
-	ret = hyper_dmabuf_exporter_ringbuf_init(ring_attr->remote_domain);
+	ret = ops->init_tx_ch(tx_ch_attr->remote_domain);
 
 	return ret;
 }
 
-static int hyper_dmabuf_importer_ring_setup(void *data)
+static int hyper_dmabuf_rx_ch_setup(void *data)
 {
-	struct ioctl_hyper_dmabuf_importer_ring_setup *setup_imp_ring_attr;
-	struct hyper_dmabuf_ring_info_import *ring_info;
+	struct ioctl_hyper_dmabuf_rx_ch_setup *rx_ch_attr;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	int ret = 0;
 
 	if (!data) {
@@ -56,17 +46,9 @@ static int hyper_dmabuf_importer_ring_setup(void *data)
 		return -1;
 	}
 
-	setup_imp_ring_attr = (struct ioctl_hyper_dmabuf_importer_ring_setup *)data;
-
-	/* check if the ring ch already exist */
-	ring_info = hyper_dmabuf_find_importer_ring(setup_imp_ring_attr->source_domain);
+	rx_ch_attr = (struct ioctl_hyper_dmabuf_rx_ch_setup *)data;
 
-	if (ring_info) {
-		printk("(importer's) ring ch to domid = %d already exist\n", ring_info->sdomain);
-		return 0;
-	}
-
-	ret = hyper_dmabuf_importer_ringbuf_init(setup_imp_ring_attr->source_domain);
+	ret = ops->init_rx_ch(rx_ch_attr->source_domain);
 
 	return ret;
 }
@@ -74,13 +56,14 @@ static int hyper_dmabuf_importer_ring_setup(void *data)
 static int hyper_dmabuf_export_remote(void *data)
 {
 	struct ioctl_hyper_dmabuf_export_remote *export_remote_attr;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	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];
+	struct hyper_dmabuf_req *req;
+	int operands[MAX_NUMBER_OF_OPERANDS];
 	int ret = 0;
 
 	if (!data) {
@@ -125,6 +108,7 @@ static int hyper_dmabuf_export_remote(void *data)
 	sgt_info = kmalloc(sizeof(*sgt_info), GFP_KERNEL);
 
 	sgt_info->hyper_dmabuf_id = hyper_dmabuf_get_id();
+
 	/* TODO: We might need to consider using port number on event channel? */
 	sgt_info->hyper_dmabuf_rdomain = export_remote_attr->remote_domain;
 	sgt_info->dma_buf = dma_buf;
@@ -163,15 +147,14 @@ static int hyper_dmabuf_export_remote(void *data)
 
 	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);
+	operands[4] = ops->share_pages (page_info->pages, export_remote_attr->remote_domain,
+					page_info->nents, &sgt_info->refs_info);
+
 	/* driver/application specific private info, max 32 bytes */
 	operands[5] = export_remote_attr->private[0];
 	operands[6] = export_remote_attr->private[1];
@@ -182,7 +165,8 @@ static int hyper_dmabuf_export_remote(void *data)
 
 	/* 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, false))
+
+	if(ops->send_req(export_remote_attr->remote_domain, req, false))
 		goto fail_send_request;
 
 	/* free msg */
@@ -215,8 +199,10 @@ static int hyper_dmabuf_export_remote(void *data)
 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;
-	struct hyper_dmabuf_ring_rq *req;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
+	struct hyper_dmabuf_imported_sgt_info *sgt_info;
+	struct hyper_dmabuf_req *req;
+	struct page **data_pages;
 	int operand;
 	int ret = 0;
 
@@ -228,43 +214,48 @@ static int hyper_dmabuf_export_fd_ioctl(void *data)
 	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 */
+	sgt_info = hyper_dmabuf_find_imported(export_fd_attr->hyper_dmabuf_id);
+	if (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_DOM_ID(imported_sgt_info->hyper_dmabuf_id));
-
-	if (!imported_sgt_info->sgt) {
-		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_DOM_ID(imported_sgt_info->hyper_dmabuf_id),
-							&imported_sgt_info->shared_pages_info);
-
-		/* send notifiticatio for first export_fd to exporter */
-		operand = imported_sgt_info->hyper_dmabuf_id;
-		req = kcalloc(1, sizeof(*req), GFP_KERNEL);
-		hyper_dmabuf_create_request(req, HYPER_DMABUF_FIRST_EXPORT, &operand);
-
-		ret = hyper_dmabuf_send_request(HYPER_DMABUF_DOM_ID(operand), req, false);
-
-		if (!imported_sgt_info->sgt || ret) {
-			kfree(req);
-			printk("Failed to create sgt or notify exporter\n");
-			return -EINVAL;
-		}
+		sgt_info->ref_handle, sgt_info->frst_ofst,
+		sgt_info->last_len, sgt_info->nents,
+		HYPER_DMABUF_DOM_ID(sgt_info->hyper_dmabuf_id));
+
+	if (!sgt_info->sgt) {
+		data_pages = ops->map_shared_pages(sgt_info->ref_handle,
+						   HYPER_DMABUF_DOM_ID(sgt_info->hyper_dmabuf_id),
+						   sgt_info->nents,
+						   &sgt_info->refs_info);
+
+		sgt_info->sgt = hyper_dmabuf_create_sgt(data_pages, sgt_info->frst_ofst,
+							sgt_info->last_len, sgt_info->nents);
+
+	}
+
+	/* send notification for export_fd to exporter */
+	operand = sgt_info->hyper_dmabuf_id;
+
+	req = kcalloc(1, sizeof(*req), GFP_KERNEL);
+	hyper_dmabuf_create_request(req, HYPER_DMABUF_FIRST_EXPORT, &operand);
+
+	ret = ops->send_req(HYPER_DMABUF_DOM_ID(operand), req, false);
+
+	if (!sgt_info->sgt || ret) {
 		kfree(req);
+		printk("Failed to create sgt or notify exporter\n");
+		return -EINVAL;
 	}
+	kfree(req);
 
-	export_fd_attr->fd = hyper_dmabuf_export_fd(imported_sgt_info, export_fd_attr->flags);
+	export_fd_attr->fd = hyper_dmabuf_export_fd(sgt_info, export_fd_attr->flags);
 
 	if (export_fd_attr->fd < 0) {
 		/* fail to get fd */
 		ret = export_fd_attr->fd;
+	} else {
+		sgt_info->num_importers++;
 	}
 
 	return ret;
@@ -276,8 +267,9 @@ static int hyper_dmabuf_export_fd_ioctl(void *data)
 static int hyper_dmabuf_unexport(void *data)
 {
 	struct ioctl_hyper_dmabuf_unexport *unexport_attr;
+	struct hyper_dmabuf_backend_ops *ops = hyper_dmabuf_private.backend_ops;
 	struct hyper_dmabuf_sgt_info *sgt_info;
-	struct hyper_dmabuf_ring_rq *req;
+	struct hyper_dmabuf_req *req;
 	int ret;
 
 	if (!data) {
@@ -301,7 +293,7 @@ static int hyper_dmabuf_unexport(void *data)
 	hyper_dmabuf_create_request(req, HYPER_DMABUF_NOTIFY_UNEXPORT, &unexport_attr->hyper_dmabuf_id);
 
 	/* Now send unexport request to remote domain, marking that buffer should not be used anymore */
-	ret = hyper_dmabuf_send_request(sgt_info->hyper_dmabuf_rdomain, req, true);
+	ret = ops->send_req(sgt_info->hyper_dmabuf_rdomain, req, true);
 	if (ret < 0) {
 		kfree(req);
 		return -EFAULT;
@@ -405,8 +397,8 @@ static int hyper_dmabuf_query(void *data)
 }
 
 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_TX_CH_SETUP, hyper_dmabuf_tx_ch_setup, 0),
+	HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_RX_CH_SETUP, hyper_dmabuf_rx_ch_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_UNEXPORT, hyper_dmabuf_unexport, 0),
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.h
new file mode 100644
index 0000000..de216d3
--- /dev/null
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.h
@@ -0,0 +1,87 @@
+#ifndef __LINUX_PUBLIC_HYPER_DMABUF_IOCTL_H__
+#define __LINUX_PUBLIC_HYPER_DMABUF_IOCTL_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_TX_CH_SETUP \
+_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_hyper_dmabuf_tx_ch_setup))
+struct ioctl_hyper_dmabuf_tx_ch_setup {
+	/* IN parameters */
+	/* Remote domain id */
+	int remote_domain;
+};
+
+#define IOCTL_HYPER_DMABUF_RX_CH_SETUP \
+_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_hyper_dmabuf_rx_ch_setup))
+struct ioctl_hyper_dmabuf_rx_ch_setup {
+	/* IN parameters */
+	/* Source domain id */
+	int source_domain;
+};
+
+#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 */
+	int dmabuf_fd;
+	/* Domain id to which buffer should be exported */
+	int remote_domain;
+	/* exported dma buf id */
+	int hyper_dmabuf_id;
+	int 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 */
+	int hyper_dmabuf_id;
+	/* flags */
+	int flags;
+	/* OUT parameters */
+	/* exported dma buf fd */
+	int fd;
+};
+
+#define IOCTL_HYPER_DMABUF_UNEXPORT \
+_IOC(_IOC_NONE, 'G', 4, sizeof(struct ioctl_hyper_dmabuf_unexport))
+struct ioctl_hyper_dmabuf_unexport {
+	/* IN parameters */
+	/* hyper dmabuf id to be unexported */
+	int hyper_dmabuf_id;
+	/* OUT parameters */
+	/* Status of request */
+	int 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 */
+	int hyper_dmabuf_id;
+	/* item to be queried */
+	int item;
+	/* OUT parameters */
+	/* Value of queried item */
+	int info;
+};
+
+#endif //__LINUX_PUBLIC_HYPER_DMABUF_DRV_H__
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
index a2d687f..4647115 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c
@@ -5,11 +5,10 @@
 #include <linux/dma-buf.h>
 #include <xen/grant_table.h>
 #include <linux/workqueue.h>
+#include "hyper_dmabuf_msg.h"
 #include "hyper_dmabuf_drv.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"
 
 #define FORCED_UNEXPORTING 0
@@ -18,18 +17,17 @@ extern struct hyper_dmabuf_private hyper_dmabuf_private;
 
 struct cmd_process {
 	struct work_struct work;
-	struct hyper_dmabuf_ring_rq *rq;
+	struct hyper_dmabuf_req *rq;
 	int domid;
 };
 
-void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
-				        enum hyper_dmabuf_command command, int *operands)
+void hyper_dmabuf_create_request(struct hyper_dmabuf_req *req,
+				 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;
+	req->status = HYPER_DMABUF_REQ_NOT_RESPONDED;
+	req->command = command;
 
 	switch(command) {
 	/* as exporter, commands to importer */
@@ -44,7 +42,7 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
 		 * operands5~8 : Driver-specific private data (e.g. graphic buffer's meta info)
 		 */
 		for (i=0; i < 8; i++)
-			request->operands[i] = operands[i];
+			req->operands[i] = operands[i];
 		break;
 
 	case HYPER_DMABUF_NOTIFY_UNEXPORT:
@@ -52,7 +50,7 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
 		/* command : DMABUF_DESTROY,
 		 * operands0 : hyper_dmabuf_id
 		 */
-		request->operands[0] = operands[0];
+		req->operands[0] = operands[0];
 		break;
 
 	case HYPER_DMABUF_FIRST_EXPORT:
@@ -60,7 +58,7 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
 		/* command : HYPER_DMABUF_FIRST_EXPORT,
 		 * operands0 : hyper_dmabuf_id
 		 */
-		request->operands[0] = operands[0];
+		req->operands[0] = operands[0];
 		break;
 
 	case HYPER_DMABUF_OPS_TO_REMOTE:
@@ -77,7 +75,7 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
 		 * operands1 : map(=1)/unmap(=2)/attach(=3)/detach(=4)
 		 */
 		for (i=0; i<2; i++)
-			request->operands[i] = operands[i];
+			req->operands[i] = operands[i];
 		break;
 
 	default:
@@ -88,10 +86,10 @@ void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request,
 
 void cmd_process_work(struct work_struct *work)
 {
-	struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
 	struct hyper_dmabuf_sgt_info *sgt_info;
+	struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
 	struct cmd_process *proc = container_of(work, struct cmd_process, work);
-	struct hyper_dmabuf_ring_rq *req;
+	struct hyper_dmabuf_req *req;
 	int domid;
 	int i;
 
@@ -114,7 +112,7 @@ void cmd_process_work(struct work_struct *work)
 		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];
+		imported_sgt_info->ref_handle = req->operands[4];
 
 		printk("DMABUF was exported\n");
 		printk("\thyper_dmabuf_id %d\n", req->operands[0]);
@@ -139,10 +137,7 @@ void cmd_process_work(struct work_struct *work)
 			break;
 		}
 
-		if (sgt_info->importer_exported)
-			printk("warning: exported flag is not supposed to be 1 already\n");
-
-		sgt_info->importer_exported = 1;
+		sgt_info->importer_exported++;
 		break;
 
 	case HYPER_DMABUF_OPS_TO_REMOTE:
@@ -160,11 +155,11 @@ void cmd_process_work(struct work_struct *work)
 	kfree(proc);
 }
 
-int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_ring_rq *req)
+int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_req *req)
 {
 	struct cmd_process *proc;
-	struct hyper_dmabuf_ring_rq *temp_req;
-	struct hyper_dmabuf_imported_sgt_info *imported_sgt_info;
+	struct hyper_dmabuf_req *temp_req;
+	struct hyper_dmabuf_imported_sgt_info *sgt_info;
 	int ret;
 
 	if (!req) {
@@ -189,22 +184,21 @@ int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_ring_rq *req)
 		 * operands0 : hyper_dmabuf_id
 		 */
 
-		imported_sgt_info =
-			hyper_dmabuf_find_imported(req->operands[0]);
+		sgt_info = hyper_dmabuf_find_imported(req->operands[0]);
 
-		if (imported_sgt_info) {
+		if (sgt_info) {
 			/* if anything is still using dma_buf */
-			if (imported_sgt_info->dma_buf &&
-			    dmabuf_refcount(imported_sgt_info->dma_buf) > 0) {
+			if (sgt_info->dma_buf &&
+			    dmabuf_refcount(sgt_info->dma_buf) > 0) {
 				/*
 				 * Buffer is still in  use, just mark that it should
 				 * not be allowed to export its fd anymore.
 				 */
-				imported_sgt_info->valid = 0;
+				sgt_info->valid = 0;
 			} else {
 				/* No one is using buffer, remove it from imported list */
 				hyper_dmabuf_remove_imported(req->operands[0]);
-				kfree(imported_sgt_info);
+				kfree(sgt_info);
 			}
 		} else {
 			req->status = HYPER_DMABUF_REQ_ERROR;
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
index 1e9d827..ac4caeb 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h
@@ -1,6 +1,22 @@
 #ifndef __HYPER_DMABUF_MSG_H__
 #define __HYPER_DMABUF_MSG_H__
 
+#define MAX_NUMBER_OF_OPERANDS 9
+
+struct hyper_dmabuf_req {
+	unsigned int request_id;
+	unsigned int status;
+	unsigned int command;
+	unsigned int operands[MAX_NUMBER_OF_OPERANDS];
+};
+
+struct hyper_dmabuf_resp {
+	unsigned int response_id;
+	unsigned int status;
+	unsigned int command;
+	unsigned int operands[MAX_NUMBER_OF_OPERANDS];
+};
+
 enum hyper_dmabuf_command {
 	HYPER_DMABUF_EXPORT = 0x10,
 	HYPER_DMABUF_FIRST_EXPORT,
@@ -35,10 +51,11 @@ enum hyper_dmabuf_req_feedback {
 };
 
 /* 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);
+void hyper_dmabuf_create_request(struct hyper_dmabuf_req *req,
+				 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);
+int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_req *req);
 
 #endif // __HYPER_DMABUF_MSG_H__
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c
index c5950e0..0f4735c 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_remote_sync.c
@@ -5,9 +5,9 @@
 #include <linux/dma-buf.h>
 #include "hyper_dmabuf_struct.h"
 #include "hyper_dmabuf_list.h"
+#include "hyper_dmabuf_msg.h"
 #include "hyper_dmabuf_drv.h"
 #include "hyper_dmabuf_id.h"
-#include "xen/hyper_dmabuf_xen_comm.h"
 #include "hyper_dmabuf_msg.h"
 #include "hyper_dmabuf_imp.h"
 
@@ -133,6 +133,8 @@ int hyper_dmabuf_remote_sync(int id, int ops)
 
 	case HYPER_DMABUF_OPS_RELEASE:
 		/* place holder */
+                sgt_info->importer_exported--;
+
 		break;
 
 	case HYPER_DMABUF_OPS_BEGIN_CPU_ACCESS:
diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
index b52f958..f053dd10 100644
--- a/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
+++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h
@@ -1,14 +1,6 @@
 #ifndef __HYPER_DMABUF_STRUCT_H__
 #define __HYPER_DMABUF_STRUCT_H__
 
-#include <xen/interface/grant_table.h>
-
-/* 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
-
 /* stack of mapped sgts */
 struct sgt_list {
 	struct sg_table *sgt;
@@ -33,15 +25,6 @@ struct vmap_vaddr_list {
 	struct list_head list;
 };
 
-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 */
@@ -69,8 +52,8 @@ struct hyper_dmabuf_sgt_info {
 	struct kmap_vaddr_list *va_kmapped;
 	struct vmap_vaddr_list *va_vmapped;
 	bool valid;
-	bool importer_exported; /* exported locally on importer's side */
-	struct hyper_dmabuf_shared_pages_info shared_pages_info;
+	int importer_exported; /* exported locally on importer's side */
+	void *refs_info; /* hypervisor-specific info for the references */
 	int private[4]; /* device specific info (e.g. image's meta info?) */
 };
 
@@ -79,14 +62,15 @@ struct hyper_dmabuf_sgt_info {
  * 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 ref_handle; /* reference number of top level addressing page of shared pages */
 	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 dma_buf *dma_buf;
 	struct sg_table *sgt; /* sgt pointer after importing buffer */
-	struct hyper_dmabuf_shared_pages_info shared_pages_info;
+	void *refs_info;
 	bool valid;
+	int num_importers;
 	int private[4]; /* device specific info (e.g. image's meta info?) */
 };
 
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
index f9e0df3..bd37ec2 100644
--- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c
@@ -10,16 +10,15 @@
 #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;
 
-struct hyper_dmabuf_ring_rq req_pending = {0};
+struct hyper_dmabuf_req req_pending = {0};
 
-/* Creates entry in xen store that will keep details of all exporter rings created by this domain */
-int32_t hyper_dmabuf_setup_data_dir()
+/* Creates entry in xen store that will keep details of all
+ * exporter rings created by this domain
+ */
+static int xen_comm_setup_data_dir(void)
 {
 	char buf[255];
 
@@ -27,13 +26,13 @@ int32_t hyper_dmabuf_setup_data_dir()
 	return xenbus_mkdir(XBT_NIL, buf, "");
 }
 
-
 /* Removes entry from xenstore with exporter ring details.
- * Other domains that has connected to any of exporter rings created by this domain,
- * will be notified about removal of this entry and will treat that as signal to
- * cleanup importer rings created for this domain
+ * Other domains that has connected to any of exporter rings
+ * created by this domain, will be notified about removal of
+ * this entry and will treat that as signal to cleanup importer
+ * rings created for this domain
  */
-int32_t hyper_dmabuf_destroy_data_dir()
+static int xen_comm_destroy_data_dir(void)
 {
 	char buf[255];
 
@@ -41,18 +40,19 @@ int32_t hyper_dmabuf_destroy_data_dir()
 	return xenbus_rm(XBT_NIL, buf, "");
 }
 
-/*
- * Adds xenstore entries with details of exporter ring created for given remote domain.
- * It requires special daemon running in dom0 to make sure that given remote domain will
- * have right permissions to access that data.
+/* Adds xenstore entries with details of exporter ring created
+ * for given remote domain. It requires special daemon running
+ * in dom0 to make sure that given remote domain will have right
+ * permissions to access that data.
  */
-static int32_t hyper_dmabuf_expose_ring_details(uint32_t domid, uint32_t rdomid, uint32_t grefid, uint32_t port)
+static int xen_comm_expose_ring_details(int domid, int rdomid,
+					int gref, int port)
 {
 	char buf[255];
 	int ret;
 
 	sprintf(buf, "/local/domain/%d/data/hyper_dmabuf/%d", domid, rdomid);
-	ret = xenbus_printf(XBT_NIL, buf, "grefid", "%d", grefid);
+	ret = xenbus_printf(XBT_NIL, buf, "grefid", "%d", gref);
 
 	if (ret) {
 		printk("Failed to write xenbus entry %s: %d\n", buf, ret);
@@ -72,7 +72,7 @@ static int32_t hyper_dmabuf_expose_ring_details(uint32_t domid, uint32_t rdomid,
 /*
  * Queries details of ring exposed by remote domain.
  */
-static int32_t hyper_dmabuf_get_ring_details(uint32_t domid, uint32_t rdomid, uint32_t *grefid, uint32_t *port)
+static int xen_comm_get_ring_details(int domid, int rdomid, int *grefid, int *port)
 {
 	char buf[255];
 	int ret;
@@ -95,10 +95,10 @@ static int32_t hyper_dmabuf_get_ring_details(uint32_t domid, uint32_t rdomid, ui
 	return (ret <= 0 ? 1 : 0);
 }
 
-int32_t hyper_dmabuf_get_domid(void)
+int hyper_dmabuf_get_domid(void)
 {
 	struct xenbus_transaction xbt;
-	int32_t domid;
+	int domid;
 
         xenbus_transaction_start(&xbt);
 
@@ -110,29 +110,35 @@ int32_t hyper_dmabuf_get_domid(void)
 	return domid;
 }
 
-int hyper_dmabuf_next_req_id_export(void)
+static int xen_comm_next_req_id(void)
 {
         export_req_id++;
         return export_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 *info);
-static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *info);
-
-/*
- * Callback function that will be called on any change of xenbus path being watched.
- * Used for detecting creation/destruction of remote domain exporter ring.
- * When remote domain's exporter ring will be detected, importer ring on this domain will be created.
- * When remote domain's exporter ring destruction will be detected it will celanup this domain importer ring.
- * Destruction can be caused by unloading module by remote domain or it's crash/force shutdown.
+static irqreturn_t front_ring_isr(int irq, void *info);
+static irqreturn_t back_ring_isr(int irq, void *info);
+
+/* Callback function that will be called on any change of xenbus path
+ * being watched. Used for detecting creation/destruction of remote
+ * domain exporter ring.
+ *
+ * When remote domain's exporter ring will be detected, importer ring
+ * on this domain will be created.
+ *
+ * When remote domain's exporter ring destruction will be detected it
+ * will celanup this domain importer ring.
+ *
+ * Destruction can be caused by unloading module by remote domain or
+ * it's crash/force shutdown.
  */
-static void remote_domain_exporter_watch_cb(struct xenbus_watch *watch,
-				   const char *path, const char *token)
+static void remote_dom_exporter_watch_cb(struct xenbus_watch *watch,
+					 const char *path, const char *token)
 {
 	int rdom,ret;
 	uint32_t grefid, port;
-	struct hyper_dmabuf_ring_info_import *ring_info;
+	struct xen_comm_rx_ring_info *ring_info;
 
 	/* Check which domain has changed its exporter rings */
 	ret = sscanf(watch->node, "/local/domain/%d/", &rdom);
@@ -141,39 +147,49 @@ static void remote_domain_exporter_watch_cb(struct xenbus_watch *watch,
 	}
 
 	/* Check if we have importer ring for given remote domain alrady created */
-	ring_info = hyper_dmabuf_find_importer_ring(rdom);
-
-	/*
-	 * Try to query remote domain exporter ring details - if that will fail and we have
-	 * importer ring that means remote domains has cleanup its exporter ring, so our
-	 * importer ring is no longer useful.
-	 * If querying details will succeed and we don't have importer ring, it means that
-	 * remote domain has setup it for us and we should connect to it.
+	ring_info = xen_comm_find_rx_ring(rdom);
+
+	/* Try to query remote domain exporter ring details - if that will
+	 * fail and we have importer ring that means remote domains has cleanup
+	 * its exporter ring, so our importer ring is no longer useful.
+	 *
+	 * If querying details will succeed and we don't have importer ring,
+	 * it means that remote domain has setup it for us and we should connect
+	 * to it.
 	 */
-	ret = hyper_dmabuf_get_ring_details(hyper_dmabuf_get_domid(), rdom, &grefid, &port);
+	ret = xen_comm_get_ring_details(hyper_dmabuf_get_domid(), rdom,
+					&grefid, &port);
 
 	if (ring_info && ret != 0) {
 		printk("Remote exporter closed, cleaninup importer\n");
-		hyper_dmabuf_importer_ringbuf_cleanup(rdom);
+		hyper_dmabuf_xen_cleanup_rx_rbuf(rdom);
 	} else if (!ring_info && ret == 0) {
 		printk("Registering importer\n");
-		hyper_dmabuf_importer_ringbuf_init(rdom);
+		hyper_dmabuf_xen_init_rx_rbuf(rdom);
 	}
 }
 
 /* exporter needs to generated info for page sharing */
-int hyper_dmabuf_exporter_ringbuf_init(int rdomain)
+int hyper_dmabuf_xen_init_tx_rbuf(int domid)
 {
-	struct hyper_dmabuf_ring_info_export *ring_info;
-	struct hyper_dmabuf_sring *sring;
+	struct xen_comm_tx_ring_info *ring_info;
+	struct xen_comm_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);
+	/* check if there's any existing tx channel in the table */
+	ring_info = xen_comm_find_tx_ring(domid);
+
+	if (ring_info) {
+		printk("tx ring ch to domid = %d already exist\ngref = %d, port = %d\n",
+		ring_info->rdomain, ring_info->gref_ring, ring_info->port);
+		return 0;
+	}
+
+	ring_info = kmalloc(sizeof(*ring_info), GFP_KERNEL);
 
 	/* from exporter to importer */
 	shared_ring = (void *)__get_free_pages(GFP_KERNEL, 1);
@@ -181,20 +197,22 @@ int hyper_dmabuf_exporter_ringbuf_init(int rdomain)
 		return -EINVAL;
 	}
 
-	sring = (struct hyper_dmabuf_sring *) shared_ring;
+	sring = (struct xen_comm_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);
+	ring_info->gref_ring = gnttab_grant_foreign_access(domid,
+							   virt_to_mfn(shared_ring),
+							   0);
 	if (ring_info->gref_ring < 0) {
-		return -EINVAL; /* fail to get gref */
+		/* fail to get gref */
+		return -EINVAL;
 	}
 
 	alloc_unbound.dom = DOMID_SELF;
-	alloc_unbound.remote_dom = rdomain;
+	alloc_unbound.remote_dom = domid;
 	ret = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
 					&alloc_unbound);
 	if (ret != 0) {
@@ -204,7 +222,7 @@ int hyper_dmabuf_exporter_ringbuf_init(int rdomain)
 
 	/* setting up interrupt */
 	ret = bind_evtchn_to_irqhandler(alloc_unbound.port,
-					hyper_dmabuf_front_ring_isr, 0,
+					front_ring_isr, 0,
 					NULL, (void*) ring_info);
 
 	if (ret < 0) {
@@ -216,7 +234,7 @@ int hyper_dmabuf_exporter_ringbuf_init(int rdomain)
 		return -EINVAL;
 	}
 
-	ring_info->rdomain = rdomain;
+	ring_info->rdomain = domid;
 	ring_info->irq = ret;
 	ring_info->port = alloc_unbound.port;
 
@@ -226,109 +244,128 @@ int hyper_dmabuf_exporter_ringbuf_init(int rdomain)
 		ring_info->port,
 		ring_info->irq);
 
-	ret = hyper_dmabuf_register_exporter_ring(ring_info);
+	ret = xen_comm_add_tx_ring(ring_info);
 
-	ret = hyper_dmabuf_expose_ring_details(hyper_dmabuf_get_domid(), rdomain,
-                                               ring_info->gref_ring, ring_info->port);
+	ret = xen_comm_expose_ring_details(hyper_dmabuf_get_domid(), domid,
+					   ring_info->gref_ring, ring_info->port);
 
 	/*
 	 * Register watch for remote domain exporter ring.
-	 * When remote domain will setup its exporter ring, we will automatically connect our importer ring to it.
+	 * When remote domain will setup its exporter ring,
+	 * we will automatically connect our importer ring to it.
 	 */
-	ring_info->watch.callback = remote_domain_exporter_watch_cb;
+	ring_info->watch.callback = remote_dom_exporter_watch_cb;
 	ring_info->watch.node = (const char*) kmalloc(sizeof(char) * 255, GFP_KERNEL);
-	sprintf((char*)ring_info->watch.node, "/local/domain/%d/data/hyper_dmabuf/%d/port", rdomain, hyper_dmabuf_get_domid());
+	sprintf((char*)ring_info->watch.node,
+		"/local/domain/%d/data/hyper_dmabuf/%d/port",
+		domid, hyper_dmabuf_get_domid());
+
 	register_xenbus_watch(&ring_info->watch);
 
 	return ret;
 }
 
 /* cleans up exporter ring created for given remote domain */
-void hyper_dmabuf_exporter_ringbuf_cleanup(int rdomain)
+void hyper_dmabuf_xen_cleanup_tx_rbuf(int domid)
 {
-	struct hyper_dmabuf_ring_info_export *ring_info;
+	struct xen_comm_tx_ring_info *ring_info;
 
 	/* check if we at all have exporter ring for given rdomain */
-	ring_info = hyper_dmabuf_find_exporter_ring(rdomain);
+	ring_info = xen_comm_find_tx_ring(domid);
 
 	if (!ring_info) {
 		return;
 	}
 
-	hyper_dmabuf_remove_exporter_ring(rdomain);
+	xen_comm_remove_tx_ring(domid);
 
 	unregister_xenbus_watch(&ring_info->watch);
 	kfree(ring_info->watch.node);
 
-	/* No need to close communication channel, will be done by this function */
-	unbind_from_irqhandler(ring_info->irq,	(void*) ring_info);
+	/* No need to close communication channel, will be done by
+	 * this function
+	 */
+	unbind_from_irqhandler(ring_info->irq, (void*) ring_info);
 
-	/* No need to free sring page, will be freed by this function when other side will end its access */
+	/* No need to free sring page, will be freed by this function
+	 * when other side will end its access
+	 */
 	gnttab_end_foreign_access(ring_info->gref_ring, 0,
 				  (unsigned long) ring_info->ring_front.sring);
 
 	kfree(ring_info);
 }
 
-/* importer needs to know about shared page and port numbers for ring buffer and event channel */
-int hyper_dmabuf_importer_ringbuf_init(int sdomain)
+/* importer needs to know about shared page and port numbers for
+ * ring buffer and event channel
+ */
+int hyper_dmabuf_xen_init_rx_rbuf(int domid)
 {
-	struct hyper_dmabuf_ring_info_import *ring_info;
-	struct hyper_dmabuf_sring *sring;
+	struct xen_comm_rx_ring_info *ring_info;
+	struct xen_comm_sring *sring;
 
 	struct page *shared_ring;
 
-	struct gnttab_map_grant_ref *ops;
+	struct gnttab_map_grant_ref *map_ops;
+
 	int ret;
-	int importer_gref, importer_port;
+	int rx_gref, rx_port;
 
-	ret = hyper_dmabuf_get_ring_details(hyper_dmabuf_get_domid(), sdomain,
-					    &importer_gref, &importer_port);
+	/* check if there's existing rx ring channel */
+	ring_info = xen_comm_find_rx_ring(domid);
+
+	if (ring_info) {
+		printk("rx ring ch from domid = %d already exist\n", ring_info->sdomain);
+		return 0;
+	}
+
+	ret = xen_comm_get_ring_details(hyper_dmabuf_get_domid(), domid,
+					&rx_gref, &rx_port);
 
 	if (ret) {
-		printk("Domain %d has not created exporter ring for current domain\n", sdomain);
+		printk("Domain %d has not created exporter ring for current domain\n", domid);
 		return ret;
 	}
 
-	ring_info = (struct hyper_dmabuf_ring_info_import *)
-			kmalloc(sizeof(*ring_info), GFP_KERNEL);
+	ring_info = kmalloc(sizeof(*ring_info), GFP_KERNEL);
 
-	ring_info->sdomain = sdomain;
-	ring_info->evtchn = importer_port;
+	ring_info->sdomain = domid;
+	ring_info->evtchn = rx_port;
 
-	ops = (struct gnttab_map_grant_ref*)kmalloc(sizeof(*ops), GFP_KERNEL);
+	map_ops = kmalloc(sizeof(*map_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, importer_gref, sdomain);
+	gnttab_set_map_op(&map_ops[0], (unsigned long)pfn_to_kaddr(page_to_pfn(shared_ring)),
+			  GNTMAP_host_map, rx_gref, domid);
+
 	gnttab_set_unmap_op(&ring_info->unmap_op, (unsigned long)pfn_to_kaddr(page_to_pfn(shared_ring)),
-			GNTMAP_host_map, -1);
+			    GNTMAP_host_map, -1);
 
-	ret = gnttab_map_refs(ops, NULL, &shared_ring, 1);
+	ret = gnttab_map_refs(map_ops, NULL, &shared_ring, 1);
 	if (ret < 0) {
 		printk("Cannot map ring\n");
 		return -EINVAL;
 	}
 
-	if (ops[0].status) {
+	if (map_ops[0].status) {
 		printk("Ring mapping failed\n");
 		return -EINVAL;
 	} else {
-		ring_info->unmap_op.handle = ops[0].handle;
+		ring_info->unmap_op.handle = map_ops[0].handle;
 	}
 
-	kfree(ops);
+	kfree(map_ops);
 
-	sring = (struct hyper_dmabuf_sring*) pfn_to_kaddr(page_to_pfn(shared_ring));
+	sring = (struct xen_comm_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, importer_port,
-						hyper_dmabuf_back_ring_isr, 0,
-						NULL, (void*)ring_info);
+	ret = bind_interdomain_evtchn_to_irqhandler(domid, rx_port,
+						    back_ring_isr, 0,
+						    NULL, (void*)ring_info);
 	if (ret < 0) {
 		return -EINVAL;
 	}
@@ -336,35 +373,35 @@ int hyper_dmabuf_importer_ringbuf_init(int sdomain)
 	ring_info->irq = ret;
 
 	printk("%s: bound to eventchannel port: %d  irq: %d\n", __func__,
-		importer_port,
+		rx_port,
 		ring_info->irq);
 
-	ret = hyper_dmabuf_register_importer_ring(ring_info);
+	ret = xen_comm_add_rx_ring(ring_info);
 
 	/* Setup communcation channel in opposite direction */
-	if (!hyper_dmabuf_find_exporter_ring(sdomain)) {
-		ret = hyper_dmabuf_exporter_ringbuf_init(sdomain);
+	if (!xen_comm_find_tx_ring(domid)) {
+		ret = hyper_dmabuf_xen_init_tx_rbuf(domid);
 	}
 
 	return ret;
 }
 
 /* clenas up importer ring create for given source domain */
-void hyper_dmabuf_importer_ringbuf_cleanup(int sdomain)
+void hyper_dmabuf_xen_cleanup_rx_rbuf(int domid)
 {
-	struct hyper_dmabuf_ring_info_import *ring_info;
+	struct xen_comm_rx_ring_info *ring_info;
 	struct page *shared_ring;
 
 	/* check if we have importer ring created for given sdomain */
-	ring_info = hyper_dmabuf_find_importer_ring(sdomain);
+	ring_info = xen_comm_find_rx_ring(domid);
 
 	if (!ring_info)
 		return;
 
-	hyper_dmabuf_remove_importer_ring(sdomain);
+	xen_comm_remove_rx_ring(domid);
 
 	/* no need to close event channel, will be done by that function */
-	unbind_from_irqhandler(ring_info->irq,	(void*) ring_info);
+	unbind_from_irqhandler(ring_info->irq, (void*)ring_info);
 
 	/* unmapping shared ring page */
 	shared_ring = virt_to_page(ring_info->ring_back.sring);
@@ -374,23 +411,39 @@ void hyper_dmabuf_importer_ringbuf_cleanup(int sdomain)
 	kfree(ring_info);
 }
 
-/* cleans up all exporter/importer rings */
-void hyper_dmabuf_cleanup_ringbufs(void)
+int hyper_dmabuf_xen_init_comm_env(void)
 {
-	hyper_dmabuf_foreach_exporter_ring(hyper_dmabuf_exporter_ringbuf_cleanup);
-	hyper_dmabuf_foreach_importer_ring(hyper_dmabuf_importer_ringbuf_cleanup);
+	int ret;
+
+	xen_comm_ring_table_init();
+	ret = xen_comm_setup_data_dir();
+
+	return ret;
 }
 
-int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req, int wait)
+/* cleans up all tx/rx rings */
+static void hyper_dmabuf_xen_cleanup_all_rbufs(void)
 {
-	struct hyper_dmabuf_front_ring *ring;
-	struct hyper_dmabuf_ring_rq *new_req;
-	struct hyper_dmabuf_ring_info_export *ring_info;
+	xen_comm_foreach_tx_ring(hyper_dmabuf_xen_cleanup_tx_rbuf);
+	xen_comm_foreach_rx_ring(hyper_dmabuf_xen_cleanup_rx_rbuf);
+}
+
+void hyper_dmabuf_xen_destroy_comm(void)
+{
+	hyper_dmabuf_xen_cleanup_all_rbufs();
+	xen_comm_destroy_data_dir();
+}
+
+int hyper_dmabuf_xen_send_req(int domid, struct hyper_dmabuf_req *req, int wait)
+{
+	struct xen_comm_front_ring *ring;
+	struct hyper_dmabuf_req *new_req;
+	struct xen_comm_tx_ring_info *ring_info;
 	int notify;
 	int timeout = 1000;
 
 	/* find a ring info for the channel */
-	ring_info = hyper_dmabuf_find_exporter_ring(domain);
+	ring_info = xen_comm_find_tx_ring(domid);
 	if (!ring_info) {
 		printk("Can't find ring info for the channel\n");
 		return -EINVAL;
@@ -407,6 +460,8 @@ int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req, int
 		return -EIO;
 	}
 
+	req->request_id = xen_comm_next_req_id();
+
 	/* update req_pending with current request */
 	memcpy(&req_pending, req, sizeof(req_pending));
 
@@ -438,19 +493,19 @@ int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req, int
 }
 
 /* ISR for handling request */
-static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *info)
+static irqreturn_t back_ring_isr(int irq, void *info)
 {
 	RING_IDX rc, rp;
-	struct hyper_dmabuf_ring_rq req;
-	struct hyper_dmabuf_ring_rp resp;
+	struct hyper_dmabuf_req req;
+	struct hyper_dmabuf_resp resp;
 
 	int notify, more_to_do;
 	int ret;
 
-	struct hyper_dmabuf_ring_info_import *ring_info;
-	struct hyper_dmabuf_back_ring *ring;
+	struct xen_comm_rx_ring_info *ring_info;
+	struct xen_comm_back_ring *ring;
 
-	ring_info = (struct hyper_dmabuf_ring_info_import *)info;
+	ring_info = (struct xen_comm_rx_ring_info *)info;
 	ring = &ring_info->ring_back;
 
 	do {
@@ -490,17 +545,17 @@ static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *info)
 }
 
 /* ISR for handling responses */
-static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, void *info)
+static irqreturn_t front_ring_isr(int irq, void *info)
 {
 	/* front ring only care about response from back */
-	struct hyper_dmabuf_ring_rp *resp;
+	struct hyper_dmabuf_resp *resp;
 	RING_IDX i, rp;
 	int more_to_do, ret;
 
-	struct hyper_dmabuf_ring_info_export *ring_info;
-	struct hyper_dmabuf_front_ring *ring;
+	struct xen_comm_tx_ring_info *ring_info;
+	struct xen_comm_front_ring *ring;
 
-	ring_info = (struct hyper_dmabuf_ring_info_export *)info;
+	ring_info = (struct xen_comm_tx_ring_info *)info;
 	ring = &ring_info->ring_front;
 
 	do {
@@ -518,7 +573,7 @@ static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, void *info)
 			if (resp->status == HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP) {
 				/* parsing response */
 				ret = hyper_dmabuf_msg_parse(ring_info->rdomain,
-							(struct hyper_dmabuf_ring_rq *)resp);
+							(struct hyper_dmabuf_req *)resp);
 
 				if (ret < 0) {
 					printk("getting error while parsing response\n");
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h
index 4ab031a..ba41e9d 100644
--- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h
@@ -3,27 +3,14 @@
 
 #include "xen/interface/io/ring.h"
 #include "xen/xenbus.h"
+#include "../hyper_dmabuf_msg.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(xen_comm, struct hyper_dmabuf_req, struct hyper_dmabuf_resp);
 
-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;
+struct xen_comm_tx_ring_info {
+        struct xen_comm_front_ring ring_front;
 	int rdomain;
         int gref_ring;
         int irq;
@@ -31,39 +18,35 @@ struct hyper_dmabuf_ring_info_export {
 	struct xenbus_watch watch;
 };
 
-struct hyper_dmabuf_ring_info_import {
+struct xen_comm_rx_ring_info {
         int sdomain;
         int irq;
         int evtchn;
-        struct hyper_dmabuf_back_ring ring_back;
+        struct xen_comm_back_ring ring_back;
 	struct gnttab_unmap_grant_ref unmap_op;
 };
 
-int32_t hyper_dmabuf_get_domid(void);
-int32_t hyper_dmabuf_setup_data_dir(void);
-int32_t hyper_dmabuf_destroy_data_dir(void);
+int hyper_dmabuf_get_domid(void);
 
-int hyper_dmabuf_next_req_id_export(void);
+int hyper_dmabuf_xen_init_comm_env(void);
 
 /* exporter needs to generated info for page sharing */
-int hyper_dmabuf_exporter_ringbuf_init(int rdomain);
+int hyper_dmabuf_xen_init_tx_rbuf(int domid);
 
-/* importer needs to know about shared page and port numbers for ring buffer and event channel */
-int hyper_dmabuf_importer_ringbuf_init(int sdomain);
+/* importer needs to know about shared page and port numbers
+ * for ring buffer and event channel
+ */
+int hyper_dmabuf_xen_init_rx_rbuf(int domid);
 
 /* cleans up exporter ring created for given domain */
-void hyper_dmabuf_exporter_ringbuf_cleanup(int rdomain);
+void hyper_dmabuf_xen_cleanup_tx_rbuf(int domid);
 
 /* cleans up importer ring created for given domain */
-void hyper_dmabuf_importer_ringbuf_cleanup(int sdomain);
+void hyper_dmabuf_xen_cleanup_rx_rbuf(int domid);
 
-/* cleans up all exporter/importer rings */
-void hyper_dmabuf_cleanup_ringbufs(void);
+void hyper_dmabuf_xen_destroy_comm(void);
 
 /* send request to the remote domain */
-int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req, int wait);
-
-/* called by interrupt (WORKQUEUE) */
-int hyper_dmabuf_send_response(struct hyper_dmabuf_ring_rp* response, int domain);
+int hyper_dmabuf_xen_send_req(int domid, struct hyper_dmabuf_req *req, int wait);
 
 #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
index a068276..2a1f45b 100644
--- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c
@@ -9,80 +9,73 @@
 #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);
+DECLARE_HASHTABLE(xen_comm_tx_ring_hash, MAX_ENTRY_TX_RING);
+DECLARE_HASHTABLE(xen_comm_rx_ring_hash, MAX_ENTRY_RX_RING);
 
-int hyper_dmabuf_ring_table_init()
+void xen_comm_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;
+	hash_init(xen_comm_rx_ring_hash);
+	hash_init(xen_comm_tx_ring_hash);
 }
 
-int hyper_dmabuf_register_exporter_ring(struct hyper_dmabuf_ring_info_export *ring_info)
+int xen_comm_add_tx_ring(struct xen_comm_tx_ring_info *ring_info)
 {
-	struct hyper_dmabuf_exporter_ring_info *info_entry;
+	struct xen_comm_tx_ring_info_entry *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,
+	hash_add(xen_comm_tx_ring_hash, &info_entry->node,
 		info_entry->info->rdomain);
 
 	return 0;
 }
 
-int hyper_dmabuf_register_importer_ring(struct hyper_dmabuf_ring_info_import *ring_info)
+int xen_comm_add_rx_ring(struct xen_comm_rx_ring_info *ring_info)
 {
-	struct hyper_dmabuf_importer_ring_info *info_entry;
+	struct xen_comm_rx_ring_info_entry *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,
+	hash_add(xen_comm_rx_ring_hash, &info_entry->node,
 		info_entry->info->sdomain);
 
 	return 0;
 }
 
-struct hyper_dmabuf_ring_info_export *hyper_dmabuf_find_exporter_ring(int domid)
+struct xen_comm_tx_ring_info *xen_comm_find_tx_ring(int domid)
 {
-	struct hyper_dmabuf_exporter_ring_info *info_entry;
+	struct xen_comm_tx_ring_info_entry *info_entry;
 	int bkt;
 
-	hash_for_each(hyper_dmabuf_hash_exporter_ring, bkt, info_entry, node)
+	hash_for_each(xen_comm_tx_ring_hash, 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 xen_comm_rx_ring_info *xen_comm_find_rx_ring(int domid)
 {
-	struct hyper_dmabuf_importer_ring_info *info_entry;
+	struct xen_comm_rx_ring_info_entry *info_entry;
 	int bkt;
 
-	hash_for_each(hyper_dmabuf_hash_importer_ring, bkt, info_entry, node)
+	hash_for_each(xen_comm_rx_ring_hash, bkt, info_entry, node)
 		if(info_entry->info->sdomain == domid)
 			return info_entry->info;
 
 	return NULL;
 }
 
-int hyper_dmabuf_remove_exporter_ring(int domid)
+int xen_comm_remove_tx_ring(int domid)
 {
-	struct hyper_dmabuf_exporter_ring_info *info_entry;
+	struct xen_comm_tx_ring_info_entry *info_entry;
 	int bkt;
 
-	hash_for_each(hyper_dmabuf_hash_exporter_ring, bkt, info_entry, node)
+	hash_for_each(xen_comm_tx_ring_hash, bkt, info_entry, node)
 		if(info_entry->info->rdomain == domid) {
 			hash_del(&info_entry->node);
 			kfree(info_entry);
@@ -92,12 +85,12 @@ int hyper_dmabuf_remove_exporter_ring(int domid)
 	return -1;
 }
 
-int hyper_dmabuf_remove_importer_ring(int domid)
+int xen_comm_remove_rx_ring(int domid)
 {
-	struct hyper_dmabuf_importer_ring_info *info_entry;
+	struct xen_comm_rx_ring_info_entry *info_entry;
 	int bkt;
 
-	hash_for_each(hyper_dmabuf_hash_importer_ring, bkt, info_entry, node)
+	hash_for_each(xen_comm_rx_ring_hash, bkt, info_entry, node)
 		if(info_entry->info->sdomain == domid) {
 			hash_del(&info_entry->node);
 			kfree(info_entry);
@@ -107,24 +100,26 @@ int hyper_dmabuf_remove_importer_ring(int domid)
 	return -1;
 }
 
-void hyper_dmabuf_foreach_exporter_ring(void (*func)(int rdom))
+void xen_comm_foreach_tx_ring(void (*func)(int domid))
 {
-	struct hyper_dmabuf_exporter_ring_info *info_entry;
+	struct xen_comm_tx_ring_info_entry *info_entry;
 	struct hlist_node *tmp;
 	int bkt;
 
-	hash_for_each_safe(hyper_dmabuf_hash_exporter_ring, bkt, tmp, info_entry, node) {
+	hash_for_each_safe(xen_comm_tx_ring_hash, bkt, tmp,
+			   info_entry, node) {
 		func(info_entry->info->rdomain);
 	}
 }
 
-void hyper_dmabuf_foreach_importer_ring(void (*func)(int sdom))
+void xen_comm_foreach_rx_ring(void (*func)(int domid))
 {
-	struct hyper_dmabuf_importer_ring_info *info_entry;
+	struct xen_comm_rx_ring_info_entry *info_entry;
 	struct hlist_node *tmp;
 	int bkt;
 
-	hash_for_each_safe(hyper_dmabuf_hash_importer_ring, bkt, tmp, info_entry, node) {
+	hash_for_each_safe(xen_comm_rx_ring_hash, bkt, tmp,
+			   info_entry, node) {
 		func(info_entry->info->sdomain);
 	}
 }
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
index fd1958c..18b3afd 100644
--- a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h
@@ -2,40 +2,38 @@
 #define __HYPER_DMABUF_XEN_COMM_LIST_H__
 
 /* number of bits to be used for exported dmabufs hash table */
-#define MAX_ENTRY_EXPORT_RING 7
+#define MAX_ENTRY_TX_RING 7
 /* number of bits to be used for imported dmabufs hash table */
-#define MAX_ENTRY_IMPORT_RING 7
+#define MAX_ENTRY_RX_RING 7
 
-struct hyper_dmabuf_exporter_ring_info {
-        struct hyper_dmabuf_ring_info_export *info;
+struct xen_comm_tx_ring_info_entry {
+        struct xen_comm_tx_ring_info *info;
         struct hlist_node node;
 };
 
-struct hyper_dmabuf_importer_ring_info {
-        struct hyper_dmabuf_ring_info_import *info;
+struct xen_comm_rx_ring_info_entry {
+        struct xen_comm_rx_ring_info *info;
         struct hlist_node node;
 };
 
-int hyper_dmabuf_ring_table_init(void);
+void xen_comm_ring_table_init(void);
 
-int hyper_dmabuf_ring_table_destroy(void);
+int xen_comm_add_tx_ring(struct xen_comm_tx_ring_info *ring_info);
 
-int hyper_dmabuf_register_exporter_ring(struct hyper_dmabuf_ring_info_export *ring_info);
+int xen_comm_add_rx_ring(struct xen_comm_rx_ring_info *ring_info);
 
-int hyper_dmabuf_register_importer_ring(struct hyper_dmabuf_ring_info_import *ring_info);
+int xen_comm_remove_tx_ring(int domid);
 
-struct hyper_dmabuf_ring_info_export *hyper_dmabuf_find_exporter_ring(int domid);
+int xen_comm_remove_rx_ring(int domid);
 
-struct hyper_dmabuf_ring_info_import *hyper_dmabuf_find_importer_ring(int domid);
+struct xen_comm_tx_ring_info *xen_comm_find_tx_ring(int domid);
 
-int hyper_dmabuf_remove_exporter_ring(int domid);
-
-int hyper_dmabuf_remove_importer_ring(int domid);
+struct xen_comm_rx_ring_info *xen_comm_find_rx_ring(int domid);
 
 /* iterates over all exporter rings and calls provided function for each of them */
-void hyper_dmabuf_foreach_exporter_ring(void (*func)(int rdom));
+void xen_comm_foreach_tx_ring(void (*func)(int domid));
 
 /* iterates over all importer rings and calls provided function for each of them */
-void hyper_dmabuf_foreach_importer_ring(void (*func)(int sdom));
+void xen_comm_foreach_rx_ring(void (*func)(int domid));
 
 #endif // __HYPER_DMABUF_XEN_COMM_LIST_H__
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.c
new file mode 100644
index 0000000..e7b871a
--- /dev/null
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.c
@@ -0,0 +1,22 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <xen/grant_table.h>
+#include "../hyper_dmabuf_msg.h"
+#include "../hyper_dmabuf_drv.h"
+#include "hyper_dmabuf_xen_drv.h"
+#include "hyper_dmabuf_xen_comm.h"
+#include "hyper_dmabuf_xen_shm.h"
+
+struct hyper_dmabuf_backend_ops xen_backend_ops = {
+	.get_vm_id = hyper_dmabuf_get_domid,
+	.share_pages = hyper_dmabuf_xen_share_pages,
+	.unshare_pages = hyper_dmabuf_xen_unshare_pages,
+	.map_shared_pages = (void *)hyper_dmabuf_xen_map_shared_pages,
+	.unmap_shared_pages = hyper_dmabuf_xen_unmap_shared_pages,
+	.init_comm_env = hyper_dmabuf_xen_init_comm_env,
+	.destroy_comm = hyper_dmabuf_xen_destroy_comm,
+	.init_rx_ch = hyper_dmabuf_xen_init_rx_rbuf,
+	.init_tx_ch = hyper_dmabuf_xen_init_tx_rbuf,
+	.send_req = hyper_dmabuf_xen_send_req,
+};
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.h b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.h
new file mode 100644
index 0000000..e351c08
--- /dev/null
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_drv.h
@@ -0,0 +1,20 @@
+#ifndef __HYPER_DMABUF_XEN_DRV_H__
+#define __HYPER_DMABUF_XEN_DRV_H__
+#include <xen/interface/grant_table.h>
+
+extern struct hyper_dmabuf_backend_ops xen_backend_ops;
+
+/* Main purpose of this structure is to keep
+ * all references created or acquired for sharing
+ * pages with another domain for freeing those later
+ * when unsharing.
+ */
+struct xen_shared_pages_info {
+        grant_ref_t lvl3_gref; /* top level refid */
+        grant_ref_t *lvl3_table; /* page of top level addressing, it contains refids of 2nd level pages */
+        grant_ref_t *lvl2_table; /* table of 2nd level pages, that contains refids to data pages */
+        struct gnttab_unmap_grant_ref* unmap_ops; /* unmap ops for mapped pages */
+        struct page **data_pages; /* data pages to be unmapped */
+};
+
+#endif // __HYPER_DMABUF_XEN_COMM_H__
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c
new file mode 100644
index 0000000..c0045d4
--- /dev/null
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.c
@@ -0,0 +1,356 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <xen/grant_table.h>
+#include <asm/xen/page.h>
+#include "hyper_dmabuf_xen_drv.h"
+
+#define REFS_PER_PAGE (PAGE_SIZE/sizeof(grant_ref_t))
+
+/*
+ * 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.
+ *
+ *      3rd 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.
+ */
+int hyper_dmabuf_xen_share_pages(struct page **pages, int domid, int nents,
+				 void **refs_info)
+{
+	grant_ref_t lvl3_gref;
+	grant_ref_t *lvl2_table;
+	grant_ref_t *lvl3_table;
+
+	/*
+	 * Calculate number of pages needed for 2nd level addresing:
+	 */
+	int n_lvl2_grefs = (nents/REFS_PER_PAGE +
+			   ((nents % REFS_PER_PAGE) ? 1: 0));
+
+	struct xen_shared_pages_info *sh_pages_info;
+	int i;
+
+	lvl3_table = (grant_ref_t *)__get_free_pages(GFP_KERNEL, 1);
+	lvl2_table = (grant_ref_t *)__get_free_pages(GFP_KERNEL, n_lvl2_grefs);
+
+	sh_pages_info = kmalloc(sizeof(*sh_pages_info), GFP_KERNEL);
+	*refs_info = (void *)sh_pages_info;
+
+	/* share data pages in rw mode*/
+	for (i=0; i<nents; i++) {
+		lvl2_table[i] = gnttab_grant_foreign_access(domid,
+							    pfn_to_mfn(page_to_pfn(pages[i])),
+							    0);
+	}
+
+	/* Share 2nd level addressing pages in readonly mode*/
+	for (i=0; i< n_lvl2_grefs; i++) {
+		lvl3_table[i] = gnttab_grant_foreign_access(domid,
+							   virt_to_mfn((unsigned long)lvl2_table+i*PAGE_SIZE ),
+							   1);
+	}
+
+	/* Share lvl3_table in readonly mode*/
+	lvl3_gref = gnttab_grant_foreign_access(domid,
+						virt_to_mfn((unsigned long)lvl3_table),
+						1);
+
+
+	/* Store lvl3_table page to be freed later */
+	sh_pages_info->lvl3_table = lvl3_table;
+
+	/* Store lvl2_table pages to be freed later */
+	sh_pages_info->lvl2_table = lvl2_table;
+
+	/* Store exported pages refid to be unshared later */
+	sh_pages_info->lvl3_gref = lvl3_gref;
+
+	return lvl3_gref;
+}
+
+int hyper_dmabuf_xen_unshare_pages(void **refs_info, int nents) {
+	struct xen_shared_pages_info *sh_pages_info;
+	int n_lvl2_grefs = (nents/REFS_PER_PAGE + ((nents % REFS_PER_PAGE) ? 1: 0));
+	int i;
+
+	sh_pages_info = (struct xen_shared_pages_info *)(*refs_info);
+
+	if (sh_pages_info->lvl3_table == NULL ||
+	    sh_pages_info->lvl2_table ==  NULL ||
+	    sh_pages_info->lvl3_gref == -1) {
+		printk("gref table for hyper_dmabuf already cleaned up\n");
+		return 0;
+	}
+
+	/* End foreign access for data pages, but do not free them */
+	for (i = 0; i < nents; i++) {
+		if (gnttab_query_foreign_access(sh_pages_info->lvl2_table[i])) {
+			printk("refid not shared !!\n");
+		}
+		gnttab_end_foreign_access_ref(sh_pages_info->lvl2_table[i], 0);
+		gnttab_free_grant_reference(sh_pages_info->lvl2_table[i]);
+	}
+
+	/* End foreign access for 2nd level addressing pages */
+	for (i = 0; i < n_lvl2_grefs; i++) {
+		if (gnttab_query_foreign_access(sh_pages_info->lvl3_table[i])) {
+			printk("refid not shared !!\n");
+		}
+		if (!gnttab_end_foreign_access_ref(sh_pages_info->lvl3_table[i], 1)) {
+			printk("refid still in use!!!\n");
+		}
+		gnttab_free_grant_reference(sh_pages_info->lvl3_table[i]);
+	}
+
+	/* End foreign access for top level addressing page */
+	if (gnttab_query_foreign_access(sh_pages_info->lvl3_gref)) {
+		printk("gref not shared !!\n");
+	}
+
+	gnttab_end_foreign_access_ref(sh_pages_info->lvl3_gref, 1);
+	gnttab_free_grant_reference(sh_pages_info->lvl3_gref);
+
+	/* freeing all pages used for 2 level addressing */
+	free_pages((unsigned long)sh_pages_info->lvl2_table, n_lvl2_grefs);
+	free_pages((unsigned long)sh_pages_info->lvl3_table, 1);
+
+	sh_pages_info->lvl3_gref = -1;
+	sh_pages_info->lvl2_table = NULL;
+	sh_pages_info->lvl3_table = NULL;
+	kfree(sh_pages_info);
+	sh_pages_info = NULL;
+
+	return 0;
+}
+
+/*
+ * Maps provided top level ref id and then return array of pages containing data refs.
+ */
+struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int nents, void **refs_info)
+{
+	struct page *lvl3_table_page;
+	struct page **lvl2_table_pages;
+	struct page **data_pages;
+	struct xen_shared_pages_info *sh_pages_info;
+
+	grant_ref_t *lvl3_table;
+	grant_ref_t *lvl2_table;
+
+	struct gnttab_map_grant_ref lvl3_map_ops;
+	struct gnttab_unmap_grant_ref lvl3_unmap_ops;
+
+	struct gnttab_map_grant_ref *lvl2_map_ops;
+	struct gnttab_unmap_grant_ref *lvl2_unmap_ops;
+
+	struct gnttab_map_grant_ref *data_map_ops;
+	struct gnttab_unmap_grant_ref *data_unmap_ops;
+
+	int nents_last = nents % REFS_PER_PAGE;
+	int n_lvl2_grefs = (nents / REFS_PER_PAGE) + ((nents_last > 0) ? 1 : 0);
+	int i, j, k;
+
+	sh_pages_info = kmalloc(sizeof(*sh_pages_info), GFP_KERNEL);
+	*refs_info = (void *) sh_pages_info;
+
+	lvl2_table_pages = kcalloc(sizeof(struct page*), n_lvl2_grefs, GFP_KERNEL);
+	data_pages = kcalloc(sizeof(struct page*), nents, GFP_KERNEL);
+
+	lvl2_map_ops = kcalloc(sizeof(*lvl2_map_ops), n_lvl2_grefs, GFP_KERNEL);
+	lvl2_unmap_ops = kcalloc(sizeof(*lvl2_unmap_ops), n_lvl2_grefs, GFP_KERNEL);
+
+	data_map_ops = kcalloc(sizeof(*data_map_ops), nents, GFP_KERNEL);
+	data_unmap_ops = kcalloc(sizeof(*data_unmap_ops), nents, GFP_KERNEL);
+
+	/* Map top level addressing page */
+	if (gnttab_alloc_pages(1, &lvl3_table_page)) {
+		printk("Cannot allocate pages\n");
+		return NULL;
+	}
+
+	lvl3_table = (grant_ref_t *)pfn_to_kaddr(page_to_pfn(lvl3_table_page));
+
+	gnttab_set_map_op(&lvl3_map_ops, (unsigned long)lvl3_table, GNTMAP_host_map | GNTMAP_readonly,
+			  (grant_ref_t)lvl3_gref, domid);
+
+	gnttab_set_unmap_op(&lvl3_unmap_ops, (unsigned long)lvl3_table, GNTMAP_host_map | GNTMAP_readonly, -1);
+
+	if (gnttab_map_refs(&lvl3_map_ops, NULL, &lvl3_table_page, 1)) {
+		printk("\nxen: dom0: HYPERVISOR map grant ref failed");
+		return NULL;
+	}
+
+	if (lvl3_map_ops.status) {
+		printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d",
+			lvl3_map_ops.status);
+		return NULL;
+	} else {
+		lvl3_unmap_ops.handle = lvl3_map_ops.handle;
+	}
+
+	/* Map all second level pages */
+	if (gnttab_alloc_pages(n_lvl2_grefs, lvl2_table_pages)) {
+		printk("Cannot allocate pages\n");
+		return NULL;
+	}
+
+	for (i = 0; i < n_lvl2_grefs; i++) {
+		lvl2_table = (grant_ref_t *)pfn_to_kaddr(page_to_pfn(lvl2_table_pages[i]));
+		gnttab_set_map_op(&lvl2_map_ops[i], (unsigned long)lvl2_table, GNTMAP_host_map | GNTMAP_readonly,
+				  lvl3_table[i], domid);
+		gnttab_set_unmap_op(&lvl2_unmap_ops[i], (unsigned long)lvl2_table, GNTMAP_host_map | GNTMAP_readonly, -1);
+	}
+
+	/* Unmap top level page, as it won't be needed any longer */
+	if (gnttab_unmap_refs(&lvl3_unmap_ops, NULL, &lvl3_table_page, 1)) {
+		printk("\xen: cannot unmap top level page\n");
+		return NULL;
+	}
+
+	if (gnttab_map_refs(lvl2_map_ops, NULL, lvl2_table_pages, n_lvl2_grefs)) {
+		printk("\nxen: dom0: HYPERVISOR map grant ref failed");
+		return NULL;
+	}
+
+	/* Checks if pages were mapped correctly */
+	for (i = 0; i < n_lvl2_grefs; i++) {
+		if (lvl2_map_ops[i].status) {
+			printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d",
+			       lvl2_map_ops[i].status);
+			return NULL;
+		} else {
+			lvl2_unmap_ops[i].handle = lvl2_map_ops[i].handle;
+		}
+	}
+
+	if (gnttab_alloc_pages(nents, data_pages)) {
+		printk("Cannot allocate pages\n");
+		return NULL;
+	}
+
+	k = 0;
+
+	for (i = 0; i < (nents_last ? n_lvl2_grefs - 1 : n_lvl2_grefs); i++) {
+		lvl2_table = pfn_to_kaddr(page_to_pfn(lvl2_table_pages[i]));
+		for (j = 0; j < REFS_PER_PAGE; j++) {
+			gnttab_set_map_op(&data_map_ops[k],
+					  (unsigned long)pfn_to_kaddr(page_to_pfn(data_pages[k])),
+					  GNTMAP_host_map,
+					  lvl2_table[j], domid);
+
+			gnttab_set_unmap_op(&data_unmap_ops[k],
+					    (unsigned long)pfn_to_kaddr(page_to_pfn(data_pages[k])),
+					    GNTMAP_host_map, -1);
+			k++;
+		}
+	}
+
+	/* for grefs in the last lvl2 table page */
+	lvl2_table = pfn_to_kaddr(page_to_pfn(lvl2_table_pages[n_lvl2_grefs - 1]));
+
+	for (j = 0; j < nents_last; j++) {
+		gnttab_set_map_op(&data_map_ops[k],
+				  (unsigned long)pfn_to_kaddr(page_to_pfn(data_pages[k])),
+				  GNTMAP_host_map,
+				  lvl2_table[j], domid);
+
+		gnttab_set_unmap_op(&data_unmap_ops[k],
+				    (unsigned long)pfn_to_kaddr(page_to_pfn(data_pages[k])),
+				    GNTMAP_host_map, -1);
+		k++;
+	}
+
+	if (gnttab_map_refs(data_map_ops, NULL, data_pages, nents)) {
+		printk("\nxen: dom0: HYPERVISOR map grant ref failed\n");
+		return NULL;
+	}
+
+	/* unmapping lvl2 table pages */
+	if (gnttab_unmap_refs(lvl2_unmap_ops, NULL, lvl2_table_pages,
+			      n_lvl2_grefs)) {
+		printk("Cannot unmap 2nd level refs\n");
+		return NULL;
+	}
+
+	for (i = 0; i < nents; i++) {
+		if (data_map_ops[i].status) {
+			printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d\n",
+				data_map_ops[i].status);
+			return NULL;
+		} else {
+			data_unmap_ops[i].handle = data_map_ops[i].handle;
+		}
+	}
+
+	/* store these references for unmapping in the future */
+	sh_pages_info->unmap_ops = data_unmap_ops;
+	sh_pages_info->data_pages = data_pages;
+
+	gnttab_free_pages(1, &lvl3_table_page);
+	gnttab_free_pages(n_lvl2_grefs, lvl2_table_pages);
+	kfree(lvl2_table_pages);
+	kfree(lvl2_map_ops);
+	kfree(lvl2_unmap_ops);
+	kfree(data_map_ops);
+
+	return data_pages;
+}
+
+int hyper_dmabuf_xen_unmap_shared_pages(void **refs_info, int nents) {
+	struct xen_shared_pages_info *sh_pages_info;
+
+	sh_pages_info = (struct xen_shared_pages_info *)(*refs_info);
+
+	if (sh_pages_info->unmap_ops == NULL ||
+	    sh_pages_info->data_pages == NULL) {
+		printk("Imported pages already cleaned up or buffer was not imported yet\n");
+		return 0;
+	}
+
+	if (gnttab_unmap_refs(sh_pages_info->unmap_ops, NULL,
+			      sh_pages_info->data_pages, nents) ) {
+		printk("Cannot unmap data pages\n");
+		return -EINVAL;
+	}
+
+	gnttab_free_pages(nents, sh_pages_info->data_pages);
+
+	kfree(sh_pages_info->data_pages);
+	kfree(sh_pages_info->unmap_ops);
+	sh_pages_info->unmap_ops = NULL;
+	sh_pages_info->data_pages = NULL;
+	kfree(sh_pages_info);
+	sh_pages_info = NULL;
+
+	return 0;
+}
diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.h b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.h
new file mode 100644
index 0000000..2287804
--- /dev/null
+++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_shm.h
@@ -0,0 +1,19 @@
+#ifndef __HYPER_DMABUF_XEN_SHM_H__
+#define __HYPER_DMABUF_XEN_SHM_H__
+
+/* 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. */
+int hyper_dmabuf_xen_share_pages(struct page **pages, int domid, int nents,
+				 void **refs_info);
+
+int hyper_dmabuf_xen_unshare_pages(void **refs_info, int nents);
+
+/* Maps provided top level ref id and then return array of pages containing data refs.
+ */
+struct page ** hyper_dmabuf_xen_map_shared_pages(int lvl3_gref, int domid, int nents,
+						void **refs_info);
+
+int hyper_dmabuf_xen_unmap_shared_pages(void **refs_info, int nents);
+
+#endif /* __HYPER_DMABUF_XEN_SHM_H__ */
-- 
2.7.4


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

  parent reply	other threads:[~2017-12-19 19:49 UTC|newest]

Thread overview: 159+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-19 19:29 [RFC PATCH 01/60] hyper_dmabuf: initial working version of hyper_dmabuf drv Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 02/60] hyper_dmabuf: added a doc for hyper_dmabuf sharing Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 03/60] hyper_dmabuf: re-use dma_buf previously exported if exist Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 04/60] hyper_dmabuf: new index, k for pointing a right n-th page Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 05/60] hyper_dmabuf: skip creating a comm ch if exist for the VM Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 06/60] hyper_dmabuf: map shared pages only once when importing Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 07/60] hyper_dmabuf: message parsing done via workqueue Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 08/60] hyper_dmabuf: automatic comm channel initialization using xenstore Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 09/60] hyper_dmabuf: indirect DMA_BUF synchronization via shadowing Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 10/60] hyper_dmabuf: make sure to free memory to prevent leak Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 11/60] hyper_dmabuf: check stack before unmapping/detaching shadow DMA_BUF Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 12/60] hyper_dmabuf: two different unexporting mechanisms Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 13/60] hyper_dmabuf: postponing cleanup of hyper_DMABUF Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 14/60] hyper_dmabuf: clean-up process based on file->f_count Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 15/60] hyper_dmabuf: reusing previously released hyper_dmabuf_id Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim [this message]
2017-12-19 19:29   ` [RFC PATCH 16/60] hyper_dmabuf: define hypervisor specific backend API Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 17/60] hyper_dmabuf: use dynamic debug macros for logging Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 18/60] hyper_dmabuf: reset comm channel when one end has disconnected Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 19/60] hyper_dmabuf: fix the case with sharing a buffer with 2 pages Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 20/60] hyper_dmabuf: optimized loop with less condition check Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 21/60] hyper_dmabuf: exposing drv information using sysfs Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 22/60] hyper_dmabuf: configure license Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 23/60] hyper_dmabuf: use CONFIG_HYPER_DMABUF_XEN instead of CONFIG_XEN Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 24/60] hyper_dmabuf: waits for resp only if WAIT_AFTER_SYNC_REQ == 1 Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 25/60] hyper_dmabuf: introduced delayed unexport Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 26/60] hyper_dmabuf: add mutexes to prevent several race conditions Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 27/60] hyper_dmabuf: use proper error codes Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 28/60] hyper_dmabuf: address several synchronization issues Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 29/60] hyper_dmabuf: make sure to release allocated buffers when exiting Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 30/60] hyper_dmabuf: free already mapped pages when error happens Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 31/60] hyper_dmabuf: built-in compilation option Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 32/60] hyper_dmabuf: make all shared pages read-only Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 33/60] hyper_dmabuf: error checking on the result of dma_buf_map_attachment Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 34/60] hyper_dmabuf: extend DMA bitmask to 64-bits Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 35/60] hyper_dmabuf: 128bit hyper_dmabuf_id with random keys Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 36/60] hyper_dmabuf: error handling when share_pages fails Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 37/60] hyper_dmabuf: implementation of query ioctl Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 38/60] hyper_dmabuf: preventing self exporting of dma_buf Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 39/60] hyper_dmabuf: correcting DMA-BUF clean-up order Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 40/60] hyper_dmabuf: do not use 'private' as field name Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 41/60] hyper_dmabuf: re-organize driver source Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 42/60] hyper_dmabuf: always generate a new random keys Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:29 ` [RFC PATCH 43/60] hyper_dmabuf: fixes on memory leaks in various places Dongwon Kim
2017-12-19 19:29   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 44/60] hyper_dmabuf: proper handling of sgt_info->priv Dongwon Kim
2017-12-19 19:30   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 45/60] hyper_dmabuf: adding poll/read for event generation Dongwon Kim
2017-12-19 19:30   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 46/60] hyper_dmabuf: delay auto initialization of comm_env Dongwon Kim
2017-12-19 19:30   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 47/60] hyper_dmabuf: fix issues with event-polling Dongwon Kim
2017-12-19 19:30   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 48/60] hyper_dmabuf: add query items for buffer private info Dongwon Kim
2017-12-19 19:30   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 49/60] hyper_dmabuf: general clean-up and fixes Dongwon Kim
2017-12-19 19:30   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 50/60] hyper_dmabuf: fix styling err and warns caught by checkpatch.pl Dongwon Kim
2017-12-19 19:30 ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 51/60] hyper_dmabuf: missing mutex_unlock and move spinlock Dongwon Kim
2017-12-19 19:30   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 52/60] hyper_dmabuf: remove prefix 'hyper_dmabuf' from static func and backend APIs Dongwon Kim
2017-12-19 19:30 ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 53/60] hyper_dmabuf: define fastpath_export for exporting existing buffer Dongwon Kim
2017-12-19 19:30   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 54/60] hyper_dmabuf: 'backend_ops' reduced to 'bknd_ops' and 'ops' to 'bknd_ops' Dongwon Kim
2017-12-19 19:30   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 55/60] hyper_dmabuf: fixed wrong send_req call Dongwon Kim
2017-12-19 19:30 ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 56/60] hyper_dmabuf: add initialization and cleanup to bknd_ops Dongwon Kim
2017-12-19 19:30 ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 57/60] hyper_dmabuf: change type of ref to shared pages to unsigned long Dongwon Kim
2017-12-19 19:30   ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 58/60] hyper_dmabuf: move device node out of /dev/xen/ Dongwon Kim
2017-12-19 19:30 ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 59/60] hyper_dmabuf: freeing hy_drv_priv when drv init fails (v2) Dongwon Kim
2017-12-19 19:30 ` Dongwon Kim
2017-12-19 19:30 ` [RFC PATCH 60/60] hyper_dmabuf: move hyper_dmabuf to under drivers/dma-buf/ Dongwon Kim
2017-12-19 19:30 ` Dongwon Kim
2017-12-19 23:27 ` [RFC PATCH 01/60] hyper_dmabuf: initial working version of hyper_dmabuf drv Dongwon Kim
2017-12-19 23:27 ` Dongwon Kim
2017-12-19 23:27   ` Dongwon Kim
2017-12-20  8:17   ` Juergen Gross
2017-12-20  8:17   ` [Xen-devel] " Juergen Gross
2018-01-10 23:21     ` Dongwon Kim
2018-01-10 23:21     ` [Xen-devel] " Dongwon Kim
2018-01-10 23:21       ` Dongwon Kim
2017-12-20  8:38   ` Oleksandr Andrushchenko
2017-12-20  8:38   ` [Xen-devel] " Oleksandr Andrushchenko
2018-01-10 23:14     ` Dongwon Kim
2018-01-10 23:14     ` [Xen-devel] " Dongwon Kim
2017-12-20  9:59   ` Daniel Vetter
2017-12-20  9:59     ` Daniel Vetter
2017-12-26 18:19     ` Matt Roper
2017-12-26 18:19       ` Matt Roper
2017-12-29 13:03       ` Tomeu Vizoso
2017-12-29 13:03       ` Tomeu Vizoso
2017-12-29 13:03         ` Tomeu Vizoso
2017-12-26 18:19     ` Matt Roper
2018-01-10 23:13     ` Dongwon Kim
2018-01-10 23:13     ` Dongwon Kim
2017-12-20  9:59   ` Daniel Vetter
2018-02-15  1:34 ` Dongwon Kim
2018-02-15  1:34 ` Dongwon Kim
2018-02-15  1:34   ` Dongwon Kim

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1513711816-2618-16-git-send-email-dongwon.kim@intel.com \
    --to=dongwon.kim@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mateuszx.potrola@intel.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.