summaryrefslogtreecommitdiff
path: root/arch/arc/mm/tlb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-10 18:24:14 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-10 18:24:14 +0400
commit6019958d146a4f127dae727a930f902c92531e6e (patch)
tree126cfbdafb7008ce9701dd2ccc27c54cab2d36f4 /arch/arc/mm/tlb.c
parent977b58e1dd6fc2a751fb427798bfb8256476c93e (diff)
parente7d5bab5efb94a82d80cab3ad68c357ce73ea596 (diff)
downloadlinux-6019958d146a4f127dae727a930f902c92531e6e.tar.xz
Merge tag 'arc-v3.10-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
Pull second set of arc arch updates from Vineet Gupta: "Aliasing VIPT dcache support for ARC I'm satisified with testing, specially with fuse which has historically given grief to VIPT arches (ARM/PARISC...)" * tag 'arc-v3.10-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc: ARC: [TB10x] Remove GENERIC_GPIO ARC: [mm] Aliasing VIPT dcache support 4/4 ARC: [mm] Aliasing VIPT dcache support 3/4 ARC: [mm] Aliasing VIPT dcache support 2/4 ARC: [mm] Aliasing VIPT dcache support 1/4 ARC: [mm] refactor the core (i|d)cache line ops loops ARC: [mm] serious bug in vaddr based icache flush
Diffstat (limited to 'arch/arc/mm/tlb.c')
-rw-r--r--arch/arc/mm/tlb.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 003d69ac6ffa..066145b5f348 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -421,25 +421,40 @@ void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
/*
* Called at the end of pagefault, for a userspace mapped page
* -pre-install the corresponding TLB entry into MMU
- * -Finalize the delayed D-cache flush (wback+inv kernel mapping)
+ * -Finalize the delayed D-cache flush of kernel mapping of page due to
+ * flush_dcache_page(), copy_user_page()
+ *
+ * Note that flush (when done) involves both WBACK - so physical page is
+ * in sync as well as INV - so any non-congruent aliases don't remain
*/
void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
pte_t *ptep)
{
unsigned long vaddr = vaddr_unaligned & PAGE_MASK;
+ unsigned long paddr = pte_val(*ptep) & PAGE_MASK;
create_tlb(vma, vaddr, ptep);
- /* icache doesn't snoop dcache, thus needs to be made coherent here */
- if (vma->vm_flags & VM_EXEC) {
+ /*
+ * Exec page : Independent of aliasing/page-color considerations,
+ * since icache doesn't snoop dcache on ARC, any dirty
+ * K-mapping of a code page needs to be wback+inv so that
+ * icache fetch by userspace sees code correctly.
+ * !EXEC page: If K-mapping is NOT congruent to U-mapping, flush it
+ * so userspace sees the right data.
+ * (Avoids the flush for Non-exec + congruent mapping case)
+ */
+ if (vma->vm_flags & VM_EXEC || addr_not_cache_congruent(paddr, vaddr)) {
struct page *page = pfn_to_page(pte_pfn(*ptep));
- /* if page was dcache dirty, flush now */
int dirty = test_and_clear_bit(PG_arch_1, &page->flags);
if (dirty) {
- unsigned long paddr = pte_val(*ptep) & PAGE_MASK;
- __flush_dcache_page(paddr);
- __inv_icache_page(paddr, vaddr);
+ /* wback + inv dcache lines */
+ __flush_dcache_page(paddr, paddr);
+
+ /* invalidate any existing icache lines */
+ if (vma->vm_flags & VM_EXEC)
+ __inv_icache_page(paddr, vaddr);
}
}
}