From: NIIBE Y. <gn...@ch...> - 2000-09-18 05:11:56
|
I've mistakenly removed the definitionn of flush_cache_page (the function for flushing the cache for user space), which is reverted. And as Documentation/cachetlb.txt says, now is the transition time from flush_page_to_ram to copy_user_page/clear_user_page/flush_dcache_page. I've implement copy_user_page and clear_user_page. 2000-09-18 NIIBE Yutaka <gn...@m1...> Follow new cache handling scheme. Because now is the transition time (I think it's not fully changed to use "flush_dcache_page"), let's leave flush_page_to_ram. * arch/sh/mm/cache.c (clear_user_page, copy_user_page): Implemented. (__flush_page_to_ram): New function. (flush_page_to_ram): Use __flush_page_to_ram. * include/asm-sh/page.h (clear_user_page, copy_user_page): Define function for SH-4. Revert the changes of 2000-09-09. * arch/sh/mm/cache.c (flush_cache_page): Reverted. * include/asm-sh/pgtable.h (flush_cache_page): Ditto. Index: arch/sh/mm/cache.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/mm/cache.c,v retrieving revision 1.20 diff -u -r1.20 cache.c --- arch/sh/mm/cache.c 2000/09/09 01:49:39 1.20 +++ arch/sh/mm/cache.c 2000/09/18 05:04:57 @@ -354,6 +354,39 @@ } /* + * Write back and invalidate D-caches for the page. + * + * ADDR: Virtual Address (U0 address) + * + * NOTE: We need to flush the _physical_ page entry. + * Flushing the cache lines for U0 only isn't enough. + * We need to flush for P1 too, which may contain aliases. + */ +void flush_cache_page(struct vm_area_struct *vma, unsigned long addr) +{ + pgd_t *dir; + pmd_t *pmd; + pte_t *pte; + pte_t entry; + unsigned long phys; + struct page *pg; + + dir = pgd_offset(vma->vm_mm, addr); + pmd = pmd_offset(dir, addr); + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) + return; + pte = pte_offset(pmd, addr); + entry = *pte; + if (pte_none(entry) || !pte_present(entry)) + return; + phys = pte_val(entry)&PAGE_MASK; + pg = virt_to_page(__va(phys)); + flush_dcache_page(pg); +} + +/* * Write-back & invalidate the cache. * * After accessing the memory from kernel space (P1-area), we need to @@ -362,12 +395,12 @@ * We search the D-cache to see if we have the entries corresponding to * the page, and if found, write back them. */ -void flush_page_to_ram(struct page *pg) +void __flush_page_to_ram(void *kaddr) { unsigned long phys, addr, data, i; /* Physical address of this page */ - phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START; + phys = PHYSADDR(kaddr); jump_to_P2(); /* Loop all the D-cache */ @@ -382,6 +415,15 @@ back_to_P1(); } +void flush_page_to_ram(struct page *pg) +{ + unsigned long phys; + + /* Physical address of this page */ + phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START; + __flush_page_to_ram(phys_to_virt(phys)); +} + /* * Check entries of the I-cache & D-cache of the page. * (To see "alias" issues) @@ -437,5 +479,22 @@ dump_stack(); printk("--------------------\n"); } +} + +/* Page is 4K, OC size is 16K, there are four lines. */ +#define CACHE_ALIAS 0x00003000 + +void clear_user_page(void *to, unsigned long address) +{ + clear_page(to); + if (((address ^ (unsigned long)to) & CACHE_ALIAS)) + __flush_page_to_ram(to); +} + +void copy_user_page(void *to, void *from, unsigned long address) +{ + copy_page(to, from); + if (((address ^ (unsigned long)to) & CACHE_ALIAS)) + __flush_page_to_ram(to); } #endif Index: include/asm-sh/page.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/page.h,v retrieving revision 1.4 diff -u -r1.4 page.h --- include/asm-sh/page.h 2000/08/16 08:34:06 1.4 +++ include/asm-sh/page.h 2000/09/18 05:04:58 @@ -26,8 +26,14 @@ #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) #define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) + +#if defined(__sh3__) #define clear_user_page(page, vaddr) clear_page(page) #define copy_user_page(to, from, vaddr) copy_page(to, from) +#elif defined(__SH4__) +extern void clear_user_page(void *to, unsigned long address); +extern void copy_user_page(void *to, void *from, unsigned long address); +#endif /* * These are used to make use of C type-checking.. Index: include/asm-sh/pgtable.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/pgtable.h,v retrieving revision 1.11 diff -u -r1.11 pgtable.h --- include/asm-sh/pgtable.h 2000/09/09 01:49:40 1.11 +++ include/asm-sh/pgtable.h 2000/09/18 05:04:59 @@ -47,7 +47,7 @@ extern void flush_cache_mm(struct mm_struct *mm); extern void flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end); -#define flush_cache_page(vma, vmaddr) do { } while (0) +extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr); extern void flush_page_to_ram(struct page *page); extern void flush_dcache_page(struct page *pg); extern void flush_icache_range(unsigned long start, unsigned long end); Index: mm/vmscan.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/mm/vmscan.c,v retrieving revision 1.13 diff -u -r1.13 vmscan.c --- mm/vmscan.c 2000/09/04 06:41:54 1.13 +++ mm/vmscan.c 2000/09/18 05:05:05 @@ -138,7 +138,6 @@ * * That would get rid of a lot of problems. */ - flush_page_to_ram(page); flush_cache_page(vma, address); if (vma->vm_ops && (swapout = vma->vm_ops->swapout)) { int error; |