[xtensa-cvscommit] linux/arch/xtensa/mm cache.c,1.3,1.4
Brought to you by:
zankel
|
From: <ma...@us...> - 2003-02-07 01:49:11
|
Update of /cvsroot/xtensa/linux/arch/xtensa/mm
In directory sc8-pr-cvs1:/tmp/cvs-serv18839
Modified Files:
cache.c
Log Message:
Fix flush_cache_page when called for vma's other than current one.
Also proactively attempt to fix flush_icache_range in a similar manner.
Index: cache.c
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/mm/cache.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** cache.c 29 Jan 2003 02:27:59 -0000 1.3
--- cache.c 7 Feb 2003 01:49:06 -0000 1.4
***************
*** 93,105 ****
}
void flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
{
struct mm_struct *mm = vma->vm_mm;
unsigned long flags;
if (!mm || mm->context == NO_CONTEXT)
return;
- addr &= PAGE_MASK;
#ifdef DEBUG_CACHE
printk("cpage[%d,%08lx]", (long)mm->context, addr);
--- 93,120 ----
}
+ /*
+ * Writeback and invalidate all cache entries
+ * (on Xtensa this includes both I and D, both
+ * physically cached and virtually indexed)
+ * for a page located at virtual address 'addr'
+ * of virtual address space described by 'vma'
+ * (which is NOT necessarily the same as the
+ * current task's virtual address space).
+ */
void flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
{
struct mm_struct *mm = vma->vm_mm;
unsigned long flags;
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+ /*
+ * If owns no valid ASID yet, cannot possibly have gotten
+ * this page into the cache.
+ */
if (!mm || mm->context == NO_CONTEXT)
return;
#ifdef DEBUG_CACHE
printk("cpage[%d,%08lx]", (long)mm->context, addr);
***************
*** 107,112 ****
save_and_cli(flags);
! xthal_dcache_region_writeback_inv((void *)addr, PAGE_SIZE);
! xthal_icache_region_invalidate((void *)addr, PAGE_SIZE);
restore_flags(flags);
}
--- 122,168 ----
save_and_cli(flags);
! addr &= PAGE_MASK;
! pgdp = pgd_offset(mm, addr);
! pmdp = pmd_offset(pgdp, addr);
! ptep = pte_offset(pmdp, addr);
!
! /*
! * If the page isn't marked valid, the page cannot possibly be
! * in the cache.
! */
! if (!(pte_val(*ptep) & _PAGE_VALID))
! goto out;
!
! /*
! * Doing flushes for another task (or ASID) than the current one is
! * a bit tricky, because Xtensa processor cache operation ("hit")
! * instructions take virtual addresses, not physical addresses.
! * XTFIXME: For now, we just flush (writeback and invalidate)
! * the entire caches. This can be optimized in a number of ways:
! * - if cache aliasing was supported, we could use indexed
! * cache operations on only the relevant subset of the caches
! * - in general, we could use an otherwise available 4 kB
! * wired way to map some reserved 4 kB kernel-mappable virtual
! * page to this page's physical address (available from *ptep)
! * and run the xthal region routines on this temporarily
! * mapped virtual page. Eg:
! * special_kmap_vaddr = (some constant, properly computed)
! * setup wired way from special_kmap_vaddr to *ptep's paddr
! * addr = special_kmap_vaddr
! * ...execute xthal_*cache_region_*() functions below...
! */
! #if 0 /* XTFIXME - not sure this test actually works on Xtensa arch right now... */
! if (mm->context != current->active_mm->context) {
! #endif
! xthal_dcache_all_writeback_inv();
! xthal_icache_all_invalidate();
! #if 0 /* XTFIXME - continuation of above #if */
! } else {
! /* Flushing in the current task's address space: */
! xthal_dcache_region_writeback_inv((void *)addr, PAGE_SIZE);
! xthal_icache_region_invalidate((void *)addr, PAGE_SIZE);
! }
! #endif
! out:
restore_flags(flags);
}
***************
*** 137,141 ****
#endif
! flush_icache_range(start, start + PAGE_SIZE);
}
--- 193,201 ----
#endif
! if (mm->context != current->active_mm->context) {
! flush_cache_all();
! } else {
! flush_icache_range(start, start + PAGE_SIZE);
! }
}
|