aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-03-25 10:31:10 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-25 12:10:56 -0500
commit267b48014a5c0c2ae90b04dad5d95ceb903365a6 (patch)
tree95f5475b7b7f6e5b4fd023f51fb2fa826d95a754
parentbd6633476922b7b51227f7f704c2546e763ae5ed (diff)
[PATCH] x86_64: Try to allocate node memmap near the end of node
This fixes problems with very large nodes (over 128GB) filling up all of the first 4GB with their mem_map and not leaving enough space for the swiotlb. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/x86_64/mm/numa.c12
-rw-r--r--include/linux/bootmem.h3
-rw-r--r--mm/bootmem.c2
3 files changed, 15 insertions, 2 deletions
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index e4b62753a19a..07471a3eb190 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -149,7 +149,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
149/* Initialize final allocator for a zone */ 149/* Initialize final allocator for a zone */
150void __init setup_node_zones(int nodeid) 150void __init setup_node_zones(int nodeid)
151{ 151{
152 unsigned long start_pfn, end_pfn; 152 unsigned long start_pfn, end_pfn, memmapsize, limit;
153 unsigned long zones[MAX_NR_ZONES]; 153 unsigned long zones[MAX_NR_ZONES];
154 unsigned long holes[MAX_NR_ZONES]; 154 unsigned long holes[MAX_NR_ZONES];
155 155
@@ -159,6 +159,16 @@ void __init setup_node_zones(int nodeid)
159 Dprintk(KERN_INFO "Setting up node %d %lx-%lx\n", 159 Dprintk(KERN_INFO "Setting up node %d %lx-%lx\n",
160 nodeid, start_pfn, end_pfn); 160 nodeid, start_pfn, end_pfn);
161 161
162 /* Try to allocate mem_map at end to not fill up precious <4GB
163 memory. */
164 memmapsize = sizeof(struct page) * (end_pfn-start_pfn);
165 limit = end_pfn << PAGE_SHIFT;
166 NODE_DATA(nodeid)->node_mem_map =
167 __alloc_bootmem_core(NODE_DATA(nodeid)->bdata,
168 memmapsize, SMP_CACHE_BYTES,
169 round_down(limit - memmapsize, PAGE_SIZE),
170 limit);
171
162 size_zones(zones, holes, start_pfn, end_pfn); 172 size_zones(zones, holes, start_pfn, end_pfn);
163 free_area_init_node(nodeid, NODE_DATA(nodeid), zones, 173 free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
164 start_pfn, holes); 174 start_pfn, holes);
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 993da8cc9706..7155452fb4a8 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -51,6 +51,9 @@ extern void * __init __alloc_bootmem_low_node(pg_data_t *pgdat,
51 unsigned long size, 51 unsigned long size,
52 unsigned long align, 52 unsigned long align,
53 unsigned long goal); 53 unsigned long goal);
54extern void * __init __alloc_bootmem_core(struct bootmem_data *bdata,
55 unsigned long size, unsigned long align, unsigned long goal,
56 unsigned long limit);
54#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE 57#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
55extern void __init reserve_bootmem (unsigned long addr, unsigned long size); 58extern void __init reserve_bootmem (unsigned long addr, unsigned long size);
56#define alloc_bootmem(x) \ 59#define alloc_bootmem(x) \
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 35c32290f717..b55bd39fc5dd 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -152,7 +152,7 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr,
152 * 152 *
153 * NOTE: This function is _not_ reentrant. 153 * NOTE: This function is _not_ reentrant.
154 */ 154 */
155static void * __init 155void * __init
156__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size, 156__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
157 unsigned long align, unsigned long goal, unsigned long limit) 157 unsigned long align, unsigned long goal, unsigned long limit)
158{ 158{