aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/mm/numa.c
diff options
context:
space:
mode:
authorAmul Shah <amul.shah@unisys.com>2007-02-13 07:26:19 -0500
committerAndi Kleen <andi@basil.nowhere.org>2007-02-13 07:26:19 -0500
commit076422d2af7e3d8e72c6e70843f6ea377714b082 (patch)
tree942ec9d2e7f3f74d6694af99a745ee74ef851268 /arch/x86_64/mm/numa.c
parent0812a579c92fefa57506821fa08e90f47cb6dbdd (diff)
[PATCH] x86-64: Allocate the NUMA hash function nodemap dynamically
Remove the statically allocated memory to NUMA node hash map in favor of a dynamically allocated memory to node hash map (it is cache aligned). This patch has the nice side effect in that it allows the hash map to grow for systems with large amounts of memory (256GB - 1TB), but suffer from having small PCI space tacked onto the boot node (which is somewhere between 192MB to 512MB on the ES7000). Signed-off-by: Amul Shah <amul.shah@unisys.com> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Andi Kleen <ak@suse.de> Cc: Rohit Seth <rohitseth@google.com> Signed-off-by: Andrew Morton <akpm@osdl.org>
Diffstat (limited to 'arch/x86_64/mm/numa.c')
-rw-r--r--arch/x86_64/mm/numa.c74
1 files changed, 65 insertions, 9 deletions
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 2ee2e003606c..7d9c428f4094 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -36,6 +36,8 @@ unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
36cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly; 36cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly;
37 37
38int numa_off __initdata; 38int numa_off __initdata;
39unsigned long __initdata nodemap_addr;
40unsigned long __initdata nodemap_size;
39 41
40 42
41/* 43/*
@@ -52,34 +54,87 @@ populate_memnodemap(const struct bootnode *nodes, int numnodes, int shift)
52 int res = -1; 54 int res = -1;
53 unsigned long addr, end; 55 unsigned long addr, end;
54 56
55 if (shift >= 64) 57 memset(memnodemap, 0xff, memnodemapsize);
56 return -1;
57 memset(memnodemap, 0xff, sizeof(memnodemap));
58 for (i = 0; i < numnodes; i++) { 58 for (i = 0; i < numnodes; i++) {
59 addr = nodes[i].start; 59 addr = nodes[i].start;
60 end = nodes[i].end; 60 end = nodes[i].end;
61 if (addr >= end) 61 if (addr >= end)
62 continue; 62 continue;
63 if ((end >> shift) >= NODEMAPSIZE) 63 if ((end >> shift) >= memnodemapsize)
64 return 0; 64 return 0;
65 do { 65 do {
66 if (memnodemap[addr >> shift] != 0xff) 66 if (memnodemap[addr >> shift] != 0xff)
67 return -1; 67 return -1;
68 memnodemap[addr >> shift] = i; 68 memnodemap[addr >> shift] = i;
69 addr += (1UL << shift); 69 addr += (1UL << shift);
70 } while (addr < end); 70 } while (addr < end);
71 res = 1; 71 res = 1;
72 } 72 }
73 return res; 73 return res;
74} 74}
75 75
76int __init compute_hash_shift(struct bootnode *nodes, int numnodes) 76static int __init allocate_cachealigned_memnodemap(void)
77{
78 unsigned long pad, pad_addr;
79
80 memnodemap = memnode.embedded_map;
81 if (memnodemapsize <= 48) {
82 printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
83 nodemap_addr, nodemap_addr + nodemap_size);
84 return 0;
85 }
86
87 pad = L1_CACHE_BYTES - 1;
88 pad_addr = 0x8000;
89 nodemap_size = pad + memnodemapsize;
90 nodemap_addr = find_e820_area(pad_addr, end_pfn<<PAGE_SHIFT,
91 nodemap_size);
92 if (nodemap_addr == -1UL) {
93 printk(KERN_ERR
94 "NUMA: Unable to allocate Memory to Node hash map\n");
95 nodemap_addr = nodemap_size = 0;
96 return -1;
97 }
98 pad_addr = (nodemap_addr + pad) & ~pad;
99 memnodemap = phys_to_virt(pad_addr);
100
101 printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
102 nodemap_addr, nodemap_addr + nodemap_size);
103 return 0;
104}
105
106/*
107 * The LSB of all start and end addresses in the node map is the value of the
108 * maximum possible shift.
109 */
110static int __init
111extract_lsb_from_nodes (const struct bootnode *nodes, int numnodes)
77{ 112{
78 int shift = 20; 113 int i;
114 unsigned long start, end;
115 unsigned long bitfield = 0, memtop = 0;
79 116
80 while (populate_memnodemap(nodes, numnodes, shift + 1) >= 0) 117 for (i = 0; i < numnodes; i++) {
81 shift++; 118 start = nodes[i].start;
119 end = nodes[i].end;
120 if (start >= end)
121 continue;
122 bitfield |= start | end;
123 if (end > memtop)
124 memtop = end;
125 }
126 i = find_first_bit(&bitfield, sizeof(unsigned long)*8);
127 memnodemapsize = (memtop >> i)+1;
128 return i;
129}
130
131int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
132{
133 int shift;
82 134
135 shift = extract_lsb_from_nodes(nodes, numnodes);
136 if (allocate_cachealigned_memnodemap())
137 return -1;
83 printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n", 138 printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
84 shift); 139 shift);
85 140
@@ -290,6 +345,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
290 end_pfn << PAGE_SHIFT); 345 end_pfn << PAGE_SHIFT);
291 /* setup dummy node covering all memory */ 346 /* setup dummy node covering all memory */
292 memnode_shift = 63; 347 memnode_shift = 63;
348 memnodemap = memnode.embedded_map;
293 memnodemap[0] = 0; 349 memnodemap[0] = 0;
294 nodes_clear(node_online_map); 350 nodes_clear(node_online_map);
295 node_set_online(0); 351 node_set_online(0);