xen: allow balloon driver to use more than one memory region
authorDavid Vrabel <david.vrabel@citrix.com>
Wed, 28 Sep 2011 16:46:34 +0000 (17:46 +0100)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Thu, 29 Sep 2011 15:12:10 +0000 (11:12 -0400)
Allow the xen balloon driver to populate its list of extra pages from
more than one region of memory.  This will allow platforms to provide
(for example) a region of low memory and a region of high memory.

The maximum possible number of extra regions is 128 (== E820MAX) which
is quite large so xen_extra_mem is placed in __initdata.  This is safe
as both xen_memory_setup() and balloon_init() are in __init.

The balloon regions themselves are not altered (i.e., there is still
only the one region).

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
arch/x86/xen/setup.c
drivers/xen/balloon.c
include/xen/page.h

index c983717c018ca757555ece7c6a8777ef369cbf1b..0c8e974c738a963448f08496a57f1498979588dd 100644 (file)
@@ -37,7 +37,7 @@ extern void xen_syscall_target(void);
 extern void xen_syscall32_target(void);
 
 /* Amount of extra memory space we add to the e820 ranges */
-phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
+struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
 
 /* Number of pages released from the initial allocation. */
 unsigned long xen_released_pages;
@@ -59,7 +59,7 @@ static void __init xen_add_extra_mem(unsigned long pages)
        unsigned long pfn;
 
        u64 size = (u64)pages * PAGE_SIZE;
-       u64 extra_start = xen_extra_mem_start + xen_extra_mem_size;
+       u64 extra_start = xen_extra_mem[0].start + xen_extra_mem[0].size;
 
        if (!pages)
                return;
@@ -69,7 +69,7 @@ static void __init xen_add_extra_mem(unsigned long pages)
 
        memblock_x86_reserve_range(extra_start, extra_start + size, "XEN EXTRA");
 
-       xen_extra_mem_size += size;
+       xen_extra_mem[0].size += size;
 
        xen_max_p2m_pfn = PFN_DOWN(extra_start + size);
 
@@ -242,7 +242,7 @@ char * __init xen_memory_setup(void)
 
        memcpy(map_raw, map, sizeof(map));
        e820.nr_map = 0;
-       xen_extra_mem_start = mem_end;
+       xen_extra_mem[0].start = mem_end;
        for (i = 0; i < memmap.nr_entries; i++) {
                unsigned long long end;
 
@@ -270,8 +270,8 @@ char * __init xen_memory_setup(void)
                                e820_add_region(end, delta, E820_UNUSABLE);
                }
 
-               if (map[i].size > 0 && end > xen_extra_mem_start)
-                       xen_extra_mem_start = end;
+               if (map[i].size > 0 && end > xen_extra_mem[0].start)
+                       xen_extra_mem[0].start = end;
 
                /* Add region if any remains */
                if (map[i].size > 0)
@@ -279,10 +279,10 @@ char * __init xen_memory_setup(void)
        }
        /* Align the balloon area so that max_low_pfn does not get set
         * to be at the _end_ of the PCI gap at the far end (fee01000).
-        * Note that xen_extra_mem_start gets set in the loop above to be
-        * past the last E820 region. */
-       if (xen_initial_domain() && (xen_extra_mem_start < (1ULL<<32)))
-               xen_extra_mem_start = (1ULL<<32);
+        * Note that the start of balloon area gets set in the loop above
+        * to be past the last E820 region. */
+       if (xen_initial_domain() && (xen_extra_mem[0].start < (1ULL<<32)))
+               xen_extra_mem[0].start = (1ULL<<32);
 
        /*
         * In domU, the ISA region is normal, usable memory, but we
index 9efb993090aa32588c43b3288380e2266630bb45..fc43b53651d7e46e7c4ba93044f84b4ee3b6fe66 100644 (file)
@@ -555,11 +555,32 @@ void free_xenballooned_pages(int nr_pages, struct page** pages)
 }
 EXPORT_SYMBOL(free_xenballooned_pages);
 
-static int __init balloon_init(void)
+static void __init balloon_add_region(unsigned long start_pfn,
+                                     unsigned long pages)
 {
        unsigned long pfn, extra_pfn_end;
        struct page *page;
 
+       /*
+        * If the amount of usable memory has been limited (e.g., with
+        * the 'mem' command line parameter), don't add pages beyond
+        * this limit.
+        */
+       extra_pfn_end = min(max_pfn, start_pfn + pages);
+
+       for (pfn = start_pfn; pfn < extra_pfn_end; pfn++) {
+               page = pfn_to_page(pfn);
+               /* totalram_pages and totalhigh_pages do not
+                  include the boot-time balloon extension, so
+                  don't subtract from it. */
+               __balloon_append(page);
+       }
+}
+
+static int __init balloon_init(void)
+{
+       int i;
+
        if (!xen_domain())
                return -ENODEV;
 
@@ -587,23 +608,12 @@ static int __init balloon_init(void)
 
        /*
         * Initialize the balloon with pages from the extra memory
-        * region (see arch/x86/xen/setup.c).
-        *
-        * If the amount of usable memory has been limited (e.g., with
-        * the 'mem' command line parameter), don't add pages beyond
-        * this limit.
+        * regions (see arch/x86/xen/setup.c).
         */
-       extra_pfn_end = min(max_pfn,
-                           (unsigned long)PFN_DOWN(xen_extra_mem_start
-                                                   + xen_extra_mem_size));
-       for (pfn = PFN_UP(xen_extra_mem_start);
-            pfn < extra_pfn_end;
-            pfn++) {
-               page = pfn_to_page(pfn);
-               /* totalram_pages and totalhigh_pages do not include the boot-time
-                  balloon extension, so don't subtract from it. */
-               __balloon_append(page);
-       }
+       for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++)
+               if (xen_extra_mem[i].size)
+                       balloon_add_region(PFN_UP(xen_extra_mem[i].start),
+                                          PFN_DOWN(xen_extra_mem[i].size));
 
        return 0;
 }
index 92b61f8c772cd2ea27fcdfa460a0315d5da158aa..12765b6f9517ee6169d73ba667fb86d4ce57a016 100644 (file)
@@ -3,7 +3,15 @@
 
 #include <asm/xen/page.h>
 
-extern phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
+struct xen_memory_region {
+       phys_addr_t start;
+       phys_addr_t size;
+};
+
+#define XEN_EXTRA_MEM_MAX_REGIONS 128 /* == E820MAX */
+
+extern __initdata
+struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS];
 
 extern unsigned long xen_released_pages;