xen/grant-table: pre-populate kernel unmap ops for xen_gnttab_unmap_refs()
authorDavid Vrabel <david.vrabel@citrix.com>
Mon, 5 Jan 2015 14:13:41 +0000 (14:13 +0000)
committerDavid Vrabel <david.vrabel@citrix.com>
Wed, 28 Jan 2015 14:03:10 +0000 (14:03 +0000)
When unmapping grants, instead of converting the kernel map ops to
unmap ops on the fly, pre-populate the set of unmap ops.

This allows the grant unmap for the kernel mappings to be trivially
batched in the future.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
arch/arm/include/asm/xen/page.h
arch/arm/xen/p2m.c
arch/x86/include/asm/xen/page.h
arch/x86/xen/p2m.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
include/xen/grant_table.h

index 68c739b3fdf41b8b70dd09170661ae95f6c352dc..2f7e6ff67d51556218dbc4e9858442da6601df81 100644 (file)
@@ -92,7 +92,7 @@ extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
                                   struct page **pages, unsigned int count);
 
 extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
-                                    struct gnttab_map_grant_ref *kmap_ops,
+                                    struct gnttab_unmap_grant_ref *kunmap_ops,
                                     struct page **pages, unsigned int count);
 
 bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
index 05485777625474e835fc41a5d57fb494ca778552..cb7a14c5cd69e6814df607cea20afe9342e0e8d2 100644 (file)
@@ -102,7 +102,7 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
 EXPORT_SYMBOL_GPL(set_foreign_p2m_mapping);
 
 int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
-                             struct gnttab_map_grant_ref *kmap_ops,
+                             struct gnttab_unmap_grant_ref *kunmap_ops,
                              struct page **pages, unsigned int count)
 {
        int i;
index 5eea09915a158cdbf7fc24570010e3c211e050ec..e9f52fe2d56a0ca47a3dc2df957fb2087ed06956 100644 (file)
@@ -55,7 +55,7 @@ extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
                                   struct gnttab_map_grant_ref *kmap_ops,
                                   struct page **pages, unsigned int count);
 extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
-                                    struct gnttab_map_grant_ref *kmap_ops,
+                                    struct gnttab_unmap_grant_ref *kunmap_ops,
                                     struct page **pages, unsigned int count);
 extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
 
