stephan, oille,

Please check the memhole patch.

when the hole_startk ==  one node basek,
1. it will modify base reg instead of hole reg
2. or if K8_HW_MEM_HOLE_SIZE_AUTO =1, then hole_startk will be moved to pri node mem middle....

this could solve the problem such as
1. two nodes, and first cpu have 2G installed, and memhole size is set to 2G, or mmio_basek is 2G, ( 2 IB installed).
2. four nodes. and every node has 1 G installed, and mmio will be 1G, and memhole is 1G.....

New Mem hole behavoir will be
1. if K8_HW_MEM_HOLE_SIZEK == 0, then don't set mem_hole
2. if it is set, and it make hole_startk <= mmio_basek, will not reset mem hole in northbridge.c
3. if it is set, and it make hole_startk > mmio_basek, memhole will be reset in northbeidge.c
4. if hole_startk met with basek, it will use base reg instead of increase the hole_sizek to make hole_startk to the middle of pri node.

YH
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










-- 
LinuxBIOS mailing list
LinuxBIOS@openbios.org
http://www.openbios.org/mailman/listinfo/linuxbios

Reply via email to