Commit a2f3aa02576632cdb60bd3de1f4bf55e9ac65604
Committed by
Linus Torvalds
1 parent
47a4d5be7c
Exists in
master
and in
20 other branches
[PATCH] Fix sparsemem on Cell
Fix an oops experienced on the Cell architecture when init-time functions, early_*(), are called at runtime. It alters the call paths to make sure that the callers explicitly say whether the call is being made on behalf of a hotplug even, or happening at boot-time. It has been compile tested on ppc64, ia64, s390, i386 and x86_64. Acked-by: Arnd Bergmann <arndb@de.ibm.com> Signed-off-by: Dave Hansen <haveblue@us.ibm.com> Cc: Yasunori Goto <y-goto@jp.fujitsu.com> Acked-by: Andy Whitcroft <apw@shadowen.org> Cc: Christoph Lameter <clameter@engr.sgi.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 6 changed files with 34 additions and 16 deletions Side-by-side Diff
arch/ia64/mm/init.c
... | ... | @@ -543,7 +543,8 @@ |
543 | 543 | |
544 | 544 | if (map_start < map_end) |
545 | 545 | memmap_init_zone((unsigned long)(map_end - map_start), |
546 | - args->nid, args->zone, page_to_pfn(map_start)); | |
546 | + args->nid, args->zone, page_to_pfn(map_start), | |
547 | + MEMMAP_EARLY); | |
547 | 548 | return 0; |
548 | 549 | } |
549 | 550 | |
... | ... | @@ -552,7 +553,7 @@ |
552 | 553 | unsigned long start_pfn) |
553 | 554 | { |
554 | 555 | if (!vmem_map) |
555 | - memmap_init_zone(size, nid, zone, start_pfn); | |
556 | + memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY); | |
556 | 557 | else { |
557 | 558 | struct page *start; |
558 | 559 | struct memmap_init_callback_data args; |
arch/s390/mm/vmem.c
include/linux/mm.h
... | ... | @@ -978,7 +978,8 @@ |
978 | 978 | #endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */ |
979 | 979 | #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */ |
980 | 980 | extern void set_dma_reserve(unsigned long new_dma_reserve); |
981 | -extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long); | |
981 | +extern void memmap_init_zone(unsigned long, int, unsigned long, | |
982 | + unsigned long, enum memmap_context); | |
982 | 983 | extern void setup_per_zone_pages_min(void); |
983 | 984 | extern void mem_init(void); |
984 | 985 | extern void show_mem(void); |
include/linux/mmzone.h
... | ... | @@ -450,9 +450,13 @@ |
450 | 450 | void wakeup_kswapd(struct zone *zone, int order); |
451 | 451 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, |
452 | 452 | int classzone_idx, int alloc_flags); |
453 | - | |
453 | +enum memmap_context { | |
454 | + MEMMAP_EARLY, | |
455 | + MEMMAP_HOTPLUG, | |
456 | +}; | |
454 | 457 | extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn, |
455 | - unsigned long size); | |
458 | + unsigned long size, | |
459 | + enum memmap_context context); | |
456 | 460 | |
457 | 461 | #ifdef CONFIG_HAVE_MEMORY_PRESENT |
458 | 462 | void memory_present(int nid, unsigned long start, unsigned long end); |
mm/memory_hotplug.c
... | ... | @@ -67,11 +67,13 @@ |
67 | 67 | zone_type = zone - pgdat->node_zones; |
68 | 68 | if (!populated_zone(zone)) { |
69 | 69 | int ret = 0; |
70 | - ret = init_currently_empty_zone(zone, phys_start_pfn, nr_pages); | |
70 | + ret = init_currently_empty_zone(zone, phys_start_pfn, | |
71 | + nr_pages, MEMMAP_HOTPLUG); | |
71 | 72 | if (ret < 0) |
72 | 73 | return ret; |
73 | 74 | } |
74 | - memmap_init_zone(nr_pages, nid, zone_type, phys_start_pfn); | |
75 | + memmap_init_zone(nr_pages, nid, zone_type, | |
76 | + phys_start_pfn, MEMMAP_HOTPLUG); | |
75 | 77 | return 0; |
76 | 78 | } |
77 | 79 |
mm/page_alloc.c
... | ... | @@ -1956,17 +1956,24 @@ |
1956 | 1956 | * done. Non-atomic initialization, single-pass. |
1957 | 1957 | */ |
1958 | 1958 | void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, |
1959 | - unsigned long start_pfn) | |
1959 | + unsigned long start_pfn, enum memmap_context context) | |
1960 | 1960 | { |
1961 | 1961 | struct page *page; |
1962 | 1962 | unsigned long end_pfn = start_pfn + size; |
1963 | 1963 | unsigned long pfn; |
1964 | 1964 | |
1965 | 1965 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { |
1966 | - if (!early_pfn_valid(pfn)) | |
1967 | - continue; | |
1968 | - if (!early_pfn_in_nid(pfn, nid)) | |
1969 | - continue; | |
1966 | + /* | |
1967 | + * There can be holes in boot-time mem_map[]s | |
1968 | + * handed to this function. They do not | |
1969 | + * exist on hotplugged memory. | |
1970 | + */ | |
1971 | + if (context == MEMMAP_EARLY) { | |
1972 | + if (!early_pfn_valid(pfn)) | |
1973 | + continue; | |
1974 | + if (!early_pfn_in_nid(pfn, nid)) | |
1975 | + continue; | |
1976 | + } | |
1970 | 1977 | page = pfn_to_page(pfn); |
1971 | 1978 | set_page_links(page, zone, nid, pfn); |
1972 | 1979 | init_page_count(page); |
... | ... | @@ -1993,7 +2000,7 @@ |
1993 | 2000 | |
1994 | 2001 | #ifndef __HAVE_ARCH_MEMMAP_INIT |
1995 | 2002 | #define memmap_init(size, nid, zone, start_pfn) \ |
1996 | - memmap_init_zone((size), (nid), (zone), (start_pfn)) | |
2003 | + memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY) | |
1997 | 2004 | #endif |
1998 | 2005 | |
1999 | 2006 | static int __cpuinit zone_batchsize(struct zone *zone) |
... | ... | @@ -2239,7 +2246,8 @@ |
2239 | 2246 | |
2240 | 2247 | __meminit int init_currently_empty_zone(struct zone *zone, |
2241 | 2248 | unsigned long zone_start_pfn, |
2242 | - unsigned long size) | |
2249 | + unsigned long size, | |
2250 | + enum memmap_context context) | |
2243 | 2251 | { |
2244 | 2252 | struct pglist_data *pgdat = zone->zone_pgdat; |
2245 | 2253 | int ret; |
... | ... | @@ -2683,7 +2691,8 @@ |
2683 | 2691 | if (!size) |
2684 | 2692 | continue; |
2685 | 2693 | |
2686 | - ret = init_currently_empty_zone(zone, zone_start_pfn, size); | |
2694 | + ret = init_currently_empty_zone(zone, zone_start_pfn, | |
2695 | + size, MEMMAP_EARLY); | |
2687 | 2696 | BUG_ON(ret); |
2688 | 2697 | zone_start_pfn += size; |
2689 | 2698 | } |