index 70fb5075c901f5b0c370478b156288764f609ad8..df40b2888eae25fd5940f725809411b8e962dc51 100644 (file)
@@ -816,7 +816,7 @@ static struct page *m2p_find_override(unsigned long mfn)
 }
 
 static int m2p_remove_override(struct page *page,
-                              struct gnttab_map_grant_ref *kmap_op,
+                              struct gnttab_unmap_grant_ref *kunmap_op,
                               unsigned long mfn)
 {
        unsigned long flags;
@@ -840,7 +840,7 @@ static int m2p_remove_override(struct page *page,
        list_del(&page->lru);
        spin_unlock_irqrestore(&m2p_override_lock, flags);
 
-       if (kmap_op != NULL) {
+       if (kunmap_op != NULL) {
                if (!PageHighMem(page)) {
                        struct multicall_space mcs;
                        struct gnttab_unmap_and_replace *unmap_op;
@@ -855,13 +855,13 @@ static int m2p_remove_override(struct page *page,
                         * issued. In this case handle is going to -1 because
                         * it hasn't been modified yet.
                         */
-                       if (kmap_op->handle == -1)
+                       if (kunmap_op->handle == -1)
                                xen_mc_flush();
                        /*
                         * Now if kmap_op->handle is negative it means that the
                         * hypercall actually returned an error.
                         */
-                       if (kmap_op->handle == GNTST_general_error) {
+                       if (kunmap_op->handle == GNTST_general_error) {
                                pr_warn("m2p_remove_override: pfn %lx mfn %lx, failed to modify kernel mappings",
                                        pfn, mfn);
                                put_balloon_scratch_page();
@@ -873,9 +873,9 @@ static int m2p_remove_override(struct page *page,
                        mcs = __xen_mc_entry(
                                sizeof(struct gnttab_unmap_and_replace));
                        unmap_op = mcs.args;
-                       unmap_op->host_addr = kmap_op->host_addr;
+                       unmap_op->host_addr = kunmap_op->host_addr;
                        unmap_op->new_addr = scratch_page_address;
-                       unmap_op->handle = kmap_op->handle;
+                       unmap_op->handle = kunmap_op->handle;
 
                        MULTI_grant_table_op(mcs.mc,
                                GNTTABOP_unmap_and_replace, unmap_op, 1);
@@ -887,7 +887,6 @@ static int m2p_remove_override(struct page *page,
 
                        xen_mc_issue(PARAVIRT_LAZY_MMU);
 
-                       kmap_op->host_addr = 0;
                        put_balloon_scratch_page();
                }
        }
@@ -912,7 +911,7 @@ static int m2p_remove_override(struct page *page,
 }
 
 int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
-                             struct gnttab_map_grant_ref *kmap_ops,
+                             struct gnttab_unmap_grant_ref *kunmap_ops,
                              struct page **pages, unsigned int count)
 {
        int i, ret = 0;
@@ -921,7 +920,7 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return 0;
 
-       if (kmap_ops &&
+       if (kunmap_ops &&
            !in_interrupt() &&
            paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
                arch_enter_lazy_mmu_mode();
@@ -942,8 +941,8 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
                ClearPagePrivate(pages[i]);
                set_phys_to_machine(pfn, pages[i]->index);
 
-               if (kmap_ops)
-                       ret = m2p_remove_override(pages[i], &kmap_ops[i], mfn);
+               if (kunmap_ops)
+                       ret = m2p_remove_override(pages[i], &kunmap_ops[i], mfn);
                if (ret)
                        goto out;
        }
index 073b4a19a8b0796bf320130201ec8e7e98f2cff4..6444172f2842eae08c6a8a73c75b0b246dade124 100644 (file)
@@ -91,6 +91,7 @@ struct grant_map {
        struct gnttab_map_grant_ref   *map_ops;
        struct gnttab_unmap_grant_ref *unmap_ops;
        struct gnttab_map_grant_ref   *kmap_ops;
+       struct gnttab_unmap_grant_ref *kunmap_ops;
        struct page **pages;
 };
 
@@ -124,6 +125,7 @@ static void gntdev_free_map(struct grant_map *map)
        kfree(map->map_ops);
        kfree(map->unmap_ops);
        kfree(map->kmap_ops);
+       kfree(map->kunmap_ops);
        kfree(map);
 }
 
@@ -140,11 +142,13 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
        add->map_ops   = kcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL);
        add->unmap_ops = kcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL);
        add->kmap_ops  = kcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL);
+       add->kunmap_ops = kcalloc(count, sizeof(add->kunmap_ops[0]), GFP_KERNEL);
        add->pages     = kcalloc(count, sizeof(add->pages[0]), GFP_KERNEL);
        if (NULL == add->grants    ||
            NULL == add->map_ops   ||
            NULL == add->unmap_ops ||
            NULL == add->kmap_ops  ||
+           NULL == add->kunmap_ops ||
            NULL == add->pages)
                goto err;
 
@@ -155,6 +159,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
                add->map_ops[i].handle = -1;
                add->unmap_ops[i].handle = -1;
                add->kmap_ops[i].handle = -1;
+               add->kunmap_ops[i].handle = -1;
        }
 
        add->index = 0;
@@ -280,6 +285,8 @@ static int map_grant_pages(struct grant_map *map)
                                map->flags | GNTMAP_host_map,
                                map->grants[i].ref,
                                map->grants[i].domid);
+                       gnttab_set_unmap_op(&map->kunmap_ops[i], address,
+                               map->flags | GNTMAP_host_map, -1);
                }
        }
 
@@ -290,13 +297,14 @@ static int map_grant_pages(struct grant_map *map)
                return err;
 
        for (i = 0; i < map->count; i++) {
-               if (map->map_ops[i].status)
+               if (map->map_ops[i].status) {
                        err = -EINVAL;
-               else {
-                       BUG_ON(map->map_ops[i].handle == -1);
-                       map->unmap_ops[i].handle = map->map_ops[i].handle;
-                       pr_debug("map handle=%d\n", map->map_ops[i].handle);
+                       continue;
                }
+
+               map->unmap_ops[i].handle = map->map_ops[i].handle;
+               if (use_ptemod)
+                       map->kunmap_ops[i].handle = map->kmap_ops[i].handle;
        }
        return err;
 }
@@ -316,7 +324,7 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
        }
 
        err = gnttab_unmap_refs(map->unmap_ops + offset,
-                       use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset,
+                       use_ptemod ? map->kunmap_ops + offset : NULL, map->pages + offset,
                        pages);
        if (err)
                return err;
index 7786291ba229d93190516013863a933cc9eeeb86..999d7abdbcecf645c2426bdf9c23f2a00935a196 100644 (file)
@@ -738,7 +738,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
 EXPORT_SYMBOL_GPL(gnttab_map_refs);
 
 int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
-                     struct gnttab_map_grant_ref *kmap_ops,
+                     struct gnttab_unmap_grant_ref *kunmap_ops,
                      struct page **pages, unsigned int count)
 {
        int ret;
@@ -747,7 +747,7 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
        if (ret)
                return ret;
 
-       return clear_foreign_p2m_mapping(unmap_ops, kmap_ops, pages, count);
+       return clear_foreign_p2m_mapping(unmap_ops, kunmap_ops, pages, count);
 }
 EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
 
index 3387465b9caa65ebebf0bdbb4a25c2dd74641907..7235d8f3545972d1c74017755caa410b4475fa4a 100644 (file)
@@ -167,7 +167,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                    struct gnttab_map_grant_ref *kmap_ops,
                    struct page **pages, unsigned int count);
 int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
-                     struct gnttab_map_grant_ref *kunmap_ops,
+                     struct gnttab_unmap_grant_ref *kunmap_ops,
                      struct page **pages, unsigned int count);
 
 /* Perform a batch of grant map/copy operations. Retry every batch slot