Skip to contentSkip to conversation

gntdev: steal in-domain memory for HVM mappings

PATCH New Daniel De Graaf 1 participant 1 message Aug 26, 2010 Xen hypervisor interface

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 gntdev: steal in-domain memory for HVM mappings

Since Xen cannot modify the page tables to allow access outside of the machine in HVM, change to allocating kernel memory and having Xen change the physical mappings of that memory.

Signature · 2 lines
Daniel De Graaf
National Security Agency
drivers/xen/gntdev.c +59 -16
index a33e443..d783da8 100644
@@ -25,6 +25,7 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/mmu_notifier.h>
+#include <linux/vmalloc.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/sched.h>
@@ -67,6 +68,7 @@ struct grant_map {
 	struct ioctl_gntdev_grant_ref *grants;
 	struct gnttab_map_grant_ref   *map_ops;
 	struct gnttab_unmap_grant_ref *unmap_ops;
+	void* start;
 };
 
 /* ------------------------------------------------------------------ */
@@ -95,6 +97,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
 	add->grants    = kzalloc(sizeof(add->grants[0])    * count, GFP_KERNEL);
 	add->map_ops   = kzalloc(sizeof(add->map_ops[0])   * count, GFP_KERNEL);
 	add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL);
+	add->start = NULL;
 	if (NULL == add->grants  ||
 	    NULL == add->map_ops ||
 	    NULL == add->unmap_ops)
@@ -187,6 +190,7 @@ static void gntdev_free_map(struct grant_map *map)
 {
 	if (!map)
 		return;
+	vfree(map->start);
 	kfree(map->grants);
 	kfree(map->map_ops);
 	kfree(map->unmap_ops);
@@ -212,6 +216,24 @@ static int find_grant_ptes(pte_t *pte, pgtable_t token, unsigned long addr, void
 	return 0;
 }
 
+static int hvm_setup_grant_ops(struct grant_map *map)
+{
+	int i;
+	map->start = vmalloc(map->count << PAGE_SHIFT);
+	if (!map->start)
+		return -ENOMEM;
+
+	for(i = 0; i < map->count; i++) {
+		void* address = map->start + (i << PAGE_SHIFT);
+		u64 mfn = (u64)pfn_to_kaddr(vmalloc_to_pfn(address));
+		gnttab_set_map_op(&map->map_ops[i], mfn, map->flags,
+		                  map->grants[i].ref, map->grants[i].domid);
+		gnttab_set_unmap_op(&map->unmap_ops[i], mfn, map->flags, 0);
+	}
+
+	return 0;
+}
+
 static int map_grant_pages(struct grant_map *map)
 {
 	int i, err = 0;
@@ -266,10 +288,27 @@ static void gntdev_vma_close(struct vm_area_struct *vma)
 
 static int gntdev_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
-	if (debug)
-		printk("%s: vaddr %p, pgoff %ld (shouldn't happen)\n",
-		       __FUNCTION__, vmf->virtual_address, vmf->pgoff);
-	vmf->flags = VM_FAULT_ERROR;
+	struct page *page;
+	struct grant_map *map = vma->vm_private_data;
+	pgoff_t pgoff = vmf->pgoff - vma->vm_pgoff;
+	
+	if (!map || !map->start) {
+		if (debug)
+			printk("%s: vaddr %p, pgoff %ld (shouldn't happen)\n",
+				__FUNCTION__, vmf->virtual_address, pgoff);
+		return VM_FAULT_SIGBUS;
+	}
+
+	if (pgoff < 0 || pgoff > map->count)
+		return VM_FAULT_SIGBUS;
+
+	page = vmalloc_to_page(map->start + (pgoff << PAGE_SHIFT));
+	if (!page)
+		return VM_FAULT_SIGBUS;
+	
+	get_page(page);
+	vmf->page = page;
+
 	return 0;
 }
 
@@ -573,29 +612,33 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_flags |= VM_DONTCOPY;
 	vma->vm_flags |= VM_DONTEXPAND;
+	vma->vm_flags |= VM_FOREIGN;
 
 	vma->vm_private_data = map;
 	map->vma = vma;
 
-	map->flags = GNTMAP_host_map | GNTMAP_application_map | GNTMAP_contains_pte;
+	map->flags = GNTMAP_host_map;
 	if (!(vma->vm_flags & VM_WRITE))
 		map->flags |= GNTMAP_readonly;
 
-	err = apply_to_page_range(vma->vm_mm, vma->vm_start,
-				  vma->vm_end - vma->vm_start,
-				  find_grant_ptes, map);
-	if (err) {
-		goto unlock_out;
-		if (debug)
-			printk("%s: find_grant_ptes() failure.\n", __FUNCTION__);
+	if (xen_pv_domain()) {
+		// Add foreign mapping by page table modification
+		map->flags |= GNTMAP_application_map | GNTMAP_contains_pte;
+
+		err = apply_to_page_range(vma->vm_mm, vma->vm_start,
+					  vma->vm_end - vma->vm_start,
+					  find_grant_ptes, map);
+	} else {
+		// Add mapping by sharing in-domain memory
+		err = hvm_setup_grant_ops(map);
 	}
+	if (err)
+		goto unlock_out;
 
 	err = map_grant_pages(map);
-	if (err) {
+	if (err)
 		goto unlock_out;
-		if (debug)
-			printk("%s: map_grant_pages() failure.\n", __FUNCTION__);
-	}
+
 	map->is_mapped = 1;
 
 unlock_out:

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel