diff options
-rw-r--r-- | arch/x86/kernel/e820.c | 11 | ||||
-rw-r--r-- | arch/x86/mm/discontig_32.c | 19 | ||||
-rw-r--r-- | arch/x86/mm/init_32.c | 62 | ||||
-rw-r--r-- | include/asm-x86/e820.h | 1 | ||||
-rw-r--r-- | include/asm-x86/highmem.h | 3 | ||||
-rw-r--r-- | include/linux/mm.h | 2 | ||||
-rw-r--r-- | mm/page_alloc.c | 8 |
7 files changed, 71 insertions, 35 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 5051ce744b4e..ed46b7a6bc13 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
@@ -612,17 +612,6 @@ void __init free_early(u64 start, u64 end) | |||
612 | early_res[j - 1].end = 0; | 612 | early_res[j - 1].end = 0; |
613 | } | 613 | } |
614 | 614 | ||
615 | int __init page_is_reserved_early(unsigned long pagenr) | ||
616 | { | ||
617 | u64 start = (u64)pagenr << PAGE_SHIFT; | ||
618 | int i; | ||
619 | struct early_res *r; | ||
620 | |||
621 | i = find_overlapped_early(start, start + PAGE_SIZE); | ||
622 | r = &early_res[i]; | ||
623 | return (i < MAX_EARLY_RES && r->end); | ||
624 | } | ||
625 | |||
626 | void __init early_res_to_bootmem(u64 start, u64 end) | 615 | void __init early_res_to_bootmem(u64 start, u64 end) |
627 | { | 616 | { |
628 | int i; | 617 | int i; |
diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c index c3f119e99e0d..7c4d0255f8d8 100644 --- a/arch/x86/mm/discontig_32.c +++ b/arch/x86/mm/discontig_32.c | |||
@@ -100,7 +100,6 @@ unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn, | |||
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | extern unsigned long find_max_low_pfn(void); | 102 | extern unsigned long find_max_low_pfn(void); |
103 | extern void add_one_highpage_init(struct page *, int, int); | ||
104 | extern unsigned long highend_pfn, highstart_pfn; | 103 | extern unsigned long highend_pfn, highstart_pfn; |
105 | 104 | ||
106 | #define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE) | 105 | #define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE) |
@@ -432,10 +431,10 @@ void __init set_highmem_pages_init(int bad_ppro) | |||
432 | { | 431 | { |
433 | #ifdef CONFIG_HIGHMEM | 432 | #ifdef CONFIG_HIGHMEM |
434 | struct zone *zone; | 433 | struct zone *zone; |
435 | struct page *page; | 434 | int nid; |
436 | 435 | ||
437 | for_each_zone(zone) { | 436 | for_each_zone(zone) { |
438 | unsigned long node_pfn, zone_start_pfn, zone_end_pfn; | 437 | unsigned long zone_start_pfn, zone_end_pfn; |
439 | 438 | ||
440 | if (!is_highmem(zone)) | 439 | if (!is_highmem(zone)) |
441 | continue; | 440 | continue; |
@@ -443,16 +442,12 @@ void __init set_highmem_pages_init(int bad_ppro) | |||
443 | zone_start_pfn = zone->zone_start_pfn; | 442 | zone_start_pfn = zone->zone_start_pfn; |
444 | zone_end_pfn = zone_start_pfn + zone->spanned_pages; | 443 | zone_end_pfn = zone_start_pfn + zone->spanned_pages; |
445 | 444 | ||
445 | nid = zone_to_nid(zone); | ||
446 | printk("Initializing %s for node %d (%08lx:%08lx)\n", | 446 | printk("Initializing %s for node %d (%08lx:%08lx)\n", |
447 | zone->name, zone_to_nid(zone), | 447 | zone->name, nid, zone_start_pfn, zone_end_pfn); |
448 | zone_start_pfn, zone_end_pfn); | 448 | |
449 | 449 | add_highpages_with_active_regions(nid, zone_start_pfn, | |
450 | for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++) { | 450 | zone_end_pfn, bad_ppro); |
451 | if (!pfn_valid(node_pfn)) | ||
452 | continue; | ||
453 | page = pfn_to_page(node_pfn); | ||
454 | add_one_highpage_init(page, node_pfn, bad_ppro); | ||
455 | } | ||
456 | } | 451 | } |
457 | totalram_pages += totalhigh_pages; | 452 | totalram_pages += totalhigh_pages; |
458 | #endif | 453 | #endif |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index abadb1da70df..ba07a489230e 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -287,10 +287,10 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) | |||
287 | pkmap_page_table = pte; | 287 | pkmap_page_table = pte; |
288 | } | 288 | } |
289 | 289 | ||
290 | void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro) | 290 | static void __init |
291 | add_one_highpage_init(struct page *page, int pfn, int bad_ppro) | ||
291 | { | 292 | { |
292 | if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn)) && | 293 | if (!(bad_ppro && page_kills_ppro(pfn))) { |
293 | !page_is_reserved_early(pfn)) { | ||
294 | ClearPageReserved(page); | 294 | ClearPageReserved(page); |
295 | init_page_count(page); | 295 | init_page_count(page); |
296 | __free_page(page); | 296 | __free_page(page); |
@@ -299,18 +299,58 @@ void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro) | |||
299 | SetPageReserved(page); | 299 | SetPageReserved(page); |
300 | } | 300 | } |
301 | 301 | ||
302 | struct add_highpages_data { | ||
303 | unsigned long start_pfn; | ||
304 | unsigned long end_pfn; | ||
305 | int bad_ppro; | ||
306 | }; | ||
307 | |||
308 | static void __init add_highpages_work_fn(unsigned long start_pfn, | ||
309 | unsigned long end_pfn, void *datax) | ||
310 | { | ||
311 | int node_pfn; | ||
312 | struct page *page; | ||
313 | unsigned long final_start_pfn, final_end_pfn; | ||
314 | struct add_highpages_data *data; | ||
315 | int bad_ppro; | ||
316 | |||
317 | data = (struct add_highpages_data *)datax; | ||
318 | bad_ppro = data->bad_ppro; | ||
319 | |||
320 | final_start_pfn = max(start_pfn, data->start_pfn); | ||
321 | final_end_pfn = min(end_pfn, data->end_pfn); | ||
322 | if (final_start_pfn >= final_end_pfn) | ||
323 | return; | ||
324 | |||
325 | for (node_pfn = final_start_pfn; node_pfn < final_end_pfn; | ||
326 | node_pfn++) { | ||
327 | if (!pfn_valid(node_pfn)) | ||
328 | continue; | ||
329 | page = pfn_to_page(node_pfn); | ||
330 | add_one_highpage_init(page, node_pfn, bad_ppro); | ||
331 | } | ||
332 | |||
333 | } | ||
334 | |||
335 | void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn, | ||
336 | unsigned long end_pfn, | ||
337 | int bad_ppro) | ||
338 | { | ||
339 | struct add_highpages_data data; | ||
340 | |||
341 | data.start_pfn = start_pfn; | ||
342 | data.end_pfn = end_pfn; | ||
343 | data.bad_ppro = bad_ppro; | ||
344 | |||
345 | work_with_active_regions(nid, add_highpages_work_fn, &data); | ||
346 | } | ||
347 | |||
302 | #ifndef CONFIG_NUMA | 348 | #ifndef CONFIG_NUMA |
303 | static void __init set_highmem_pages_init(int bad_ppro) | 349 | static void __init set_highmem_pages_init(int bad_ppro) |
304 | { | 350 | { |
305 | int pfn; | 351 | add_highpages_with_active_regions(0, highstart_pfn, highend_pfn, |
352 | bad_ppro); | ||
306 | 353 | ||
307 | for (pfn = highstart_pfn; pfn < highend_pfn; pfn++) { | ||
308 | /* | ||
309 | * Holes under sparsemem might not have no mem_map[]: | ||
310 | */ | ||
311 | if (pfn_valid(pfn)) | ||
312 | add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro); | ||
313 | } | ||
314 | totalram_pages += totalhigh_pages; | 354 | totalram_pages += totalhigh_pages; |
315 | } | 355 | } |
316 | #endif /* !CONFIG_NUMA */ | 356 | #endif /* !CONFIG_NUMA */ |
diff --git a/include/asm-x86/e820.h b/include/asm-x86/e820.h index 6b0ce745a60c..55d310596907 100644 --- a/include/asm-x86/e820.h +++ b/include/asm-x86/e820.h | |||
@@ -86,7 +86,6 @@ extern u64 find_e820_area_size(u64 start, u64 *sizep, u64 align); | |||
86 | extern void reserve_early(u64 start, u64 end, char *name); | 86 | extern void reserve_early(u64 start, u64 end, char *name); |
87 | extern void free_early(u64 start, u64 end); | 87 | extern void free_early(u64 start, u64 end); |
88 | extern void early_res_to_bootmem(u64 start, u64 end); | 88 | extern void early_res_to_bootmem(u64 start, u64 end); |
89 | extern int page_is_reserved_early(unsigned long pagenr); | ||
90 | extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); | 89 | extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); |
91 | 90 | ||
92 | extern unsigned long e820_end_of_ram(void); | 91 | extern unsigned long e820_end_of_ram(void); |
diff --git a/include/asm-x86/highmem.h b/include/asm-x86/highmem.h index e153f3b44774..85c4fea41ff6 100644 --- a/include/asm-x86/highmem.h +++ b/include/asm-x86/highmem.h | |||
@@ -74,6 +74,9 @@ struct page *kmap_atomic_to_page(void *ptr); | |||
74 | 74 | ||
75 | #define flush_cache_kmaps() do { } while (0) | 75 | #define flush_cache_kmaps() do { } while (0) |
76 | 76 | ||
77 | extern void add_highpages_with_active_regions(int nid, unsigned long start_pfn, | ||
78 | unsigned long end_pfn, int bad_ppro); | ||
79 | |||
77 | #endif /* __KERNEL__ */ | 80 | #endif /* __KERNEL__ */ |
78 | 81 | ||
79 | #endif /* _ASM_HIGHMEM_H */ | 82 | #endif /* _ASM_HIGHMEM_H */ |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 034a3156d2f0..e4de460907c1 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1011,6 +1011,8 @@ extern unsigned long find_min_pfn_with_active_regions(void); | |||
1011 | extern unsigned long find_max_pfn_with_active_regions(void); | 1011 | extern unsigned long find_max_pfn_with_active_regions(void); |
1012 | extern void free_bootmem_with_active_regions(int nid, | 1012 | extern void free_bootmem_with_active_regions(int nid, |
1013 | unsigned long max_low_pfn); | 1013 | unsigned long max_low_pfn); |
1014 | typedef void (*work_fn_t)(unsigned long, unsigned long, void *); | ||
1015 | extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data); | ||
1014 | extern void sparse_memory_present_with_active_regions(int nid); | 1016 | extern void sparse_memory_present_with_active_regions(int nid); |
1015 | #ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID | 1017 | #ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID |
1016 | extern int early_pfn_to_nid(unsigned long pfn); | 1018 | extern int early_pfn_to_nid(unsigned long pfn); |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d80e1868e570..41c6e3aa059f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -2929,6 +2929,14 @@ void __init free_bootmem_with_active_regions(int nid, | |||
2929 | } | 2929 | } |
2930 | } | 2930 | } |
2931 | 2931 | ||
2932 | void __init work_with_active_regions(int nid, work_fn_t work_fn, void *data) | ||
2933 | { | ||
2934 | int i; | ||
2935 | |||
2936 | for_each_active_range_index_in_nid(i, nid) | ||
2937 | work_fn(early_node_map[i].start_pfn, early_node_map[i].end_pfn, | ||
2938 | data); | ||
2939 | } | ||
2932 | /** | 2940 | /** |
2933 | * sparse_memory_present_with_active_regions - Call memory_present for each active range | 2941 | * sparse_memory_present_with_active_regions - Call memory_present for each active range |
2934 | * @nid: The node to call memory_present for. If MAX_NUMNODES, all nodes will be used. | 2942 | * @nid: The node to call memory_present for. If MAX_NUMNODES, all nodes will be used. |