From: NIIBE Y. <gn...@m1...> - 2002-04-03 02:24:14
|
David McKay wrote: > It is in chapter 4 of the hardware manual, section 4.5 > "Memory-mapped Cache Configuration". It says "the OC content can be read > and > written by a P1 and P2 area program ......". Thank you. I've now understood. OC can be handled at P1. IC should be handled at P2. So, here is the change for 2.4 (not applying 2002-04-01 change). I'll commit this soon. 2002-04-03 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 and I-cache handling. (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 3 Apr 2002 02:21:06 -0000 @@ -207,10 +207,51 @@ void flush_cache_sigtramp(unsigned long restore_flags(flags); } +static void flush_cache_4096_all(unsigned long start) +{ +#if defined(CONFIG_CPU_SUBTYPE_SH7751) || defined(CONFIG_CPU_SUBTYPE_ST40STB1) + /* + * SH7751 and ST40 have no restriction to handle cache. + * (While SH7750 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_SH7751) || defined(CONFIG_CPU_SUBTYPE_ST40STB1) + if (start >= CACHE_OC_ADDRESS_ARRAY) { + /* + * 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); + } + } else +#endif + { register unsigned long addr __asm__ ("r4"); register unsigned long data __asm__ ("r0"); register unsigned long __r5 __asm__ ("r5") = phys; @@ -223,18 +264,7 @@ 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 +291,55 @@ 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 +401,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 3 Apr 2002 02:21:06 -0000 @@ -182,7 +182,6 @@ ENTRY(__clear_user_page) nop .L4096: .word 4096 -#if defined(CONFIG_CPU_SUBTYPE_SH7750) ENTRY(__flush_cache_4096) .rept 128 mov.l @r4,r0 @@ -191,6 +190,34 @@ ENTRY(__flush_cache_4096) bf 1f mov.l r7,@r4 1: add #32,r4 + .endr + nop + nop + nop + nop + nop + nop + nop + rts + nop + +#if defined(CONFIG_CPU_SUBTYPE_SH7750) +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 3 Apr 2002 02:21:06 -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 -- |