diff options
Diffstat (limited to 'drivers/xen/gntdev.c')
-rw-r--r-- | drivers/xen/gntdev.c | 38 |
1 files changed, 5 insertions, 33 deletions
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index d96d311b858e..017ce600fbc6 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c | |||
@@ -36,6 +36,7 @@ | |||
36 | 36 | ||
37 | #include <xen/xen.h> | 37 | #include <xen/xen.h> |
38 | #include <xen/grant_table.h> | 38 | #include <xen/grant_table.h> |
39 | #include <xen/balloon.h> | ||
39 | #include <xen/gntdev.h> | 40 | #include <xen/gntdev.h> |
40 | #include <xen/events.h> | 41 | #include <xen/events.h> |
41 | #include <asm/xen/hypervisor.h> | 42 | #include <asm/xen/hypervisor.h> |
@@ -122,10 +123,10 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) | |||
122 | NULL == add->pages) | 123 | NULL == add->pages) |
123 | goto err; | 124 | goto err; |
124 | 125 | ||
126 | if (alloc_xenballooned_pages(count, add->pages)) | ||
127 | goto err; | ||
128 | |||
125 | for (i = 0; i < count; i++) { | 129 | for (i = 0; i < count; i++) { |
126 | add->pages[i] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM); | ||
127 | if (add->pages[i] == NULL) | ||
128 | goto err; | ||
129 | add->map_ops[i].handle = -1; | 130 | add->map_ops[i].handle = -1; |
130 | add->unmap_ops[i].handle = -1; | 131 | add->unmap_ops[i].handle = -1; |
131 | } | 132 | } |
@@ -137,11 +138,6 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) | |||
137 | return add; | 138 | return add; |
138 | 139 | ||
139 | err: | 140 | err: |
140 | if (add->pages) | ||
141 | for (i = 0; i < count; i++) { | ||
142 | if (add->pages[i]) | ||
143 | __free_page(add->pages[i]); | ||
144 | } | ||
145 | kfree(add->pages); | 141 | kfree(add->pages); |
146 | kfree(add->grants); | 142 | kfree(add->grants); |
147 | kfree(add->map_ops); | 143 | kfree(add->map_ops); |
@@ -184,8 +180,6 @@ static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv, | |||
184 | 180 | ||
185 | static void gntdev_put_map(struct grant_map *map) | 181 | static void gntdev_put_map(struct grant_map *map) |
186 | { | 182 | { |
187 | int i; | ||
188 | |||
189 | if (!map) | 183 | if (!map) |
190 | return; | 184 | return; |
191 | 185 | ||
@@ -202,29 +196,7 @@ static void gntdev_put_map(struct grant_map *map) | |||
202 | if (!use_ptemod) | 196 | if (!use_ptemod) |
203 | unmap_grant_pages(map, 0, map->count); | 197 | unmap_grant_pages(map, 0, map->count); |
204 | 198 | ||
205 | for (i = 0; i < map->count; i++) { | 199 | free_xenballooned_pages(map->count, map->pages); |
206 | uint32_t check, *tmp; | ||
207 | if (!map->pages[i]) | ||
208 | continue; | ||
209 | /* XXX When unmapping in an HVM domain, Xen will | ||
210 | * sometimes end up mapping the GFN to an invalid MFN. | ||
211 | * In this case, writes will be discarded and reads will | ||
212 | * return all 0xFF bytes. Leak these unusable GFNs | ||
213 | * until Xen supports fixing their p2m mapping. | ||
214 | * | ||
215 | * Confirmed present in Xen 4.1-RC3 with HVM source | ||
216 | */ | ||
217 | tmp = kmap(map->pages[i]); | ||
218 | *tmp = 0xdeaddead; | ||
219 | mb(); | ||
220 | check = *tmp; | ||
221 | kunmap(map->pages[i]); | ||
222 | if (check == 0xdeaddead) | ||
223 | __free_page(map->pages[i]); | ||
224 | else | ||
225 | pr_debug("Discard page %d=%ld\n", i, | ||
226 | page_to_pfn(map->pages[i])); | ||
227 | } | ||
228 | } | 200 | } |
229 | kfree(map->pages); | 201 | kfree(map->pages); |
230 | kfree(map->grants); | 202 | kfree(map->grants); |