From: NIIBE Y. <gn...@m1...> - 2001-08-07 14:17:50
|
SUGIOKA Toshinobu writes: > Yes. This works good, nice performance. Thanks for testing. I'll commit following. It does more clean-up. * arch/sh/mm/cache-sh4.c (ptep_get_and_clear): Moved to ... (check_cache_page): Removed. (__flush_icache_page): Removed. * include/asm-sh/pgtable.h (__flush_icache_page): Removed. * include/asm-sh/pgalloc.h (ptep_get_and_clear): ... here. (ptep_test_and_clear_young, ptep_test_and_clear_dirty, ptep_set_wrprotect, ptep_mkdirty): Moved from pgtable.h. (ptep_get_and_clear needs definition of mm.h). * include/asm-sh/pgtable.h (PG_mapped): Renamed from PG_mapped_with_alias. (__flush_cache_page): Removed last argument, and add first arg. * arch/sh/mm/cache-sh4.c (__flush_cache_page): Take u0 address as first argument. Don't care about I-cache. (flush_dcache_page): Follow the change. * include/asm-sh/ide.h (ide_insw): Removed. * drivers/cdrom/gdrom.c (gdrom_intr): Remove __flush_wback_region. * arch/sh/mm/fault.c (update_mmu_cache): Flush the cache when first mapped, even if it has no alias. (We needed this to for NFS). Index: arch/sh/mm/cache-sh4.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/mm/cache-sh4.c,v retrieving revision 1.11 diff -u -r1.11 cache-sh4.c --- arch/sh/mm/cache-sh4.c 2001/08/07 05:20:02 1.11 +++ arch/sh/mm/cache-sh4.c 2001/08/07 14:09:50 @@ -196,9 +196,8 @@ /* * Writeback&Invalidate the D-cache of the page - * Invalidate the I-cache of the page, if needed */ -void __flush_cache_page(unsigned long phys, int exec) +void __flush_cache_page(unsigned long u0, unsigned long phys) { unsigned long addr, data; unsigned long flags; @@ -207,74 +206,65 @@ save_and_cli(flags); jump_to_P2(); - /* Loop all the D-cache */ - for (addr = CACHE_OC_ADDRESS_ARRAY; - addr < (CACHE_OC_ADDRESS_ARRAY - +(CACHE_OC_NUM_ENTRIES<< CACHE_OC_ENTRY_SHIFT)); - addr += (1<<CACHE_OC_ENTRY_SHIFT)) { - data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); - if (data == phys) - ctrl_outl(0, addr); - } - - if (exec) - /* Loop all the I-cache */ - for (addr = CACHE_IC_ADDRESS_ARRAY; - addr < (CACHE_IC_ADDRESS_ARRAY - +(CACHE_IC_NUM_ENTRIES<< CACHE_IC_ENTRY_SHIFT)); - addr += (1<<CACHE_IC_ENTRY_SHIFT)) { - data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); - if (data == phys) - ctrl_outl(0, addr); - } - back_to_P1(); - restore_flags(flags); -} - -void __flush_icache_page(unsigned long u0, unsigned long phys) -{ - unsigned long addr, data; - unsigned long flags; - phys|=CACHE_VALID; - - save_and_cli(flags); if (u0) { - jump_to_P2(); - /* Loop half of the I-cache */ - for (addr = CACHE_IC_ADDRESS_ARRAY|(u0&0x1000); - addr < ((CACHE_IC_ADDRESS_ARRAY|(u0&0x1000)) - +(CACHE_IC_NUM_ENTRIES/2<<CACHE_IC_ENTRY_SHIFT)); - addr += (1<<CACHE_IC_ENTRY_SHIFT)) { + if ((u0^phys) & CACHE_ALIAS) { + /* Loop 4K of the D-cache */ + for (addr = CACHE_OC_ADDRESS_ARRAY | (u0 & CACHE_ALIAS); + addr < (CACHE_OC_ADDRESS_ARRAY + (u0 & CACHE_ALIAS) + +(CACHE_OC_NUM_ENTRIES/4<<CACHE_OC_ENTRY_SHIFT)); + addr += (1<<CACHE_OC_ENTRY_SHIFT)) { + data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); + if (data == phys) + ctrl_outl(0, addr); + } + } + /* Loop another 4K of the D-cache */ + for (addr = CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS); + addr < (CACHE_OC_ADDRESS_ARRAY + (phys & CACHE_ALIAS) + +(CACHE_OC_NUM_ENTRIES/4<<CACHE_OC_ENTRY_SHIFT)); + addr += (1<<CACHE_OC_ENTRY_SHIFT)) { data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); if (data == phys) ctrl_outl(0, addr); } - back_to_P1(); } else { - jump_to_P2(); - /* Loop all the I-cache */ - for (addr = CACHE_IC_ADDRESS_ARRAY; - addr < (CACHE_IC_ADDRESS_ARRAY - +(CACHE_IC_NUM_ENTRIES << CACHE_IC_ENTRY_SHIFT)); - addr += (1<<CACHE_IC_ENTRY_SHIFT)) { + /* Loop all the D-cache */ + for (addr = CACHE_OC_ADDRESS_ARRAY; + addr < (CACHE_OC_ADDRESS_ARRAY + +(CACHE_OC_NUM_ENTRIES<< CACHE_OC_ENTRY_SHIFT)); + addr += (1<<CACHE_OC_ENTRY_SHIFT)) { data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); if (data == phys) ctrl_outl(0, addr); } - back_to_P1(); } + +#if 0 /* DEBUG DEBUG */ + /* Loop all the I-cache */ + for (addr = CACHE_IC_ADDRESS_ARRAY; + addr < (CACHE_IC_ADDRESS_ARRAY + +(CACHE_IC_NUM_ENTRIES<< CACHE_IC_ENTRY_SHIFT)); + addr += (1<<CACHE_IC_ENTRY_SHIFT)) { + data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID); + if (data == phys) { + printk(KERN_INFO "__flush_cache_page: I-cache entry found\n"); + ctrl_outl(0, addr); + } + } +#endif + back_to_P1(); restore_flags(flags); } /* - * Write back & invalidate the I/D-cache of the page. + * Write back & invalidate the D-cache of the page. * (To avoid "alias" issues) */ void flush_dcache_page(struct page *page) { if (test_bit(PG_mapped_with_alias, &page->flags)) - __flush_cache_page(PHYSADDR(page_address(page)), 1); + __flush_cache_page(0, PHYSADDR(page_address(page))); } void flush_cache_all(void) @@ -393,68 +383,6 @@ } /* - * Check entries of the I-cache & D-cache of the page. - * (To see "alias" issues) - */ -void check_cache_page(struct page *pg) -{ - unsigned long phys, addr, data, i; - unsigned long kaddr; - unsigned long cache_line_index; - int bingo = 0; - unsigned long flags; - - /* Physical address of this page */ - phys = PHYSADDR(page_address(pg)); - kaddr = phys + PAGE_OFFSET; - cache_line_index = (kaddr&CACHE_OC_ENTRY_MASK)>>CACHE_OC_ENTRY_SHIFT; - - save_and_cli(flags); - jump_to_P2(); - /* Loop all the D-cache */ - for (i=0; i<CACHE_OC_NUM_ENTRIES; i++) { - addr = CACHE_OC_ADDRESS_ARRAY| (i<<CACHE_OC_ENTRY_SHIFT); - data = ctrl_inl(addr); - if ((data & (CACHE_UPDATED|CACHE_VALID)) - == (CACHE_UPDATED|CACHE_VALID) - && (data&PAGE_MASK) == phys) { - data &= ~(CACHE_VALID|CACHE_UPDATED); - ctrl_outl(data, addr); - if ((i^cache_line_index)&0x180) - bingo |= 1; - } - } - - cache_line_index &= 0xff; - /* Loop all the I-cache */ - for (i=0; i<CACHE_IC_NUM_ENTRIES; i++) { - addr = CACHE_IC_ADDRESS_ARRAY| (i<<CACHE_IC_ENTRY_SHIFT); - data = ctrl_inl(addr); - if ((data & CACHE_VALID) && (data&PAGE_MASK) == phys) { - data &= ~CACHE_VALID; - ctrl_outl(data, addr); - if (((i^cache_line_index)&0x80)) - bingo |= 2; - } - } - back_to_P1(); - restore_flags(flags); - - if (bingo) { - extern void dump_stack(void); - - if (bingo&1) - printk("BINGO!\n"); -#if 0 - if (bingo&2) - printk("Bingo!\n"); -#endif - dump_stack(); - printk("--------------------\n"); - } -} - -/* * clear_user_page * @to: P1 address * @address: U0 address to be mapped @@ -523,18 +451,4 @@ pte_clear(pte); up(&p3map_sem[(address & CACHE_ALIAS)>>12]); } -} - -pte_t ptep_get_and_clear(pte_t *ptep) -{ - pte_t pte = *ptep; - - if (!pte_not_present(pte)) { - struct page *page = pte_page(pte); - if (VALID_PAGE(page)&& - (!page->mapping || !(page->mapping->i_mmap_shared))) - __clear_bit(PG_mapped_with_alias, &page->flags); - } - pte_clear(ptep); - return pte; } Index: arch/sh/mm/fault.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/mm/fault.c,v retrieving revision 1.45 diff -u -r1.45 fault.c --- arch/sh/mm/fault.c 2001/08/07 05:20:02 1.45 +++ arch/sh/mm/fault.c 2001/08/07 14:09:50 @@ -290,14 +290,12 @@ return; #if defined(__SH4__) - if ((address ^ pte_val(pte)) & CACHE_ALIAS) { - page = pte_page(pte); - if (VALID_PAGE(page) && - !test_bit(PG_mapped_with_alias, &page->flags)) { - unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; - __flush_cache_page(phys, 1); - set_bit(PG_mapped_with_alias, &page->flags); - } + page = pte_page(pte); + if (VALID_PAGE(page) && + !test_bit(PG_mapped_with_alias, &page->flags)) { + unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; + __flush_cache_page(address, phys); + set_bit(PG_mapped_with_alias, &page->flags); } #endif Index: drivers/cdrom/gdrom.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/drivers/cdrom/gdrom.c,v retrieving revision 1.4 diff -u -r1.4 gdrom.c --- drivers/cdrom/gdrom.c 2001/08/03 23:50:59 1.4 +++ drivers/cdrom/gdrom.c 2001/08/07 14:09:50 @@ -144,7 +144,6 @@ } insw(GDROM_DATA, ctrl->buf, count/2); - __flush_wback_region(ctrl->buf, count); ctrl->buf += count; ctrl->size -= count; } Index: include/asm-sh/ide.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/ide.h,v retrieving revision 1.16 diff -u -r1.16 ide.h --- include/asm-sh/ide.h 2001/08/03 11:22:06 1.16 +++ include/asm-sh/ide.h 2001/08/07 14:09:52 @@ -17,21 +17,6 @@ #include <linux/config.h> #include <asm/machvec.h> -#if defined(__SH4__) -#undef insw -#define insw(port, buf, nr) ide_insw((port), (buf), (nr)) - -static __inline__ void ide_insw(unsigned long port, - void *dst, - unsigned long count) -{ - extern void _insw (unsigned long port, void *dst, unsigned long count); - - _insw(port, dst, count); - __flush_wback_region(dst, (count << 1)); -} -#endif - #ifndef MAX_HWIFS /* Should never have less than 2, ide-pci.c(ide_match_hwif) requires it */ #define MAX_HWIFS 2 Index: include/asm-sh/pgalloc.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/pgalloc.h,v retrieving revision 1.9 diff -u -r1.9 pgalloc.h --- include/asm-sh/pgalloc.h 2001/07/18 04:24:43 1.9 +++ include/asm-sh/pgalloc.h 2001/08/07 14:09:53 @@ -95,4 +95,62 @@ { /* Nothing to do */ } +#if defined(__SH4__) +/* + * For SH-4, we have our own implementation for ptep_get_and_clear + */ +static inline pte_t ptep_get_and_clear(pte_t *ptep) +{ + pte_t pte = *ptep; + + pte_clear(ptep); + if (!pte_not_present(pte)) { + struct page *page = pte_page(pte); + if (VALID_PAGE(page)&& + (!page->mapping || !(page->mapping->i_mmap_shared))) + __clear_bit(PG_mapped_with_alias, &page->flags); + } + return pte; +} +#else +static inline pte_t ptep_get_and_clear(pte_t *ptep) +{ + pte_t pte = *ptep; + pte_clear(ptep); + return pte; +} +#endif + +/* + * Following functions are same as generic ones. + */ +static inline int ptep_test_and_clear_young(pte_t *ptep) +{ + pte_t pte = *ptep; + if (!pte_young(pte)) + return 0; + set_pte(ptep, pte_mkold(pte)); + return 1; +} + +static inline int ptep_test_and_clear_dirty(pte_t *ptep) +{ + pte_t pte = *ptep; + if (!pte_dirty(pte)) + return 0; + set_pte(ptep, pte_mkclean(pte)); + return 1; +} + +static inline void ptep_set_wrprotect(pte_t *ptep) +{ + pte_t old_pte = *ptep; + set_pte(ptep, pte_wrprotect(old_pte)); +} + +static inline void ptep_mkdirty(pte_t *ptep) +{ + pte_t old_pte = *ptep; + set_pte(ptep, pte_mkdirty(old_pte)); +} #endif /* __ASM_SH_PGALLOC_H */ Index: include/asm-sh/pgtable.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/pgtable.h,v retrieving revision 1.41 diff -u -r1.41 pgtable.h --- include/asm-sh/pgtable.h 2001/08/07 05:20:03 1.41 +++ include/asm-sh/pgtable.h 2001/08/07 14:09:53 @@ -52,6 +52,10 @@ /* * Caches are broken on SH-4, so we need them. */ + +/* Page is 4K, OC size is 16K, there are four lines. */ +#define CACHE_ALIAS 0x00003000 + extern void flush_cache_all(void); extern void flush_cache_mm(struct mm_struct *mm); extern void flush_cache_range(struct mm_struct *mm, unsigned long start, @@ -70,8 +74,7 @@ extern void __flush_purge_region(void *start, int size); /* Flush a page */ -extern void __flush_cache_page(unsigned long phys, int exec); -extern void __flush_icache_page(unsigned long u0, unsigned long phys); +extern void __flush_cache_page(unsigned long u0, unsigned long phys); /* Initialization of P3 area for copy_user_page */ extern void p3_cache_init(void); @@ -297,55 +300,6 @@ * (We needed atomic implementation for SMP) * */ - -#if defined(__SH4__) -/* Page is 4K, OC size is 16K, there are four lines. */ -#define CACHE_ALIAS 0x00003000 -/* - * For SH-4, we have our own implementation for ptep_get_and_clear - */ -extern pte_t ptep_get_and_clear(pte_t *ptep); -#else -static inline pte_t ptep_get_and_clear(pte_t *ptep) -{ - pte_t pte = *ptep; - pte_clear(ptep); - return pte; -} -#endif - -/* - * Following functions are same as generic ones. - */ -static inline int ptep_test_and_clear_young(pte_t *ptep) -{ - pte_t pte = *ptep; - if (!pte_young(pte)) - return 0; - set_pte(ptep, pte_mkold(pte)); - return 1; -} - -static inline int ptep_test_and_clear_dirty(pte_t *ptep) -{ - pte_t pte = *ptep; - if (!pte_dirty(pte)) - return 0; - set_pte(ptep, pte_mkclean(pte)); - return 1; -} - -static inline void ptep_set_wrprotect(pte_t *ptep) -{ - pte_t old_pte = *ptep; - set_pte(ptep, pte_wrprotect(old_pte)); -} - -static inline void ptep_mkdirty(pte_t *ptep) -{ - pte_t old_pte = *ptep; - set_pte(ptep, pte_mkdirty(old_pte)); -} #define pte_same(A,B) (pte_val(A) == pte_val(B)) -- |