[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Replace boot-time free-pages bitmap with a region list.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1247087311 -3600 # Node ID d6c1d7992f437c625135c2f8752fc94078ec4c31 # Parent ef38784f9f85ba8db24af84c345b33da08970b13 Replace boot-time free-pages bitmap with a region list. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/ia64/xen/xenmem.c | 6 - xen/arch/ia64/xen/xensetup.c | 4 xen/arch/x86/mm.c | 2 xen/arch/x86/setup.c | 17 +- xen/arch/x86/tboot.c | 7 - xen/arch/x86/x86_64/mm.c | 1 xen/common/kexec.c | 1 xen/common/page_alloc.c | 253 ++++++++++++++++--------------------------- xen/include/asm-x86/mm.h | 10 - xen/include/xen/mm.h | 5 10 files changed, 110 insertions(+), 196 deletions(-) diff -r ef38784f9f85 -r d6c1d7992f43 xen/arch/ia64/xen/xenmem.c --- a/xen/arch/ia64/xen/xenmem.c Wed Jul 08 16:47:58 2009 +0100 +++ b/xen/arch/ia64/xen/xenmem.c Wed Jul 08 22:08:31 2009 +0100 @@ -87,8 +87,6 @@ alloc_dir_page(void) { unsigned long mfn = alloc_boot_pages(1, 1); unsigned long dir; - if (!mfn) - panic("Not enough memory for virtual frame table!\n"); ++table_size; dir = mfn << PAGE_SHIFT; clear_page(__va(dir)); @@ -101,8 +99,6 @@ alloc_table_page(unsigned long fill) unsigned long mfn = alloc_boot_pages(1, 1); unsigned long *table; unsigned long i; - if (!mfn) - panic("Not enough memory for virtual frame table!\n"); ++table_size; table = (unsigned long *)__va((mfn << PAGE_SHIFT)); for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) @@ -245,8 +241,6 @@ void __init init_frametable(void) * address is identity mapped */ pfn = alloc_boot_pages( frame_table_size >> PAGE_SHIFT, FT_ALIGN_SIZE >> PAGE_SHIFT); - if (pfn == 0) - panic("Not enough memory for frame table.\n"); frame_table = __va(pfn << PAGE_SHIFT); memset(frame_table, 0, frame_table_size); diff -r ef38784f9f85 -r d6c1d7992f43 xen/arch/ia64/xen/xensetup.c --- a/xen/arch/ia64/xen/xensetup.c Wed Jul 08 16:47:58 2009 +0100 +++ b/xen/arch/ia64/xen/xensetup.c Wed Jul 08 22:08:31 2009 +0100 @@ -514,9 +514,7 @@ skip_move: efi_print(); xen_heap_start = memguard_init(ia64_imva(&_end)); - printk("Before xen_heap_start: %p\n", xen_heap_start); - xen_heap_start = __va(init_boot_allocator(__pa(xen_heap_start))); - printk("After xen_heap_start: %p\n", xen_heap_start); + printk("xen_heap_start: %p\n", xen_heap_start); efi_memmap_walk(filter_rsvd_memory, init_boot_pages); efi_memmap_walk(xen_count_pages, &nr_pages); diff -r ef38784f9f85 -r d6c1d7992f43 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Wed Jul 08 16:47:58 2009 +0100 +++ b/xen/arch/x86/mm.c Wed Jul 08 22:08:31 2009 +0100 @@ -199,8 +199,6 @@ void __init init_frametable(void) while (nr_pages + 4 - i < page_step) page_step >>= PAGETABLE_ORDER; mfn = alloc_boot_pages(page_step, page_step); - if ( mfn == 0 ) - panic("Not enough memory for frame table\n"); map_pages_to_xen( FRAMETABLE_VIRT_START + (i << PAGE_SHIFT), mfn, page_step, PAGE_HYPERVISOR); diff -r ef38784f9f85 -r d6c1d7992f43 xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Wed Jul 08 16:47:58 2009 +0100 +++ b/xen/arch/x86/setup.c Wed Jul 08 22:08:31 2009 +0100 @@ -97,7 +97,6 @@ cpumask_t cpu_present_map; cpumask_t cpu_present_map; unsigned long xen_phys_start; -unsigned long allocator_bitmap_end; #ifdef CONFIG_X86_32 /* Limits of Xen heap, used to initialise the allocator. */ @@ -764,24 +763,21 @@ void __init __start_xen(unsigned long mb EARLY_FAIL("Not enough memory to relocate the dom0 kernel image.\n"); reserve_e820_ram(&boot_e820, initial_images_base, initial_images_end); - /* Initialise boot heap. */ - allocator_bitmap_end = init_boot_allocator(__pa(&_end)); #if defined(CONFIG_X86_32) - xenheap_initial_phys_start = allocator_bitmap_end; + xenheap_initial_phys_start = __pa(&_end); xenheap_phys_end = DIRECTMAP_MBYTES << 20; #else if ( !xen_phys_start ) EARLY_FAIL("Not enough memory to relocate Xen.\n"); - reserve_e820_ram(&boot_e820, __pa(&_start), allocator_bitmap_end); + reserve_e820_ram(&boot_e820, __pa(&_start), __pa(&_end)); #endif /* Late kexec reservation (dynamic start address). */ kexec_reserve_area(&boot_e820); /* - * With the boot allocator now initialised, we can walk every RAM region - * and map it in its entirety (on x86/64, at least) and notify it to the - * boot allocator. + * Walk every RAM region and map it in its entirety (on x86/64, at least) + * and notify it to the boot allocator. */ for ( i = 0; i < boot_e820.nr_map; i++ ) { @@ -1132,7 +1128,6 @@ int xen_in_range(paddr_t start, paddr_t if ( !xen_regions[0].s ) { extern char __init_begin[], __bss_start[]; - extern unsigned long allocator_bitmap_end; /* S3 resume code (and other real mode trampoline code) */ xen_regions[0].s = bootsym_phys(trampoline_start); @@ -1144,9 +1139,9 @@ int xen_in_range(paddr_t start, paddr_t xen_regions[2].s = __pa(&__per_cpu_start); xen_regions[2].e = xen_regions[2].s + (((paddr_t)last_cpu(cpu_possible_map) + 1) << PERCPU_SHIFT); - /* bss + boot allocator bitmap */ + /* bss */ xen_regions[3].s = __pa(&__bss_start); - xen_regions[3].e = allocator_bitmap_end; + xen_regions[3].e = __pa(&_end); } for ( i = 0; i < ARRAY_SIZE(xen_regions); i++ ) diff -r ef38784f9f85 -r d6c1d7992f43 xen/arch/x86/tboot.c --- a/xen/arch/x86/tboot.c Wed Jul 08 16:47:58 2009 +0100 +++ b/xen/arch/x86/tboot.c Wed Jul 08 22:08:31 2009 +0100 @@ -47,7 +47,6 @@ static uint64_t sinit_base, sinit_size; #define TXTCR_HEAP_SIZE 0x0308 extern char __init_begin[], __per_cpu_start[], __bss_start[]; -extern unsigned long allocator_bitmap_end; #define SHA1_SIZE 20 typedef uint8_t sha1_hash_t[SHA1_SIZE]; @@ -299,7 +298,7 @@ void tboot_shutdown(uint32_t shutdown_ty /* * Xen regions for tboot to MAC */ - g_tboot_shared->num_mac_regions = 5; + g_tboot_shared->num_mac_regions = 4; /* S3 resume code (and other real mode trampoline code) */ g_tboot_shared->mac_regions[0].start = bootsym_phys(trampoline_start); g_tboot_shared->mac_regions[0].size = bootsym_phys(trampoline_end) - @@ -315,10 +314,6 @@ void tboot_shutdown(uint32_t shutdown_ty /* bss */ g_tboot_shared->mac_regions[3].start = (uint64_t)__pa(&__bss_start); g_tboot_shared->mac_regions[3].size = __pa(&_end) - __pa(&__bss_start); - /* boot allocator bitmap */ - g_tboot_shared->mac_regions[4].start = (uint64_t)__pa(&_end); - g_tboot_shared->mac_regions[4].size = allocator_bitmap_end - - __pa(&_end); /* * MAC domains and other Xen memory diff -r ef38784f9f85 -r d6c1d7992f43 xen/arch/x86/x86_64/mm.c --- a/xen/arch/x86/x86_64/mm.c Wed Jul 08 16:47:58 2009 +0100 +++ b/xen/arch/x86/x86_64/mm.c Wed Jul 08 22:08:31 2009 +0100 @@ -68,7 +68,6 @@ void *alloc_xen_pagetable(void) } mfn = alloc_boot_pages(1, 1); - BUG_ON(mfn == 0); return mfn_to_virt(mfn); } diff -r ef38784f9f85 -r d6c1d7992f43 xen/common/kexec.c --- a/xen/common/kexec.c Wed Jul 08 16:47:58 2009 +0100 +++ b/xen/common/kexec.c Wed Jul 08 22:08:31 2009 +0100 @@ -334,7 +334,6 @@ static void crash_save_vmcoreinfo(void) VMCOREINFO_SYMBOL(domain_list); VMCOREINFO_SYMBOL(frame_table); - VMCOREINFO_SYMBOL(alloc_bitmap); VMCOREINFO_SYMBOL(max_page); VMCOREINFO_STRUCT_SIZE(page_info); diff -r ef38784f9f85 -r d6c1d7992f43 xen/common/page_alloc.c --- a/xen/common/page_alloc.c Wed Jul 08 16:47:58 2009 +0100 +++ b/xen/common/page_alloc.c Wed Jul 08 22:08:31 2009 +0100 @@ -69,117 +69,78 @@ PAGE_LIST_HEAD(page_offlined_list); /* Broken page list, protected by heap_lock. */ PAGE_LIST_HEAD(page_broken_list); -/********************* - * ALLOCATION BITMAP - * One bit per page of memory. Bit set => page is allocated. - */ - -unsigned long *alloc_bitmap; -#define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8) - -#define allocated_in_map(_pn) \ -({ unsigned long ___pn = (_pn); \ - !!(alloc_bitmap[___pn/PAGES_PER_MAPWORD] & \ - (1UL<<(___pn&(PAGES_PER_MAPWORD-1)))); }) - -/* - * Hint regarding bitwise arithmetic in map_{alloc,free}: - * -(1<<n) sets all bits >= n. - * (1<<n)-1 sets all bits < n. - * Variable names in map_{alloc,free}: - * *_idx == Index into `alloc_bitmap' array. - * *_off == Bit offset within an element of the `alloc_bitmap' array. - */ - -static void map_alloc(unsigned long first_page, unsigned long nr_pages) -{ - unsigned long start_off, end_off, curr_idx, end_idx; - -#ifndef NDEBUG - unsigned long i; - /* Check that the block isn't already allocated. */ - for ( i = 0; i < nr_pages; i++ ) - ASSERT(!allocated_in_map(first_page + i)); -#endif - - curr_idx = first_page / PAGES_PER_MAPWORD; - start_off = first_page & (PAGES_PER_MAPWORD-1); - end_idx = (first_page + nr_pages) / PAGES_PER_MAPWORD; - end_off = (first_page + nr_pages) & (PAGES_PER_MAPWORD-1); - - if ( curr_idx == end_idx ) - { - alloc_bitmap[curr_idx] |= ((1UL<<end_off)-1) & -(1UL<<start_off); - } - else - { - alloc_bitmap[curr_idx] |= -(1UL<<start_off); - while ( ++curr_idx < end_idx ) alloc_bitmap[curr_idx] = ~0UL; - alloc_bitmap[curr_idx] |= (1UL<<end_off)-1; - } -} - -static void map_free(unsigned long first_page, unsigned long nr_pages) -{ - unsigned long start_off, end_off, curr_idx, end_idx; - -#ifndef NDEBUG - unsigned long i; - /* Check that the block isn't already freed. */ - for ( i = 0; i < nr_pages; i++ ) - ASSERT(allocated_in_map(first_page + i)); -#endif - - curr_idx = first_page / PAGES_PER_MAPWORD; - start_off = first_page & (PAGES_PER_MAPWORD-1); - end_idx = (first_page + nr_pages) / PAGES_PER_MAPWORD; - end_off = (first_page + nr_pages) & (PAGES_PER_MAPWORD-1); - - if ( curr_idx == end_idx ) - { - alloc_bitmap[curr_idx] &= -(1UL<<end_off) | ((1UL<<start_off)-1); - } - else - { - alloc_bitmap[curr_idx] &= (1UL<<start_off)-1; - while ( ++curr_idx != end_idx ) alloc_bitmap[curr_idx] = 0; - alloc_bitmap[curr_idx] &= -(1UL<<end_off); - } -} - - - /************************* * BOOT-TIME ALLOCATOR */ -static unsigned long first_valid_mfn = ~0UL; - -/* Initialise allocator to handle up to @max_page pages. */ -paddr_t __init init_boot_allocator(paddr_t bitmap_start) -{ - unsigned long bitmap_size; - - bitmap_start = round_pgup(bitmap_start); - - /* - * 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 += 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); - - return bitmap_start + bitmap_size; +static unsigned long __initdata first_valid_mfn = ~0UL; + +static struct bootmem_region { + unsigned long s, e; /* MFNs @s through @e-1 inclusive are free */ +} *__initdata bootmem_region_list; +static unsigned int __initdata nr_bootmem_regions; + +static void __init boot_bug(int line) +{ + panic("Boot BUG at %s:%d\n", __FILE__, line); +} +#define BOOT_BUG_ON(p) if ( p ) boot_bug(__LINE__); + +static void __init bootmem_region_add(unsigned long s, unsigned long e) +{ + unsigned int i; + + if ( (bootmem_region_list == NULL) && (s < e) ) + bootmem_region_list = mfn_to_virt(s++); + + if ( s >= e ) + return; + + for ( i = 0; i < nr_bootmem_regions; i++ ) + if ( s < bootmem_region_list[i].e ) + break; + + BOOT_BUG_ON((i < nr_bootmem_regions) && (e > bootmem_region_list[i].s)); + BOOT_BUG_ON(nr_bootmem_regions == + (PAGE_SIZE / sizeof(struct bootmem_region))); + + memmove(&bootmem_region_list[i+1], &bootmem_region_list[i], + (nr_bootmem_regions - i) * sizeof(*bootmem_region_list)); + bootmem_region_list[i] = (struct bootmem_region) { s, e }; + nr_bootmem_regions++; +} + +static void __init bootmem_region_zap(unsigned long s, unsigned long e) +{ + unsigned int i; + + for ( i = 0; i < nr_bootmem_regions; i++ ) + { + struct bootmem_region *r = &bootmem_region_list[i]; + if ( e <= r->s ) + break; + if ( s >= r->e ) + continue; + if ( s <= r->s ) + { + r->s = min(e, r->e); + } + else if ( e >= r->e ) + { + r->e = s; + } + else + { + unsigned long _e = r->e; + r->e = s; + bootmem_region_add(e, _e); + } + } } void __init init_boot_pages(paddr_t ps, paddr_t pe) { - unsigned long bad_spfn, bad_epfn, i; + unsigned long bad_spfn, bad_epfn; const char *p; ps = round_pgup(ps); @@ -189,7 +150,7 @@ void __init init_boot_pages(paddr_t ps, first_valid_mfn = min_t(unsigned long, ps >> PAGE_SHIFT, first_valid_mfn); - map_free(ps >> PAGE_SHIFT, (pe - ps) >> PAGE_SHIFT); + bootmem_region_add(ps >> PAGE_SHIFT, pe >> PAGE_SHIFT); /* Check new pages against the bad-page list. */ p = opt_badpage; @@ -217,32 +178,29 @@ void __init init_boot_pages(paddr_t ps, printk("Marking pages %lx through %lx as bad\n", bad_spfn, bad_epfn); - for ( i = bad_spfn; i <= bad_epfn; i++ ) - if ( (i < max_page) && !allocated_in_map(i) ) - map_alloc(i, 1); + bootmem_region_zap(bad_spfn, bad_epfn+1); } } unsigned long __init alloc_boot_pages( unsigned long nr_pfns, unsigned long pfn_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) ) - { - for ( i = 0; i < nr_pfns; i++ ) - if ( allocated_in_map(pg+i) ) - break; - if ( i == nr_pfns ) - { - map_alloc(pg, nr_pfns); - return pg; - } - } - + unsigned long pg, _e; + int i; + + for ( i = nr_bootmem_regions - 1; i >= 0; i-- ) + { + struct bootmem_region *r = &bootmem_region_list[i]; + pg = (r->e - nr_pfns) & ~(pfn_align - 1); + if ( pg < r->s ) + continue; + _e = r->e; + r->e = pg; + bootmem_region_add(pg + nr_pfns, _e); + return pg; + } + + BOOT_BUG_ON(1); return 0; } @@ -660,12 +618,7 @@ int offline_page(unsigned long mfn, int *status = 0; pg = mfn_to_page(mfn); -#if defined(__x86_64__) - /* Xen's txt mfn in x86_64 is reserved in e820 */ if ( is_xen_fixed_mfn(mfn) ) -#elif defined(__i386__) - if ( is_xen_heap_mfn(mfn) ) -#endif { *status = PG_OFFLINE_XENPAGE | PG_OFFLINE_FAILED | (DOMID_XEN << PG_OFFLINE_OWNER_SHIFT); @@ -673,14 +626,14 @@ int offline_page(unsigned long mfn, int } /* - * N.B. xen's txt in x86_64 is marked reserved and handled already - * Also kexec range is reserved + * N.B. xen's txt in x86_64 is marked reserved and handled already. + * Also kexec range is reserved. */ - if ( !page_is_ram_type(mfn, RAM_TYPE_CONVENTIONAL) ) - { + if ( !page_is_ram_type(mfn, RAM_TYPE_CONVENTIONAL) ) + { *status = PG_OFFLINE_FAILED | PG_OFFLINE_NOT_CONV_RAM; return -EINVAL; - } + } spin_lock(&heap_lock); @@ -703,7 +656,7 @@ int offline_page(unsigned long mfn, int /* Release the reference since it will not be allocated anymore */ put_page(pg); } - else if ( old_info & PGC_xen_heap) + else if ( old_info & PGC_xen_heap ) { *status = PG_OFFLINE_XENPAGE | PG_OFFLINE_PENDING | (DOMID_XEN << PG_OFFLINE_OWNER_SHIFT); @@ -880,31 +833,18 @@ static unsigned long avail_heap_pages( return free_pages; } -#define avail_for_domheap(mfn) !(allocated_in_map(mfn) || is_xen_heap_mfn(mfn)) void __init end_boot_allocator(void) { - unsigned long i, nr = 0; - int curr_free, next_free; + unsigned int i; /* 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++ ) - { - curr_free = next_free; - next_free = avail_for_domheap(i+1); - if ( next_free ) - map_alloc(i+1, 1); /* prevent merging in free_heap_pages() */ - if ( curr_free ) - ++nr; - else if ( nr ) - { - init_heap_pages(mfn_to_page(i - nr), nr); - nr = 0; - } - } - if ( nr ) - init_heap_pages(mfn_to_page(i - nr), nr); + for ( i = 0; i < nr_bootmem_regions; i++ ) + { + struct bootmem_region *r = &bootmem_region_list[i]; + if ( r->s < r->e ) + init_heap_pages(mfn_to_page(r->s), r->e - r->s); + } + init_heap_pages(virt_to_page(bootmem_region_list), 1); if ( !dma_bitsize && (num_online_nodes() > 1) ) { @@ -923,7 +863,6 @@ void __init end_boot_allocator(void) printk(" DMA width %u bits", dma_bitsize); printk("\n"); } -#undef avail_for_domheap /* * Scrub all unallocated pages in all heap zones. This function is more diff -r ef38784f9f85 -r d6c1d7992f43 xen/include/asm-x86/mm.h --- a/xen/include/asm-x86/mm.h Wed Jul 08 16:47:58 2009 +0100 +++ b/xen/include/asm-x86/mm.h Wed Jul 08 22:08:31 2009 +0100 @@ -219,14 +219,14 @@ struct page_info unsigned long _mfn = (mfn); \ (_mfn < paddr_to_pfn(xenheap_phys_end)); \ }) -#else -extern unsigned long allocator_bitmap_end; +#define is_xen_fixed_mfn(mfn) is_xen_heap_mfn(mfn) +#else #define is_xen_heap_page(page) ((page)->count_info & PGC_xen_heap) #define is_xen_heap_mfn(mfn) \ (__mfn_valid(mfn) && is_xen_heap_page(__mfn_to_page(mfn))) -#define is_xen_fixed_mfn(mfn) \ - ( (mfn << PAGE_SHIFT) >= __pa(&_start) && \ - (mfn << PAGE_SHIFT) <= allocator_bitmap_end ) +#define is_xen_fixed_mfn(mfn) \ + ((((mfn) << PAGE_SHIFT) >= __pa(&_start)) && \ + (((mfn) << PAGE_SHIFT) <= __pa(&_end))) #endif #if defined(__i386__) diff -r ef38784f9f85 -r d6c1d7992f43 xen/include/xen/mm.h --- a/xen/include/xen/mm.h Wed Jul 08 16:47:58 2009 +0100 +++ b/xen/include/xen/mm.h Wed Jul 08 22:08:31 2009 +0100 @@ -37,7 +37,6 @@ struct page_info; struct page_info; /* Boot-time allocator. Turns into generic allocator after bootstrap. */ -paddr_t init_boot_allocator(paddr_t bitmap_start); void init_boot_pages(paddr_t ps, paddr_t pe); unsigned long alloc_boot_pages( unsigned long nr_pfns, unsigned long pfn_align); @@ -307,9 +306,7 @@ int guest_remove_page(struct domain *d, #define RAM_TYPE_RESERVED 0x00000002 #define RAM_TYPE_UNUSABLE 0x00000004 #define RAM_TYPE_ACPI 0x00000008 -/* Returns TRUE if the whole page at @mfn is of the requested RAM type(s) above. */ +/* TRUE if the whole page at @mfn is of the requested RAM type(s) above. */ int page_is_ram_type(unsigned long mfn, unsigned long mem_type); -extern unsigned long *alloc_bitmap; /* for vmcoreinfo */ - #endif /* __XEN_MM_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |