diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c index c39aacbd60..9e1ea60094 100644 --- a/xen/arch/arm/bootfdt.c +++ b/xen/arch/arm/bootfdt.c @@ -313,6 +313,8 @@ static int __init process_chosen_node(const void *fdt, int node, MEMBANK_STATIC_HEAP); if ( rc ) return rc; + + bootinfo.static_heap = true; } printk("Checking for initrd in /chosen\n"); diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h index 94b7e74b4d..0651059537 100644 --- a/xen/arch/arm/include/asm/setup.h +++ b/xen/arch/arm/include/asm/setup.h @@ -97,6 +97,7 @@ struct bootinfo { #ifdef CONFIG_ACPI struct meminfo acpi; #endif + bool static_heap; }; struct map_range_data diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 6687572fca..61b4f258a0 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -556,6 +556,44 @@ static paddr_t __init consider_modules(paddr_t s, paddr_t e, } return e; } + +/* + * Find a contiguous region that fits in the static heap region with + * required size and alignment, and return the end address of the region + * if found otherwise 0. + */ +static paddr_t __init fit_xenheap_in_static_heap(uint32_t size, paddr_t align) +{ + unsigned int i; + paddr_t end = 0, aligned_start, aligned_end; + paddr_t bank_start, bank_size, bank_end; + + for ( i = 0 ; i < bootinfo.reserved_mem.nr_banks; i++ ) + { + if ( bootinfo.reserved_mem.bank[i].type != MEMBANK_STATIC_HEAP ) + continue; + + bank_start = bootinfo.reserved_mem.bank[i].start; + bank_size = bootinfo.reserved_mem.bank[i].size; + bank_end = bank_start + bank_size; + + if ( bank_size < size ) + continue; + + aligned_end = bank_end & ~(align - 1); + aligned_start = (aligned_end - size) & ~(align - 1); + + if ( aligned_start > bank_start ) + /* + * Allocate the xenheap as high as possible to keep low-memory + * available (assuming the admin supplied region below 4GB) + * for other use (e.g. domain memory allocation). + */ + end = max(end, aligned_end); + } + + return end; +} #endif /* @@ -661,22 +699,51 @@ static void __init init_staticmem_pages(void) } /* - * Populate the boot allocator. All the RAM but the following regions - * will be added: + * Populate the boot allocator. + * If a static heap was not provided by the admin, all the RAM but the + * following regions will be added: * - Modules (e.g., Xen, Kernel) * - Reserved regions * - Xenheap (arm32 only) + * If a static heap was provided by the admin, populate the boot + * allocator with the corresponding regions only, but with Xenheap excluded + * on arm32. */ static void __init populate_boot_allocator(void) { unsigned int i; const struct meminfo *banks = &bootinfo.mem; + paddr_t s, e; + + if ( bootinfo.static_heap ) + { + for ( i = 0 ; i < bootinfo.reserved_mem.nr_banks; i++ ) + { + if ( bootinfo.reserved_mem.bank[i].type != MEMBANK_STATIC_HEAP ) + continue; + + s = bootinfo.reserved_mem.bank[i].start; + e = s + bootinfo.reserved_mem.bank[i].size; +#ifdef CONFIG_ARM_32 + /* Avoid the xenheap, note that the xenheap cannot across a bank */ + if ( s <= mfn_to_maddr(directmap_mfn_start) && + e >= mfn_to_maddr(directmap_mfn_end) ) + { + init_boot_pages(s, mfn_to_maddr(directmap_mfn_start)); + init_boot_pages(mfn_to_maddr(directmap_mfn_end), e); + } + else +#endif + init_boot_pages(s, e); + } + + return; + } for ( i = 0; i < banks->nr_banks; i++ ) { const struct membank *bank = &banks->bank[i]; paddr_t bank_end = bank->start + bank->size; - paddr_t s, e; s = bank->start; while ( s < bank_end ) @@ -714,8 +781,8 @@ static void __init populate_boot_allocator(void) #ifdef CONFIG_ARM_32 static void __init setup_mm(void) { - paddr_t ram_start, ram_end, ram_size, e; - unsigned long ram_pages; + paddr_t ram_start, ram_end, ram_size, e, bank_start, bank_end, bank_size; + paddr_t static_heap_end = 0, static_heap_size = 0; unsigned long heap_pages, xenheap_pages, domheap_pages; unsigned int i; const uint32_t ctr = READ_CP32(CTR); @@ -735,30 +802,51 @@ static void __init setup_mm(void) for ( i = 1; i < bootinfo.mem.nr_banks; i++ ) { - paddr_t bank_start = bootinfo.mem.bank[i].start; - paddr_t bank_size = bootinfo.mem.bank[i].size; - paddr_t bank_end = bank_start + bank_size; + bank_start = bootinfo.mem.bank[i].start; + bank_size = bootinfo.mem.bank[i].size; + bank_end = bank_start + bank_size; ram_size = ram_size + bank_size; ram_start = min(ram_start,bank_start); ram_end = max(ram_end,bank_end); } - total_pages = ram_pages = ram_size >> PAGE_SHIFT; + total_pages = ram_size >> PAGE_SHIFT; + + if ( bootinfo.static_heap ) + { + for ( i = 0 ; i < bootinfo.reserved_mem.nr_banks; i++ ) + { + if ( bootinfo.reserved_mem.bank[i].type != MEMBANK_STATIC_HEAP ) + continue; + + bank_start = bootinfo.reserved_mem.bank[i].start; + bank_size = bootinfo.reserved_mem.bank[i].size; + bank_end = bank_start + bank_size; + + static_heap_size += bank_size; + static_heap_end = max(static_heap_end, bank_end); + } + + heap_pages = static_heap_size >> PAGE_SHIFT; + } + else + heap_pages = total_pages; /* * If the user has not requested otherwise via the command line * then locate the xenheap using these constraints: * + * - must be contiguous * - must be 32 MiB aligned * - must not include Xen itself or the boot modules - * - must be at most 1GB or 1/32 the total RAM in the system if less + * - must be at most 1GB or 1/32 the total RAM in the system (or static + heap if enabled) if less * - must be at least 32M * * We try to allocate the largest xenheap possible within these * constraints. */ - heap_pages = ram_pages; if ( opt_xenheap_megabytes ) xenheap_pages = opt_xenheap_megabytes << (20-PAGE_SHIFT); else @@ -770,7 +858,9 @@ static void __init setup_mm(void) do { - e = consider_modules(ram_start, ram_end, + e = bootinfo.static_heap ? + fit_xenheap_in_static_heap(pfn_to_paddr(xenheap_pages), MB(32)) : + consider_modules(ram_start, ram_end, pfn_to_paddr(xenheap_pages), 32<<20, 0); if ( e ) @@ -780,7 +870,7 @@ static void __init setup_mm(void) } while ( !opt_xenheap_megabytes && xenheap_pages > 32<<(20-PAGE_SHIFT) ); if ( ! e ) - panic("Not not enough space for xenheap\n"); + panic("Not enough space for xenheap\n"); domheap_pages = heap_pages - xenheap_pages; @@ -825,7 +915,7 @@ static void __init setup_mm(void) static void __init setup_mm(void) { const struct meminfo *banks = &bootinfo.mem; - paddr_t ram_start = ~0; + paddr_t ram_start = INVALID_PADDR; paddr_t ram_end = 0; paddr_t ram_size = 0; unsigned int i;