]> xenbits.xensource.com Git - legacy/linux-2.6.18-xen.git/commitdiff
linux/x86: revert the effect of xen_limit_pages_to_max_mfn()
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 28 Nov 2008 13:30:58 +0000 (13:30 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 28 Nov 2008 13:30:58 +0000 (13:30 +0000)
Signed-off-by: Jan Beulich <jbeulich@novell.com>
arch/i386/mm/hypervisor.c
arch/i386/mm/pgtable-xen.c
arch/x86_64/mm/pageattr-xen.c
drivers/xen/core/gnttab.c
drivers/xen/netback/netback.c
include/linux/page-flags.h
mm/page_alloc.c

index c36106d4ef210fb3d4bdae3e1c248a5e4a5134b7..9fb9e6b464ec4b504c9cfb0345671d7cb9eacada 100644 (file)
@@ -374,6 +374,15 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
 }
 EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
 
+static void undo_limit_pages(struct page *pages, unsigned int order)
+{
+       BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+       BUG_ON(order > MAX_CONTIG_ORDER);
+       xen_limit_pages_to_max_mfn(pages, order, 0);
+       ClearPageForeign(pages);
+       __free_pages(pages, order);
+}
+
 int xen_limit_pages_to_max_mfn(
        struct page *pages, unsigned int order, unsigned int address_bits)
 {
@@ -402,16 +411,28 @@ int xen_limit_pages_to_max_mfn(
        if (unlikely(order > MAX_CONTIG_ORDER))
                return -ENOMEM;
 
-       bitmap_zero(limit_map, 1U << order);
+       if (address_bits) {
+               if (address_bits < PAGE_SHIFT)
+                       return -EINVAL;
+               bitmap_zero(limit_map, 1U << order);
+       } else if (order) {
+               BUILD_BUG_ON(sizeof(pages->index) != sizeof(*limit_map));
+               for (i = 0; i < BITS_TO_LONGS(1U << order); ++i)
+                       limit_map[i] = pages[i + 1].index;
+       } else
+               __set_bit(0, limit_map);
+
        set_xen_guest_handle(exchange.in.extent_start, in_frames);
        set_xen_guest_handle(exchange.out.extent_start, out_frames);
 
        /* 0. Scrub the pages. */
        for (i = 0, n = 0; i < 1U<<order ; i++) {
                page = &pages[i];
-               if (!(pfn_to_mfn(page_to_pfn(page)) >> (address_bits - PAGE_SHIFT)))
-                       continue;
-               __set_bit(i, limit_map);
+               if (address_bits) {
+                       if (!(pfn_to_mfn(page_to_pfn(page)) >> (address_bits - PAGE_SHIFT)))
+                               continue;
+                       __set_bit(i, limit_map);
+               }
 
                if (!PageHighMem(page))
                        scrub_pages(page_address(page), 1);
@@ -497,7 +518,19 @@ int xen_limit_pages_to_max_mfn(
 
        balloon_unlock(flags);
 
-       return success ? 0 : -ENOMEM;
+       if (!success)
+               return -ENOMEM;
+
+       if (address_bits) {
+               if (order) {
+                       BUILD_BUG_ON(sizeof(*limit_map) != sizeof(pages->index));
+                       for (i = 0; i < BITS_TO_LONGS(1U << order); ++i)
+                               pages[i + 1].index = limit_map[i];
+               }
+               SetPageForeign(pages, undo_limit_pages);
+       }
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(xen_limit_pages_to_max_mfn);
 
index cab41bd7fc9bc347f9f1c88acf1971f66bda95fe..fa783a432bf6a7925daa3ba98257eb6b2d1d1e60 100644 (file)
@@ -152,6 +152,12 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
        return pte;
 }
 
+static void _pte_free(struct page *page, unsigned int order)
+{
+       BUG_ON(order);
+       pte_free(page);
+}
+
 struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
        struct page *pte;
@@ -162,7 +168,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
        pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
 #endif
        if (pte) {
-               SetPageForeign(pte, pte_free);
+               SetPageForeign(pte, _pte_free);
                init_page_count(pte);
        }
        return pte;
index 60a2ed4faa5e5fb2d8be9b068bcfa38af416f25f..9f11e4339d86b265378e19fdd6b3b6e9e7e90d0f 100644 (file)
@@ -248,13 +248,19 @@ void _arch_exit_mmap(struct mm_struct *mm)
                mm_unpin(mm);
 }
 
+static void _pte_free(struct page *page, unsigned int order)
+{
+       BUG_ON(order);
+       pte_free(page);
+}
+
 struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
        struct page *pte;
 
        pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
        if (pte) {
-               SetPageForeign(pte, pte_free);
+               SetPageForeign(pte, _pte_free);
                init_page_count(pte);
        }
        return pte;
index fd83ea0bf0995286a8644df051c7f8199fcc0469..8fa4d14988009af6dea06465927f9231130ae2d8 100644 (file)
@@ -505,8 +505,9 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
        return 0;
 }
 
-static void gnttab_page_free(struct page *page)
+static void gnttab_page_free(struct page *page, unsigned int order)
 {
+       BUG_ON(order);
        ClearPageForeign(page);
        gnttab_reset_grant_page(page);
        put_page(page);
index 79ce9ad0ce6813ff21099c2a4db78b7211c9f76f..919d65514024df8b0fa167e7f88144409232f2d7 100644 (file)
@@ -55,7 +55,6 @@ struct netbk_tx_pending_inuse {
 };
 
 static void netif_idx_release(u16 pending_idx);
-static void netif_page_release(struct page *page);
 static void make_tx_response(netif_t *netif, 
                             netif_tx_request_t *txp,
                             s8       st);
@@ -1436,8 +1435,9 @@ static void netif_idx_release(u16 pending_idx)
        tasklet_schedule(&net_tx_tasklet);
 }
 
-static void netif_page_release(struct page *page)
+static void netif_page_release(struct page *page, unsigned int order)
 {
+       BUG_ON(order);
        netif_idx_release(netif_page_index(page));
 }
 
index 033e4c3b5e6b16fe5e07250e5f690125024d75e2..9fb0909c049b7fb4f0443ab71026c7132b8f2910 100644 (file)
 #define PageForeign(page)      test_bit(PG_foreign, &(page)->flags)
 #define SetPageForeign(_page, dtor) do {               \
        set_bit(PG_foreign, &(_page)->flags);           \
-       BUG_ON((dtor) == (void (*)(struct page *))0);   \
+       BUG_ON((dtor) == (void (*)(struct page *, unsigned int))0); \
        (_page)->index = (long)(dtor);                  \
 } while (0)
 #define ClearPageForeign(page) do {                    \
        clear_bit(PG_foreign, &(page)->flags);          \
        (page)->index = 0;                              \
 } while (0)
-#define PageForeignDestructor(_page)                   \
-       ((void (*)(struct page *))(_page)->index)(_page)
+#define PageForeignDestructor(_page, order)            \
+       ((void (*)(struct page *, unsigned int))(_page)->index)(_page, order)
 
 struct page;   /* forward declaration */
 
index c9f834eee7752d7cbb189e8616d7f7db4a96c35d..19ef4668e35d8abb0d8a2890254a178e65eaf74e 100644 (file)
@@ -453,7 +453,7 @@ static void __free_pages_ok(struct page *page, unsigned int order)
 
 #ifdef CONFIG_XEN
        if (PageForeign(page)) {
-               PageForeignDestructor(page);
+               PageForeignDestructor(page, order);
                return;
        }
 #endif
@@ -737,7 +737,7 @@ static void fastcall free_hot_cold_page(struct page *page, int cold)
 
 #ifdef CONFIG_XEN
        if (PageForeign(page)) {
-               PageForeignDestructor(page);
+               PageForeignDestructor(page, 0);
                return;
        }
 #endif