From: NIIBE Y. <gn...@m1...> - 2002-04-01 02:17:14
|
And here's the change for 2.4. 2002-04-01 NIIBE Yutaka <gn...@m1...> * arch/sh/mm/cache-sh4.c (flush_cache_4096_all): New function. (flush_icache_all): New function. (flush_cache_4096): Changed the ifdef condition only for ST40STB1. (flush_cache_all, flush_cache_range): New implementation using flush_icache_all and flush_cache_4096_all. * arch/sh/mm/clear_page.S (__flush_cache_4096_all): New function. Index: arch/sh/mm/cache-sh4.c =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/mm/cache-sh4.c,v retrieving revision 1.1.1.1.2.4 diff -u -3 -p -r1.1.1.1.2.4 cache-sh4.c --- arch/sh/mm/cache-sh4.c 29 Mar 2002 00:01:08 -0000 1.1.1.1.2.4 +++ arch/sh/mm/cache-sh4.c 1 Apr 2002 02:13:31 -0000 @@ -207,10 +207,48 @@ void flush_cache_sigtramp(unsigned long restore_flags(flags); } +static void flush_cache_4096_all(unsigned long start) +{ +#if defined(CONFIG_CPU_SUBTYPE_ST40STB1) + /* + * ST40 have no restriction to handle cache. + * (While SH7750/SH7751 must do that at P2 area.) + */ + unsigned long addr; + for (addr = start; addr < start + 4096; addr += 32) + ctrl_outl(0, addr); +#else + register unsigned long __r0 __asm__ ("r0") = 0; + register unsigned long __r1 __asm__ ("r1") = 128; + register unsigned long __r4 __asm__ ("r4"); + register unsigned long __r5 __asm__ ("r5"); + register unsigned long __r6 __asm__ ("r6"); + register unsigned long __r7 __asm__ ("r7"); + extern void __flush_cache_4096_all(unsigned long); + + asm volatile("jsr @%7; nop" + : "=&r" (__r4), "=&r" (__r5), "=&r" (__r6), "=&r" (__r7) + : "0" (start), "r" (__r0), "r" (__r1), + "r" (__flush_cache_4096_all + 0x20000000) + : "pr"); +#endif +} + static inline void flush_cache_4096(unsigned long start, unsigned long phys) { -#if defined(CONFIG_CPU_SUBTYPE_SH7750) +#if defined(CONFIG_CPU_SUBTYPE_ST40STB1) + /* + * ST40 have no restriction to handle cache. + * (While SH7750/SH7751 must do that at P2 area.) + */ + unsigned long addr, data; + for (addr = start; addr < start + 4096; addr += 32) { + data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); + if (data == phys) + ctrl_outl(0, addr); + } +#else register unsigned long addr __asm__ ("r4"); register unsigned long data __asm__ ("r0"); register unsigned long __r5 __asm__ ("r5") = phys; @@ -223,17 +261,6 @@ static inline void flush_cache_4096(unsi : "0" (start), "1" (__flush_cache_4096 + 0x20000000), "r" (__r5), "r" (__r6), "r" (__r7) : "pr"); -#else - /* - * SH7751 and ST40 have no restriction to handle cache. - * (While SH7750 must do that at P2 area.) - */ - unsigned long addr, data; - for (addr = start; addr < start + 4096; addr += 32) { - data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); - if (data == phys) - ctrl_outl(0, addr); - } #endif } @@ -261,25 +288,56 @@ void flush_dcache_page(struct page *page } } -void flush_cache_all(void) +static inline void flush_icache_all(void) { - extern unsigned long empty_zero_page[1024]; unsigned long flags; - unsigned long addr; save_and_cli(flags); + jump_to_P2(); + /* Flush I-cache */ + ctrl_outl(CCR_CACHE_VAL|CCR_CACHE_ICI, CCR); + back_to_P1(); + restore_flags(flags); +} + +#undef C_IMPLEMENTATION_OF_CACHE_ALL + +void flush_cache_all(void) +{ + extern unsigned long empty_zero_page[1024]; /* Prefetch the data to write back D-cache */ + +#ifdef C_IMPLEMENTATION_OF_CACHE_ALL + unsigned long addr; + for (addr = (unsigned long)empty_zero_page; addr < (unsigned long)empty_zero_page + 1024*16; addr += L1_CACHE_BYTES) asm volatile("pref @%0"::"r" (addr)); - - jump_to_P2(); - /* Flush D-cache/I-cache */ - ctrl_outl(CCR_CACHE_INIT, CCR); - back_to_P1(); - restore_flags(flags); +#else + unsigned long a0, a1, a2, a3, cnt; + asm volatile( + "mov %0, %1; add #32, %1\n\t" + "mov %0, %2; add #64, %2\n\t" + "mov %1, %3; add #64, %3\n\t" + "1:\n\t" + "pref @%0\n\t" + "dt %4\n\t" + "pref @%1\n\t" + "add %5, %0\n\t" + "pref @%2\n\t" + "add %5, %1\n\t" + "pref @%3\n\t" + "add %5, %2\n\t" + "bf/s 1b\n\t" + " add %5, %3" + : "=&r" (a0), "=&r" (a1), "=&r" (a2), "=&r" (a3), "=&r" (cnt) + : "r" (32*4), "0" (empty_zero_page), "4" (1024*16/32/4) + : "t"); + } +#endif + flush_icache_all(); } void flush_cache_mm(struct mm_struct *mm) @@ -341,15 +399,51 @@ static void __flush_cache_page(struct vm void flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - /* - * We could call flush_cache_page for the pages of these - * range, but it's really time consuming (we have to scan the - * caches all the time...). - * - * We can't use A-bit magic, as there's the case we don't have - * valid entry on TLB. - */ - flush_cache_all(); + unsigned long p = start & PAGE_MASK; + pgd_t *dir; + pmd_t *pmd; + pte_t *pte; + pte_t entry; + unsigned long phys; + unsigned long d = 0; + + dir = pgd_offset(mm, p); + pmd = pmd_offset(dir, p); + + do { + if (pmd_none(*pmd) || pmd_bad(*pmd)) { + p &= ~((1 << PMD_SHIFT) -1); + p += (1 << PMD_SHIFT); + pmd++; + continue; + } + pte = pte_offset(pmd, p); + do { + entry = *pte; + if ((pte_val(entry) & _PAGE_PRESENT)) { + phys = pte_val(entry)&PTE_PHYS_MASK; + if ((p^phys) & CACHE_ALIAS) { + d |= 1 << ((p & CACHE_ALIAS)>>12); + d |= 1 << ((phys & CACHE_ALIAS)>>12); + if (d == 0x0f) + goto loop_exit; + } + } + pte++; + p += PAGE_SIZE; + } while (p < end && (unsigned long)pte & PAGE_MASK); + pmd++; + } while (p < end); + loop_exit: + if (d & 1) + flush_cache_4096_all(CACHE_OC_ADDRESS_ARRAY); + if (d & 2) + flush_cache_4096_all(CACHE_OC_ADDRESS_ARRAY | 0x1000); + if (d & 4) + flush_cache_4096_all(CACHE_OC_ADDRESS_ARRAY | 0x2000); + if (d & 8) + flush_cache_4096_all(CACHE_OC_ADDRESS_ARRAY | 0x3000); + flush_icache_all(); } /* Index: arch/sh/mm/clear_page.S =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/mm/clear_page.S,v retrieving revision 1.1.1.1.2.1 diff -u -3 -p -r1.1.1.1.2.1 clear_page.S --- arch/sh/mm/clear_page.S 29 Mar 2002 00:01:08 -0000 1.1.1.1.2.1 +++ arch/sh/mm/clear_page.S 1 Apr 2002 02:13:31 -0000 @@ -182,7 +182,7 @@ ENTRY(__clear_user_page) nop .L4096: .word 4096 -#if defined(CONFIG_CPU_SUBTYPE_SH7750) +#if !defined(CONFIG_CPU_SUBTYPE_ST40STB1) /* SH7750 or SH7751 */ ENTRY(__flush_cache_4096) .rept 128 mov.l @r4,r0 @@ -191,6 +191,33 @@ ENTRY(__flush_cache_4096) bf 1f mov.l r7,@r4 1: add #32,r4 + .endr + nop + nop + nop + nop + nop + nop + nop + rts + nop + +ENTRY(__flush_cache_4096_all) + mov r4,r5 + mov r4,r6 + mov r4,r7 + add #32,r5 + add #-64,r6 + add #-32,r7 + .rept 32 + mov.l r0,@r4 + add r1,r6 + mov.l r0,@r5 + add r1,r7 + mov.l r0,@r6 + add r1,r4 + mov.l r0,@r7 + add r1,r5 .endr nop nop Index: arch/sh/mm/copy_page.S =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/mm/copy_page.S,v retrieving revision 1.1.1.1.2.1 diff -u -3 -p -r1.1.1.1.2.1 copy_page.S --- arch/sh/mm/copy_page.S 29 Mar 2002 00:01:08 -0000 1.1.1.1.2.1 +++ arch/sh/mm/copy_page.S 1 Apr 2002 02:13:31 -0000 @@ -84,7 +84,6 @@ ENTRY(copy_page) * r10 --- to * r11 --- from */ -#include <linux/linkage.h> ENTRY(__copy_user_page) mov.l r8,@-r15 mov.l r9,@-r15 |