diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index aa1cc5fe9904..0f267d9c73ff 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -210,6 +210,7 @@ static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES]; | |||
210 | static unsigned long __initdata required_kernelcore; | 210 | static unsigned long __initdata required_kernelcore; |
211 | static unsigned long __initdata required_movablecore; | 211 | static unsigned long __initdata required_movablecore; |
212 | static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES]; | 212 | static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES]; |
213 | static unsigned long __meminitdata zone_movable_limit[MAX_NUMNODES]; | ||
213 | 214 | ||
214 | /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */ | 215 | /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */ |
215 | int movable_zone; | 216 | int movable_zone; |
@@ -4375,6 +4376,77 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid, | |||
4375 | return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn); | 4376 | return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn); |
4376 | } | 4377 | } |
4377 | 4378 | ||
4379 | /** | ||
4380 | * sanitize_zone_movable_limit - Sanitize the zone_movable_limit array. | ||
4381 | * | ||
4382 | * zone_movable_limit is initialized as 0. This function will try to get | ||
4383 | * the first ZONE_MOVABLE pfn of each node from movablemem_map, and | ||
4384 | * assigne them to zone_movable_limit. | ||
4385 | * zone_movable_limit[nid] == 0 means no limit for the node. | ||
4386 | * | ||
4387 | * Note: Each range is represented as [start_pfn, end_pfn) | ||
4388 | */ | ||
4389 | static void __meminit sanitize_zone_movable_limit(void) | ||
4390 | { | ||
4391 | int map_pos = 0, i, nid; | ||
4392 | unsigned long start_pfn, end_pfn; | ||
4393 | |||
4394 | if (!movablemem_map.nr_map) | ||
4395 | return; | ||
4396 | |||
4397 | /* Iterate all ranges from minimum to maximum */ | ||
4398 | for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) { | ||
4399 | /* | ||
4400 | * If we have found lowest pfn of ZONE_MOVABLE of the node | ||
4401 | * specified by user, just go on to check next range. | ||
4402 | */ | ||
4403 | if (zone_movable_limit[nid]) | ||
4404 | continue; | ||
4405 | |||
4406 | #ifdef CONFIG_ZONE_DMA | ||
4407 | /* Skip DMA memory. */ | ||
4408 | if (start_pfn < arch_zone_highest_possible_pfn[ZONE_DMA]) | ||
4409 | start_pfn = arch_zone_highest_possible_pfn[ZONE_DMA]; | ||
4410 | #endif | ||
4411 | |||
4412 | #ifdef CONFIG_ZONE_DMA32 | ||
4413 | /* Skip DMA32 memory. */ | ||
4414 | if (start_pfn < arch_zone_highest_possible_pfn[ZONE_DMA32]) | ||
4415 | start_pfn = arch_zone_highest_possible_pfn[ZONE_DMA32]; | ||
4416 | #endif | ||
4417 | |||
4418 | #ifdef CONFIG_HIGHMEM | ||
4419 | /* Skip lowmem if ZONE_MOVABLE is highmem. */ | ||
4420 | if (zone_movable_is_highmem() && | ||
4421 | start_pfn < arch_zone_lowest_possible_pfn[ZONE_HIGHMEM]) | ||
4422 | start_pfn = arch_zone_lowest_possible_pfn[ZONE_HIGHMEM]; | ||
4423 | #endif | ||
4424 | |||
4425 | if (start_pfn >= end_pfn) | ||
4426 | continue; | ||
4427 | |||
4428 | while (map_pos < movablemem_map.nr_map) { | ||
4429 | if (end_pfn <= movablemem_map.map[map_pos].start_pfn) | ||
4430 | break; | ||
4431 | |||
4432 | if (start_pfn >= movablemem_map.map[map_pos].end_pfn) { | ||
4433 | map_pos++; | ||
4434 | continue; | ||
4435 | } | ||
4436 | |||
4437 | /* | ||
4438 | * The start_pfn of ZONE_MOVABLE is either the minimum | ||
4439 | * pfn specified by movablemem_map, or 0, which means | ||
4440 | * the node has no ZONE_MOVABLE. | ||
4441 | */ | ||
4442 | zone_movable_limit[nid] = max(start_pfn, | ||
4443 | movablemem_map.map[map_pos].start_pfn); | ||
4444 | |||
4445 | break; | ||
4446 | } | ||
4447 | } | ||
4448 | } | ||
4449 | |||
4378 | #else /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ | 4450 | #else /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ |
4379 | static inline unsigned long __meminit zone_spanned_pages_in_node(int nid, | 4451 | static inline unsigned long __meminit zone_spanned_pages_in_node(int nid, |
4380 | unsigned long zone_type, | 4452 | unsigned long zone_type, |
@@ -4392,7 +4464,6 @@ static inline unsigned long __meminit zone_absent_pages_in_node(int nid, | |||
4392 | 4464 | ||
4393 | return zholes_size[zone_type]; | 4465 | return zholes_size[zone_type]; |
4394 | } | 4466 | } |
4395 | |||
4396 | #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ | 4467 | #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ |
4397 | 4468 | ||
4398 | static void __meminit calculate_node_totalpages(struct pglist_data *pgdat, | 4469 | static void __meminit calculate_node_totalpages(struct pglist_data *pgdat, |
@@ -4839,7 +4910,6 @@ static void __init find_zone_movable_pfns_for_nodes(void) | |||
4839 | goto out; | 4910 | goto out; |
4840 | 4911 | ||
4841 | /* usable_startpfn is the lowest possible pfn ZONE_MOVABLE can be at */ | 4912 | /* usable_startpfn is the lowest possible pfn ZONE_MOVABLE can be at */ |
4842 | find_usable_zone_for_movable(); | ||
4843 | usable_startpfn = arch_zone_lowest_possible_pfn[movable_zone]; | 4913 | usable_startpfn = arch_zone_lowest_possible_pfn[movable_zone]; |
4844 | 4914 | ||
4845 | restart: | 4915 | restart: |
@@ -4998,6 +5068,8 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn) | |||
4998 | 5068 | ||
4999 | /* Find the PFNs that ZONE_MOVABLE begins at in each node */ | 5069 | /* Find the PFNs that ZONE_MOVABLE begins at in each node */ |
5000 | memset(zone_movable_pfn, 0, sizeof(zone_movable_pfn)); | 5070 | memset(zone_movable_pfn, 0, sizeof(zone_movable_pfn)); |
5071 | find_usable_zone_for_movable(); | ||
5072 | sanitize_zone_movable_limit(); | ||
5001 | find_zone_movable_pfns_for_nodes(); | 5073 | find_zone_movable_pfns_for_nodes(); |
5002 | 5074 | ||
5003 | /* Print out the zone ranges */ | 5075 | /* Print out the zone ranges */ |