struct page **pages;
unsigned int nr_pages, array_size, i;
gfp_t nested_gfp = (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO;
+#ifdef CONFIG_XEN
+ gfp_t dma_mask = gfp_mask & (__GFP_DMA | __GFP_DMA32);
+
+ BUILD_BUG_ON((__GFP_DMA | __GFP_DMA32) != (__GFP_DMA + __GFP_DMA32));
+ if (dma_mask == (__GFP_DMA | __GFP_DMA32))
+ gfp_mask &= ~(__GFP_DMA | __GFP_DMA32);
+#endif
nr_pages = (area->size - PAGE_SIZE) >> PAGE_SHIFT;
array_size = (nr_pages * sizeof(struct page *));
goto fail;
}
area->pages[i] = page;
+#ifdef CONFIG_XEN
+ if (dma_mask) {
+ if (xen_limit_pages_to_max_mfn(page, 0, 32)) {
+ area->nr_pages = i + 1;
+ goto fail;
+ }
+ if (gfp_mask & __GFP_ZERO)
+ clear_highpage(page);
+ }
+#endif
}
if (map_vm_area(area, prot, &pages))
#define GFP_VMALLOC32 GFP_DMA32 | GFP_KERNEL
#elif defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA)
#define GFP_VMALLOC32 GFP_DMA | GFP_KERNEL
+#elif defined(CONFIG_XEN)
+#define GFP_VMALLOC32 __GFP_DMA | __GFP_DMA32 | GFP_KERNEL
#else
#define GFP_VMALLOC32 GFP_KERNEL
#endif
return NULL;
}
+#ifdef CONFIG_XEN
+ /*
+ * If the allocated address space is passed to a hypercall before
+ * being used then we cannot rely on a page fault to trigger an update
+ * of the page tables. So sync all the page tables here unless the
+ * caller is going to have the affected PTEs updated directly.
+ */
+ if (!ptes)
+ vmalloc_sync_all();
+#endif
+
return area;
}
EXPORT_SYMBOL_GPL(alloc_vm_area);