|
@@ -36,6 +36,8 @@ unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
|
|
|
cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly;
|
|
|
|
|
|
int numa_off __initdata;
|
|
|
+unsigned long __initdata nodemap_addr;
|
|
|
+unsigned long __initdata nodemap_size;
|
|
|
|
|
|
|
|
|
/*
|
|
@@ -52,34 +54,87 @@ populate_memnodemap(const struct bootnode *nodes, int numnodes, int shift)
|
|
|
int res = -1;
|
|
|
unsigned long addr, end;
|
|
|
|
|
|
- if (shift >= 64)
|
|
|
- return -1;
|
|
|
- memset(memnodemap, 0xff, sizeof(memnodemap));
|
|
|
+ memset(memnodemap, 0xff, memnodemapsize);
|
|
|
for (i = 0; i < numnodes; i++) {
|
|
|
addr = nodes[i].start;
|
|
|
end = nodes[i].end;
|
|
|
if (addr >= end)
|
|
|
continue;
|
|
|
- if ((end >> shift) >= NODEMAPSIZE)
|
|
|
+ if ((end >> shift) >= memnodemapsize)
|
|
|
return 0;
|
|
|
do {
|
|
|
if (memnodemap[addr >> shift] != 0xff)
|
|
|
return -1;
|
|
|
memnodemap[addr >> shift] = i;
|
|
|
- addr += (1UL << shift);
|
|
|
+ addr += (1UL << shift);
|
|
|
} while (addr < end);
|
|
|
res = 1;
|
|
|
}
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
-int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
|
|
|
+static int __init allocate_cachealigned_memnodemap(void)
|
|
|
+{
|
|
|
+ unsigned long pad, pad_addr;
|
|
|
+
|
|
|
+ memnodemap = memnode.embedded_map;
|
|
|
+ if (memnodemapsize <= 48) {
|
|
|
+ printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
|
|
|
+ nodemap_addr, nodemap_addr + nodemap_size);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ pad = L1_CACHE_BYTES - 1;
|
|
|
+ pad_addr = 0x8000;
|
|
|
+ nodemap_size = pad + memnodemapsize;
|
|
|
+ nodemap_addr = find_e820_area(pad_addr, end_pfn<<PAGE_SHIFT,
|
|
|
+ nodemap_size);
|
|
|
+ if (nodemap_addr == -1UL) {
|
|
|
+ printk(KERN_ERR
|
|
|
+ "NUMA: Unable to allocate Memory to Node hash map\n");
|
|
|
+ nodemap_addr = nodemap_size = 0;
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ pad_addr = (nodemap_addr + pad) & ~pad;
|
|
|
+ memnodemap = phys_to_virt(pad_addr);
|
|
|
+
|
|
|
+ printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
|
|
|
+ nodemap_addr, nodemap_addr + nodemap_size);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * The LSB of all start and end addresses in the node map is the value of the
|
|
|
+ * maximum possible shift.
|
|
|
+ */
|
|
|
+static int __init
|
|
|
+extract_lsb_from_nodes (const struct bootnode *nodes, int numnodes)
|
|
|
{
|
|
|
- int shift = 20;
|
|
|
+ int i;
|
|
|
+ unsigned long start, end;
|
|
|
+ unsigned long bitfield = 0, memtop = 0;
|
|
|
|
|
|
- while (populate_memnodemap(nodes, numnodes, shift + 1) >= 0)
|
|
|
- shift++;
|
|
|
+ for (i = 0; i < numnodes; i++) {
|
|
|
+ start = nodes[i].start;
|
|
|
+ end = nodes[i].end;
|
|
|
+ if (start >= end)
|
|
|
+ continue;
|
|
|
+ bitfield |= start | end;
|
|
|
+ if (end > memtop)
|
|
|
+ memtop = end;
|
|
|
+ }
|
|
|
+ i = find_first_bit(&bitfield, sizeof(unsigned long)*8);
|
|
|
+ memnodemapsize = (memtop >> i)+1;
|
|
|
+ return i;
|
|
|
+}
|
|
|
+
|
|
|
+int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
|
|
|
+{
|
|
|
+ int shift;
|
|
|
|
|
|
+ shift = extract_lsb_from_nodes(nodes, numnodes);
|
|
|
+ if (allocate_cachealigned_memnodemap())
|
|
|
+ return -1;
|
|
|
printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
|
|
|
shift);
|
|
|
|
|
@@ -290,6 +345,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
|
|
|
end_pfn << PAGE_SHIFT);
|
|
|
/* setup dummy node covering all memory */
|
|
|
memnode_shift = 63;
|
|
|
+ memnodemap = memnode.embedded_map;
|
|
|
memnodemap[0] = 0;
|
|
|
nodes_clear(node_online_map);
|
|
|
node_set_online(0);
|