diff options
Diffstat (limited to 'arch/arm/mm/mmu.c')
| -rw-r--r-- | arch/arm/mm/mmu.c | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4f56617a2392..53cdbd39ec8e 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) |
| @@ -1160,7 +1195,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
| 1160 | /* | 1195 | /* |
| 1161 | * Allocate the vector page early. | 1196 | * Allocate the vector page early. |
| 1162 | */ | 1197 | */ |
| 1163 | vectors = early_alloc(PAGE_SIZE); | 1198 | vectors = early_alloc(PAGE_SIZE * 2); |
| 1164 | 1199 | ||
| 1165 | early_trap_init(vectors); | 1200 | early_trap_init(vectors); |
| 1166 | 1201 | ||
| @@ -1205,15 +1240,27 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
| 1205 | map.pfn = __phys_to_pfn(virt_to_phys(vectors)); | 1240 | map.pfn = __phys_to_pfn(virt_to_phys(vectors)); |
| 1206 | map.virtual = 0xffff0000; | 1241 | map.virtual = 0xffff0000; |
| 1207 | map.length = PAGE_SIZE; | 1242 | map.length = PAGE_SIZE; |
| 1243 | #ifdef CONFIG_KUSER_HELPERS | ||
| 1208 | map.type = MT_HIGH_VECTORS; | 1244 | map.type = MT_HIGH_VECTORS; |
| 1245 | #else | ||
| 1246 | map.type = MT_LOW_VECTORS; | ||
| 1247 | #endif | ||
| 1209 | create_mapping(&map); | 1248 | create_mapping(&map); |
| 1210 | 1249 | ||
| 1211 | if (!vectors_high()) { | 1250 | if (!vectors_high()) { |
| 1212 | map.virtual = 0; | 1251 | map.virtual = 0; |
| 1252 | map.length = PAGE_SIZE * 2; | ||
| 1213 | map.type = MT_LOW_VECTORS; | 1253 | map.type = MT_LOW_VECTORS; |
| 1214 | create_mapping(&map); | 1254 | create_mapping(&map); |
| 1215 | } | 1255 | } |
| 1216 | 1256 | ||
| 1257 | /* Now create a kernel read-only mapping */ | ||
| 1258 | map.pfn += 1; | ||
| 1259 | map.virtual = 0xffff0000 + PAGE_SIZE; | ||
| 1260 | map.length = PAGE_SIZE; | ||
| 1261 | map.type = MT_LOW_VECTORS; | ||
| 1262 | create_mapping(&map); | ||
| 1263 | |||
| 1217 | /* | 1264 | /* |
| 1218 | * Ask the machine support to map in the statically mapped devices. | 1265 | * Ask the machine support to map in the statically mapped devices. |
| 1219 | */ | 1266 | */ |
| @@ -1276,8 +1323,6 @@ void __init paging_init(struct machine_desc *mdesc) | |||
| 1276 | { | 1323 | { |
| 1277 | void *zero_page; | 1324 | void *zero_page; |
| 1278 | 1325 | ||
| 1279 | memblock_set_current_limit(arm_lowmem_limit); | ||
| 1280 | |||
| 1281 | build_mem_type_table(); | 1326 | build_mem_type_table(); |
| 1282 | prepare_page_table(); | 1327 | prepare_page_table(); |
| 1283 | map_lowmem(); | 1328 | map_lowmem(); |
