Hi create r4k_blast_page{indexed} functions. That allows to remove the r4600 variant of the r4k_flush_page_cache. Once there, fix the bug we were testing _PAGE_VALID, instead of _PAGE_PRESENT. Once there, also define a nice inline to test for _PAGE_VALID. Later, Juan. build/arch/mips/mm/c-r4k.c | 122 +++++++++++++++------------------------ build/include/asm-mips/pgtable.h | 1 2 files changed, 48 insertions(+), 75 deletions(-) diff -puN build/include/asm-mips/pgtable.h~c-r4k_flush_cache_page build/include/asm-mips/pgtable.h --- 24/build/include/asm-mips/pgtable.h~c-r4k_flush_cache_page 2003-03-28 01:18:02.000000000 +0100 +++ 24-quintela/build/include/asm-mips/pgtable.h 2003-03-28 01:19:33.000000000 +0100 @@ -220,6 +220,7 @@ static inline void pmd_set(pmd_t * pmdp, static inline int pte_none(pte_t pte) { return !(pte_val(pte) & ~_PAGE_GLOBAL); } static inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } +static inline int pte_valid(pte_t pte) { return pte_val(pte) & _PAGE_VALID; } /* Certain architectures need to do special things when pte's * within a page table are directly modified. Thus, the following diff -puN build/arch/mips/mm/c-r4k.c~c-r4k_flush_cache_page build/arch/mips/mm/c-r4k.c --- 24/build/arch/mips/mm/c-r4k.c~c-r4k_flush_cache_page 2003-03-28 01:18:16.000000000 +0100 +++ 24-quintela/build/arch/mips/mm/c-r4k.c 2003-03-28 01:37:01.000000000 +0100 @@ -228,6 +228,49 @@ init: goto *l; } +static void r4k_blast_cache_page(unsigned long page, int exec) +{ + r4k_blast_dcache_page(page); + if (exec) + r4k_blast_icache_page(page); +} + +static void r4k_blast_cache_page_indexed(unsigned long page, int exec) +{ + unsigned long addr = (KSEG0 + (page & (dcache_size - 1))); + static void *l = &&init; + + goto *l; + +normal: + r4k_blast_dcache_page_indexed(addr); + if (exec) + r4k_blast_icache_page_indexed(addr); + return; + +r4600: + r4k_blast_dcache_page_indexed(addr); + r4k_blast_dcache_page_indexed(addr & dcache_waybit); + if (exec) { + r4k_blast_icache_page_indexed(addr); + r4k_blast_icache_page_indexed(addr ^ icache_waybit); + } + return; + +init: + switch(mips_cpu.cputype) { + case CPU_R4600: /* QED style two way caches? */ + case CPU_R4700: + case CPU_R5000: + case CPU_NEVADA: + l = && r4600; + break; + default: + l = &&normal; + } + goto *l; +} + static inline void r4k_flush_scache_all(void) { r4k_blast_dcache(); @@ -286,7 +329,7 @@ static void r4k_flush_cache_page(struct * If the page isn't marked valid, the page cannot possibly be * in the cache. */ - if (!(pte_val(*ptep) & _PAGE_VALID)) + if (!pte_present(*ptep)) return; /* @@ -295,11 +338,8 @@ static void r4k_flush_cache_page(struct * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if (mm == current->active_mm) { - r4k_blast_dcache_page(page); - if (exec) - r4k_blast_icache_page(page); - + if ((mm == current->active_mm) && pte_valid(*ptep)) { + r4k_blast_cache_page(page, exec); return; } @@ -307,66 +347,7 @@ static void r4k_flush_cache_page(struct * Do indexed flush, too much work to get the (possible) TLB refills * to work correctly. */ - page = (KSEG0 + (page & (dcache_size - 1))); - r4k_blast_dcache_page_indexed(page); - if (exec) - r4k_blast_icache_page_indexed(page); -} - -static void r4k_flush_cache_page_r4600(struct vm_area_struct *vma, - unsigned long page) -{ - int exec = vma->vm_flags & VM_EXEC; - struct mm_struct *mm = vma->vm_mm; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (cpu_context(smp_processor_id(), mm) == 0) - return; - - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_PRESENT)) - return; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { - r4k_blast_dcache_page(page); - if (exec) - r4k_blast_icache_page(page); - - return; - } - - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = KSEG0 + (page & (dcache_size - 1)); - r4k_blast_dcache_page_indexed(page); - r4k_blast_dcache_page_indexed(page ^ dcache_waybit); - - if (exec) { - r4k_blast_icache_page_indexed(page); - r4k_blast_icache_page_indexed(page ^ icache_waybit); - } + r4k_blast_cache_page_indexed(page, exec); } static void r4k_flush_dcache_page_impl(struct page *page) @@ -791,15 +772,6 @@ void __init ld_mmu_r4xx0(void) _flush_dcache_page = r4k_flush_dcache_page; _flush_icache_page = r4k_flush_icache_page; - switch(mips_cpu.cputype) { - case CPU_R4600: /* QED style two way caches? */ - case CPU_R4700: - case CPU_R5000: - case CPU_NEVADA: - _flush_cache_page = r4k_flush_cache_page_r4600; - } - - switch(read_c0_prid() & 0xfff0) { case 0x2010: _flush_cache_sigtramp = r4600v17_flush_cache_sigtramp; _ -- In theory, practice and theory are the same, but in practice they are different -- Larry McVoy