summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorKeith Mannthey <kmannth@us.ibm.com>2005-07-28 21:15:38 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-28 21:46:00 -0700
commitb684664fd495fd640353c0f786751763db77dcfb (patch)
tree348f3d452f9d1a78ec1a3684ef53380d41ec9db8 /arch
parent17158d17aa726142255050b407ad701a6f191aba (diff)
downloadlinux-3.10-b684664fd495fd640353c0f786751763db77dcfb.tar.gz
linux-3.10-b684664fd495fd640353c0f786751763db77dcfb.tar.bz2
linux-3.10-b684664fd495fd640353c0f786751763db77dcfb.zip
[PATCH] x86_64: Fix overflow in NUMA hash function setup
Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/mm/numa.c50
1 files changed, 26 insertions, 24 deletions
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index ac61c186eb0..70cb2904a90 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -36,34 +36,36 @@ int numa_off __initdata;
int __init compute_hash_shift(struct node *nodes, int numnodes)
{
int i;
- int shift = 24;
- u64 addr;
+ int shift = 20;
+ unsigned long addr,maxend=0;
- /* When in doubt use brute force. */
- while (shift < 48) {
- memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE);
- for (i = 0; i < numnodes; i++) {
- if (nodes[i].start == nodes[i].end)
- continue;
- for (addr = nodes[i].start;
- addr < nodes[i].end;
- addr += (1UL << shift)) {
- if (memnodemap[addr >> shift] != 0xff &&
- memnodemap[addr >> shift] != i) {
- printk(KERN_INFO
- "node %d shift %d addr %Lx conflict %d\n",
- i, shift, addr, memnodemap[addr>>shift]);
- goto next;
- }
- memnodemap[addr >> shift] = i;
+ for (i = 0; i < numnodes; i++)
+ if ((nodes[i].start != nodes[i].end) && (nodes[i].end > maxend))
+ maxend = nodes[i].end;
+
+ while ((1UL << shift) < (maxend / NODEMAPSIZE))
+ shift++;
+
+ printk (KERN_DEBUG"Using %d for the hash shift. Max adder is %lx \n",
+ shift,maxend);
+ memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE);
+ for (i = 0; i < numnodes; i++) {
+ if (nodes[i].start == nodes[i].end)
+ continue;
+ for (addr = nodes[i].start;
+ addr < nodes[i].end;
+ addr += (1UL << shift)) {
+ if (memnodemap[addr >> shift] != 0xff) {
+ printk(KERN_INFO
+ "Your memory is not aligned you need to rebuild your kernel "
+ "with a bigger NODEMAPSIZE shift=%d adder=%lu\n",
+ shift,addr);
+ return -1;
}
+ memnodemap[addr >> shift] = i;
}
- return shift;
- next:
- shift++;
}
- memset(memnodemap,0,sizeof(*memnodemap) * NODEMAPSIZE);
- return -1;
+ return shift;
}
#ifdef CONFIG_SPARSEMEM