Commit 267b4801 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[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: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent bd663347
...@@ -149,7 +149,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en ...@@ -149,7 +149,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
/* Initialize final allocator for a zone */ /* Initialize final allocator for a zone */
void __init setup_node_zones(int nodeid) void __init setup_node_zones(int nodeid)
{ {
unsigned long start_pfn, end_pfn; unsigned long start_pfn, end_pfn, memmapsize, limit;
unsigned long zones[MAX_NR_ZONES]; unsigned long zones[MAX_NR_ZONES];
unsigned long holes[MAX_NR_ZONES]; unsigned long holes[MAX_NR_ZONES];
...@@ -159,6 +159,16 @@ void __init setup_node_zones(int nodeid) ...@@ -159,6 +159,16 @@ void __init setup_node_zones(int nodeid)
Dprintk(KERN_INFO "Setting up node %d %lx-%lx\n", Dprintk(KERN_INFO "Setting up node %d %lx-%lx\n",
nodeid, start_pfn, end_pfn); nodeid, start_pfn, end_pfn);
/* Try to allocate mem_map at end to not fill up precious <4GB
memory. */
memmapsize = sizeof(struct page) * (end_pfn-start_pfn);
limit = end_pfn << PAGE_SHIFT;
NODE_DATA(nodeid)->node_mem_map =
__alloc_bootmem_core(NODE_DATA(nodeid)->bdata,
memmapsize, SMP_CACHE_BYTES,
round_down(limit - memmapsize, PAGE_SIZE),
limit);
size_zones(zones, holes, start_pfn, end_pfn); size_zones(zones, holes, start_pfn, end_pfn);
free_area_init_node(nodeid, NODE_DATA(nodeid), zones, free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
start_pfn, holes); start_pfn, holes);
......
...@@ -51,6 +51,9 @@ extern void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, ...@@ -51,6 +51,9 @@ extern void * __init __alloc_bootmem_low_node(pg_data_t *pgdat,
unsigned long size, unsigned long size,
unsigned long align, unsigned long align,
unsigned long goal); unsigned long goal);
extern void * __init __alloc_bootmem_core(struct bootmem_data *bdata,
unsigned long size, unsigned long align, unsigned long goal,
unsigned long limit);
#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
extern void __init reserve_bootmem (unsigned long addr, unsigned long size); extern void __init reserve_bootmem (unsigned long addr, unsigned long size);
#define alloc_bootmem(x) \ #define alloc_bootmem(x) \
......
...@@ -152,7 +152,7 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, ...@@ -152,7 +152,7 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr,
* *
* NOTE: This function is _not_ reentrant. * NOTE: This function is _not_ reentrant.
*/ */
static void * __init void * __init
__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size, __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
unsigned long align, unsigned long goal, unsigned long limit) unsigned long align, unsigned long goal, unsigned long limit)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment