@@ -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");
@@ -97,6 +97,7 @@ struct bootinfo {
#ifdef CONFIG_ACPI
struct meminfo acpi;
#endif
+ bool static_heap;
};
struct map_range_data
@@ -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;