From: Andi Kleen <ak@suse.de> Apply this handy patch and boot with numa=fake=4 (or how many nodes you want, 8 max right now). There is a minor issue with the hash function, which can make the last node be bigger than the others. Is probably fixable if it should be a problem. Signed-off-by: Andrew Morton <akpm@osdl.org> --- /dev/null | 0 25-akpm/arch/x86_64/mm/numa.c | 55 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff -puN arch/x86_64/mm/numa.c~x86_64-numa-emulation arch/x86_64/mm/numa.c --- 25/arch/x86_64/mm/numa.c~x86_64-numa-emulation 2004-08-04 22:13:47.710023216 -0700 +++ 25-akpm/arch/x86_64/mm/numa.c 2004-08-04 22:13:47.717022152 -0700 @@ -163,10 +163,58 @@ void __init numa_init_array(void) set_bit(0, &node_to_cpumask[cpu_to_node(0)]); } +int numa_fake __initdata = 0; + +/* Numa emulation */ +static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn) +{ + int i; + struct node nodes[MAXNODE]; + unsigned long sz = ((end_pfn - start_pfn)<<PAGE_SHIFT) / numa_fake; + + /* Kludge needed for the hash function */ + if (hweight64(sz) > 1) { + unsigned long x = 1; + while ((x << 1) < sz) + x <<= 1; + if (x < sz/2) + printk("Numa emulation unbalanced. Complain to maintainer\n"); + sz = x; + } + + memset(&nodes,0,sizeof(nodes)); + for (i = 0; i < numa_fake; i++) { + nodes[i].start = (start_pfn<<PAGE_SHIFT) + i*sz; + if (i == numa_fake-1) + sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start; + nodes[i].end = nodes[i].start + sz; + if (i != numa_fake-1) + nodes[i].end--; + printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", + i, + nodes[i].start, nodes[i].end, + (nodes[i].end - nodes[i].start) >> 20); + } + numnodes = numa_fake; + memnode_shift = compute_hash_shift(nodes); + if (memnode_shift < 0) { + memnode_shift = 0; + printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n"); + return -1; + } + for (i = 0; i < numa_fake; i++) + setup_node_bootmem(i, nodes[i].start, nodes[i].end); + numa_init_array(); + return 0; +} + void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) { int i; + if (numa_fake && !numa_emulation(start_pfn, end_pfn)) + return; + #ifdef CONFIG_K8_NUMA if (!numa_off && !k8_scan_nodes(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT)) return; @@ -215,8 +263,13 @@ void __init paging_init(void) /* [numa=off] */ __init int numa_setup(char *opt) { - if (!strncmp(opt,"off",3)) + if (!strcmp(opt,"off")) numa_off = 1; + if(!strncmp(opt, "fake=", 5)) { + numa_fake = simple_strtoul(opt+5,NULL,0); ; + if (numa_fake >= MAX_NUMNODES) + numa_fake = MAX_NUMNODES; + } return 1; } diff -L arch/x86_64/mm/numa.c-EMU -puN /dev/null /dev/null _