x86_64: Remove statically-partitioned Xen heap.
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 16 Jan 2009 15:12:12 +0000 (15:12 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 16 Jan 2009 15:12:12 +0000 (15:12 +0000)
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/ia64/xen/machine_kexec.c
xen/arch/x86/machine_kexec.c
xen/arch/x86/mm.c
xen/arch/x86/setup.c
xen/arch/x86/x86_32/machine_kexec.c
xen/arch/x86/x86_64/machine_kexec.c
xen/common/kexec.c
xen/common/page_alloc.c
xen/include/asm-x86/config.h
xen/include/asm-x86/mm.h

index 9fcd189d66da7e353045d7e33de500399ab2d40d..270fc0b71b438c9eee34185e50abd4a7716cf451 100644 (file)
@@ -195,6 +195,7 @@ int machine_kexec_get(xen_kexec_range_t *range)
 
 void arch_crash_save_vmcoreinfo(void)
 {
+    VMCOREINFO_SYMBOL(xenheap_phys_end);
        VMCOREINFO_SYMBOL(dom_xen);
        VMCOREINFO_SYMBOL(dom_io);
        VMCOREINFO_SYMBOL(xen_pstart);
index d98eb77fa7c6d286bfbd6671bf79938ce12926f6..4d15e4b0639474e2d1143abf3a7fd506e8dd3b85 100644 (file)
@@ -150,6 +150,9 @@ void arch_crash_save_vmcoreinfo(void)
        VMCOREINFO_SYMBOL(dom_xen);
        VMCOREINFO_SYMBOL(dom_io);
 
+#ifdef CONFIG_X86_32
+    VMCOREINFO_SYMBOL(xenheap_phys_end);
+#endif
 #ifdef CONFIG_X86_PAE
        VMCOREINFO_SYMBOL_ALIAS(pgd_l3, idle_pg_table);
 #endif
index 7cf13378069d126dd07c70cf4d773a55017b80d5..7b04ae5c973f24fd9f64abbc4cb9bde341e06bce 100644 (file)
@@ -329,7 +329,7 @@ void share_xen_page_with_guest(
 
     page_set_owner(page, d);
     wmb(); /* install valid domain ptr before updating refcnt. */
-    ASSERT(page->count_info == 0);
+    ASSERT((page->count_info & (PGC_allocated|PGC_count_mask)) == 0);
 
     /* Only add to the allocation list if the domain isn't dying. */
     if ( !d->is_dying )
@@ -4722,12 +4722,18 @@ void __set_fixmap(
 void memguard_init(void)
 {
     unsigned long start = max_t(unsigned long, xen_phys_start, 1UL << 20);
+#ifdef __i386__
     map_pages_to_xen(
         (unsigned long)__va(start),
         start >> PAGE_SHIFT,
         (xenheap_phys_end - start) >> PAGE_SHIFT,
         __PAGE_HYPERVISOR|MAP_SMALL_PAGES);
-#ifdef __x86_64__
+#else
+    map_pages_to_xen(
+        (unsigned long)__va(start),
+        start >> PAGE_SHIFT,
+        (__pa(&_end) + PAGE_SIZE - 1 - start) >> PAGE_SHIFT,
+        __PAGE_HYPERVISOR|MAP_SMALL_PAGES);
     BUG_ON(start != xen_phys_start);
     map_pages_to_xen(
         XEN_VIRT_START,
index 051b542ce3113721dc0abbd0fa4ea10286026de7..34609ca8cd7fe5fe2afa3bf592c178eb03045566 100644 (file)
@@ -54,15 +54,6 @@ extern u16 boot_edid_caps;
 extern u8 boot_edid_info[128];
 extern struct boot_video_info boot_vid_info;
 
-/*
- * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
- * page_info table and allocation bitmap.
- */
-static unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
-#if defined(CONFIG_X86_64)
-integer_param("xenheap_megabytes", opt_xenheap_megabytes);
-#endif
-
 /* opt_nosmp: If true, secondary processors are ignored. */
 static int opt_nosmp = 0;
 boolean_param("nosmp", opt_nosmp);
@@ -105,8 +96,10 @@ cpumask_t cpu_present_map;
 
 unsigned long xen_phys_start;
 
+#ifdef CONFIG_X86_32
 /* Limits of Xen heap, used to initialise the allocator. */
 unsigned long xenheap_phys_start, xenheap_phys_end;
+#endif
 
 extern void arch_init_memory(void);
 extern void init_IRQ(void);
@@ -421,6 +414,7 @@ void __init __start_xen(unsigned long mbi_p)
     multiboot_info_t *mbi = __va(mbi_p);
     module_t *mod = (module_t *)__va(mbi->mods_addr);
     unsigned long nr_pages, modules_length;
+    unsigned long allocator_bitmap_end;
     int i, e820_warn = 0, bytes = 0;
     struct ns16550_defaults ns16550 = {
         .data_bits = 8,
@@ -599,23 +593,6 @@ void __init __start_xen(unsigned long mbi_p)
     /* Sanitise the raw E820 map to produce a final clean version. */
     max_page = init_e820(memmap_type, e820_raw, &e820_raw_nr);
 
-#ifdef CONFIG_X86_64
-    /*
-     * On x86/64 we are able to account for the allocation bitmap
-     * (allocated in common/page_alloc.c:init_boot_allocator()) stealing
-     * from the Xen heap. Here we make the Xen heap appropriately larger.
-     */
-    opt_xenheap_megabytes += (max_page / 8) >> 20;
-#endif
-
-    /*
-     * Since there are some stubs getting built on the stacks which use
-     * direct calls/jumps, the heap must be confined to the lower 2G so
-     * that those branches can reach their targets.
-     */
-    if ( opt_xenheap_megabytes > 2048 )
-        opt_xenheap_megabytes = 2048;
-
     /* Create a temporary copy of the E820 map. */
     memcpy(&boot_e820, &e820, sizeof(e820));
 
@@ -654,8 +631,9 @@ void __init __start_xen(unsigned long mbi_p)
             s >> PAGE_SHIFT, (e-s) >> PAGE_SHIFT, PAGE_HYPERVISOR);
 
 #if defined(CONFIG_X86_64)
+#define reloc_size ((__pa(&_end) + mask) & ~mask)
         /* Is the region suitable for relocating Xen? */
-        if ( !xen_phys_start && (((e-s) >> 20) >= opt_xenheap_megabytes) )
+        if ( !xen_phys_start && ((e-s) >= reloc_size) )
         {
             extern l2_pgentry_t l2_xenmap[];
             l4_pgentry_t *pl4e;
@@ -664,7 +642,7 @@ void __init __start_xen(unsigned long mbi_p)
             int i, j, k;
 
             /* Select relocation address. */
-            e = (e - (opt_xenheap_megabytes << 20)) & ~mask;
+            e -= reloc_size;
             xen_phys_start = e;
             bootsym(trampoline_xen_phys_start) = e;
 
@@ -760,15 +738,15 @@ void __init __start_xen(unsigned long mbi_p)
         EARLY_FAIL("Not enough memory to relocate the dom0 kernel image.\n");
     reserve_e820_ram(&boot_e820, initial_images_start, initial_images_end);
 
-    /* Initialise Xen heap and boot heap. */
-    xenheap_phys_start = init_boot_allocator(__pa(&_end));
-    xenheap_phys_end   = opt_xenheap_megabytes << 20;
-#if defined(CONFIG_X86_64)
+    /* Initialise boot heap. */
+    allocator_bitmap_end = init_boot_allocator(__pa(&_end));
+#if defined(CONFIG_X86_32)
+    xenheap_phys_start = allocator_bitmap_end;
+    xenheap_phys_end   = DIRECTMAP_MBYTES << 20;
+#else
     if ( !xen_phys_start )
         EARLY_FAIL("Not enough memory to relocate Xen.\n");
-    xenheap_phys_end += xen_phys_start;
-    reserve_e820_ram(&boot_e820, xen_phys_start,
-                     xen_phys_start + (opt_xenheap_megabytes<<20));
+    reserve_e820_ram(&boot_e820, __pa(&_start), allocator_bitmap_end);
 #endif
 
     /* Late kexec reservation (dynamic start address). */
@@ -861,23 +839,23 @@ void __init __start_xen(unsigned long mbi_p)
 
     numa_initmem_init(0, max_page);
 
-    /* Initialise the Xen heap, skipping RAM holes. */
+#if defined(CONFIG_X86_32)
+    /* Initialise the Xen heap. */
     init_xenheap_pages(xenheap_phys_start, xenheap_phys_end);
     nr_pages = (xenheap_phys_end - xenheap_phys_start) >> PAGE_SHIFT;
-#ifdef __x86_64__
-    init_xenheap_pages(xen_phys_start, __pa(&_start));
-    nr_pages += (__pa(&_start) - xen_phys_start) >> PAGE_SHIFT;
-    vesa_init();
-#endif
     xenheap_phys_start = xen_phys_start;
     printk("Xen heap: %luMB (%lukB)\n", 
            nr_pages >> (20 - PAGE_SHIFT),
            nr_pages << (PAGE_SHIFT - 10));
+#endif
 
     end_boot_allocator();
-
     early_boot = 0;
 
+#if defined(CONFIG_X86_64)
+    vesa_init();
+#endif
+
     softirq_init();
 
     early_cpu_init();
@@ -1115,10 +1093,15 @@ void arch_get_xen_caps(xen_capabilities_info_t *info)
 
 int xen_in_range(paddr_t start, paddr_t end)
 {
-    start = max_t(paddr_t, start, xenheap_phys_start);
-    end = min_t(paddr_t, end, xenheap_phys_end);
-    return start < end; 
+#if defined(CONFIG_X86_32)
+    paddr_t xs = xenheap_phys_start;
+    paddr_t xe = xenheap_phys_end;
+#else
+    paddr_t xs = __pa(&_start);
+    paddr_t xe = __pa(&_end);
+#endif
+
+    return (start < xe) && (end > xs);
 }
 
 /*
index b22ddbf5dc0a0d4d8fa1b8c5b98a2c27ba099353..11b8cae944b16c388ddebedf26130841b0e3b95f 100644 (file)
@@ -6,8 +6,6 @@
  * - Magnus Damm <magnus@valinux.co.jp>
  */
 
-#ifndef CONFIG_COMPAT
-
 #include <xen/types.h>
 #include <xen/kernel.h>
 #include <asm/page.h>
@@ -20,7 +18,6 @@ int machine_kexec_get_xen(xen_kexec_range_t *range)
                       (unsigned long)range->start;
         return 0;
 }
-#endif
 
 /*
  * Local variables:
index 96413cb8287a4b74417ca3033875b17e839547d0..0d4b1a10cf9f5fa42d6818b596d92804efd89d43 100644 (file)
@@ -6,20 +6,17 @@
  * - Magnus Damm <magnus@valinux.co.jp>
  */
 
-#ifndef CONFIG_COMPAT
-
 #include <xen/types.h>
+#include <xen/kernel.h>
 #include <asm/page.h>
 #include <public/kexec.h>
 
 int machine_kexec_get_xen(xen_kexec_range_t *range)
 {
-        range->start = xenheap_phys_start;
-        range->size = (unsigned long)xenheap_phys_end -
-                      (unsigned long)range->start;
+        range->start = virt_to_maddr(_start);
+        range->size = virt_to_maddr(_end) - (unsigned long)range->start;
         return 0;
 }
-#endif
 
 /*
  * Local variables:
index 2eb73e94b5399cd7d126a3d51f33a849d6d890b8..aa7b5ee577f67370778ac6c6c6e68335a38bfdc8 100644 (file)
@@ -336,7 +336,6 @@ static void crash_save_vmcoreinfo(void)
     VMCOREINFO_SYMBOL(frame_table);
     VMCOREINFO_SYMBOL(alloc_bitmap);
     VMCOREINFO_SYMBOL(max_page);
-    VMCOREINFO_SYMBOL(xenheap_phys_end);
 
     VMCOREINFO_STRUCT_SIZE(page_info);
     VMCOREINFO_STRUCT_SIZE(domain);
index d9e0a2946ac738c4b9cc4179c03d43254cec89b5..d151e40108b00fb951eb48f174458a0986f9e4f2 100644 (file)
@@ -634,6 +634,8 @@ void __init scrub_heap_pages(void)
  * XEN-HEAP SUB-ALLOCATOR
  */
 
+#ifndef __x86_64__
+
 void init_xenheap_pages(paddr_t ps, paddr_t pe)
 {
     ps = round_pgup(ps);
@@ -689,6 +691,55 @@ void free_xenheap_pages(void *v, unsigned int order)
     free_heap_pages(MEMZONE_XEN, virt_to_page(v), order);
 }
 
+#else
+
+void init_xenheap_pages(paddr_t ps, paddr_t pe)
+{
+    init_domheap_pages(ps, pe);
+}
+
+void *alloc_xenheap_pages(unsigned int order)
+{
+    struct page_info *pg;
+    unsigned int i;
+
+    ASSERT(!in_irq());
+
+    pg = alloc_heap_pages(
+        MEMZONE_XEN+1, 31, cpu_to_node(smp_processor_id()), order);
+    if ( unlikely(pg == NULL) )
+        goto no_memory;
+
+    for ( i = 0; i < (1u << order); i++ )
+        pg[i].count_info |= PGC_xen_heap;
+
+    return page_to_virt(pg);
+
+ no_memory:
+    printk("Cannot handle page request order %d!\n", order);
+    return NULL;
+}
+
+void free_xenheap_pages(void *v, unsigned int order)
+{
+    struct page_info *pg;
+    unsigned int i;
+
+    ASSERT(!in_irq());
+
+    if ( v == NULL )
+        return;
+
+    pg = virt_to_page(v);
+
+    for ( i = 0; i < (1u << order); i++ )
+        pg[i].count_info &= ~PGC_xen_heap;
+
+    free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, order);
+}
+
+#endif
+
 
 
 /*************************
index b490887a64bf7ff7ff3c6257c84deb2494d32192..51337c0b79a64f6a90f6cd3142921ce08f370531 100644 (file)
@@ -117,8 +117,6 @@ extern unsigned int video_mode, video_flags;
 
 #define asmlinkage
 
-#define XENHEAP_DEFAULT_MB (16)
-
 #define PML4_ENTRY_BITS  39
 #ifndef __ASSEMBLY__
 #define PML4_ENTRY_BYTES (1UL << PML4_ENTRY_BITS)
@@ -310,7 +308,6 @@ extern unsigned int video_mode, video_flags;
 #define RO_MPT_VIRT_END                FRAMETABLE_VIRT_START
 #define RO_MPT_VIRT_START      (RO_MPT_VIRT_END - (MACHPHYS_MBYTES<<20))
 
-#define XENHEAP_DEFAULT_MB     (DIRECTMAP_MBYTES)
 #define DIRECTMAP_PHYS_END     (DIRECTMAP_MBYTES<<20)
 
 /* Maximum linear address accessible via guest memory segments. */
@@ -340,7 +337,10 @@ extern unsigned int video_mode, video_flags;
 #endif /* __i386__ */
 
 #ifndef __ASSEMBLY__
-extern unsigned long xen_phys_start, xenheap_phys_start, xenheap_phys_end;
+extern unsigned long xen_phys_start;
+#if defined(__i386__)
+extern unsigned long xenheap_phys_start, xenheap_phys_end;
+#endif
 #endif
 
 /* GDT/LDT shadow mapping area. The first per-domain-mapping sub-area. */
index d017c4cb56a8ae6f0cc6d15157aa73cd38750a9c..b10e548db2bcae207fed50832713e9d5c347dbfd 100644 (file)
@@ -135,6 +135,10 @@ struct page_info
  /* Page is locked? */
 # define _PGC_locked        30
 # define PGC_locked         (1U<<_PGC_out_of_sync)
+#else
+ /* Page is Xen heap? */
+# define _PGC_xen_heap      30
+# define PGC_xen_heap       (1U<<_PGC_xen_heap)
 #endif
  /* Set when is using a page as a page table */
 #define _PGC_page_table     29
@@ -145,12 +149,17 @@ struct page_info
  /* 26-bit count of references to this frame. */
 #define PGC_count_mask      ((1U<<26)-1)
 
+#if defined(__i386__)
 #define is_xen_heap_page(page) is_xen_heap_mfn(page_to_mfn(page))
 #define is_xen_heap_mfn(mfn) ({                         \
     unsigned long _mfn = (mfn);                         \
     ((_mfn >= paddr_to_pfn(xenheap_phys_start)) &&      \
      (_mfn < paddr_to_pfn(xenheap_phys_end)));          \
 })
+#else
+#define is_xen_heap_page(page) ((page)->count_info & PGC_xen_heap)
+#define is_xen_heap_mfn(mfn) is_xen_heap_page(&frame_table[mfn])
+#endif
 
 #if defined(__i386__)
 #define pickle_domptr(_d)   ((u32)(unsigned long)(_d))