diff options
author | Yinghai Lu <yinghai@kernel.org> | 2009-03-04 04:22:35 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-04 14:55:03 -0500 |
commit | a71edd1f46c8a599509bda478fb4eea27fb0da63 (patch) | |
tree | fba6a512878a5b67b3b5f5fa5024e30d0db7407d | |
parent | 6d2e91bf80e4410207f01edb0962aec9213f3533 (diff) |
x86: fix bootmem cross node for 32bit numa
Impact: fix panic on system 2g x4 sockets
Found one system with 4 sockets and every sockets has 2g can not boot
with numa32 because boot mem is crossing nodes.
So try to have numa version of setup_bootmem_allocator().
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
LKML-Reference: <49AE485B.8000902@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/mm/init_32.c | 46 | ||||
-rw-r--r-- | arch/x86/mm/numa_32.c | 5 |
2 files changed, 43 insertions, 8 deletions
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 917c4e60c767..67bdb59d4e10 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -776,9 +776,37 @@ static void __init zone_sizes_init(void) | |||
776 | free_area_init_nodes(max_zone_pfns); | 776 | free_area_init_nodes(max_zone_pfns); |
777 | } | 777 | } |
778 | 778 | ||
779 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
780 | static unsigned long __init setup_node_bootmem(int nodeid, | ||
781 | unsigned long start_pfn, | ||
782 | unsigned long end_pfn, | ||
783 | unsigned long bootmap) | ||
784 | { | ||
785 | unsigned long bootmap_size; | ||
786 | |||
787 | if (start_pfn > max_low_pfn) | ||
788 | return bootmap; | ||
789 | if (end_pfn > max_low_pfn) | ||
790 | end_pfn = max_low_pfn; | ||
791 | |||
792 | /* don't touch min_low_pfn */ | ||
793 | bootmap_size = init_bootmem_node(NODE_DATA(nodeid), | ||
794 | bootmap >> PAGE_SHIFT, | ||
795 | start_pfn, end_pfn); | ||
796 | printk(KERN_INFO " node %d low ram: %08lx - %08lx\n", | ||
797 | nodeid, start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); | ||
798 | printk(KERN_INFO " node %d bootmap %08lx - %08lx\n", | ||
799 | nodeid, bootmap, bootmap + bootmap_size); | ||
800 | free_bootmem_with_active_regions(nodeid, end_pfn); | ||
801 | early_res_to_bootmem(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); | ||
802 | |||
803 | return bootmap + bootmap_size; | ||
804 | } | ||
805 | #endif | ||
806 | |||
779 | void __init setup_bootmem_allocator(void) | 807 | void __init setup_bootmem_allocator(void) |
780 | { | 808 | { |
781 | int i; | 809 | int nodeid; |
782 | unsigned long bootmap_size, bootmap; | 810 | unsigned long bootmap_size, bootmap; |
783 | /* | 811 | /* |
784 | * Initialize the boot-time allocator (with low memory only): | 812 | * Initialize the boot-time allocator (with low memory only): |
@@ -791,18 +819,24 @@ void __init setup_bootmem_allocator(void) | |||
791 | panic("Cannot find bootmem map of size %ld\n", bootmap_size); | 819 | panic("Cannot find bootmem map of size %ld\n", bootmap_size); |
792 | reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP"); | 820 | reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP"); |
793 | 821 | ||
794 | /* don't touch min_low_pfn */ | ||
795 | bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT, | ||
796 | min_low_pfn, max_low_pfn); | ||
797 | printk(KERN_INFO " mapped low ram: 0 - %08lx\n", | 822 | printk(KERN_INFO " mapped low ram: 0 - %08lx\n", |
798 | max_pfn_mapped<<PAGE_SHIFT); | 823 | max_pfn_mapped<<PAGE_SHIFT); |
799 | printk(KERN_INFO " low ram: %08lx - %08lx\n", | 824 | printk(KERN_INFO " low ram: %08lx - %08lx\n", |
800 | min_low_pfn<<PAGE_SHIFT, max_low_pfn<<PAGE_SHIFT); | 825 | min_low_pfn<<PAGE_SHIFT, max_low_pfn<<PAGE_SHIFT); |
826 | |||
827 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
828 | for_each_online_node(nodeid) | ||
829 | bootmap = setup_node_bootmem(nodeid, node_start_pfn[nodeid], | ||
830 | node_end_pfn[nodeid], bootmap); | ||
831 | #else | ||
832 | /* don't touch min_low_pfn */ | ||
833 | bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT, | ||
834 | min_low_pfn, max_low_pfn); | ||
801 | printk(KERN_INFO " bootmap %08lx - %08lx\n", | 835 | printk(KERN_INFO " bootmap %08lx - %08lx\n", |
802 | bootmap, bootmap + bootmap_size); | 836 | bootmap, bootmap + bootmap_size); |
803 | for_each_online_node(i) | 837 | free_bootmem_with_active_regions(0, max_low_pfn); |
804 | free_bootmem_with_active_regions(i, max_low_pfn); | ||
805 | early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT); | 838 | early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT); |
839 | #endif | ||
806 | 840 | ||
807 | after_init_bootmem = 1; | 841 | after_init_bootmem = 1; |
808 | } | 842 | } |
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c index 451fe95a0352..3daefa04ace5 100644 --- a/arch/x86/mm/numa_32.c +++ b/arch/x86/mm/numa_32.c | |||
@@ -416,10 +416,11 @@ void __init initmem_init(unsigned long start_pfn, | |||
416 | for_each_online_node(nid) | 416 | for_each_online_node(nid) |
417 | propagate_e820_map_node(nid); | 417 | propagate_e820_map_node(nid); |
418 | 418 | ||
419 | for_each_online_node(nid) | 419 | for_each_online_node(nid) { |
420 | memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); | 420 | memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); |
421 | NODE_DATA(nid)->bdata = &bootmem_node_data[nid]; | ||
422 | } | ||
421 | 423 | ||
422 | NODE_DATA(0)->bdata = &bootmem_node_data[0]; | ||
423 | setup_bootmem_allocator(); | 424 | setup_bootmem_allocator(); |
424 | } | 425 | } |
425 | 426 | ||