diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 71 |
1 files changed, 33 insertions, 38 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index db1ff4ac0cc6..c26d3152f9ba 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -5450,6 +5450,30 @@ void __ref build_all_zonelists(pg_data_t *pgdat) | |||
5450 | #endif | 5450 | #endif |
5451 | } | 5451 | } |
5452 | 5452 | ||
5453 | /* If zone is ZONE_MOVABLE but memory is mirrored, it is an overlapped init */ | ||
5454 | static bool __meminit | ||
5455 | overlap_memmap_init(unsigned long zone, unsigned long *pfn) | ||
5456 | { | ||
5457 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | ||
5458 | static struct memblock_region *r; | ||
5459 | |||
5460 | if (mirrored_kernelcore && zone == ZONE_MOVABLE) { | ||
5461 | if (!r || *pfn >= memblock_region_memory_end_pfn(r)) { | ||
5462 | for_each_memblock(memory, r) { | ||
5463 | if (*pfn < memblock_region_memory_end_pfn(r)) | ||
5464 | break; | ||
5465 | } | ||
5466 | } | ||
5467 | if (*pfn >= memblock_region_memory_base_pfn(r) && | ||
5468 | memblock_is_mirror(r)) { | ||
5469 | *pfn = memblock_region_memory_end_pfn(r); | ||
5470 | return true; | ||
5471 | } | ||
5472 | } | ||
5473 | #endif | ||
5474 | return false; | ||
5475 | } | ||
5476 | |||
5453 | /* | 5477 | /* |
5454 | * Initially all pages are reserved - free ones are freed | 5478 | * Initially all pages are reserved - free ones are freed |
5455 | * up by free_all_bootmem() once the early boot process is | 5479 | * up by free_all_bootmem() once the early boot process is |
@@ -5459,12 +5483,8 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
5459 | unsigned long start_pfn, enum memmap_context context, | 5483 | unsigned long start_pfn, enum memmap_context context, |
5460 | struct vmem_altmap *altmap) | 5484 | struct vmem_altmap *altmap) |
5461 | { | 5485 | { |
5462 | unsigned long end_pfn = start_pfn + size; | 5486 | unsigned long pfn, end_pfn = start_pfn + size; |
5463 | unsigned long pfn; | ||
5464 | struct page *page; | 5487 | struct page *page; |
5465 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | ||
5466 | struct memblock_region *r = NULL, *tmp; | ||
5467 | #endif | ||
5468 | 5488 | ||
5469 | if (highest_memmap_pfn < end_pfn - 1) | 5489 | if (highest_memmap_pfn < end_pfn - 1) |
5470 | highest_memmap_pfn = end_pfn - 1; | 5490 | highest_memmap_pfn = end_pfn - 1; |
@@ -5492,39 +5512,17 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
5492 | * There can be holes in boot-time mem_map[]s handed to this | 5512 | * There can be holes in boot-time mem_map[]s handed to this |
5493 | * function. They do not exist on hotplugged memory. | 5513 | * function. They do not exist on hotplugged memory. |
5494 | */ | 5514 | */ |
5495 | if (context != MEMMAP_EARLY) | 5515 | if (context == MEMMAP_EARLY) { |
5496 | goto not_early; | 5516 | if (!early_pfn_valid(pfn)) |
5497 | |||
5498 | if (!early_pfn_valid(pfn)) | ||
5499 | continue; | ||
5500 | if (!early_pfn_in_nid(pfn, nid)) | ||
5501 | continue; | ||
5502 | |||
5503 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | ||
5504 | /* | ||
5505 | * Check given memblock attribute by firmware which can affect | ||
5506 | * kernel memory layout. If zone==ZONE_MOVABLE but memory is | ||
5507 | * mirrored, it's an overlapped memmap init. skip it. | ||
5508 | */ | ||
5509 | if (mirrored_kernelcore && zone == ZONE_MOVABLE) { | ||
5510 | if (!r || pfn >= memblock_region_memory_end_pfn(r)) { | ||
5511 | for_each_memblock(memory, tmp) | ||
5512 | if (pfn < memblock_region_memory_end_pfn(tmp)) | ||
5513 | break; | ||
5514 | r = tmp; | ||
5515 | } | ||
5516 | if (pfn >= memblock_region_memory_base_pfn(r) && | ||
5517 | memblock_is_mirror(r)) { | ||
5518 | /* already initialized as NORMAL */ | ||
5519 | pfn = memblock_region_memory_end_pfn(r); | ||
5520 | continue; | 5517 | continue; |
5521 | } | 5518 | if (!early_pfn_in_nid(pfn, nid)) |
5519 | continue; | ||
5520 | if (overlap_memmap_init(zone, &pfn)) | ||
5521 | continue; | ||
5522 | if (defer_init(nid, pfn, end_pfn)) | ||
5523 | break; | ||
5522 | } | 5524 | } |
5523 | #endif | ||
5524 | if (defer_init(nid, pfn, end_pfn)) | ||
5525 | break; | ||
5526 | 5525 | ||
5527 | not_early: | ||
5528 | page = pfn_to_page(pfn); | 5526 | page = pfn_to_page(pfn); |
5529 | __init_single_page(page, pfn, zone, nid); | 5527 | __init_single_page(page, pfn, zone, nid); |
5530 | if (context == MEMMAP_HOTPLUG) | 5528 | if (context == MEMMAP_HOTPLUG) |
@@ -5541,9 +5539,6 @@ not_early: | |||
5541 | * can be created for invalid pages (for alignment) | 5539 | * can be created for invalid pages (for alignment) |
5542 | * check here not to call set_pageblock_migratetype() against | 5540 | * check here not to call set_pageblock_migratetype() against |
5543 | * pfn out of zone. | 5541 | * pfn out of zone. |
5544 | * | ||
5545 | * Please note that MEMMAP_HOTPLUG path doesn't clear memmap | ||
5546 | * because this is done early in sparse_add_one_section | ||
5547 | */ | 5542 | */ |
5548 | if (!(pfn & (pageblock_nr_pages - 1))) { | 5543 | if (!(pfn & (pageblock_nr_pages - 1))) { |
5549 | set_pageblock_migratetype(page, MIGRATE_MOVABLE); | 5544 | set_pageblock_migratetype(page, MIGRATE_MOVABLE); |