diff options
Diffstat (limited to 'arch/arm/mm/init.c')
| -rw-r--r-- | arch/arm/mm/init.c | 118 |
1 files changed, 73 insertions, 45 deletions
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 8277802ec859..3a7279c1ce5e 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
| @@ -120,6 +120,32 @@ void show_mem(void) | |||
| 120 | printk("%d pages swap cached\n", cached); | 120 | printk("%d pages swap cached\n", cached); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | static void __init find_node_limits(int node, struct meminfo *mi, | ||
| 124 | unsigned long *min, unsigned long *max_low, unsigned long *max_high) | ||
| 125 | { | ||
| 126 | int i; | ||
| 127 | |||
| 128 | *min = -1UL; | ||
| 129 | *max_low = *max_high = 0; | ||
| 130 | |||
| 131 | for_each_nodebank(i, mi, node) { | ||
| 132 | struct membank *bank = &mi->bank[i]; | ||
| 133 | unsigned long start, end; | ||
| 134 | |||
| 135 | start = bank_pfn_start(bank); | ||
| 136 | end = bank_pfn_end(bank); | ||
| 137 | |||
| 138 | if (*min > start) | ||
| 139 | *min = start; | ||
| 140 | if (*max_high < end) | ||
| 141 | *max_high = end; | ||
| 142 | if (bank->highmem) | ||
| 143 | continue; | ||
| 144 | if (*max_low < end) | ||
| 145 | *max_low = end; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 123 | /* | 149 | /* |
| 124 | * FIXME: We really want to avoid allocating the bootmap bitmap | 150 | * FIXME: We really want to avoid allocating the bootmap bitmap |
| 125 | * over the top of the initrd. Hopefully, this is located towards | 151 | * over the top of the initrd. Hopefully, this is located towards |
| @@ -210,41 +236,25 @@ static inline void map_memory_bank(struct membank *bank) | |||
| 210 | #endif | 236 | #endif |
| 211 | } | 237 | } |
| 212 | 238 | ||
| 213 | static unsigned long __init bootmem_init_node(int node, struct meminfo *mi) | 239 | static void __init bootmem_init_node(int node, struct meminfo *mi, |
| 240 | unsigned long start_pfn, unsigned long end_pfn) | ||
| 214 | { | 241 | { |
| 215 | unsigned long start_pfn, end_pfn, boot_pfn; | 242 | unsigned long boot_pfn; |
| 216 | unsigned int boot_pages; | 243 | unsigned int boot_pages; |
| 217 | pg_data_t *pgdat; | 244 | pg_data_t *pgdat; |
| 218 | int i; | 245 | int i; |
| 219 | 246 | ||
| 220 | start_pfn = -1UL; | ||
| 221 | end_pfn = 0; | ||
| 222 | |||
| 223 | /* | 247 | /* |
| 224 | * Calculate the pfn range, and map the memory banks for this node. | 248 | * Map the memory banks for this node. |
| 225 | */ | 249 | */ |
| 226 | for_each_nodebank(i, mi, node) { | 250 | for_each_nodebank(i, mi, node) { |
| 227 | struct membank *bank = &mi->bank[i]; | 251 | struct membank *bank = &mi->bank[i]; |
| 228 | unsigned long start, end; | ||
| 229 | 252 | ||
| 230 | start = bank_pfn_start(bank); | 253 | if (!bank->highmem) |
| 231 | end = bank_pfn_end(bank); | 254 | map_memory_bank(bank); |
| 232 | |||
| 233 | if (start_pfn > start) | ||
| 234 | start_pfn = start; | ||
| 235 | if (end_pfn < end) | ||
| 236 | end_pfn = end; | ||
| 237 | |||
| 238 | map_memory_bank(bank); | ||
| 239 | } | 255 | } |
| 240 | 256 | ||
| 241 | /* | 257 | /* |
| 242 | * If there is no memory in this node, ignore it. | ||
| 243 | */ | ||
| 244 | if (end_pfn == 0) | ||
| 245 | return end_pfn; | ||
| 246 | |||
| 247 | /* | ||
| 248 | * Allocate the bootmem bitmap page. | 258 | * Allocate the bootmem bitmap page. |
| 249 | */ | 259 | */ |
| 250 | boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); | 260 | boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); |
| @@ -260,7 +270,8 @@ static unsigned long __init bootmem_init_node(int node, struct meminfo *mi) | |||
| 260 | 270 | ||
| 261 | for_each_nodebank(i, mi, node) { | 271 | for_each_nodebank(i, mi, node) { |
| 262 | struct membank *bank = &mi->bank[i]; | 272 | struct membank *bank = &mi->bank[i]; |
| 263 | free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank)); | 273 | if (!bank->highmem) |
| 274 | free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank)); | ||
| 264 | memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank)); | 275 | memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank)); |
| 265 | } | 276 | } |
| 266 | 277 | ||
| @@ -269,8 +280,6 @@ static unsigned long __init bootmem_init_node(int node, struct meminfo *mi) | |||
| 269 | */ | 280 | */ |
| 270 | reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT, | 281 | reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT, |
| 271 | boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); | 282 | boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); |
| 272 | |||
| 273 | return end_pfn; | ||
| 274 | } | 283 | } |
| 275 | 284 | ||
| 276 | static void __init bootmem_reserve_initrd(int node) | 285 | static void __init bootmem_reserve_initrd(int node) |
| @@ -297,33 +306,39 @@ static void __init bootmem_reserve_initrd(int node) | |||
| 297 | static void __init bootmem_free_node(int node, struct meminfo *mi) | 306 | static void __init bootmem_free_node(int node, struct meminfo *mi) |
| 298 | { | 307 | { |
| 299 | unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; | 308 | unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; |
| 300 | unsigned long start_pfn, end_pfn; | 309 | unsigned long min, max_low, max_high; |
| 301 | pg_data_t *pgdat = NODE_DATA(node); | ||
| 302 | int i; | 310 | int i; |
| 303 | 311 | ||
| 304 | start_pfn = pgdat->bdata->node_min_pfn; | 312 | find_node_limits(node, mi, &min, &max_low, &max_high); |
| 305 | end_pfn = pgdat->bdata->node_low_pfn; | ||
| 306 | 313 | ||
| 307 | /* | 314 | /* |
| 308 | * initialise the zones within this node. | 315 | * initialise the zones within this node. |
| 309 | */ | 316 | */ |
| 310 | memset(zone_size, 0, sizeof(zone_size)); | 317 | memset(zone_size, 0, sizeof(zone_size)); |
| 311 | memset(zhole_size, 0, sizeof(zhole_size)); | ||
| 312 | 318 | ||
| 313 | /* | 319 | /* |
| 314 | * The size of this node has already been determined. If we need | 320 | * The size of this node has already been determined. If we need |
| 315 | * to do anything fancy with the allocation of this memory to the | 321 | * to do anything fancy with the allocation of this memory to the |
| 316 | * zones, now is the time to do it. | 322 | * zones, now is the time to do it. |
| 317 | */ | 323 | */ |
| 318 | zone_size[0] = end_pfn - start_pfn; | 324 | zone_size[0] = max_low - min; |
| 325 | #ifdef CONFIG_HIGHMEM | ||
| 326 | zone_size[ZONE_HIGHMEM] = max_high - max_low; | ||
| 327 | #endif | ||
| 319 | 328 | ||
| 320 | /* | 329 | /* |
| 321 | * For each bank in this node, calculate the size of the holes. | 330 | * For each bank in this node, calculate the size of the holes. |
| 322 | * holes = node_size - sum(bank_sizes_in_node) | 331 | * holes = node_size - sum(bank_sizes_in_node) |
| 323 | */ | 332 | */ |
| 324 | zhole_size[0] = zone_size[0]; | 333 | memcpy(zhole_size, zone_size, sizeof(zhole_size)); |
| 325 | for_each_nodebank(i, mi, node) | 334 | for_each_nodebank(i, mi, node) { |
| 326 | zhole_size[0] -= bank_pfn_size(&mi->bank[i]); | 335 | int idx = 0; |
| 336 | #ifdef CONFIG_HIGHMEM | ||
| 337 | if (mi->bank[i].highmem) | ||
| 338 | idx = ZONE_HIGHMEM; | ||
| 339 | #endif | ||
| 340 | zhole_size[idx] -= bank_pfn_size(&mi->bank[i]); | ||
| 341 | } | ||
| 327 | 342 | ||
| 328 | /* | 343 | /* |
| 329 | * Adjust the sizes according to any special requirements for | 344 | * Adjust the sizes according to any special requirements for |
| @@ -331,13 +346,13 @@ static void __init bootmem_free_node(int node, struct meminfo *mi) | |||
| 331 | */ | 346 | */ |
| 332 | arch_adjust_zones(node, zone_size, zhole_size); | 347 | arch_adjust_zones(node, zone_size, zhole_size); |
| 333 | 348 | ||
| 334 | free_area_init_node(node, zone_size, start_pfn, zhole_size); | 349 | free_area_init_node(node, zone_size, min, zhole_size); |
| 335 | } | 350 | } |
| 336 | 351 | ||
| 337 | void __init bootmem_init(void) | 352 | void __init bootmem_init(void) |
| 338 | { | 353 | { |
| 339 | struct meminfo *mi = &meminfo; | 354 | struct meminfo *mi = &meminfo; |
| 340 | unsigned long memend_pfn = 0; | 355 | unsigned long min, max_low, max_high; |
| 341 | int node, initrd_node; | 356 | int node, initrd_node; |
| 342 | 357 | ||
| 343 | /* | 358 | /* |
| @@ -345,11 +360,29 @@ void __init bootmem_init(void) | |||
| 345 | */ | 360 | */ |
| 346 | initrd_node = check_initrd(mi); | 361 | initrd_node = check_initrd(mi); |
| 347 | 362 | ||
| 363 | max_low = max_high = 0; | ||
| 364 | |||
| 348 | /* | 365 | /* |
| 349 | * Run through each node initialising the bootmem allocator. | 366 | * Run through each node initialising the bootmem allocator. |
| 350 | */ | 367 | */ |
| 351 | for_each_node(node) { | 368 | for_each_node(node) { |
| 352 | unsigned long end_pfn = bootmem_init_node(node, mi); | 369 | unsigned long node_low, node_high; |
| 370 | |||
| 371 | find_node_limits(node, mi, &min, &node_low, &node_high); | ||
| 372 | |||
| 373 | if (node_low > max_low) | ||
| 374 | max_low = node_low; | ||
| 375 | if (node_high > max_high) | ||
| 376 | max_high = node_high; | ||
| 377 | |||
| 378 | /* | ||
| 379 | * If there is no memory in this node, ignore it. | ||
| 380 | * (We can't have nodes which have no lowmem) | ||
| 381 | */ | ||
| 382 | if (node_low == 0) | ||
| 383 | continue; | ||
| 384 | |||
| 385 | bootmem_init_node(node, mi, min, node_low); | ||
| 353 | 386 | ||
| 354 | /* | 387 | /* |
| 355 | * Reserve any special node zero regions. | 388 | * Reserve any special node zero regions. |
| @@ -362,12 +395,6 @@ void __init bootmem_init(void) | |||
| 362 | */ | 395 | */ |
| 363 | if (node == initrd_node) | 396 | if (node == initrd_node) |
| 364 | bootmem_reserve_initrd(node); | 397 | bootmem_reserve_initrd(node); |
| 365 | |||
| 366 | /* | ||
| 367 | * Remember the highest memory PFN. | ||
| 368 | */ | ||
| 369 | if (end_pfn > memend_pfn) | ||
| 370 | memend_pfn = end_pfn; | ||
| 371 | } | 398 | } |
| 372 | 399 | ||
| 373 | /* | 400 | /* |
| @@ -383,7 +410,7 @@ void __init bootmem_init(void) | |||
| 383 | for_each_node(node) | 410 | for_each_node(node) |
| 384 | bootmem_free_node(node, mi); | 411 | bootmem_free_node(node, mi); |
| 385 | 412 | ||
| 386 | high_memory = __va((memend_pfn << PAGE_SHIFT) - 1) + 1; | 413 | high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1; |
| 387 | 414 | ||
| 388 | /* | 415 | /* |
| 389 | * This doesn't seem to be used by the Linux memory manager any | 416 | * This doesn't seem to be used by the Linux memory manager any |
| @@ -393,7 +420,8 @@ void __init bootmem_init(void) | |||
| 393 | * Note: max_low_pfn and max_pfn reflect the number of _pages_ in | 420 | * Note: max_low_pfn and max_pfn reflect the number of _pages_ in |
| 394 | * the system, not the maximum PFN. | 421 | * the system, not the maximum PFN. |
| 395 | */ | 422 | */ |
| 396 | max_pfn = max_low_pfn = memend_pfn - PHYS_PFN_OFFSET; | 423 | max_low_pfn = max_low - PHYS_PFN_OFFSET; |
| 424 | max_pfn = max_high - PHYS_PFN_OFFSET; | ||
| 397 | } | 425 | } |
| 398 | 426 | ||
| 399 | static inline int free_area(unsigned long pfn, unsigned long end, char *s) | 427 | static inline int free_area(unsigned long pfn, unsigned long end, char *s) |
