diff options
author | David Vrabel <david.vrabel@citrix.com> | 2015-01-05 09:13:41 -0500 |
---|---|---|
committer | David Vrabel <david.vrabel@citrix.com> | 2015-01-28 09:03:10 -0500 |
commit | 853d0289340026b30f93fd0e768340221d4e605c (patch) | |
tree | 17d52ad1d7ae43007d8b664bbdba2a50db7dbb81 | |
parent | d8ac3dd41aea245f65465449efc35dd3ac71e91d (diff) |
xen/grant-table: pre-populate kernel unmap ops for xen_gnttab_unmap_refs()
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>
-rw-r--r-- | arch/arm/include/asm/xen/page.h | 2 | ||||
-rw-r--r-- | arch/arm/xen/p2m.c | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/xen/page.h | 2 | ||||
-rw-r--r-- | arch/x86/xen/p2m.c | 21 | ||||
-rw-r--r-- | drivers/xen/gntdev.c | 20 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 4 | ||||
-rw-r--r-- | include/xen/grant_table.h | 2 |
7 files changed, 30 insertions, 23 deletions
diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h index 68c739b3fdf4..2f7e6ff67d51 100644 --- a/arch/arm/include/asm/xen/page.h +++ b/arch/arm/include/asm/xen/page.h | |||
@@ -92,7 +92,7 @@ extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, | |||
92 | struct page **pages, unsigned int count); | 92 | struct page **pages, unsigned int count); |
93 | 93 | ||
94 | extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, | 94 | extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, |
95 | struct gnttab_map_grant_ref *kmap_ops, | 95 | struct gnttab_unmap_grant_ref *kunmap_ops, |
96 | struct page **pages, unsigned int count); | 96 | struct page **pages, unsigned int count); |
97 | 97 | ||
98 | bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); | 98 | bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); |
diff --git a/arch/arm/xen/p2m.c b/arch/arm/xen/p2m.c index 054857776254..cb7a14c5cd69 100644 --- a/arch/arm/xen/p2m.c +++ b/arch/arm/xen/p2m.c | |||
@@ -102,7 +102,7 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, | |||
102 | EXPORT_SYMBOL_GPL(set_foreign_p2m_mapping); | 102 | EXPORT_SYMBOL_GPL(set_foreign_p2m_mapping); |
103 | 103 | ||
104 | int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, | 104 | int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, |
105 | struct gnttab_map_grant_ref *kmap_ops, | 105 | struct gnttab_unmap_grant_ref *kunmap_ops, |
106 | struct page **pages, unsigned int count) | 106 | struct page **pages, unsigned int count) |
107 | { | 107 | { |
108 | int i; | 108 | int i; |
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 5eea09915a15..e9f52fe2d56a 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h | |||
@@ -55,7 +55,7 @@ extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, | |||
55 | struct gnttab_map_grant_ref *kmap_ops, | 55 | struct gnttab_map_grant_ref *kmap_ops, |
56 | struct page **pages, unsigned int count); | 56 | struct page **pages, unsigned int count); |
57 | extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, | 57 | extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, |
58 | struct gnttab_map_grant_ref *kmap_ops, | 58 | struct gnttab_unmap_grant_ref *kunmap_ops, |
59 | struct page **pages, unsigned int count); | 59 | struct page **pages, unsigned int count); |
60 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); | 60 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); |
61 | 61 | ||
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 70fb5075c901..df40b2888eae 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
@@ -816,7 +816,7 @@ static struct page *m2p_find_override(unsigned long mfn) | |||
816 | } | 816 | } |
817 | 817 | ||
818 | static int m2p_remove_override(struct page *page, | 818 | static int m2p_remove_override(struct page *page, |
819 | struct gnttab_map_grant_ref *kmap_op, | 819 | struct gnttab_unmap_grant_ref *kunmap_op, |
820 | unsigned long mfn) | 820 | unsigned long mfn) |
821 | { | 821 | { |
822 | unsigned long flags; | 822 | unsigned long flags; |
@@ -840,7 +840,7 @@ static int m2p_remove_override(struct page *page, | |||
840 | list_del(&page->lru); | 840 | list_del(&page->lru); |
841 | spin_unlock_irqrestore(&m2p_override_lock, flags); | 841 | spin_unlock_irqrestore(&m2p_override_lock, flags); |
842 | 842 | ||
843 | if (kmap_op != NULL) { | 843 | if (kunmap_op != NULL) { |
844 | if (!PageHighMem(page)) { | 844 | if (!PageHighMem(page)) { |
845 | struct multicall_space mcs; | 845 | struct multicall_space mcs; |
846 | struct gnttab_unmap_and_replace *unmap_op; | 846 | struct gnttab_unmap_and_replace *unmap_op; |
@@ -855,13 +855,13 @@ static int m2p_remove_override(struct page *page, | |||
855 | * issued. In this case handle is going to -1 because | 855 | * issued. In this case handle is going to -1 because |
856 | * it hasn't been modified yet. | 856 | * it hasn't been modified yet. |
857 | */ | 857 | */ |
858 | if (kmap_op->handle == -1) | 858 | if (kunmap_op->handle == -1) |
859 | xen_mc_flush(); | 859 | xen_mc_flush(); |
860 | /* | 860 | /* |
861 | * Now if kmap_op->handle is negative it means that the | 861 | * Now if kmap_op->handle is negative it means that the |
862 | * hypercall actually returned an error. | 862 | * hypercall actually returned an error. |
863 | */ | 863 | */ |
864 | if (kmap_op->handle == GNTST_general_error) { | 864 | if (kunmap_op->handle == GNTST_general_error) { |
865 | pr_warn("m2p_remove_override: pfn %lx mfn %lx, failed to modify kernel mappings", | 865 | pr_warn("m2p_remove_override: pfn %lx mfn %lx, failed to modify kernel mappings", |
866 | pfn, mfn); | 866 | pfn, mfn); |
867 | put_balloon_scratch_page(); | 867 | put_balloon_scratch_page(); |
@@ -873,9 +873,9 @@ static int m2p_remove_override(struct page *page, | |||
873 | mcs = __xen_mc_entry( | 873 | mcs = __xen_mc_entry( |
874 | sizeof(struct gnttab_unmap_and_replace)); | 874 | sizeof(struct gnttab_unmap_and_replace)); |
875 | unmap_op = mcs.args; | 875 | unmap_op = mcs.args; |
876 | unmap_op->host_addr = kmap_op->host_addr; | 876 | unmap_op->host_addr = kunmap_op->host_addr; |
877 | unmap_op->new_addr = scratch_page_address; | 877 | unmap_op->new_addr = scratch_page_address; |
878 | unmap_op->handle = kmap_op->handle; | 878 | unmap_op->handle = kunmap_op->handle; |
879 | 879 | ||
880 | MULTI_grant_table_op(mcs.mc, | 880 | MULTI_grant_table_op(mcs.mc, |
881 | GNTTABOP_unmap_and_replace, unmap_op, 1); | 881 | GNTTABOP_unmap_and_replace, unmap_op, 1); |
@@ -887,7 +887,6 @@ static int m2p_remove_override(struct page *page, | |||
887 | 887 | ||
888 | xen_mc_issue(PARAVIRT_LAZY_MMU); | 888 | xen_mc_issue(PARAVIRT_LAZY_MMU); |
889 | 889 | ||
890 | kmap_op->host_addr = 0; | ||
891 | put_balloon_scratch_page(); | 890 | put_balloon_scratch_page(); |
892 | } | 891 | } |
893 | } | 892 | } |
@@ -912,7 +911,7 @@ static int m2p_remove_override(struct page *page, | |||
912 | } | 911 | } |
913 | 912 | ||
914 | int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, | 913 | int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, |
915 | struct gnttab_map_grant_ref *kmap_ops, | 914 | struct gnttab_unmap_grant_ref *kunmap_ops, |
916 | struct page **pages, unsigned int count) | 915 | struct page **pages, unsigned int count) |
917 | { | 916 | { |
918 | int i, ret = 0; | 917 | int i, ret = 0; |
@@ -921,7 +920,7 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, | |||
921 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 920 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
922 | return 0; | 921 | return 0; |
923 | 922 | ||
924 | if (kmap_ops && | 923 | if (kunmap_ops && |
925 | !in_interrupt() && | 924 | !in_interrupt() && |
926 | paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) { | 925 | paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) { |
927 | arch_enter_lazy_mmu_mode(); | 926 | arch_enter_lazy_mmu_mode(); |
@@ -942,8 +941,8 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, | |||
942 | ClearPagePrivate(pages[i]); | 941 | ClearPagePrivate(pages[i]); |
943 | set_phys_to_machine(pfn, pages[i]->index); | 942 | set_phys_to_machine(pfn, pages[i]->index); |
944 | 943 | ||
945 | if (kmap_ops) | 944 | if (kunmap_ops) |
946 | ret = m2p_remove_override(pages[i], &kmap_ops[i], mfn); | 945 | ret = m2p_remove_override(pages[i], &kunmap_ops[i], mfn); |
947 | if (ret) | 946 | if (ret) |
948 | goto out; | 947 | goto out; |
949 | } | 948 | } |
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 073b4a19a8b0..6444172f2842 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c | |||
@@ -91,6 +91,7 @@ struct grant_map { | |||
91 | struct gnttab_map_grant_ref *map_ops; | 91 | struct gnttab_map_grant_ref *map_ops; |
92 | struct gnttab_unmap_grant_ref *unmap_ops; | 92 | struct gnttab_unmap_grant_ref *unmap_ops; |
93 | struct gnttab_map_grant_ref *kmap_ops; | 93 | struct gnttab_map_grant_ref *kmap_ops; |
94 | struct gnttab_unmap_grant_ref *kunmap_ops; | ||
94 | struct page **pages; | 95 | struct page **pages; |
95 | }; | 96 | }; |
96 | 97 | ||
@@ -124,6 +125,7 @@ static void gntdev_free_map(struct grant_map *map) | |||
124 | kfree(map->map_ops); | 125 | kfree(map->map_ops); |
125 | kfree(map->unmap_ops); | 126 | kfree(map->unmap_ops); |
126 | kfree(map->kmap_ops); | 127 | kfree(map->kmap_ops); |
128 | kfree(map->kunmap_ops); | ||
127 | kfree(map); | 129 | kfree(map); |
128 | } | 130 | } |
129 | 131 | ||
@@ -140,11 +142,13 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) | |||
140 | add->map_ops = kcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL); | 142 | add->map_ops = kcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL); |
141 | add->unmap_ops = kcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL); | 143 | add->unmap_ops = kcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL); |
142 | add->kmap_ops = kcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL); | 144 | add->kmap_ops = kcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL); |
145 | add->kunmap_ops = kcalloc(count, sizeof(add->kunmap_ops[0]), GFP_KERNEL); | ||
143 | add->pages = kcalloc(count, sizeof(add->pages[0]), GFP_KERNEL); | 146 | add->pages = kcalloc(count, sizeof(add->pages[0]), GFP_KERNEL); |
144 | if (NULL == add->grants || | 147 | if (NULL == add->grants || |
145 | NULL == add->map_ops || | 148 | NULL == add->map_ops || |
146 | NULL == add->unmap_ops || | 149 | NULL == add->unmap_ops || |
147 | NULL == add->kmap_ops || | 150 | NULL == add->kmap_ops || |
151 | NULL == add->kunmap_ops || | ||
148 | NULL == add->pages) | 152 | NULL == add->pages) |
149 | goto err; | 153 | goto err; |
150 | 154 | ||
@@ -155,6 +159,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) | |||
155 | add->map_ops[i].handle = -1; | 159 | add->map_ops[i].handle = -1; |
156 | add->unmap_ops[i].handle = -1; | 160 | add->unmap_ops[i].handle = -1; |
157 | add->kmap_ops[i].handle = -1; | 161 | add->kmap_ops[i].handle = -1; |
162 | add->kunmap_ops[i].handle = -1; | ||
158 | } | 163 | } |
159 | 164 | ||
160 | add->index = 0; | 165 | add->index = 0; |
@@ -280,6 +285,8 @@ static int map_grant_pages(struct grant_map *map) | |||
280 | map->flags | GNTMAP_host_map, | 285 | map->flags | GNTMAP_host_map, |
281 | map->grants[i].ref, | 286 | map->grants[i].ref, |
282 | map->grants[i].domid); | 287 | map->grants[i].domid); |
288 | gnttab_set_unmap_op(&map->kunmap_ops[i], address, | ||
289 | map->flags | GNTMAP_host_map, -1); | ||
283 | } | 290 | } |
284 | } | 291 | } |
285 | 292 | ||
@@ -290,13 +297,14 @@ static int map_grant_pages(struct grant_map *map) | |||
290 | return err; | 297 | return err; |
291 | 298 | ||
292 | for (i = 0; i < map->count; i++) { | 299 | for (i = 0; i < map->count; i++) { |
293 | if (map->map_ops[i].status) | 300 | if (map->map_ops[i].status) { |
294 | err = -EINVAL; | 301 | err = -EINVAL; |
295 | else { | 302 | continue; |
296 | BUG_ON(map->map_ops[i].handle == -1); | ||
297 | map->unmap_ops[i].handle = map->map_ops[i].handle; | ||
298 | pr_debug("map handle=%d\n", map->map_ops[i].handle); | ||
299 | } | 303 | } |
304 | |||
305 | map->unmap_ops[i].handle = map->map_ops[i].handle; | ||
306 | if (use_ptemod) | ||
307 | map->kunmap_ops[i].handle = map->kmap_ops[i].handle; | ||
300 | } | 308 | } |
301 | return err; | 309 | return err; |
302 | } | 310 | } |
@@ -316,7 +324,7 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) | |||
316 | } | 324 | } |
317 | 325 | ||
318 | err = gnttab_unmap_refs(map->unmap_ops + offset, | 326 | err = gnttab_unmap_refs(map->unmap_ops + offset, |
319 | use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset, | 327 | use_ptemod ? map->kunmap_ops + offset : NULL, map->pages + offset, |
320 | pages); | 328 | pages); |
321 | if (err) | 329 | if (err) |
322 | return err; | 330 | return err; |
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 7786291ba229..999d7abdbcec 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -738,7 +738,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | |||
738 | EXPORT_SYMBOL_GPL(gnttab_map_refs); | 738 | EXPORT_SYMBOL_GPL(gnttab_map_refs); |
739 | 739 | ||
740 | int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | 740 | int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, |
741 | struct gnttab_map_grant_ref *kmap_ops, | 741 | struct gnttab_unmap_grant_ref *kunmap_ops, |
742 | struct page **pages, unsigned int count) | 742 | struct page **pages, unsigned int count) |
743 | { | 743 | { |
744 | int ret; | 744 | int ret; |
@@ -747,7 +747,7 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | |||
747 | if (ret) | 747 | if (ret) |
748 | return ret; | 748 | return ret; |
749 | 749 | ||
750 | return clear_foreign_p2m_mapping(unmap_ops, kmap_ops, pages, count); | 750 | return clear_foreign_p2m_mapping(unmap_ops, kunmap_ops, pages, count); |
751 | } | 751 | } |
752 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); | 752 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); |
753 | 753 | ||
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 3387465b9caa..7235d8f35459 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h | |||
@@ -167,7 +167,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | |||
167 | struct gnttab_map_grant_ref *kmap_ops, | 167 | struct gnttab_map_grant_ref *kmap_ops, |
168 | struct page **pages, unsigned int count); | 168 | struct page **pages, unsigned int count); |
169 | int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | 169 | int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, |
170 | struct gnttab_map_grant_ref *kunmap_ops, | 170 | struct gnttab_unmap_grant_ref *kunmap_ops, |
171 | struct page **pages, unsigned int count); | 171 | struct page **pages, unsigned int count); |
172 | 172 | ||
173 | /* Perform a batch of grant map/copy operations. Retry every batch slot | 173 | /* Perform a batch of grant map/copy operations. Retry every batch slot |