From: Paul M. <le...@Ch...> - 2002-02-28 07:47:24
|
Hello, These are a small set of cleanups for the SH4 caches that have been sitting= in my home directory for a little while, and after having just recently reciev= ed testing, have been deemed permissible to see the light of day. The changes are pretty simplistic, a few sanity checks here and there to av= oid some wasted cache flushes.. as well as a proper flush_cache_range() implementation that doesn't just act as a dummy wrapper to flush_cache_all(= ). Seems to be holding up so far. With what testing this patch has recieved thus far (thanks to M. R. Brown), it's been a bit quicker in the majority of cases..=20 Writeback - original Lethal's=20 tunnel 13.4169fps 13.4272fps flamme 12.6753fps 12.6564fps - dawafire 9.3169fps 9.300047fps - bump 10.8493fps 10.8635fps rotozoom 12.0676fps 12.054fps - plasma 8.33784fps 8.37143fps sdl/testwin 2175ms 2111ms sdl/testsprite 29.88fps 30.04fps sdl/testpalette 531/15.06fps 673/15.09fps These are obviously not very concrete benchmarks, and perhaps a bit of kern= el profiling is called for if anyone is really hesitant about any of the chang= es. Though I'd like to avoid writing a new test suite for stressing caches if at all possible.. These changes are of course only related to SH4 caches configured in write-back mode.. I've started on a patch for write-through, but that's sti= ll a work-in-progress. Regards, --=20 Paul Mundt <le...@ch...> Index: ChangeLog =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/linuxsh/linux/ChangeLog,v retrieving revision 1.32 diff -u -r1.32 ChangeLog --- ChangeLog 26 Feb 2002 09:15:15 -0000 1.32 +++ ChangeLog 28 Feb 2002 07:34:14 -0000 @@ -1,3 +1,9 @@ +2002-02-27 Paul Mundt <le...@ch...> + + * arch/sh/mm/cache-sh4.c (__flush_icache_page): Added back in. + (flush_cache_range): Rewritten entirely. + (flush_cache_mm): Only flush caches on a valid mm context. + 2002-02-26 NIIBE Yutaka <gn...@m1...> =20 Updated to 2.5.3. Index: arch/sh/mm/cache-sh4.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/linuxsh/linux/arch/sh/mm/cache-sh4.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 cache-sh4.c --- arch/sh/mm/cache-sh4.c 15 Oct 2001 20:44:53 -0000 1.1.1.1 +++ arch/sh/mm/cache-sh4.c 25 Feb 2002 08:43:04 -0000 @@ -3,7 +3,7 @@ * linux/arch/sh/mm/cache.c * * Copyright (C) 1999, 2000 Niibe Yutaka - * + * Copyright (C) 2001, 2002 Paul Mundt */ =20 #include <linux/config.h> @@ -109,7 +114,7 @@ unsigned long size, unsigned long flags); =20 if (remap_area_pages(P3SEG, 0, PAGE_SIZE*4, _PAGE_CACHABLE)) - panic("p3_cachie_init failed."); + panic("%s failed.", __FUNCTION__); sema_init (&p3map_sem[0], 1); sema_init (&p3map_sem[1], 1); sema_init (&p3map_sem[2], 1); @@ -231,19 +236,30 @@ ctrl_outl(0, addr); } =20 -#if 0 /* DEBUG DEBUG */ + back_to_P1(); + restore_flags(flags); +} + +static void __flush_icache_page(unsigned long phys) +{ + unsigned long addr, data; + unsigned long flags; + + phys |=3D CACHE_VALID; + + save_and_cli(flags); + jump_to_P2(); + /* Loop all the I-cache */ for (addr =3D CACHE_IC_ADDRESS_ARRAY; addr < (CACHE_IC_ADDRESS_ARRAY +(CACHE_IC_NUM_ENTRIES<< CACHE_IC_ENTRY_SHIFT)); addr +=3D (1<<CACHE_IC_ENTRY_SHIFT)) { data =3D ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); - if (data =3D=3D phys) { - printk(KERN_INFO "__flush_cache_page: I-cache entry found\n"); + if (data =3D=3D phys) ctrl_outl(0, addr); - } } -#endif + back_to_P1(); restore_flags(flags); } @@ -283,7 +299,19 @@ { /* Is there any good way? */ /* XXX: possibly call flush_cache_range for each vm area */ - flush_cache_all(); + /*=20 + * FIXME: Really, the optimal solution here would be able to flush out + * individual lines created by the specified context, but this isn't + * feasible for a number of architectures (such as MIPS, and some + * SPARC) .. is this possible for SuperH? (This is a non-issue if the + * SH4 cache is configured in write-through mode). + * + * In the meantime, we'll just flush all of the caches if we have a + * valid mm context.. this seems to be the simplest way to avoid at + * least a few wasted cache flushes. -Lethal + */ + if (mm->context !=3D 0) + flush_cache_all(); } =20 /* @@ -298,14 +326,39 @@ 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 not efficient (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 flags; + + if (mm->context =3D=3D 0) + return; + + start &=3D PAGE_MASK; + + if (!find_vma(mm, start)) + return; + if (mm->context !=3D current->active_mm->context) { + flush_cache_all(); + } else { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + save_and_cli(flags); + jump_to_P2(); + + for (start; start < end; start +=3D PAGE_SIZE) { + pgd =3D pgd_offset(mm, start); + pmd =3D pmd_offset(pgd, start); + pte =3D pte_offset(pmd, start); + + if (pte_val(*pte) & _PAGE_PRESENT) { + __flush_icache_page(start); + __flush_dcache_page(start); + } + } + + back_to_P1(); + restore_flags(flags); + } } =20 /* |