]> Pileus Git - ~andy/linux/blobdiff - drivers/xen/balloon.c
xen/balloon: flush persistent kmaps in correct position
[~andy/linux] / drivers / xen / balloon.c
index 37d06ea624aa953d40448bcd2a2d4943baf79fa9..61a6ac8fa8fc7ab00dcc7c33cea47981f2509d4b 100644 (file)
@@ -399,11 +399,25 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
                        state = BP_EAGAIN;
                        break;
                }
+               scrub_page(page);
 
-               pfn = page_to_pfn(page);
-               frame_list[i] = pfn_to_mfn(pfn);
+               frame_list[i] = page_to_pfn(page);
+       }
 
-               scrub_page(page);
+       /*
+        * Ensure that ballooned highmem pages don't have kmaps.
+        *
+        * Do this before changing the p2m as kmap_flush_unused()
+        * reads PTEs to obtain pages (and hence needs the original
+        * p2m entry).
+        */
+       kmap_flush_unused();
+
+       /* Update direct mapping, invalidate P2M, and add to balloon. */
+       for (i = 0; i < nr_pages; i++) {
+               pfn = frame_list[i];
+               frame_list[i] = pfn_to_mfn(pfn);
+               page = pfn_to_page(pfn);
 
 #ifdef CONFIG_XEN_HAVE_PVMMU
                /*
@@ -429,11 +443,9 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
                }
 #endif
 
-               balloon_append(pfn_to_page(pfn));
+               balloon_append(page);
        }
 
-       /* Ensure that ballooned highmem pages don't have kmaps. */
-       kmap_flush_unused();
        flush_tlb_all();
 
        set_xen_guest_handle(reservation.extent_start, frame_list);