diff -Naurp linux-2.6.16.2.orig/arch/mips/Makefile linux-2.6.16.2/arch/mips/Makefile --- linux-2.6.16.2.orig/arch/mips/Makefile 2006-04-10 23:23:36.000000000 -0400 +++ linux-2.6.16.2/arch/mips/Makefile 2006-04-10 23:30:57.000000000 -0400 @@ -665,7 +665,7 @@ endif # will break. # core-$(CONFIG_SGI_IP32) += arch/mips/sgi-ip32/ -cflags-$(CONFIG_SGI_IP32) += -Iinclude/asm-mips/mach-ip32 +cflags-$(CONFIG_SGI_IP32) += -mr10k-cache-barrier=2 -Iinclude/asm-mips/mach-ip32 load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 # diff -Naurp linux-2.6.16.2.orig/arch/mips/lib/memcpy.S linux-2.6.16.2/arch/mips/lib/memcpy.S --- linux-2.6.16.2.orig/arch/mips/lib/memcpy.S 2006-03-20 00:53:29.000000000 -0500 +++ linux-2.6.16.2/arch/mips/lib/memcpy.S 2006-04-10 23:27:39.000000000 -0400 @@ -32,6 +32,14 @@ #include #include +#ifdef CONFIG_SGI_IP32 +/* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */ +# include +# define R10KCBARRIER(addr) cache Cache_Barrier, addr; +#else +# define R10KCBARRIER(addr) +#endif + #define dst a0 #define src a1 #define len a2 @@ -195,6 +203,7 @@ FEXPORT(__copy_user) */ #define rem t8 + R10KCBARRIER(0(ra)) /* hopefully inhibits speculative store prefetch */ /* * The "issue break"s below are very approximate. * Issue delays for dcache fills will perturb the schedule, as will @@ -227,6 +236,7 @@ both_aligned: PREF( 1, 3*32(dst) ) .align 4 1: + R10KCBARRIER(0(ra)) /* ra must be valid anyway */ EXC( LOAD t0, UNIT(0)(src), l_exc) EXC( LOAD t1, UNIT(1)(src), l_exc_copy) EXC( LOAD t2, UNIT(2)(src), l_exc_copy) @@ -268,6 +278,7 @@ EXC( LOAD t2, UNIT(2)(src), l_exc_copy) EXC( LOAD t3, UNIT(3)(src), l_exc_copy) SUB len, len, 4*NBYTES ADD src, src, 4*NBYTES + R10KCBARRIER(0(ra)) EXC( STORE t0, UNIT(0)(dst), s_exc_p4u) EXC( STORE t1, UNIT(1)(dst), s_exc_p3u) EXC( STORE t2, UNIT(2)(dst), s_exc_p2u) @@ -281,6 +292,7 @@ less_than_4units: beq rem, len, copy_bytes nop 1: + R10KCBARRIER(0(ra)) EXC( LOAD t0, 0(src), l_exc) ADD src, src, NBYTES SUB len, len, NBYTES @@ -326,6 +338,7 @@ EXC( LDFIRST t3, FIRST(0)(src), l_exc) EXC( LDREST t3, REST(0)(src), l_exc_copy) SUB t2, t2, t1 # t2 = number of bytes copied xor match, t0, t1 + R10KCBARRIER(0(ra)) EXC( STFIRST t3, FIRST(0)(dst), s_exc) beq len, t2, done SUB len, len, t2 @@ -346,6 +359,7 @@ src_unaligned_dst_aligned: * It's OK to load FIRST(N+1) before REST(N) because the two addresses * are to the same unit (unless src is aligned, but it's not). */ + R10KCBARRIER(0(ra)) EXC( LDFIRST t0, FIRST(0)(src), l_exc) EXC( LDFIRST t1, FIRST(1)(src), l_exc_copy) SUB len, len, 4*NBYTES @@ -374,6 +388,7 @@ cleanup_src_unaligned: beq rem, len, copy_bytes nop 1: + R10KCBARRIER(0(ra)) EXC( LDFIRST t0, FIRST(0)(src), l_exc) EXC( LDREST t0, REST(0)(src), l_exc_copy) ADD src, src, NBYTES @@ -387,6 +402,7 @@ copy_bytes_checklen: nop copy_bytes: /* 0 < len < NBYTES */ + R10KCBARRIER(0(ra)) #define COPY_BYTE(N) \ EXC( lb t0, N(src), l_exc); \ SUB len, len, 1; \ @@ -499,6 +515,7 @@ LEAF(__rmemcpy) /* a0=dst a1=src a2= ADD a1, a2 # src = src + len r_end_bytes: + R10KCBARRIER(0(ra)) lb t0, -1(a1) SUB a2, a2, 0x1 sb t0, -1(a0) @@ -511,6 +528,7 @@ r_out: move a2, zero r_end_bytes_up: + R10KCBARRIER(0(ra)) lb t0, (a1) SUB a2, a2, 0x1 sb t0, (a0) diff -Naurp linux-2.6.16.2.orig/arch/mips/lib/strncpy_user.S linux-2.6.16.2/arch/mips/lib/strncpy_user.S --- linux-2.6.16.2.orig/arch/mips/lib/strncpy_user.S 2006-03-20 00:53:29.000000000 -0500 +++ linux-2.6.16.2/arch/mips/lib/strncpy_user.S 2006-04-10 23:27:39.000000000 -0400 @@ -5,11 +5,20 @@ * * Copyright (c) 1996, 1999 by Ralf Baechle */ +#include #include #include #include #include +#ifdef CONFIG_SGI_IP32 +/* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */ +# include +# define R10KCBARRIER(addr) cache Cache_Barrier, addr; +#else +# define R10KCBARRIER(addr) +#endif + #define EX(insn,reg,addr,handler) \ 9: insn reg, addr; \ .section __ex_table,"a"; \ @@ -38,6 +47,7 @@ FEXPORT(__strncpy_from_user_nocheck_asm) .set noreorder 1: EX(lbu, t0, (v1), fault) PTR_ADDIU v1, 1 + R10KCBARRIER(0(ra)) beqz t0, 2f sb t0, (a0) PTR_ADDIU v0, 1 diff -Naurp linux-2.6.16.2.orig/arch/mips/lib-64/memset.S linux-2.6.16.2/arch/mips/lib-64/memset.S --- linux-2.6.16.2.orig/arch/mips/lib-64/memset.S 2006-03-20 00:53:29.000000000 -0500 +++ linux-2.6.16.2/arch/mips/lib-64/memset.S 2006-04-10 23:27:39.000000000 -0400 @@ -6,10 +6,19 @@ * Copyright (C) 1998, 1999, 2000 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ +#include #include #include #include +#ifdef CONFIG_SGI_IP32 +/* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */ +# include +# define R10KCBARRIER(addr) cache Cache_Barrier, addr; +#else +# define R10KCBARRIER(addr) +#endif + #define EX(insn,reg,addr,handler) \ 9: insn reg, addr; \ .section __ex_table,"a"; \ @@ -57,6 +66,7 @@ FEXPORT(__bzero) beqz t0, 1f PTR_SUBU t0, LONGSIZE /* alignment in bytes */ + R10KCBARRIER(0(ra)) #ifdef __MIPSEB__ EX(sdl, a1, (a0), first_fixup) /* make dword aligned */ #endif @@ -74,11 +84,13 @@ FEXPORT(__bzero) PTR_ADDU t1, a0 /* end address */ .set reorder 1: PTR_ADDIU a0, 64 + R10KCBARRIER(0(ra)) f_fill64 a0, -64, a1, fwd_fixup bne t1, a0, 1b .set noreorder memset_partial: + R10KCBARRIER(0(ra)) PTR_LA t1, 2f /* where to start */ .set noat dsrl AT, t0, 1 @@ -96,6 +108,7 @@ memset_partial: beqz a2, 1f PTR_ADDU a0, a2 /* What's left */ + R10KCBARRIER(0(ra)) #ifdef __MIPSEB__ EX(sdr, a1, -1(a0), last_fixup) #endif @@ -110,6 +123,7 @@ small_memset: PTR_ADDU t1, a0, a2 1: PTR_ADDIU a0, 1 /* fill bytewise */ + R10KCBARRIER(0(ra)) bne t1, a0, 1b sb a1, -1(a0) diff -Naurp linux-2.6.16.2.orig/arch/mips/mm/c-r4k.c linux-2.6.16.2/arch/mips/mm/c-r4k.c --- linux-2.6.16.2.orig/arch/mips/mm/c-r4k.c 2006-04-10 23:23:36.000000000 -0400 +++ linux-2.6.16.2/arch/mips/mm/c-r4k.c 2006-04-10 23:27:39.000000000 -0400 @@ -646,6 +646,27 @@ static void r4k_dma_cache_inv(unsigned l bc_inv(addr, size); } + +#ifdef CONFIG_CPU_R10000 +static void r10k_dma_cache_inv(unsigned long addr, unsigned long size) +{ + unsigned long sc_lsize = current_cpu_data.scache.linesz; + unsigned long end, a; + + /* Catch bad driver code */ + BUG_ON(size == 0); + //BUG_ON(!cpu_has_subset_pcaches); + + a = addr & ~(sc_lsize - 1); + end = (addr + size - 1) & ~(sc_lsize - 1); + while (1) { + invalidate_scache_line(a); /* Hit_Invalidate_SD/S */ + if (a == end) + break; + a += sc_lsize; + } +} +#endif /* CONFIG_CPU_R10000 */ #endif /* CONFIG_DMA_NONCOHERENT */ /* @@ -1207,7 +1228,16 @@ void __init r4k_cache_init(void) #ifdef CONFIG_DMA_NONCOHERENT _dma_cache_wback_inv = r4k_dma_cache_wback_inv; _dma_cache_wback = r4k_dma_cache_wback_inv; - _dma_cache_inv = r4k_dma_cache_inv; + switch (current_cpu_data.cputype) { +#ifdef CONFIG_CPU_R10000 + case CPU_R10000: + case CPU_R12000: + _dma_cache_inv = r10k_dma_cache_inv; + break; +#endif + default: + _dma_cache_inv = r4k_dma_cache_inv; + } #endif build_clear_page(); diff -Naurp linux-2.6.16.2.orig/arch/mips/mm/cache.c linux-2.6.16.2/arch/mips/mm/cache.c --- linux-2.6.16.2.orig/arch/mips/mm/cache.c 2006-03-20 00:53:29.000000000 -0500 +++ linux-2.6.16.2/arch/mips/mm/cache.c 2006-04-10 23:27:39.000000000 -0400 @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -60,8 +61,26 @@ asmlinkage int sys_cacheflush(unsigned l if (!access_ok(VERIFY_WRITE, (void __user *) addr, bytes)) return -EFAULT; - flush_icache_range(addr, addr + bytes); - + switch (cache) { + case DCACHE: + if (bytes > 0) + (*_dma_cache_wback_inv)(addr, bytes); + break; + case ICACHE: + flush_icache_range(addr, addr + bytes); + break; + case BCACHE: +#if 0 /* Hmm, the same address in both I- and D-cache ? */ + if (bytes > 0) + (*_dma_cache_wback_inv)(addr, bytes); + flush_icache_range(addr, addr + bytes); +#else + (*flush_cache_all)(); +#endif + break; + default: + return -EINVAL; + } return 0; } diff -Naurp linux-2.6.16.2.orig/include/asm-mips/war.h linux-2.6.16.2/include/asm-mips/war.h --- linux-2.6.16.2.orig/include/asm-mips/war.h 2006-03-20 00:53:29.000000000 -0500 +++ linux-2.6.16.2/include/asm-mips/war.h 2006-04-10 23:27:39.000000000 -0400 @@ -194,6 +194,10 @@ #ifdef CONFIG_SGI_IP27 #define R10000_LLSC_WAR 1 #endif +/* Branch-likely and friends won't hurt a weird uniprocessor system either */ +#if defined(CONFIG_SGI_IP32) && defined(CONFIG_CPU_R10000) +#define R10000_LLSC_WAR 1 +#endif /* * Workarounds default to off