diff -uNr freebios2.11182005_to_s_o/src/config/Options.lb freebios2.11212005_to_s_o/src/config/Options.lb
--- freebios2.11182005_to_s_o/src/config/Options.lb	2005-11-18 22:44:46.000000000 -0800
+++ freebios2.11212005_to_s_o/src/config/Options.lb	2005-11-21 17:46:33.000000000 -0800
@@ -824,7 +824,13 @@
 define K8_HW_MEM_HOLE_SIZEK
         default 0
         export always
-        comment "Opteron E0 later memory hole size in K"
+        comment "Opteron E0 later memory hole size in K, 0 mean disable"
+end
+
+define K8_HW_MEM_HOLE_SIZE_AUTO_INC
+        default 0
+        export always
+        comment "Opteron E0 later memory hole size auto increase to avoid hole startk equal to basek"
 end
 
 define K8_HT_FREQ_1G_SUPPORT
diff -uNr freebios2.11182005_to_s_o/src/mainboard/amd/serengeti_leopard/cache_as_ram_auto.c freebios2.11212005_to_s_o/src/mainboard/amd/serengeti_leopard/cache_as_ram_auto.c
--- freebios2.11182005_to_s_o/src/mainboard/amd/serengeti_leopard/cache_as_ram_auto.c	2005-11-18 21:34:10.000000000 -0800
+++ freebios2.11212005_to_s_o/src/mainboard/amd/serengeti_leopard/cache_as_ram_auto.c	2005-11-21 17:42:13.000000000 -0800
@@ -293,7 +293,7 @@
 
 	allow_all_aps_stop(bsp_apicid);
 
-        nodes = get_nodes;
+        nodes = get_nodes();
         //It's the time to set ctrl now;
         fill_mem_ctrl(nodes, ctrl, spd_addr);
 
diff -uNr freebios2.11182005_to_s_o/src/mainboard/island/aruma/cache_as_ram_auto.c freebios2.11212005_to_s_o/src/mainboard/island/aruma/cache_as_ram_auto.c
--- freebios2.11182005_to_s_o/src/mainboard/island/aruma/cache_as_ram_auto.c	2005-11-18 21:22:30.000000000 -0800
+++ freebios2.11212005_to_s_o/src/mainboard/island/aruma/cache_as_ram_auto.c	2005-11-21 17:42:32.000000000 -0800
@@ -247,7 +247,7 @@
                	soft_reset();
        	}
 
-	nodes = get_nodes;
+	nodes = get_nodes();
         //It's the time to set ctrl now;
         fill_mem_ctrl(nodes, ctrl, spd_addr);
 
diff -uNr freebios2.11182005_to_s_o/src/mainboard/tyan/s2881/cache_as_ram_auto.c freebios2.11212005_to_s_o/src/mainboard/tyan/s2881/cache_as_ram_auto.c
--- freebios2.11182005_to_s_o/src/mainboard/tyan/s2881/cache_as_ram_auto.c	2005-11-18 22:32:58.000000000 -0800
+++ freebios2.11212005_to_s_o/src/mainboard/tyan/s2881/cache_as_ram_auto.c	2005-11-21 17:42:53.000000000 -0800
@@ -218,7 +218,7 @@
 
 	enable_smbus();
 
-        nodes = get_nodes;
+        nodes = get_nodes();
         //It's the time to set ctrl now;
         fill_mem_ctrl(nodes, ctrl, spd_addr);
 
diff -uNr freebios2.11182005_to_s_o/src/mainboard/tyan/s2885/cache_as_ram_auto.c freebios2.11212005_to_s_o/src/mainboard/tyan/s2885/cache_as_ram_auto.c
--- freebios2.11182005_to_s_o/src/mainboard/tyan/s2885/cache_as_ram_auto.c	2005-11-18 22:31:34.000000000 -0800
+++ freebios2.11212005_to_s_o/src/mainboard/tyan/s2885/cache_as_ram_auto.c	2005-11-21 17:43:03.000000000 -0800
@@ -219,7 +219,7 @@
        	}
 
 
