diff -X ../KDIFX -burpN linux-2.6.0-mm1/arch/x86_64/mm/k8topology.c linux-2.6.0-mm1-ak/arch/x86_64/mm/k8topology.c
--- linux-2.6.0-mm1/arch/x86_64/mm/k8topology.c	2003-11-24 04:46:35.000000000 +0100
+++ linux-2.6.0-mm1-ak/arch/x86_64/mm/k8topology.c	2003-12-29 03:40:52.000000000 +0100
@@ -148,24 +148,7 @@ int __init k8_scan_nodes(unsigned long s
 		setup_node_bootmem(i, nodes[i].start, nodes[i].end); 
 	} 
 
-	/* There are unfortunately some poorly designed mainboards around
-	   that only connect memory to a single CPU. This breaks the 1:1 cpu->node
-	   mapping. To avoid this fill in the mapping for all possible
-	   CPUs, as the number of CPUs is not known yet. 
-	   We round robin the existing nodes. */
-	int rr = 0;
-	for (i = 0; i < MAXNODE; i++) {
-		if (nodes_present & (1UL<<i))
-			continue;
-		if ((nodes_present >> rr) == 0) 
-			rr = 0; 
-		rr = ffz(~nodes_present >> rr); 
-		node_data[i] = node_data[rr];
-		rr++; 
-	}
-
-	if (found == 1) 
-		fake_node = 1;
+	numa_init_array();
 
 	return 0;
 } 
diff -X ../KDIFX -burpN linux-2.6.0-mm1/arch/x86_64/mm/numa.c linux-2.6.0-mm1-ak/arch/x86_64/mm/numa.c
--- linux-2.6.0-mm1/arch/x86_64/mm/numa.c	2003-11-24 04:46:35.000000000 +0100
+++ linux-2.6.0-mm1-ak/arch/x86_64/mm/numa.c	2003-12-29 05:01:52.000000000 +0100
@@ -26,6 +26,33 @@ static int numa_off __initdata; 
 
 unsigned long nodes_present; 
 
+void numa_init_array(void)
+{
+	int i;
+	int found = 0; 
+	/* There are unfortunately some poorly designed mainboards around
+	   that only connect memory to a single CPU. This breaks the 1:1 cpu->node
+	   mapping. To avoid this fill in the mapping for all possible
+	   CPUs, as the number of CPUs is not known yet. 
+	   We round robin the existing nodes. */
+	int rr = 0;
+	for (i = 0; i < MAXNODE; i++) {
+		if (nodes_present & (1UL<<i)) { 
+			found++;
+			continue;
+		}
+		if ((nodes_present >> rr) == 0) 
+			rr = 0; 
+		rr = ffz(~nodes_present >> rr); 
+		node_data[i] = node_data[rr];
+		rr++; 
+		Dprintk("**** cpu %d -> node %d\n", i, rr);
+	}
+
+	if (found == 1) 
+		fake_node = 1;
+}
+
 int __init compute_hash_shift(struct node *nodes)
 {
 	int i; 
@@ -134,10 +161,58 @@ void __init setup_node_zones(int nodeid)
 			    start_pfn, NULL); 
 } 
 
+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;
+}
+
 int fake_node;
 
 int __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
 { 
+	if (numa_fake && !numa_emulation(start_pfn, end_pfn))
+		return 0; 
+
 #ifdef CONFIG_K8_NUMA
 	if (!numa_off && !k8_scan_nodes(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT))
 		return 0; 
@@ -178,8 +253,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 -X ../KDIFX -burpN linux-2.6.0-mm1/include/asm-x86_64/proto.h linux-2.6.0-mm1-ak/include/asm-x86_64/proto.h
--- linux-2.6.0-mm1/include/asm-x86_64/proto.h	2003-10-18 23:00:50.000000000 +0200
+++ linux-2.6.0-mm1-ak/include/asm-x86_64/proto.h	2003-12-29 03:40:52.000000000 +0100
@@ -34,6 +34,7 @@ extern void time_init_smp(void);
 extern void do_softirq_thunk(void);
 
 extern int numa_setup(char *opt);
+extern void numa_init_array(void);
 
 extern int setup_early_printk(char *); 
 extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2)));
