Buggy R4600 support (was: [Oops] Indy R4600 Oops(es) w/ 2.4.19-rc1)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2002-07-01 16:28:13 +0200, Maciej W. Rozycki <macro@ds2.pg.gda.pl>
wrote in message <Pine.GSO.3.96.1020701161009.7601E-100000@delta.ds2.pg.gda.pl>:
> On Mon, 1 Jul 2002, Jan-Benedict Glaw wrote:
> > Okay, stupid idea. All these flush functions seem to be never called in
> > parallel or recursive, so if might be possible to have a global flags
> > variable and instead of always calling __save..() and __restore..(),
> > we bulid a pair of inline functions doing this. This wouldn't give
> > any penalty for !CONFIG_CPU_R4X00 and doesn't obscure the code so much
> > as all those #ifdef and #endif's would do... I'll test my suggestion
> > as fast as I reach my Indy again (is powered down at home...).
> 
>  Feel free to use the change privately.  Otherwise please code a real fix,
> i.e. a set of buggy-R4600-specific functions, as CONFIG_CPU_R4X00 means
> other processors as well, e.g. R4000 or R4400 which are fine here. 

Well, here's step 1. I've created inline functions for save/restore
flags and dropped them in where (as of 2.4.16) the calls where. My Indy
already runs (fine) with this. Now, there are two possibilities: I could
double all the cache handling functions for old R4600 and set
appropriate pointers in all the __init functions at the end of c-r4k.c.
The other variant would be to work on the inline functions to only
save/restore if this is a buggy CPU. The next step could be to only mask
out some interrupts as suggested, but I'm currently not experienced
enough to do this. I've now also looked at www.mips.com, but I cannot
find the erratta for R4600:-( I'm too dumb...

However, here's what I currently have. Feel free to throw stones at me:

Ralf: There's a little spellinck ficks at patches end...

Index: c-r4k.c
===================================================================
RCS file: /cvs/linux/arch/mips/mm/c-r4k.c,v
retrieving revision 1.3.2.3
diff -u -r1.3.2.3 c-r4k.c
--- c-r4k.c	2002/05/29 03:03:17	1.3.2.3
+++ c-r4k.c	2002/07/01 15:40:03
@@ -54,6 +54,10 @@
 
 struct bcache_ops *bcops = &no_sc_ops;
 
+#ifdef CONFIG_CPU_R4X00
+unsigned long	r4600_buggy_flags;
+#endif /* CONFIG_CPU_R4X00 */
+
 /*
  * On processors with QED R4600 style two set assosicative cache
  * this is the bit which selects the way in the cache for the
@@ -62,6 +66,26 @@
 #define icache_waybit (icache_size >> 1)
 #define dcache_waybit (dcache_size >> 1)
 
+static inline void
+r4600_bug_start(void)
+{
+#ifdef CONFIG_CPU_R4X00
+	__save_and_cli(r4600_buggy_flags);
+	__asm__ __volatile__("nop;nop;nop;nop");
+#endif /* CONFIG_CPU_R4X00 */
+	return;
+}
+
+static inline void
+r4600_bug_finish(void)
+{
+#ifdef CONFIG_CPU_R4X00
+	__restore_flags(r4600_buggy_flags);
+#endif /* CONFIG_CPU_R4X00 */
+	return;
+}
+
+
 /*
  * If you think for one second that this stuff coming up is a lot
  * of bulky code eating too many kernel cache lines.  Think _again_.
@@ -77,47 +101,65 @@
 
 static inline void r4k_flush_cache_all_s16d16i16(void)
 {
+	r4600_bug_start();
 	blast_dcache16(); blast_icache16(); blast_scache16();
+	r4600_bug_finish();
 }
 
 static inline void r4k_flush_cache_all_s32d16i16(void)
 {
+	r4600_bug_start();
 	blast_dcache16(); blast_icache16(); blast_scache32();
+	r4600_bug_finish();
 }
 
 static inline void r4k_flush_cache_all_s64d16i16(void)
 {
+	r4600_bug_start();
 	blast_dcache16(); blast_icache16(); blast_scache64();
+	r4600_bug_finish();
 }
 
 static inline void r4k_flush_cache_all_s128d16i16(void)
 {
+	r4600_bug_start();
 	blast_dcache16(); blast_icache16(); blast_scache128();
+	r4600_bug_finish();
 }
 
 static inline void r4k_flush_cache_all_s32d32i32(void)
 {
+	r4600_bug_start();
 	blast_dcache32(); blast_icache32(); blast_scache32();
+	r4600_bug_finish();
 }
 
 static inline void r4k_flush_cache_all_s64d32i32(void)
 {
+	r4600_bug_start();
 	blast_dcache32(); blast_icache32(); blast_scache64();
+	r4600_bug_finish();
 }
 
 static inline void r4k_flush_cache_all_s128d32i32(void)
 {
+	r4600_bug_start();
 	blast_dcache32(); blast_icache32(); blast_scache128();
+	r4600_bug_finish();
 }
 
 static inline void r4k_flush_cache_all_d16i16(void)
 {
+	r4600_bug_start();
 	blast_dcache16(); blast_icache16();
+	r4600_bug_finish();
 }
 
 static inline void r4k_flush_cache_all_d32i32(void)
 {
+	r4600_bug_start();
 	blast_dcache32(); blast_icache32();
+	r4600_bug_finish();
 }
 
 static void
@@ -143,6 +185,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_bug_start();
 			while (start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -152,6 +195,7 @@
 					blast_scache16_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_bug_finish();
 		}
 	}
 }
@@ -179,6 +223,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_bug_start();
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -188,6 +233,7 @@
 					blast_scache32_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_bug_finish();
 		}
 	}
 }
@@ -214,6 +260,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_bug_start();
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -223,6 +270,7 @@
 					blast_scache64_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_bug_finish();
 		}
 	}
 }
@@ -249,6 +297,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_bug_start();
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -258,6 +307,7 @@
 					blast_scache128_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_bug_finish();
 		}
 	}
 }
@@ -284,6 +334,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_bug_start();
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -293,6 +344,7 @@
 					blast_scache32_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_bug_finish();
 		}
 	}
 }
@@ -319,6 +371,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_bug_start();
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -328,6 +381,7 @@
 					blast_scache64_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_bug_finish();
 		}
 	}
 }
@@ -354,6 +408,7 @@
 			pmd_t *pmd;
 			pte_t *pte;
 
+			r4600_bug_start();
 			while(start < end) {
 				pgd = pgd_offset(mm, start);
 				pmd = pmd_offset(pgd, start);
@@ -363,6 +418,7 @@
 					blast_scache128_page(start);
 				start += PAGE_SIZE;
 			}
+			r4600_bug_finish();
 		}
 	}
 }
@@ -375,7 +431,9 @@
 #ifdef DEBUG_CACHE
 		printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
 #endif
+		r4600_bug_start();
 		blast_dcache16(); blast_icache16();
+		r4600_bug_finish();
 	}
 }
 
@@ -387,7 +445,9 @@
 #ifdef DEBUG_CACHE
 		printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
 #endif
+		r4600_bug_start();
 		blast_dcache32(); blast_icache32();
+		r4600_bug_finish();
 	}
 }
 
@@ -504,6 +564,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_bug_start();
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -533,6 +594,7 @@
 	} else
 		blast_scache16_page(page);
 out:
+	r4600_bug_finish();
 }
 
 static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma,
@@ -553,6 +615,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_bug_start();
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -581,6 +644,7 @@
 	} else
 		blast_scache32_page(page);
 out:
+	r4600_bug_finish();
 }
 
 static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma,
@@ -601,6 +665,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_bug_start();
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -629,6 +694,7 @@
 	} else
 		blast_scache64_page(page);
 out:
+	r4600_bug_finish();
 }
 
 static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma,
@@ -649,6 +715,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_bug_start();
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -678,6 +745,7 @@
 	} else
 		blast_scache128_page(page);
 out:
+	r4600_bug_finish();
 }
 
 static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma,
@@ -698,6 +766,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_bug_start();
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -727,6 +796,7 @@
 	} else
 		blast_scache32_page(page);
 out:
+	r4600_bug_finish();
 }
 
 static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma,
@@ -747,6 +817,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_bug_start();
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -776,6 +847,7 @@
 	} else
 		blast_scache64_page(page);
 out:
+	r4600_bug_finish();
 }
 
 static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma,
@@ -796,6 +868,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_bug_start();
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -824,6 +897,7 @@
 	} else
 		blast_scache128_page(page);
 out:
+	r4600_bug_finish();
 }
 
 static void r4k_flush_cache_page_d16i16(struct vm_area_struct *vma,
@@ -844,6 +918,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_bug_start();
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -872,6 +947,7 @@
 		blast_dcache16_page_indexed(page);
 	}
 out:
+	r4600_bug_finish();
 }
 
 static void r4k_flush_cache_page_d32i32(struct vm_area_struct *vma,
@@ -892,6 +968,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_bug_start();
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -921,6 +998,7 @@
 		blast_dcache32_page_indexed(page);
 	}
 out:
+	r4600_bug_finish();
 }
 
 static void r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma,
@@ -941,6 +1019,7 @@
 #ifdef DEBUG_CACHE
 	printk("cpage[%d,%08lx]", (int)mm->context, page);
 #endif
+	r4600_bug_start();
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
 	pmdp = pmd_offset(pgdp, page);
@@ -970,6 +1049,7 @@
 		blast_dcache32_page_indexed(page ^ dcache_waybit);
 	}
 out:
+	r4600_bug_finish();
 }
 
 /* If the addresses passed to these routines are valid, they are
@@ -1063,7 +1143,7 @@
 		flush_cache_all();
 	} else {
 #ifdef R4600_V2_HIT_CACHEOP_WAR
-		/* Workaround for R4600 bug.  See comment in <asm/war>. */
+		/* Workaround for R4600 bug.  See comment in <asm/war.h>. */
 		__save_and_cli(flags);
 		*(volatile unsigned long *)KSEG1;
 #endif




-- 
Jan-Benedict Glaw   .   jbglaw@lug-owl.de   .   +49-172-7608481
	 -- New APT-Proxy written in shell script --
	   http://lug-owl.de/~jbglaw/software/ap2/

Attachment: pgp00211.pgp
Description: PGP signature


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux