[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] Re: [PATCH 4/6] xen-gntdev: Support mapping in HVM domains
On Fri, Jan 21, 2011 at 10:59:06AM -0500, Daniel De Graaf wrote: > HVM does not allow direct PTE modification, so instead we request > that Xen change its internal p2m mappings on the allocated pages and > map the memory into userspace normally. > > Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> > --- > drivers/xen/gntdev.c | 115 +++++++++++++++++++++++++++++++------------- > drivers/xen/grant-table.c | 6 ++ > 2 files changed, 87 insertions(+), 34 deletions(-) > > diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c > index 256162b..a5710e8 100644 > --- a/drivers/xen/gntdev.c > +++ b/drivers/xen/gntdev.c > @@ -32,6 +32,7 @@ > #include <linux/sched.h> > #include <linux/spinlock.h> > #include <linux/slab.h> > +#include <linux/highmem.h> > > #include <xen/xen.h> > #include <xen/grant_table.h> > @@ -52,6 +53,8 @@ MODULE_PARM_DESC(limit, "Maximum number of grants that may > be mapped by " > > static atomic_t pages_mapped = ATOMIC_INIT(0); > > +static int use_ptemod; > + > struct gntdev_priv { > struct list_head maps; > /* lock protects maps from concurrent changes */ > @@ -74,6 +77,8 @@ struct grant_map { > struct page **pages; > }; > > +static int unmap_grant_pages(struct grant_map *map, int offset, int pages); > + > /* ------------------------------------------------------------------ */ > > static void gntdev_print_maps(struct gntdev_priv *priv, > @@ -179,11 +184,32 @@ static void gntdev_put_map(struct grant_map *map) > > atomic_sub(map->count, &pages_mapped); > > - if (map->pages) > + if (map->pages) { > + if (!use_ptemod) > + unmap_grant_pages(map, 0, map->count); > + > for (i = 0; i < map->count; i++) { > - if (map->pages[i]) > + uint32_t check, *tmp; > + if (!map->pages[i]) > + continue; > + /* XXX When unmapping in an HVM domain, Xen will > + * sometimes end up mapping the GFN to an invalid MFN. > + * In this case, writes will be discarded and reads will > + * return all 0xFF bytes. Leak these unusable GFNs I forgot to ask, under what version of Xen did you run this? I want to add that to the comment so when it gets fixed we know what the failing version is. > + * until Xen supports fixing their p2m mapping. > + */ > + tmp = kmap(map->pages[i]); > + *tmp = 0xdeaddead; > + mb(); > + check = *tmp; > + kunmap(map->pages[i]); > + if (check == 0xdeaddead) > __free_page(map->pages[i]); > + else > + pr_debug("Discard page %d=%ld\n", i, > + page_to_pfn(map->pages[i])); > } > + } > kfree(map->pages); > kfree(map->grants); > kfree(map->map_ops); > @@ -198,17 +224,16 @@ static int find_grant_ptes(pte_t *pte, pgtable_t token, > { > struct grant_map *map = data; > unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT; > + int flags = map->flags | GNTMAP_application_map | GNTMAP_contains_pte; > u64 pte_maddr; > > BUG_ON(pgnr >= map->count); > pte_maddr = arbitrary_virt_to_machine(pte).maddr; > > - gnttab_set_map_op(&map->map_ops[pgnr], pte_maddr, > - GNTMAP_contains_pte | map->flags, > + gnttab_set_map_op(&map->map_ops[pgnr], pte_maddr, flags, > map->grants[pgnr].ref, > map->grants[pgnr].domid); > - gnttab_set_unmap_op(&map->unmap_ops[pgnr], pte_maddr, > - GNTMAP_contains_pte | map->flags, > + gnttab_set_unmap_op(&map->unmap_ops[pgnr], pte_maddr, flags, > 0 /* handle */); > return 0; > } > @@ -216,6 +241,19 @@ static int find_grant_ptes(pte_t *pte, pgtable_t token, > static int map_grant_pages(struct grant_map *map) > { > int i, err = 0; > + phys_addr_t addr; > + > + if (!use_ptemod) { > + for (i = 0; i < map->count; i++) { > + addr = (phys_addr_t) > + pfn_to_kaddr(page_to_pfn(map->pages[i])); > + gnttab_set_map_op(&map->map_ops[i], addr, map->flags, > + map->grants[i].ref, > + map->grants[i].domid); > + gnttab_set_unmap_op(&map->unmap_ops[i], addr, > + map->flags, 0 /* handle */); > + } > + } > > pr_debug("map %d+%d\n", map->index, map->count); > err = gnttab_map_refs(map->map_ops, map->pages, map->count); > @@ -260,17 +298,8 @@ static void gntdev_vma_close(struct vm_area_struct *vma) > gntdev_put_map(map); > } > > -static int gntdev_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) > -{ > - pr_debug("vaddr %p, pgoff %ld (shouldn't happen)\n", > - vmf->virtual_address, vmf->pgoff); > - vmf->flags = VM_FAULT_ERROR; > - return 0; > -} > - > static struct vm_operations_struct gntdev_vmops = { > .close = gntdev_vma_close, > - .fault = gntdev_vma_fault, > }; > > /* ------------------------------------------------------------------ */ > @@ -355,14 +384,16 @@ static int gntdev_open(struct inode *inode, struct file > *flip) > INIT_LIST_HEAD(&priv->maps); > spin_lock_init(&priv->lock); > > - priv->mm = get_task_mm(current); > - if (!priv->mm) { > - kfree(priv); > - return -ENOMEM; > + if (use_ptemod) { > + priv->mm = get_task_mm(current); > + if (!priv->mm) { > + kfree(priv); > + return -ENOMEM; > + } > + priv->mn.ops = &gntdev_mmu_ops; > + ret = mmu_notifier_register(&priv->mn, priv->mm); > + mmput(priv->mm); > } > - priv->mn.ops = &gntdev_mmu_ops; > - ret = mmu_notifier_register(&priv->mn, priv->mm); > - mmput(priv->mm); > > if (ret) { > kfree(priv); > @@ -390,7 +421,8 @@ static int gntdev_release(struct inode *inode, struct > file *flip) > } > spin_unlock(&priv->lock); > > - mmu_notifier_unregister(&priv->mn, priv->mm); > + if (use_ptemod) > + mmu_notifier_unregister(&priv->mn, priv->mm); > kfree(priv); > return 0; > } > @@ -515,7 +547,7 @@ static int gntdev_mmap(struct file *flip, struct > vm_area_struct *vma) > int index = vma->vm_pgoff; > int count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; > struct grant_map *map; > - int err = -EINVAL; > + int i, err = -EINVAL; > > if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) > return -EINVAL; > @@ -527,9 +559,9 @@ static int gntdev_mmap(struct file *flip, struct > vm_area_struct *vma) > map = gntdev_find_map_index(priv, index, count); > if (!map) > goto unlock_out; > - if (map->vma) > + if (use_ptemod && map->vma) > goto unlock_out; > - if (priv->mm != vma->vm_mm) { > + if (use_ptemod && priv->mm != vma->vm_mm) { > printk(KERN_WARNING "Huh? Other mm?\n"); > goto unlock_out; > } > @@ -541,20 +573,24 @@ static int gntdev_mmap(struct file *flip, struct > vm_area_struct *vma) > vma->vm_flags |= VM_RESERVED|VM_DONTCOPY|VM_DONTEXPAND|VM_PFNMAP; > > vma->vm_private_data = map; > - map->vma = vma; > > - map->flags = GNTMAP_host_map | GNTMAP_application_map; > + if (use_ptemod) > + map->vma = vma; > + > + map->flags = GNTMAP_host_map; > if (!(vma->vm_flags & VM_WRITE)) > map->flags |= GNTMAP_readonly; > > spin_unlock(&priv->lock); > > - err = apply_to_page_range(vma->vm_mm, vma->vm_start, > - vma->vm_end - vma->vm_start, > - find_grant_ptes, map); > - if (err) { > - printk(KERN_WARNING "find_grant_ptes() failure.\n"); > - return err; > + if (use_ptemod) { > + err = apply_to_page_range(vma->vm_mm, vma->vm_start, > + vma->vm_end - vma->vm_start, > + find_grant_ptes, map); > + if (err) { > + printk(KERN_WARNING "find_grant_ptes() failure.\n"); > + return err; > + } > } > > err = map_grant_pages(map); > @@ -565,6 +601,15 @@ static int gntdev_mmap(struct file *flip, struct > vm_area_struct *vma) > > map->is_mapped = 1; > > + if (!use_ptemod) { > + for (i = 0; i < count; i++) { > + err = vm_insert_page(vma, vma->vm_start + i*PAGE_SIZE, > + map->pages[i]); > + if (err) > + return err; > + } > + } > + > return 0; > > unlock_out: > @@ -595,6 +640,8 @@ static int __init gntdev_init(void) > if (!xen_domain()) > return -ENODEV; > > + use_ptemod = xen_pv_domain(); > + > err = misc_register(&gntdev_miscdev); > if (err != 0) { > printk(KERN_ERR "Could not register gntdev device\n"); > diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c > index 9ef54eb..9428ced 100644 > --- a/drivers/xen/grant-table.c > +++ b/drivers/xen/grant-table.c > @@ -458,6 +458,9 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, > if (ret) > return ret; > > + if (xen_feature(XENFEAT_auto_translated_physmap)) > + return ret; > + > for (i = 0; i < count; i++) { > /* m2p override only supported for GNTMAP_contains_pte mappings > */ > if (!(map_ops[i].flags & GNTMAP_contains_pte)) > @@ -483,6 +486,9 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref > *unmap_ops, > if (ret) > return ret; > > + if (xen_feature(XENFEAT_auto_translated_physmap)) > + return ret; > + > for (i = 0; i < count; i++) { > ret = m2p_remove_override(pages[i]); > if (ret) > -- > 1.7.3.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |