# HG changeset patch
# User Jimi Xenidis <[EMAIL PROTECTED]>
# Node ID 39d3d1cfe7146a6542a7708bace0ab38f11e48b5
# Parent  2a9c6a23cd1292e9ed361e33d640ce84a6fbdb53
[XEN][POWERPC] Use a bitmap to manage the foreign page area

We needed to be able to dispense pages from the foreign map to Xen VIO
back drivers.  I thougth mempool would be an easy way to do this, but
it seems that a bitmap is far easier and simpler to do this with.

Signed-off-by: Jimi Xenidis <[EMAIL PROTECTED]>
---
 arch/powerpc/platforms/xen/balloon.c |   14 +---
 arch/powerpc/platforms/xen/gnttab.c  |  100 ++++++++++++++++-------------------
 arch/powerpc/platforms/xen/setup.h   |    4 -
 arch/powerpc/platforms/xen/util.c    |    2 
 4 files changed, 55 insertions(+), 65 deletions(-)

diff -r 2a9c6a23cd12 -r 39d3d1cfe714 arch/powerpc/platforms/xen/balloon.c
--- a/arch/powerpc/platforms/xen/balloon.c      Fri Nov 03 16:50:22 2006 -0500
+++ b/arch/powerpc/platforms/xen/balloon.c      Wed Nov 08 15:44:19 2006 -0500
@@ -11,22 +11,16 @@ struct page **alloc_empty_pages_and_page
 {
        struct page *page, **pagevec;
        int i;
-       int scrub = 0;
 
        pagevec = kmalloc(sizeof(*pagevec) * nr_pages, GFP_KERNEL);
        if (pagevec == NULL)
                return  NULL;
 
        for (i = 0; i < nr_pages; i++) {
-               page = alloc_grant_page();
+               page = alloc_foreign_page();
                pagevec[i] = page;
-
-               if (scrub) {
-                       void *vaddr;
-
-                       vaddr = page_address(page);
-                       scrub_pages(vaddr, 1);
-               }
+               /* There is no real page backing us yet so it cannot
+                * be scrubbed */
        }
 
        return pagevec;
@@ -40,7 +34,7 @@ void free_empty_pages_and_pagevec(struct
                return;
 
        for (i = 0; i < nr_pages; i++) {
-               free_grant_page(pagevec[i]);
+               free_foreign_page(pagevec[i]);
        }
        
        kfree(pagevec);
diff -r 2a9c6a23cd12 -r 39d3d1cfe714 arch/powerpc/platforms/xen/gnttab.c
--- a/arch/powerpc/platforms/xen/gnttab.c       Fri Nov 03 16:50:22 2006 -0500
+++ b/arch/powerpc/platforms/xen/gnttab.c       Wed Nov 08 15:44:19 2006 -0500
@@ -2,7 +2,6 @@
 #include <linux/config.h>
 #include <linux/vmalloc.h>
 #include <linux/memory_hotplug.h>
-#include <linux/mempool.h>
 #include <xen/gnttab.h>
 #include <asm/hypervisor.h>
 #include <xen/interface/grant_table.h>
@@ -25,8 +24,9 @@
 
 struct address_space xen_foreign_dummy_mapping;
 
-static ulong foreign_map_base;
-static ulong foreign_map_end;
+static ulong foreign_map_pfn;
+static ulong foreign_map_pgs;
+static unsigned long *foreign_map_bitmap;
 
 
 /* hijack _mapcount */
@@ -215,7 +215,9 @@ static void gnttab_post_map_grant_ref(
                        continue;
                }
 
-               BUG_ON(pa < foreign_map_base || pa >= foreign_map_end);
+               BUG_ON(pa < (foreign_map_pfn << PAGE_SHIFT));
+               BUG_ON(pa >= (foreign_map_pfn << PAGE_SHIFT) + 
+                      (foreign_map_pgs << PAGE_SHIFT));
 
                page = virt_to_page(__va(pa));
 
@@ -330,9 +332,7 @@ static ulong find_grant_maps(void)
                panic("foreign-map is 0x%lx, expect 0x%lx\n",
                      gm[0], expect);
 
-       foreign_map_base = 1UL << (gm[0] + PAGE_SHIFT);
-       foreign_map_end = foreign_map_base + (gm[1] << PAGE_SHIFT);
-
+       foreign_map_pfn = 1UL << gm[0];
        return gm[1];
 }
 
@@ -353,40 +353,27 @@ int arch_gnttab_suspend(volatile void __
        return 0;
 }
 
-static mempool_t *grant_pool;
-struct page *alloc_grant_page(void)
-{
-       void *va;
-
-       va = mempool_alloc(grant_pool, GFP_KERNEL);
-
-       return virt_to_page(va);
-}
-
-void free_grant_page(struct page *page)
-{
-       mempool_free(pfn_to_kaddr(page_to_pfn(page)), grant_pool);
-}
-
-static void *gp_alloc(gfp_t gfp_mask, void *pool_data)
-{
-       static ulong count;
-       ulong max = (ulong)pool_data;
-       void *ret = NULL;
-
-       if (count < max) {
-               ulong pfn;
-
-               pfn = (foreign_map_base >> PAGE_SHIFT) + count;
-               ret = pfn_to_kaddr(pfn);
-               ++count;
-       }
-       return ret;
-}
-
-static void gp_free(void *element, void *pool_data)
-{
-       BUG();
+struct page *alloc_foreign_page(void)
+{
+       int bit;
+       do {
+               bit = find_first_zero_bit(foreign_map_bitmap,
+                                         foreign_map_pgs);
+               if (bit >= foreign_map_pgs)
+                       return NULL;
+       } while (test_and_set_bit(bit, foreign_map_bitmap) == 1);
+
+       return pfn_to_page(foreign_map_pfn + bit);
+}
+
+void free_foreign_page(struct page *page)
+{
+       int bit = page_to_pfn(page) - foreign_map_pfn;
+
+       BUG_ON(bit < 0);
+       BUG_ON(bit >= foreign_map_pgs);
+
+       clear_bit(bit, foreign_map_bitmap);
 }
 
 static void setup_grant_area(void)
@@ -400,25 +387,39 @@ static void setup_grant_area(void)
        pgs = find_grant_maps();
        setup_foreign_segment();
 
+       printk("%s: Xen VIO will use a foreign address space of 0x%lx pages\n",
+              __func__, pgs);
+
        /* add pages to the zone */
        nid = 0;
        pgdata = NODE_DATA(nid);
        zone = pgdata->node_zones;
 
-       err = __add_pages(zone, foreign_map_base >> PAGE_SHIFT, pgs);
+       err = __add_pages(zone, foreign_map_pfn, pgs);
 
        if (err < 0) {
                printk(KERN_EMERG "%s: add_pages(0x%lx, 0x%lx) = %d\n",
-                      __func__, foreign_map_base >> PAGE_SHIFT, pgs, err);
+                      __func__, foreign_map_pfn, pgs, err);
                BUG();
        }
 
-       /* create a memory pool to manage these pages */
-       grant_pool = mempool_create(pgs, gp_alloc, gp_free, (void *)pgs);
-       if (grant_pool == NULL) {
-               printk(KERN_EMERG "%s: mempool_create(): failed\n", __func__);
+       /* create a bitmap to manage these pages */
+       foreign_map_bitmap = kmalloc(BITS_TO_LONGS(pgs) * sizeof(long),
+                                    GFP_KERNEL);
+       if (foreign_map_bitmap == NULL) {
+               printk(KERN_EMERG 
+                      "%s: could not allocate foreign_map_bitmap to "
+                      "manage 0x%lx foreign pages\n", __func__, pgs);
                BUG();
        }
+       /* I'm paranoid so make sure we assign the top bits so we
+        * don't give them away */
+       bitmap_fill(&foreign_map_bitmap[BITS_TO_LONGS(pgs) - 1],
+                   BITS_PER_LONG);
+       /* now clear all the real bits */
+       bitmap_zero(foreign_map_bitmap, pgs);
+
+       foreign_map_pgs = pgs;
 }
 
 void *arch_gnttab_map(unsigned long *frames)
@@ -439,8 +440,3 @@ void *arch_gnttab_map(unsigned long *fra
 
        return shared;
 }
-
-int arch_is_foreign_page(struct page *page)
-{
-       return ((page_to_pfn(page) << PAGE_SHIFT) >= foreign_map_base);
-}
diff -r 2a9c6a23cd12 -r 39d3d1cfe714 arch/powerpc/platforms/xen/setup.h
--- a/arch/powerpc/platforms/xen/setup.h        Fri Nov 03 16:50:22 2006 -0500
+++ b/arch/powerpc/platforms/xen/setup.h        Wed Nov 08 15:44:19 2006 -0500
@@ -22,6 +22,6 @@ static inline u64 jiffies_to_ns(unsigned
 
 #define xen_guest_handle(hnd)  ((hnd).p)
 
-extern struct page *alloc_grant_page(void);
-extern void free_grant_page(struct page *page);
+extern struct page *alloc_foreign_page(void);
+extern void free_foreign_page(struct page *page);
 
diff -r 2a9c6a23cd12 -r 39d3d1cfe714 arch/powerpc/platforms/xen/util.c
--- a/arch/powerpc/platforms/xen/util.c Fri Nov 03 16:50:22 2006 -0500
+++ b/arch/powerpc/platforms/xen/util.c Wed Nov 08 15:44:19 2006 -0500
@@ -12,7 +12,7 @@ struct vm_struct *alloc_vm_area(unsigned
        struct vm_struct *area;
        struct page *page;
 
-       page = alloc_grant_page();
+       page = alloc_foreign_page();
        if (page == NULL) {
                BUG();
                return NULL;

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@lists.xensource.com
http://lists.xensource.com/xen-ppc-devel

Reply via email to