- Update to 3.2-rc6.
[linux-flexiantxendom0-3.2.10.git] / mm / vmalloc.c
index 1d8b32f..efbe5c0 100644 (file)
@@ -1550,6 +1550,13 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
        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 *));
@@ -1586,6 +1593,16 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
                        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))
@@ -1811,6 +1828,8 @@ void *vmalloc_exec(unsigned long size)
 #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
@@ -2185,6 +2204,17 @@ struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes)
                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);