WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 2/6] Change the boot allocator function to support me

To: Keir Fraser <keir.fraser@xxxxxxxxxxxxx>, Jan Beulich <jbeulich@xxxxxxxxxx>, Tim Deegan <Tim.Deegan@xxxxxxxxxx>, "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 2/6] Change the boot allocator function to support memory add
From: "Jiang, Yunhong" <yunhong.jiang@xxxxxxxxx>
Date: Sun, 28 Jun 2009 17:27:23 +0800
Accept-language: en-US
Acceptlanguage: en-US
Cc:
Delivery-date: Sun, 28 Jun 2009 02:29:05 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Thread-index: Acn30qSePbAyG89HR16wSczYgDMjIQ==
Thread-topic: [PATCH 2/6] Change the boot allocator function to support memory add
This patch extend the boot allocator to support memory add.

We take different method for boot allocator bitmap for 32/64 system. In x32 , 
we allocate 512K bitmap to support the whole 16G memory. In x86_64, we don't 
change the allocation when system bootup, instead, we try to remap the 
allocator bitmap to some pre-defined virtual address if hot-add happen.

We also add several API to allocate the handle boot page from some range.
Signed-off-by: Jiang, Yunhong <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Wang, shane <shane.wang@xxxxxxxxx>

diff -r 54433b197b5a xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Thu Jun 25 21:41:04 2009 +0800
+++ b/xen/arch/x86/mm.c Thu Jun 25 21:41:20 2009 +0800
@@ -155,7 +155,7 @@ struct domain *dom_xen, *dom_io;

 /* Frame table and its size in pages. */
 struct page_info *__read_mostly frame_table;
-unsigned long max_page;
+unsigned long max_page, max_boot_page;
 unsigned long total_pages;

 #define PAGE_CACHE_ATTRS (_PAGE_PAT|_PAGE_PCD|_PAGE_PWT)
@@ -207,6 +207,130 @@ void __init init_frametable(void)

     memset(frame_table, 0, nr_pages << PAGE_SHIFT);
 }