-        nodes = get_nodes;
+        nodes = get_nodes();
         //It's the time to set ctrl now;
         fill_mem_ctrl(nodes, ctrl, spd_addr);
 
diff -uNr freebios2.11182005_to_s_o/src/northbridge/amd/amdk8/northbridge.c freebios2.11212005_to_s_o/src/northbridge/amd/amdk8/northbridge.c
--- freebios2.11182005_to_s_o/src/northbridge/amd/amdk8/northbridge.c	2005-11-18 22:48:23.000000000 -0800
+++ freebios2.11212005_to_s_o/src/northbridge/amd/amdk8/northbridge.c	2005-11-21 17:45:03.000000000 -0800
@@ -685,18 +685,83 @@
 #if CONFIG_PCI_64BIT_PREF_MEM == 1
 #define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH)
 #endif
-static void disable_hoist_memory(unsigned long hole_sizek, int i)
+
+#if K8_HW_MEM_HOLE_SIZEK != 0
+
+struct hw_mem_hole_info {
+	unsigned hole_startk;
+	int node_id;
+};
+
+static struct hw_mem_hole_info get_hw_mem_hole_info(void)
+{
+		struct hw_mem_hole_info mem_hole;
+		int i;
+
+                mem_hole.hole_startk = K8_HW_MEM_HOLE_SIZEK;
+		mem_hole.node_id = -1;
+
+                for (i = 0; i < 8; i++) {
+                        uint32_t base;
+                        uint32_t hole;
+                        base  = f1_read_config32(0x40 + (i << 3));
+                        if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
+                                continue;
+                        }
+
+                        hole = pci_read_config32(__f1_dev[i], 0xf0);
+                        if(hole & 1) { // we find the hole 
+	                        mem_hole.hole_startk = (hole & (0xff<<24)) >> 10;
+        	                mem_hole.node_id = i; // record the node No with hole
+                	        break; // only one hole
+			}
+                }
+
+                //We need to double check if there is speical set on base reg and limit reg are not continous instead of hole, it will find out it's hole_startk
+                if(mem_hole.node_id!=-1) {
+                        uint32_t limitk_pri = 0;
+                        for(i=0; i<8; i++) {
+                                uint32_t base, limit;
+                                unsigned base_k, limit_k;
+                                base  = f1_read_config32(0x40 + (i << 3));
+                                if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
+                                        continue;
+                                }
+
+                                base_k = (base & 0xffff0000) >> 2;
+                                if(limitk_pri != base_k) { // we find the hole 
+	                                mem_hole.hole_startk = limitk_pri;
+        	                        mem_hole.node_id = i;
+                	                break; //only one hole
+				}
+
+	                        limit = f1_read_config32(0x44 + (i << 3));
+                	        limit_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
+                                limitk_pri = limit_k;
+                        }
+                }
+		
+		return mem_hole;
+		
+}
+static void disable_hoist_memory(unsigned long hole_startk, int i)
 {
         int ii;
         device_t dev;
         uint32_t base, limit;
         uint32_t hoist;
+	uint32_t hole_sizek;
+
 
         //1. find which node has hole
         //2. change limit in that node.
         //3. change base and limit in later node
         //4. clear that node f0
 
+	//if there is not mem hole enabled, we need to change it's base instead
+
+	hole_sizek = (4*1024*1024) - hole_startk;
+
         for(ii=7;ii>i;ii--) {
 
                 base  = f1_read_config32(0x40 + (ii << 3));
@@ -710,12 +775,18 @@
         limit = f1_read_config32(0x44 + (i << 3));
         f1_write_config32(0x44 + (i << 3),limit - (hole_sizek << 2));
         dev = __f1_dev[i];
-        hoist = 0;
-        pci_write_config32(dev, 0xf0, hoist);
+	hoist = pci_read_config32(dev, 0xf0);
+	if(hoist & 1) {
+		pci_write_config32(dev, 0xf0, 0);
+	}
+	else {
+		base = pci_read_config32(dev, 0x40 + (i << 3));
+		f1_write_config32(0x40 + (i << 3),base - (hole_sizek << 2));
+	}
+		
 }
 
-/* Hole size auto from LNXI */
-static uint32_t hoist_memory(unsigned long mmio_basek, int i)
+static uint32_t hoist_memory(unsigned long hole_startk, int i)
 {
         int ii;
         uint32_t carry_over;
@@ -724,7 +795,7 @@
         uint32_t basek;
         uint32_t hoist;
 
-        carry_over = (4*1024*1024) - mmio_basek;
+        carry_over = (4*1024*1024) - hole_startk;
 
         for(ii=7;ii>i;ii--) {
 
@@ -741,16 +812,28 @@
         dev = __f1_dev[i];
         base  = pci_read_config32(dev, 0x40 + (i << 3));
         basek  = (base & 0xffff0000) >> 2;
-        hoist = /* hole start address */
-                ((mmio_basek << 10) & 0xff000000) +
-                /* hole address to memory controller address */
-                (((basek + carry_over) >> 6) & 0x0000ff00) +
-                /* enable */
-                1;
-        pci_write_config32(dev, 0xf0, hoist);
+	if(basek == hole_startk) {
+		//don't need set memhole here, because hole off set will be 0, overflow
+		//so need to change base reg instead, new basek will be 4*1024*1024
+		base &= 0x0000ffff;
+		base |= (4*1024*1024)<<2;
+		f1_write_config32(0x40 + (i<<3), base);
+	}
+	else 
+	{
+	        hoist = /* hole start address */
+        	        ((hole_startk << 10) & 0xff000000) +
+                	/* hole address to memory controller address */
+	                (((basek + carry_over) >> 6) & 0x0000ff00) +
+        	        /* enable */
+	                1;
+	
+        	pci_write_config32(dev, 0xf0, hoist);
+	}
 
         return carry_over;
 }
+#endif
 
 static void pci_domain_set_resources(device_t dev)
 {
@@ -762,7 +845,7 @@
 	uint32_t pci_tolm;
 	int i, idx;
 #if K8_HW_MEM_HOLE_SIZEK != 0
-	int j = -1;
+	struct hw_mem_hole_info mem_hole;
 	unsigned reset_memhole = 1;
 #endif
 
@@ -850,30 +933,50 @@
      * if mmio_basek is bigger that hole_basek and will use hole_basek as mmio_basek and we don't need to reset hole.
      * otherwise We reset the hole to the mmio_basek
      */
-        if (!is_cpu_pre_e0())
-        for (i = 0; i < 8; i++) {
-                uint32_t base;
-                base  = f1_read_config32(0x40 + (i << 3));
-                if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
-                        continue;
-                }
+        if (!is_cpu_pre_e0()) {
+
+		mem_hole = get_hw_mem_hole_info();
 
-                base = pci_read_config32(__f1_dev[i], 0xf0);
-                if((base & 1)==0) continue;
-                base &= 0xff<<24;
-                base >>= 10;
-                if (mmio_basek > base) { //We will use hole_basek as mmio_basek, and we don't need to reset hole anymore
-                        mmio_basek = base;
+                if ((mem_hole.node_id !=  -1) && (mmio_basek > mem_hole.hole_startk)) { //We will use hole_basek as mmio_basek, and we don't need to reset hole anymore
+                        mmio_basek = mem_hole.hole_startk;
 			reset_memhole = 0;
                 }
-		j = i; // record the node No with hole
-                break; // only one hole
-        }
-	if(reset_memhole && (j!=-1)) {
-               // We need to reset our Mem Hole, because We want more big HOLE than we already set
-               //Before that We need to disable mem hole at first, becase memhole could already be set on i+1 instead
-        	disable_hoist_memory(K8_HW_MEM_HOLE_SIZEK, j);
-        }
+		
+		//mmio_basek = 3*1024*1024; // for debug to meet boundary
+
+		if(reset_memhole) {
+			if(mem_hole.node_id!=-1) { // We need to select K8_HW_MEM_HOLE_SIZEK for raminit, it can not make hole_startk to some basek too....!
+		               // We need to reset our Mem Hole, because We want more big HOLE than we already set
+        		       //Before that We need to disable mem hole at first, becase memhole could already be set on i+1 instead
+	        		disable_hoist_memory(mem_hole.hole_startk, mem_hole.node_id);
+			}
+
+		#if K8_HW_MEM_HOLE_SIZE_AUTO_INC == 1
+			//We need to double check if the mmio_basek is valid for hole setting, if it is equal to basek, we need to decrease it some
+			uint32_t basek_pri; 
+	        	for (i = 0; i < 8; i++) {
+        	        	uint32_t base;
+				uint32_t basek;
+        	        	base  = f1_read_config32(0x40 + (i << 3));
+	        	        if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
+        	        	        continue;
+	                	}
+
+				basek = (base & 0xffff0000) >> 2;
+				if(mmio_basek == basek) {
+					mmio_basek -= (basek - basek_pri)>>1; // increase mem hole size to make sure it is on middle of pri node 
+					break; 
+				}
+				basek_pri = basek;
+			}	
+		#endif	
+        	}
+
+	} // is_cpu_pre_e0
 
 #endif
 
@@ -904,20 +1007,22 @@
 			
 		/* See if I need to split the region to accomodate pci memory space */
 		if ( (basek < 4*1024*1024 ) && (limitk > mmio_basek) ) {
-			if (basek < mmio_basek) {
+			if (basek <= mmio_basek) {
 				unsigned pre_sizek;
 				pre_sizek = mmio_basek - basek;
-				ram_resource(dev, (idx | i), basek, pre_sizek);
-				idx += 0x10;
-				sizek -= pre_sizek;
+				if(pre_sizek>0) {
+					ram_resource(dev, (idx | i), basek, pre_sizek);
+					idx += 0x10;
+					sizek -= pre_sizek;
+				}
 				#if K8_HW_MEM_HOLE_SIZEK != 0
 				if(reset_memhole) 
                 	                if(!is_cpu_pre_e0() ) 
                        		                 sizek += hoist_memory(mmio_basek,i);
 				#endif
 				
 				basek = mmio_basek;
 			}
 			if ((basek + sizek) <= 4*1024*1024) {
diff -uNr freebios2.11182005_to_s_o/src/northbridge/amd/amdk8/raminit.c freebios2.11212005_to_s_o/src/northbridge/amd/amdk8/raminit.c
--- freebios2.11182005_to_s_o/src/northbridge/amd/amdk8/raminit.c	2005-11-18 21:24:37.000000000 -0800
+++ freebios2.11212005_to_s_o/src/northbridge/amd/amdk8/raminit.c	2005-11-21 17:44:40.000000000 -0800
@@ -868,26 +868,7 @@
 	}
 }
 
-#if K8_HW_MEM_HOLE_SIZEK != 0
-#define K8_HW_MEM_HOLE_LIMITK 4*1024*1024
-#define K8_HW_MEM_HOLE_BASEK (K8_HW_MEM_HOLE_LIMITK - K8_HW_MEM_HOLE_SIZEK )
-
-static void set_hw_mem_hole(const struct mem_controller *ctrl, unsigned base_k)
-{
-        /* Route the addresses to the controller node */
-        unsigned val;
-
-        val = pci_read_config32(ctrl->f1,0xf0);
-
-        val &= 0x00ff00fe;
-        val = (K8_HW_MEM_HOLE_BASEK << 10) | ((K8_HW_MEM_HOLE_SIZEK+base_k)>>(16-10)) | 1;
-
-        pci_write_config32(ctrl->f1, 0xf0, val);
-}
-
-#endif
-
-static void set_top_mem(unsigned tom_k)
+static void set_top_mem(unsigned tom_k, unsigned hole_startk)
 {
 	/* Error if I don't have memory */
 	if (!tom_k) {
@@ -910,10 +891,11 @@
 	 */
 	if (tom_k >= 0x003f0000) {
 #if K8_HW_MEM_HOLE_SIZEK != 0
-                tom_k = K8_HW_MEM_HOLE_BASEK;
-#else
-                tom_k = 0x3f0000;
+                if(hole_startk != 0) {
+                        tom_k = hole_startk;
+                } else
 #endif
+                tom_k = 0x3f0000;
 	}
 	msr.lo = (tom_k & 0x003fffff) << 10;
 	msr.hi = (tom_k & 0xffc00000) >> 22;
@@ -1154,16 +1136,8 @@
 	/* Compute the memory base address */
 	base_k = memory_end_k(ctrl, ctrl->node_id);
 	tom_k += base_k;
-#if K8_HW_MEM_HOLE_SIZEK != 0
-	if(!is_cpu_pre_e0()) {
-                /* See if I need to check the range cover hole */
-                if ((base_k <= K8_HW_MEM_HOLE_BASEK) && (tom_k > K8_HW_MEM_HOLE_BASEK)) {
-			tom_k += K8_HW_MEM_HOLE_SIZEK;
-                }
-	}
-#endif
 	route_dram_accesses(ctrl, base_k, tom_k);
-	set_top_mem(tom_k);
+	set_top_mem(tom_k, 0);
 }
 
 static long disable_dimm(const struct mem_controller *ctrl, unsigned index, long dimm_mask)
@@ -2203,6 +2177,110 @@
 	return;
 }
 
+#if K8_HW_MEM_HOLE_SIZEK != 0
+static uint32_t hoist_memory(int controllers, const struct mem_controller *ctrl,unsigned hole_startk, int i)
+{
+        int ii;
+        uint32_t carry_over;
+        device_t dev;
+        uint32_t base, limit;
+        uint32_t basek;
+        uint32_t hoist;
+        int j;
+
+        carry_over = (4*1024*1024) - hole_startk;
+
+        for(ii=controllers - 1;ii>i;ii--) {
+                base  = pci_read_config32(ctrl[0].f1, 0x40 + (ii << 3));
+                limit = pci_read_config32(ctrl[0].f1, 0x44 + (ii << 3));
+                if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
+                        continue;
+                }
+                for(j = 0; j < controllers; j++) {
+                        pci_write_config32(ctrl[j].f1, 0x44 + (ii << 3), limit + (carry_over << 2));
+                        pci_write_config32(ctrl[j].f1, 0x40 + (ii << 3), base + (carry_over << 2));
+                }
+        }
+        limit = pci_read_config32(ctrl[0].f1, 0x44 + (i << 3));
+        for(j = 0; j < controllers; j++) {
+                pci_write_config32(ctrl[j].f1, 0x44 + (i << 3), limit + (carry_over << 2));
+        }
+        dev = ctrl[i].f1;
+        base  = pci_read_config32(dev, 0x40 + (i << 3));
+        basek  = (base & 0xffff0000) >> 2;
+        if(basek == hole_startk) {
+                //don't need set memhole here, because hole off set will be 0, overflow
+                //so need to change base reg instead, new basek will be 4*1024*1024
+                base &= 0x0000ffff;
+                base |= (4*1024*1024)<<2;
+                for(j = 0; j < controllers; j++) {
+                        pci_write_config32(ctrl[j].f1, 0x40 + (i<<3), base);
+                }
+        }
+	else {
+        	hoist = /* hole start address */
+                	((hole_startk << 10) & 0xff000000) +
+	                /* hole address to memory controller address */
+        	        (((basek + carry_over) >> 6) & 0x0000ff00) +
+                	/* enable */
+	                1;
+	        pci_write_config32(dev, 0xf0, hoist);
+	}
+
+        return carry_over;
+}
+
+static void set_hw_mem_hole(int controllers, const struct mem_controller *ctrl)
+{
+
+        uint32_t hole_startk;
+        int i;
+
+        hole_startk = 4*1024*1024 - K8_HW_MEM_HOLE_SIZEK;
+
+#if K8_HW_MEM_HOLE_SIZE_AUTO_INC == 1 
+        //We need to double check if the hole_startk is valid, if it is equal to basek, we need to decrease it some
+        uint32_t basek_pri;
+        for(i=0; i<controllers; i++) {
+                        uint32_t base;
+                        unsigned base_k;
+                        base  = pci_read_config32(ctrl[0].f1, 0x40 + (i << 3));
+                        if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
+                                continue;
+                        }
+                        base_k = (base & 0xffff0000) >> 2;
+                        if(base_k == hole_startk) {
+                                hole_startk -= (base_k - basek_pri)>>1; // decrease mem hole startk to make sure it is on middle of privous node
+                                break; //only one hole
+                        }
+                        basek_pri = base_k;
+        }
+
+#endif
+        //find node index that need do set hole
+        for(i=0; i<controllers; i++) {
+                        uint32_t base, limit;
+                        unsigned base_k, limit_k;
+                        base  = pci_read_config32(ctrl[0].f1, 0x40 + (i << 3));
+                        if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
+                                continue;
+                        }
+                        limit = pci_read_config32(ctrl[0].f1, 0x44 + (i << 3));
+                        base_k = (base & 0xffff0000) >> 2;
+                        limit_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
+			if ((base_k <= hole_startk) && (limit_k > hole_startk)) {
+                                unsigned end_k;
+                                hoist_memory(controllers, ctrl, hole_startk, i);
+                                end_k = memory_end_k(ctrl, controllers);
+                                set_top_mem(end_k, hole_startk);
+                                break; //only one hole
+                        }
+        }
+
+}
+
+#endif
+
 #define TIMEOUT_LOOPS 300000
 static void sdram_enable(int controllers, const struct mem_controller *ctrl)
 {
@@ -2301,25 +2379,16 @@
 			} while(((dcl & DCL_MemClrStatus) == 0) || ((dcl & DCL_DramEnable) == 0) );
 		}
 
-		        // init e0 mem hole here
-#if K8_HW_MEM_HOLE_SIZEK != 0
-        	if (!is_cpu_pre_e0()) {
-                        uint32_t base, limit;
-                        unsigned base_k, limit_k;
-                        base  = pci_read_config32(ctrl->f1, 0x40 + (i << 3));
-                        limit = pci_read_config32(ctrl->f1, 0x44 + (i << 3));
-                        base_k = (base & 0xffff0000) >> 2;
-                        limit_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
-                        if ((base_k <= K8_HW_MEM_HOLE_BASEK) && (limit_k > K8_HW_MEM_HOLE_BASEK)) {
-                                set_hw_mem_hole(ctrl+i, base_k);
-                        }
-                }
-        
-#endif  
-
 		print_debug(" done\r\n");
 	}
 
+#if K8_HW_MEM_HOLE_SIZEK != 0
+         // init hw mem hole here
+        /* DramHoleValid bit only can be set after MemClrStatus is set by Hardware */
+	if(!is_cpu_pre_e0())
+	        set_hw_mem_hole(controllers, ctrl);
+#endif
+
 	//FIXME add enable node interleaving here -- yhlu
 	/*needed?
 		1. check how many nodes we have , if not all has ram installed get out










