Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] powerpc: Fix sparsemem with memory holes [was Re: ppc64 oops..]

This patch should fix the crashes we have been seeing on 64-bit
powerpc systems with a memory hole when sparsemem is enabled.
I'd appreciate it if people who know more about NUMA and sparsemem
than me could look over it.

There were two bugs. The first was that if NUMA was enabled but there
was no NUMA information for the machine, the setup_nonnuma() function
was adding a single region, assuming memory was contiguous. The
second was that the loops in mem_init() and show_mem() assumed that
all pages within the span of a pgdat were valid (had a valid struct
page).

I also fixed the incorrect setting of num_physpages that Mike Kravetz
pointed out.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Paul Mackerras and committed by
Linus Torvalds
fb6d73d3 1e185b97

+10 -3
+6 -2
arch/powerpc/mm/mem.c
··· 200 200 unsigned long flags; 201 201 pgdat_resize_lock(pgdat, &flags); 202 202 for (i = 0; i < pgdat->node_spanned_pages; i++) { 203 + if (!pfn_valid(pgdat->node_start_pfn + i)) 204 + continue; 203 205 page = pgdat_page_nr(pgdat, i); 204 206 total++; 205 207 if (PageHighMem(page)) ··· 338 336 struct page *page; 339 337 unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize; 340 338 341 - num_physpages = max_pfn; /* RAM is assumed contiguous */ 339 + num_physpages = lmb.memory.size >> PAGE_SHIFT; 342 340 high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); 343 341 344 342 #ifdef CONFIG_NEED_MULTIPLE_NODES ··· 350 348 } 351 349 } 352 350 #else 353 - max_mapnr = num_physpages; 351 + max_mapnr = max_pfn; 354 352 totalram_pages += free_all_bootmem(); 355 353 #endif 356 354 for_each_pgdat(pgdat) { 357 355 for (i = 0; i < pgdat->node_spanned_pages; i++) { 356 + if (!pfn_valid(pgdat->node_start_pfn + i)) 357 + continue; 358 358 page = pgdat_page_nr(pgdat, i); 359 359 if (PageReserved(page)) 360 360 reservedpages++;
+4 -1
arch/powerpc/mm/numa.c
··· 483 483 { 484 484 unsigned long top_of_ram = lmb_end_of_DRAM(); 485 485 unsigned long total_ram = lmb_phys_mem_size(); 486 + unsigned int i; 486 487 487 488 printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", 488 489 top_of_ram, total_ram); ··· 491 490 (top_of_ram - total_ram) >> 20); 492 491 493 492 map_cpu_to_node(boot_cpuid, 0); 494 - add_region(0, 0, lmb_end_of_DRAM() >> PAGE_SHIFT); 493 + for (i = 0; i < lmb.memory.cnt; ++i) 494 + add_region(0, lmb.memory.region[i].base >> PAGE_SHIFT, 495 + lmb_size_pages(&lmb.memory, i)); 495 496 node_set_online(0); 496 497 } 497 498