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__ */
