xen: make sure stray alias mappings are gone before pinning
authorJeremy Fitzhardinge <jeremy@goop.org>
Tue, 28 Oct 2008 08:23:06 +0000 (19:23 +1100)
committerIngo Molnar <mingo@elte.hu>
Fri, 7 Nov 2008 09:05:59 +0000 (10:05 +0100)
Xen requires that all mappings of pagetable pages are read-only, so
that they can't be updated illegally.  As a result, if a page is being
turned into a pagetable page, we need to make sure all its mappings
are RO.

If the page had been used for ioremap or vmalloc, it may still have
left over mappings as a result of not having been lazily unmapped.
This change makes sure we explicitly mop them all up before pinning
the page.

Unlike aliases created by kmap, the there can be vmalloc aliases even
for non-high pages, so we must do the flush unconditionally.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Cc: Linux Memory Management List <linux-mm@kvack.org>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c

index b61534c7a4c4d5894812c5bb97a89f29a0f72338..5e4686d70f629de22f81adc96b658ab06216be24 100644 (file)
@@ -863,15 +863,16 @@ static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned l
        if (PagePinned(virt_to_page(mm->pgd))) {
                SetPagePinned(page);
 
+               vm_unmap_aliases();
                if (!PageHighMem(page)) {
                        make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn)));
                        if (level == PT_PTE && USE_SPLIT_PTLOCKS)
                                pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
-               } else
+               } else {
                        /* make sure there are no stray mappings of
                           this page */
                        kmap_flush_unused();
-                       vm_unmap_aliases();
+               }
        }
 }
 
index aba77b2b7d1853a188f42696e92255091de041b2..89f3b6edc65a0996fbc111d5c7c82084d1fa4bfc 100644 (file)
@@ -850,13 +850,16 @@ static int xen_pin_page(struct mm_struct *mm, struct page *page,
    read-only, and can be pinned. */
 static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd)
 {
+       vm_unmap_aliases();
+
        xen_mc_batch();
 
-       if (xen_pgd_walk(mm, xen_pin_page, USER_LIMIT)) {
-               /* re-enable interrupts for kmap_flush_unused */
+        if (xen_pgd_walk(mm, xen_pin_page, USER_LIMIT)) {
+               /* re-enable interrupts for flushing */
                xen_mc_issue(0);
+
                kmap_flush_unused();
-               vm_unmap_aliases();
+
                xen_mc_batch();
        }