summaryrefslogtreecommitdiff
path: root/arch/arc/mm/tlb.c
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-04-11 18:36:35 +0530
committerVineet Gupta <vgupta@synopsys.com>2013-05-07 19:08:12 +0530
commit24603fdd19d978fcc0d089d92370ee1aa3a71e84 (patch)
tree8871ebc44c1b569dce1a394eb290f2912066cc52 /arch/arc/mm/tlb.c
parent8d56bec2f2945b7e500b413d1bdc24e7dca12877 (diff)
ARC: [mm] optimise icache flush for user mappings
ARC icache doesn't snoop dcache thus executable pages need to be made coherent before mapping into userspace in flush_icache_page(). However ARC700 CDU (hardware cache flush module) requires both vaddr (index in cache) as well as paddr (tag match) to correctly identify a line in the VIPT cache. A typical ARC700 SoC has aliasing icache, thus the paddr only based flush_icache_page() API couldn't be implemented efficiently. It had to loop thru all possible alias indexes and perform the invalidate operation (ofcourse the cache op would only succeed at the index(es) where tag matches - typically only 1, but the cost of visiting all the cache-bins needs to paid nevertheless). Turns out however that the vaddr (along with paddr) is available in update_mmu_cache() hence better suits ARC icache flush semantics. With both vaddr+paddr, exactly one flush operation per line is done. Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/mm/tlb.c')
-rw-r--r--arch/arc/mm/tlb.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index c03364af9363..086be526072a 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -422,12 +422,18 @@ void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
* when a new PTE is entered in Page Tables or an existing one
* is modified. We aggresively pre-install a TLB entry
*/
-
-void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddress,
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
pte_t *ptep)
{
+ unsigned long vaddr = vaddr_unaligned & PAGE_MASK;
+
+ create_tlb(vma, vaddr, ptep);
- create_tlb(vma, vaddress, ptep);
+ /* icache doesn't snoop dcache, thus needs to be made coherent here */
+ if (vma->vm_flags & VM_EXEC) {
+ unsigned long paddr = pte_val(*ptep) & PAGE_MASK;
+ __inv_icache_page(paddr, vaddr);
+ }
}
/* Read the Cache Build Confuration Registers, Decode them and save into