|
@@ -989,6 +989,7 @@ phys_addr_t arm_lowmem_limit __initdata = 0;
|
|
|
|
|
|
void __init sanity_check_meminfo(void)
|
|
|
{
|
|
|
+ phys_addr_t memblock_limit = 0;
|
|
|
int i, j, highmem = 0;
|
|
|
phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1;
|
|
|
|
|
@@ -1052,9 +1053,32 @@ void __init sanity_check_meminfo(void)
|
|
|
bank->size = size_limit;
|
|
|
}
|
|
|
#endif
|
|
|
- if (!bank->highmem && bank->start + bank->size > arm_lowmem_limit)
|
|
|
- arm_lowmem_limit = bank->start + bank->size;
|
|
|
+ if (!bank->highmem) {
|
|
|
+ phys_addr_t bank_end = bank->start + bank->size;
|
|
|
|
|
|
+ if (bank_end > arm_lowmem_limit)
|
|
|
+ arm_lowmem_limit = bank_end;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Find the first non-section-aligned page, and point
|
|
|
+ * memblock_limit at it. This relies on rounding the
|
|
|
+ * limit down to be section-aligned, which happens at
|
|
|
+ * the end of this function.
|
|
|
+ *
|
|
|
+ * With this algorithm, the start or end of almost any
|
|
|
+ * bank can be non-section-aligned. The only exception
|
|
|
+ * is that the start of the bank 0 must be section-
|
|
|
+ * aligned, since otherwise memory would need to be
|
|
|
+ * allocated when mapping the start of bank 0, which
|
|
|
+ * occurs before any free memory is mapped.
|
|
|
+ */
|
|
|
+ if (!memblock_limit) {
|
|
|
+ if (!IS_ALIGNED(bank->start, SECTION_SIZE))
|
|
|
+ memblock_limit = bank->start;
|
|
|
+ else if (!IS_ALIGNED(bank_end, SECTION_SIZE))
|
|
|
+ memblock_limit = bank_end;
|
|
|
+ }
|
|
|
+ }
|
|
|
j++;
|
|
|
}
|
|
|
#ifdef CONFIG_HIGHMEM
|
|
@@ -1079,7 +1103,18 @@ void __init sanity_check_meminfo(void)
|
|
|
#endif
|
|
|
meminfo.nr_banks = j;
|
|
|
high_memory = __va(arm_lowmem_limit - 1) + 1;
|
|
|
- memblock_set_current_limit(arm_lowmem_limit);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Round the memblock limit down to a section size. This
|
|
|
+ * helps to ensure that we will allocate memory from the
|
|
|
+ * last full section, which should be mapped.
|
|
|
+ */
|
|
|
+ if (memblock_limit)
|
|
|
+ memblock_limit = round_down(memblock_limit, SECTION_SIZE);
|
|
|
+ if (!memblock_limit)
|
|
|
+ memblock_limit = arm_lowmem_limit;
|
|
|
+
|
|
|
+ memblock_set_current_limit(memblock_limit);
|
|
|
}
|
|
|
|
|
|
static inline void prepare_page_table(void)
|
|
@@ -1276,8 +1311,6 @@ void __init paging_init(struct machine_desc *mdesc)
|
|
|
{
|
|
|
void *zero_page;
|
|
|
|
|
|
- memblock_set_current_limit(arm_lowmem_limit);
|
|
|
-
|
|
|
build_mem_type_table();
|
|
|
prepare_page_table();
|
|
|
map_lowmem();
|