diff options
| -rw-r--r-- | arch/arm/mm/mmu.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4f56617a2392..b3fdb63783e3 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
| @@ -989,6 +989,7 @@ phys_addr_t arm_lowmem_limit __initdata = 0; | |||
| 989 | 989 | ||
| 990 | void __init sanity_check_meminfo(void) | 990 | void __init sanity_check_meminfo(void) |
| 991 | { | 991 | { |
| 992 | phys_addr_t memblock_limit = 0; | ||
| 992 | int i, j, highmem = 0; | 993 | int i, j, highmem = 0; |
| 993 | phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1; | 994 | phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1; |
| 994 | 995 | ||
| @@ -1052,9 +1053,32 @@ void __init sanity_check_meminfo(void) | |||
| 1052 | bank->size = size_limit; | 1053 | bank->size = size_limit; |
| 1053 | } | 1054 | } |
| 1054 | #endif | 1055 | #endif |
| 1055 | if (!bank->highmem && bank->start + bank->size > arm_lowmem_limit) | 1056 | if (!bank->highmem) { |
| 1056 | arm_lowmem_limit = bank->start + bank->size; | 1057 | phys_addr_t bank_end = bank->start + bank->size; |
| 1057 | 1058 | ||
| 1059 | if (bank_end > arm_lowmem_limit) | ||
| 1060 | arm_lowmem_limit = bank_end; | ||
| 1061 | |||
| 1062 | /* | ||
| 1063 | * Find the first non-section-aligned page, and point | ||
| 1064 | * memblock_limit at it. This relies on rounding the | ||
| 1065 | * limit down to be section-aligned, which happens at | ||
| 1066 | * the end of this function. | ||
| 1067 | * | ||
| 1068 | * With this algorithm, the start or end of almost any | ||
| 1069 | * bank can be non-section-aligned. The only exception | ||
| 1070 | * is that the start of the bank 0 must be section- | ||
| 1071 | * aligned, since otherwise memory would need to be | ||
| 1072 | * allocated when mapping the start of bank 0, which | ||
| 1073 | * occurs before any free memory is mapped. | ||
| 1074 | */ | ||
| 1075 | if (!memblock_limit) { | ||
| 1076 | if (!IS_ALIGNED(bank->start, SECTION_SIZE)) | ||
| 1077 | memblock_limit = bank->start; | ||
| 1078 | else if (!IS_ALIGNED(bank_end, SECTION_SIZE)) | ||
| 1079 | memblock_limit = bank_end; | ||
| 1080 | } | ||
| 1081 | } | ||
| 1058 | j++; | 1082 | j++; |
| 1059 | } | 1083 | } |
| 1060 | #ifdef CONFIG_HIGHMEM | 1084 | #ifdef CONFIG_HIGHMEM |
| @@ -1079,7 +1103,18 @@ void __init sanity_check_meminfo(void) | |||
| 1079 | #endif | 1103 | #endif |
| 1080 | meminfo.nr_banks = j; | 1104 | meminfo.nr_banks = j; |
| 1081 | high_memory = __va(arm_lowmem_limit - 1) + 1; | 1105 | high_memory = __va(arm_lowmem_limit - 1) + 1; |
| 1082 | memblock_set_current_limit(arm_lowmem_limit); | 1106 | |
| 1107 | /* | ||
| 1108 | * Round the memblock limit down to a section size. This | ||
| 1109 | * helps to ensure that we will allocate memory from the | ||
| 1110 | * last full section, which should be mapped. | ||
| 1111 | */ | ||
| 1112 | if (memblock_limit) | ||
| 1113 | memblock_limit = round_down(memblock_limit, SECTION_SIZE); | ||
| 1114 | if (!memblock_limit) | ||
| 1115 | memblock_limit = arm_lowmem_limit; | ||
| 1116 | |||
| 1117 | memblock_set_current_limit(memblock_limit); | ||
| 1083 | } | 1118 | } |
| 1084 | 1119 | ||
| 1085 | static inline void prepare_page_table(void) | 1120 | static inline void prepare_page_table(void) |
| @@ -1276,8 +1311,6 @@ void __init paging_init(struct machine_desc *mdesc) | |||
| 1276 | { | 1311 | { |
| 1277 | void *zero_page; | 1312 | void *zero_page; |
| 1278 | 1313 | ||
| 1279 | memblock_set_current_limit(arm_lowmem_limit); | ||
| 1280 | |||
| 1281 | build_mem_type_table(); | 1314 | build_mem_type_table(); |
| 1282 | prepare_page_table(); | 1315 | prepare_page_table(); |
| 1283 | map_lowmem(); | 1316 | map_lowmem(); |
