aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/e820.c11
-rw-r--r--arch/x86/mm/discontig_32.c19
-rw-r--r--arch/x86/mm/init_32.c62
-rw-r--r--include/asm-x86/e820.h1
-rw-r--r--include/asm-x86/highmem.h3
-rw-r--r--include/linux/mm.h2
-rw-r--r--mm/page_alloc.c8
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
615int __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
626void __init early_res_to_bootmem(u64 start, u64 end) 615void __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
102extern unsigned long find_max_low_pfn(void); 102extern unsigned long find_max_low_pfn(void);
103extern void add_one_highpage_init(struct page *, int, int);
104extern unsigned long highend_pfn, highstart_pfn; 103extern 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
290void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro) 290static void __init
291add_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
302struct add_highpages_data {
303 unsigned long start_pfn;
304 unsigned long end_pfn;
305 int bad_ppro;
306};
307
308static 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
335void __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
303static void __init set_highmem_pages_init(int bad_ppro) 349static 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);
86extern void reserve_early(u64 start, u64 end, char *name); 86extern void reserve_early(u64 start, u64 end, char *name);
87extern void free_early(u64 start, u64 end); 87extern void free_early(u64 start, u64 end);
88extern void early_res_to_bootmem(u64 start, u64 end); 88extern void early_res_to_bootmem(u64 start, u64 end);
89extern int page_is_reserved_early(unsigned long pagenr);
90extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); 89extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
91 90
92extern unsigned long e820_end_of_ram(void); 91extern 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
77extern 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);
1011extern unsigned long find_max_pfn_with_active_regions(void); 1011extern unsigned long find_max_pfn_with_active_regions(void);
1012extern void free_bootmem_with_active_regions(int nid, 1012extern void free_bootmem_with_active_regions(int nid,
1013 unsigned long max_low_pfn); 1013 unsigned long max_low_pfn);
1014typedef void (*work_fn_t)(unsigned long, unsigned long, void *);
1015extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data);
1014extern void sparse_memory_present_with_active_regions(int nid); 1016extern 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
1016extern int early_pfn_to_nid(unsigned long pfn); 1018extern 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
2932void __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.