diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-26 17:04:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-26 17:04:32 -0400 |
commit | c3bf9bc243092c53946fd6d8ebd6dc2f4e572d48 (patch) | |
tree | 4cabbf33e11e3a71b64394b24fe70453f41cefe8 /arch | |
parent | e3505dd50caf54e6f81f897cb347441409974a15 (diff) | |
parent | c2b91e2eec9678dbda274e906cc32ea8f711da3b (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86-bigbox-bootmem-v3
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86-bigbox-bootmem-v3:
x86_64/mm: check and print vmemmap allocation continuous
x86_64: fix setup_node_bootmem to support big mem excluding with memmap
x86_64: make reserve_bootmem_generic() use new reserve_bootmem()
mm: allow reserve_bootmem() cross nodes
mm: offset align in alloc_bootmem()
mm: fix alloc_bootmem_core to use fast searching for all nodes
mm: make mem_map allocation continuous
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/e820_64.c | 13 | ||||
-rw-r--r-- | arch/x86/kernel/setup_64.c | 3 | ||||
-rw-r--r-- | arch/x86/mm/init_64.c | 38 | ||||
-rw-r--r-- | arch/x86/mm/numa_64.c | 42 |
4 files changed, 80 insertions, 16 deletions
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index 79f0d52fa99a..645ee5e32a27 100644 --- a/arch/x86/kernel/e820_64.c +++ b/arch/x86/kernel/e820_64.c | |||
@@ -106,14 +106,19 @@ void __init free_early(unsigned long start, unsigned long end) | |||
106 | early_res[j - 1].end = 0; | 106 | early_res[j - 1].end = 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | void __init early_res_to_bootmem(void) | 109 | void __init early_res_to_bootmem(unsigned long start, unsigned long end) |
110 | { | 110 | { |
111 | int i; | 111 | int i; |
112 | unsigned long final_start, final_end; | ||
112 | for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) { | 113 | for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) { |
113 | struct early_res *r = &early_res[i]; | 114 | struct early_res *r = &early_res[i]; |
114 | printk(KERN_INFO "early res: %d [%lx-%lx] %s\n", i, | 115 | final_start = max(start, r->start); |
115 | r->start, r->end - 1, r->name); | 116 | final_end = min(end, r->end); |
116 | reserve_bootmem_generic(r->start, r->end - r->start); | 117 | if (final_start >= final_end) |
118 | continue; | ||
119 | printk(KERN_INFO " early res: %d [%lx-%lx] %s\n", i, | ||
120 | final_start, final_end - 1, r->name); | ||
121 | reserve_bootmem_generic(final_start, final_end - final_start); | ||
117 | } | 122 | } |
118 | } | 123 | } |
119 | 124 | ||
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index b04e2c011e1a..60e64c8eee92 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c | |||
@@ -190,6 +190,7 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn) | |||
190 | bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn); | 190 | bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn); |
191 | e820_register_active_regions(0, start_pfn, end_pfn); | 191 | e820_register_active_regions(0, start_pfn, end_pfn); |
192 | free_bootmem_with_active_regions(0, end_pfn); | 192 | free_bootmem_with_active_regions(0, end_pfn); |
193 | early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT); | ||
193 | reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT); | 194 | reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT); |
194 | } | 195 | } |
195 | #endif | 196 | #endif |
@@ -421,8 +422,6 @@ void __init setup_arch(char **cmdline_p) | |||
421 | contig_initmem_init(0, end_pfn); | 422 | contig_initmem_init(0, end_pfn); |
422 | #endif | 423 | #endif |
423 | 424 | ||
424 | early_res_to_bootmem(); | ||
425 | |||
426 | dma32_reserve_bootmem(); | 425 | dma32_reserve_bootmem(); |
427 | 426 | ||
428 | #ifdef CONFIG_ACPI_SLEEP | 427 | #ifdef CONFIG_ACPI_SLEEP |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 0cca62663037..5fbb8652cf59 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -810,7 +810,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) | |||
810 | void __init reserve_bootmem_generic(unsigned long phys, unsigned len) | 810 | void __init reserve_bootmem_generic(unsigned long phys, unsigned len) |
811 | { | 811 | { |
812 | #ifdef CONFIG_NUMA | 812 | #ifdef CONFIG_NUMA |
813 | int nid = phys_to_nid(phys); | 813 | int nid, next_nid; |
814 | #endif | 814 | #endif |
815 | unsigned long pfn = phys >> PAGE_SHIFT; | 815 | unsigned long pfn = phys >> PAGE_SHIFT; |
816 | 816 | ||
@@ -829,10 +829,16 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len) | |||
829 | 829 | ||
830 | /* Should check here against the e820 map to avoid double free */ | 830 | /* Should check here against the e820 map to avoid double free */ |
831 | #ifdef CONFIG_NUMA | 831 | #ifdef CONFIG_NUMA |
832 | reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT); | 832 | nid = phys_to_nid(phys); |
833 | next_nid = phys_to_nid(phys + len - 1); | ||
834 | if (nid == next_nid) | ||
835 | reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT); | ||
836 | else | ||
837 | reserve_bootmem(phys, len, BOOTMEM_DEFAULT); | ||
833 | #else | 838 | #else |
834 | reserve_bootmem(phys, len, BOOTMEM_DEFAULT); | 839 | reserve_bootmem(phys, len, BOOTMEM_DEFAULT); |
835 | #endif | 840 | #endif |
841 | |||
836 | if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) { | 842 | if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) { |
837 | dma_reserve += len / PAGE_SIZE; | 843 | dma_reserve += len / PAGE_SIZE; |
838 | set_dma_reserve(dma_reserve); | 844 | set_dma_reserve(dma_reserve); |
@@ -926,6 +932,10 @@ const char *arch_vma_name(struct vm_area_struct *vma) | |||
926 | /* | 932 | /* |
927 | * Initialise the sparsemem vmemmap using huge-pages at the PMD level. | 933 | * Initialise the sparsemem vmemmap using huge-pages at the PMD level. |
928 | */ | 934 | */ |
935 | static long __meminitdata addr_start, addr_end; | ||
936 | static void __meminitdata *p_start, *p_end; | ||
937 | static int __meminitdata node_start; | ||
938 | |||
929 | int __meminit | 939 | int __meminit |
930 | vmemmap_populate(struct page *start_page, unsigned long size, int node) | 940 | vmemmap_populate(struct page *start_page, unsigned long size, int node) |
931 | { | 941 | { |
@@ -960,12 +970,32 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node) | |||
960 | PAGE_KERNEL_LARGE); | 970 | PAGE_KERNEL_LARGE); |
961 | set_pmd(pmd, __pmd(pte_val(entry))); | 971 | set_pmd(pmd, __pmd(pte_val(entry))); |
962 | 972 | ||
963 | printk(KERN_DEBUG " [%lx-%lx] PMD ->%p on node %d\n", | 973 | /* check to see if we have contiguous blocks */ |
964 | addr, addr + PMD_SIZE - 1, p, node); | 974 | if (p_end != p || node_start != node) { |
975 | if (p_start) | ||
976 | printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n", | ||
977 | addr_start, addr_end-1, p_start, p_end-1, node_start); | ||
978 | addr_start = addr; | ||
979 | node_start = node; | ||
980 | p_start = p; | ||
981 | } | ||
982 | addr_end = addr + PMD_SIZE; | ||
983 | p_end = p + PMD_SIZE; | ||
965 | } else { | 984 | } else { |
966 | vmemmap_verify((pte_t *)pmd, node, addr, next); | 985 | vmemmap_verify((pte_t *)pmd, node, addr, next); |
967 | } | 986 | } |
968 | } | 987 | } |
969 | return 0; | 988 | return 0; |
970 | } | 989 | } |
990 | |||
991 | void __meminit vmemmap_populate_print_last(void) | ||
992 | { | ||
993 | if (p_start) { | ||
994 | printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n", | ||
995 | addr_start, addr_end-1, p_start, p_end-1, node_start); | ||
996 | p_start = NULL; | ||
997 | p_end = NULL; | ||
998 | node_start = 0; | ||
999 | } | ||
1000 | } | ||
971 | #endif | 1001 | #endif |
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 9a6892200b27..c5066d519e5d 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c | |||
@@ -196,6 +196,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, | |||
196 | unsigned long bootmap_start, nodedata_phys; | 196 | unsigned long bootmap_start, nodedata_phys; |
197 | void *bootmap; | 197 | void *bootmap; |
198 | const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); | 198 | const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); |
199 | int nid; | ||
199 | 200 | ||
200 | start = round_up(start, ZONE_ALIGN); | 201 | start = round_up(start, ZONE_ALIGN); |
201 | 202 | ||
@@ -218,9 +219,19 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, | |||
218 | NODE_DATA(nodeid)->node_start_pfn = start_pfn; | 219 | NODE_DATA(nodeid)->node_start_pfn = start_pfn; |
219 | NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn; | 220 | NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn; |
220 | 221 | ||
221 | /* Find a place for the bootmem map */ | 222 | /* |
223 | * Find a place for the bootmem map | ||
224 | * nodedata_phys could be on other nodes by alloc_bootmem, | ||
225 | * so need to sure bootmap_start not to be small, otherwise | ||
226 | * early_node_mem will get that with find_e820_area instead | ||
227 | * of alloc_bootmem, that could clash with reserved range | ||
228 | */ | ||
222 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); | 229 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); |
223 | bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); | 230 | nid = phys_to_nid(nodedata_phys); |
231 | if (nid == nodeid) | ||
232 | bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); | ||
233 | else | ||
234 | bootmap_start = round_up(start, PAGE_SIZE); | ||
224 | /* | 235 | /* |
225 | * SMP_CAHCE_BYTES could be enough, but init_bootmem_node like | 236 | * SMP_CAHCE_BYTES could be enough, but init_bootmem_node like |
226 | * to use that to align to PAGE_SIZE | 237 | * to use that to align to PAGE_SIZE |
@@ -245,10 +256,29 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, | |||
245 | 256 | ||
246 | free_bootmem_with_active_regions(nodeid, end); | 257 | free_bootmem_with_active_regions(nodeid, end); |
247 | 258 | ||
248 | reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size, | 259 | /* |
249 | BOOTMEM_DEFAULT); | 260 | * convert early reserve to bootmem reserve earlier |
250 | reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, | 261 | * otherwise early_node_mem could use early reserved mem |
251 | bootmap_pages<<PAGE_SHIFT, BOOTMEM_DEFAULT); | 262 | * on previous node |
263 | */ | ||
264 | early_res_to_bootmem(start, end); | ||
265 | |||
266 | /* | ||
267 | * in some case early_node_mem could use alloc_bootmem | ||
268 | * to get range on other node, don't reserve that again | ||
269 | */ | ||
270 | if (nid != nodeid) | ||
271 | printk(KERN_INFO " NODE_DATA(%d) on node %d\n", nodeid, nid); | ||
272 | else | ||
273 | reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, | ||
274 | pgdat_size, BOOTMEM_DEFAULT); | ||
275 | nid = phys_to_nid(bootmap_start); | ||
276 | if (nid != nodeid) | ||
277 | printk(KERN_INFO " bootmap(%d) on node %d\n", nodeid, nid); | ||
278 | else | ||
279 | reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, | ||
280 | bootmap_pages<<PAGE_SHIFT, BOOTMEM_DEFAULT); | ||
281 | |||
252 | #ifdef CONFIG_ACPI_NUMA | 282 | #ifdef CONFIG_ACPI_NUMA |
253 | srat_reserve_add_area(nodeid); | 283 | srat_reserve_add_area(nodeid); |
254 | #endif | 284 | #endif |