+
+#if defined(__x86_64__)
+static int boot_alloc_remapped = 0;
+static unsigned long mapped_pages = 0;
+
+#define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
+
+/*
+ * Extend the boot allocator bitmap and initialize the free/alloc state.
+ * It avoid copy original bitmap through splitting super page mapping into
+ * singer page mapping.
+ * It also use pages between start_pfn/end_pfn as page table page
+ */
+int arch_extend_boot_allocator(unsigned long start_pfn,
+                               unsigned long end_pfn)
+{
+    unsigned long n_size, n_pages, i, s_map_pfn, e_map_pfn;
+
+    if ( (start_pfn > end_pfn) || (start_pfn < max_page) )
+        return -EINVAL;
+
+    if (!boot_alloc_remapped)
+    {
+        unsigned long map_start, map_end, map_end_pfn;
+        unsigned long offset, o_start, o_end, o_size;
+
+        o_start = virt_to_maddr(alloc_bitmap);
+
+        o_size  = max_page / 8;
+        o_size += sizeof(unsigned long);
+        o_size  = round_pgup(o_size);
+        o_end = o_start + o_size;
+
+        map_start = o_start & ~((1UL << L2_PAGETABLE_SHIFT) -1UL);
+        map_end = o_end & ~((1UL << L2_PAGETABLE_SHIFT) -1UL);
+        map_end_pfn = map_end >> PAGE_SHIFT;
+
+        map_pages_to_xen(BOOTALLOC_VIRT_START, map_start >> PAGE_SHIFT,
+                         ((map_end - map_start) >> PAGE_SHIFT) + 1,
+                         PAGE_HYPERVISOR);
+
+        mapped_pages += (map_end - map_start) >> PAGE_SHIFT;
+
+        /*
+         * For pages in the end, it may not be 2M aligned
+         * Try to map them as 4k pages, and add some pages to be 2M aligned
+         * XXX A cleaner way is to make init_boot_allocator 2M aligned, do we
+         * care about those extra pages?
+         */
+        for (i = 0; i < (1UL << PAGETABLE_ORDER); i++)
+        {
+            if (i < (( o_end >> PAGE_SHIFT ) - map_end_pfn))
+                map_pages_to_xen(BOOTALLOC_VIRT_START +
+                                    (mapped_pages << PAGE_SHIFT),
+                                 map_end_pfn + i, 1,
+                                 PAGE_HYPERVISOR);
+            else
+            {
+                struct page_info *pg;
+                pg = alloc_domheap_page(NULL, 0);
+                if (!pg)
+                    return -ENOMEM;
+                map_pages_to_xen(BOOTALLOC_VIRT_START +
+                                    (mapped_pages  << PAGE_SHIFT),
+                                 page_to_mfn(pg), 1, PAGE_HYPERVISOR);
+                /* Mark the new created dummy page as allocated */
+                memset((void *)(BOOTALLOC_VIRT_START + (mapped_pages << 
PAGE_SHIFT)), 0xFFU, 1UL << PAGE_SHIFT);
+            }
+            mapped_pages++;
+        }
+
+        offset = o_start & ((1UL << L2_PAGETABLE_SHIFT) - 1UL);
+
+        alloc_bitmap = (unsigned long *)(BOOTALLOC_VIRT_START + offset);
+        smp_mb();
+        boot_alloc_remapped = 1;
+    }
+
+    n_size = end_pfn / 8;
+    n_size += sizeof(unsigned long);
+    n_size = round_pgup(n_size);
+    n_pages = ((unsigned long)alloc_bitmap + n_size  - BOOTALLOC_VIRT_START) >>
+                PAGE_SHIFT;
+    n_pages += ((1UL << PAGETABLE_ORDER) - 1);
+    n_pages &= ~((1UL << PAGETABLE_ORDER) - 1);
+
+    ASSERT(!(mapped_pages & ((1UL << PAGETABLE_ORDER) -1)) );
+    if ( n_pages <= mapped_pages)
+    {
+        map_free(start_pfn, end_pfn - start_pfn + 1);
+        return start_pfn;
+    }
+
+    s_map_pfn = start_pfn + (1UL << PAGETABLE_ORDER) - 1;
+    s_map_pfn = start_pfn & ~((1UL << PAGETABLE_ORDER) - 1);
+    e_map_pfn = s_map_pfn;
+    for ( i = mapped_pages; i <= n_pages; i += (1UL << PAGETABLE_ORDER) )
+    {
+        map_pages_to_xen(BOOTALLOC_VIRT_START+
+                              (i << PAGE_SHIFT),
+                         s_map_pfn + (i << PAGETABLE_ORDER ),
+                         1UL << PAGETABLE_ORDER,
+                         PAGE_HYPERVISOR);
+        e_map_pfn += (i << PAGETABLE_ORDER);
+    }
+
+    /* All new allocated page are marked as allocated initialy */
+    memset((unsigned char *)(BOOTALLOC_VIRT_START +
+                     (mapped_pages << PAGE_SHIFT)),
+            0xFFU, (n_pages - mapped_pages) << PAGE_SHIFT);
+    mapped_pages = n_pages;
+    map_free(start_pfn, s_map_pfn - start_pfn);
+    map_free(e_map_pfn, end_pfn - e_map_pfn + 1);
+
+    return start_pfn;
+}
+#else
+int arch_extend_boot_allocator(unsigned long start_pfn,
+                               unsigned long end_pfn)
+{
+    map_free(start_pfn, end_pfn - start_pfn + 1);
+       return start_pfn;
+}
+#endif

 void __init arch_init_memory(void)
 {
@@ -4402,8 +4526,6 @@ int ptwr_do_page_fault(struct vcpu *v, u

 void free_xen_pagetable(void *v)
 {
-    extern int early_boot;
-
     if ( early_boot )
         return;

diff -r 54433b197b5a xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Thu Jun 25 21:41:04 2009 +0800
+++ b/xen/arch/x86/setup.c      Thu Jun 25 21:41:21 2009 +0800
@@ -765,6 +765,9 @@ void __init __start_xen(unsigned long mb
     reserve_e820_ram(&boot_e820, initial_images_base, initial_images_end);

     /* Initialise boot heap. */
+#if defined(CONFIG_X86_32) && defined(CONFIG_MEMORY_HOTPLUG)
+    max_boot_page = 16UL << (30 - PAGE_SHIFT);
+#endif
     allocator_bitmap_end = init_boot_allocator(__pa(&_end));
 #if defined(CONFIG_X86_32)
     xenheap_initial_phys_start = allocator_bitmap_end;
diff -r 54433b197b5a xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  Thu Jun 25 21:41:04 2009 +0800
+++ b/xen/arch/x86/x86_32/mm.c  Thu Jun 25 21:41:21 2009 +0800
@@ -42,7 +42,6 @@ static unsigned long mpt_size;

 void *alloc_xen_pagetable(void)
 {
-    extern int early_boot;
     extern unsigned long xenheap_initial_phys_start;
     unsigned long mfn;

diff -r 54433b197b5a xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Thu Jun 25 21:41:04 2009 +0800
+++ b/xen/arch/x86/x86_64/mm.c  Thu Jun 25 21:41:21 2009 +0800
@@ -57,7 +57,6 @@ l2_pgentry_t __attribute__ ((__section__

 void *alloc_xen_pagetable(void)
 {
-    extern int early_boot;
     unsigned long mfn;

     if ( !early_boot )
diff -r 54433b197b5a xen/common/page_alloc.c
--- a/xen/common/page_alloc.c   Thu Jun 25 21:41:04 2009 +0800
+++ b/xen/common/page_alloc.c   Thu Jun 25 21:41:56 2009 +0800
@@ -103,7 +103,7 @@ unsigned long *alloc_bitmap;
  *  *_off == Bit offset within an element of the `alloc_bitmap' array.
  */

-static void map_alloc(unsigned long first_page, unsigned long nr_pages)
+void map_alloc(unsigned long first_page, unsigned long nr_pages)
 {
     unsigned long start_off, end_off, curr_idx, end_idx;

@@ -131,7 +131,7 @@ static void map_alloc(unsigned long firs
     }
 }

-static void map_free(unsigned long first_page, unsigned long nr_pages)
+void map_free(unsigned long first_page, unsigned long nr_pages)
 {
     unsigned long start_off, end_off, curr_idx, end_idx;

@@ -178,15 +178,33 @@ paddr_t __init init_boot_allocator(paddr
      * Allocate space for the allocation bitmap. Include an extra longword
      * of padding for possible overrun in map_alloc and map_free.
      */
-    bitmap_size  = max_page / 8;
+    bitmap_size  = (max_boot_page ? max_boot_page : max_page) / 8;
     bitmap_size += sizeof(unsigned long);
     bitmap_size  = round_pgup(bitmap_size);
     alloc_bitmap = (unsigned long *)maddr_to_virt(bitmap_start);

     /* All allocated by default. */
     memset(alloc_bitmap, ~0, bitmap_size);
+    max_boot_page = max_page;

     return bitmap_start + bitmap_size;
+}
+
+int extend_boot_allocator(unsigned long spfn, unsigned long epfn)
+{
+    int rc;
+
+    if (epfn < max_page)
+        return 0;
+
+    rc = arch_extend_boot_allocator(spfn, epfn);
+
+    if (rc < 0)
+        return rc;
+
+    max_boot_page = epfn;
+
+    return 0;
 }

 void __init init_boot_pages(paddr_t ps, paddr_t pe)
@@ -235,15 +253,22 @@ void __init init_boot_pages(paddr_t ps,
     }
 }

-unsigned long __init alloc_boot_pages(
-    unsigned long nr_pfns, unsigned long pfn_align)
+/*
+ * allocate nr_pfn with "align" alignement between start ~ end
+ */
+unsigned long alloc_boot_page_range(unsigned long start, unsigned long end,
+                                    unsigned long nr_pfns, unsigned long align)
 {
     unsigned long pg, i;
-
-    /* Search backwards to obtain highest available range. */
-    for ( pg = (max_page - nr_pfns) & ~(pfn_align - 1);
-          pg >= first_valid_mfn;
-          pg = (pg + i - nr_pfns) & ~(pfn_align - 1) )
+    if (start < first_valid_mfn)
+        start = first_valid_mfn;
+
+    if ( (end > max_boot_page) )
+        end = max_boot_page;
+
+    for (pg = (end - nr_pfns) & ~(align - 1);
+         pg >= start;
+         pg = (pg + i - nr_pfns) & ~(align - 1) )
     {
         for ( i = 0; i < nr_pfns; i++ )
             if ( allocated_in_map(pg+i) )
@@ -258,6 +283,11 @@ unsigned long __init alloc_boot_pages(
     return 0;
 }

+unsigned long __init alloc_boot_pages(
+    unsigned long nr_pfns, unsigned long pfn_align)
+{
+    return alloc_boot_page_range(first_valid_mfn, max_page, nr_pfns, 
pfn_align);
+}


 /*************************
@@ -834,7 +864,7 @@ int query_page_offline(unsigned long mfn
  * latter is not on a MAX_ORDER boundary, then we reserve the page by
  * not freeing it to the buddy allocator.
  */
-static void init_heap_pages(
+void init_heap_pages(
     struct page_info *pg, unsigned long nr_pages)
 {
     unsigned int nid_curr, nid_prev;
@@ -894,15 +924,15 @@ static unsigned long avail_heap_pages(
 }

 #define avail_for_domheap(mfn) !(allocated_in_map(mfn) || is_xen_heap_mfn(mfn))
-void __init end_boot_allocator(void)
+void end_boot_allocator_range(unsigned long spfn, unsigned long epfn)
 {
     unsigned long i, nr = 0;
     int curr_free, next_free;

     /* Pages that are free now go to the domain sub-allocator. */
-    if ( (curr_free = next_free = avail_for_domheap(first_valid_mfn)) )
-        map_alloc(first_valid_mfn, 1);
-    for ( i = first_valid_mfn; i < max_page; i++ )
+    if ( (curr_free = next_free = avail_for_domheap(spfn)) )
+        map_alloc(spfn, 1);
+    for ( i = spfn; i < epfn; i++ )
     {
         curr_free = next_free;
         next_free = avail_for_domheap(i+1);
@@ -918,6 +948,11 @@ void __init end_boot_allocator(void)
     }
     if ( nr )
         init_heap_pages(mfn_to_page(i - nr), nr);
+}
+
+void __init end_boot_allocator(void)
+{
+    end_boot_allocator_range(first_valid_mfn, max_page);

     if ( !dma_bitsize && (num_online_nodes() > 1) )
     {
@@ -936,6 +971,7 @@ void __init end_boot_allocator(void)
         printk(" DMA width %u bits", dma_bitsize);
     printk("\n");
 }
+
 #undef avail_for_domheap

 /*
diff -r 54433b197b5a xen/include/asm-ia64/mm.h
--- a/xen/include/asm-ia64/mm.h Thu Jun 25 21:41:04 2009 +0800
+++ b/xen/include/asm-ia64/mm.h Thu Jun 25 21:41:21 2009 +0800
@@ -274,6 +274,12 @@ static inline int get_page_and_type(stru
     }

     return rc;
+}
+
+int arch_extend_boot_allocator(unsigned long start_pfn,
+                               unsigned long end_pfn)
+{
+    return -ENOSYS;
 }

 #define        set_machinetophys(_mfn, _pfn) do { } while(0);
diff -r 54433b197b5a xen/include/asm-x86/config.h
--- a/xen/include/asm-x86/config.h      Thu Jun 25 21:41:04 2009 +0800
+++ b/xen/include/asm-x86/config.h      Thu Jun 25 21:41:22 2009 +0800
@@ -162,7 +162,9 @@ extern unsigned int video_mode, video_fl
  *    High read-only compatibility machine-to-phys translation table.
  *  0xffff828c80000000 - 0xffff828cbfffffff [1GB,   2^30 bytes, PML4:261]
  *    Xen text, static data, bss.
- *  0xffff828cc0000000 - 0xffff82ffffffffff [461GB,             PML4:261]
+ *  0xffff828cc0000000 - 0xffff82cfffffffff [1GB,   2^30 bytes,  PML4:261]
+ *    Boot allocator bitmap
+ *  0xffff828cd0000000 - 0xffff82ffffffffff [460GB,             PML4:261]
  *    Reserved for future use.
  *  0xffff830000000000 - 0xffff83ffffffffff [1TB,   2^40 bytes, PML4:262-263]
  *    1:1 direct mapping of all physical memory.
@@ -230,6 +232,9 @@ extern unsigned int video_mode, video_fl
 /* Slot 261: xen text, static data and bss (1GB). */
 #define XEN_VIRT_START          (HIRO_COMPAT_MPT_VIRT_END)
 #define XEN_VIRT_END            (XEN_VIRT_START + (1UL << 30))
+/* Slot 261: Boot allocator bitmap (1GB) */
+#define BOOTALLOC_VIRT_START        XEN_VIRT_END
+#define BOOTALLOC_VIRT_END          (BOOTALLOC_VIRT_START + (1UL << 30))
 /* Slot 262-263: A direct 1:1 mapping of all of physical memory. */
 #define DIRECTMAP_VIRT_START    (PML4_ADDR(262))
 #define DIRECTMAP_VIRT_END      (DIRECTMAP_VIRT_START + PML4_ENTRY_BYTES*2)
diff -r 54433b197b5a xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Thu Jun 25 21:41:04 2009 +0800
+++ b/xen/include/asm-x86/mm.h  Thu Jun 25 21:41:22 2009 +0800
@@ -266,9 +266,13 @@ extern void share_xen_page_with_privileg
     struct page_info *page, int readonly);

 extern struct page_info *frame_table;
-extern unsigned long max_page;
+extern unsigned long max_page, max_boot_page;
 extern unsigned long total_pages;
+
+extern int early_boot;
 void init_frametable(void);
+int arch_extend_boot_allocator(unsigned long start_pfn,
+                               unsigned long end_pfn);

 int free_page_type(struct page_info *page, unsigned long type,
                    int preemptible);
diff -r 54433b197b5a xen/include/xen/mm.h
--- a/xen/include/xen/mm.h      Thu Jun 25 21:41:04 2009 +0800
+++ b/xen/include/xen/mm.h      Thu Jun 25 21:41:22 2009 +0800
@@ -38,10 +38,18 @@ struct page_info;

 /* Boot-time allocator. Turns into generic allocator after bootstrap. */
 paddr_t init_boot_allocator(paddr_t bitmap_start);
+void map_free(unsigned long first_page, unsigned long nr_pages);
+void map_alloc(unsigned long first_page, unsigned long nr_pages);
 void init_boot_pages(paddr_t ps, paddr_t pe);
 unsigned long alloc_boot_pages(
     unsigned long nr_pfns, unsigned long pfn_align);
+unsigned long alloc_boot_page_range(unsigned long start, unsigned long end,
+                               unsigned long nr_pfns, unsigned long align);
+void init_heap_pages(
+    struct page_info *pg, unsigned long nr_pages);
 void end_boot_allocator(void);
+void end_boot_allocator_range(unsigned long spfn, unsigned long epfn);
+int extend_boot_allocator(unsigned long spfn, unsigned long epfn);

 /* Xen suballocator. These functions are interrupt-safe. */
 void init_xenheap_pages(paddr_t ps, paddr_t pe);

Attachment: boot_allocator.patch
Description: boot_allocator.patch

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