aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arc/include/asm/cacheflush.h1
-rw-r--r--arch/arc/mm/cache_arc700.c9
-rw-r--r--arch/arc/mm/tlb.c18
3 files changed, 21 insertions, 7 deletions
diff --git a/arch/arc/include/asm/cacheflush.h b/arch/arc/include/asm/cacheflush.h
index 65ed8d2d4597..ee1f6eae82d2 100644
--- a/arch/arc/include/asm/cacheflush.h
+++ b/arch/arc/include/asm/cacheflush.h
@@ -33,6 +33,7 @@ void flush_cache_all(void);
33void flush_icache_range(unsigned long start, unsigned long end); 33void flush_icache_range(unsigned long start, unsigned long end);
34void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len); 34void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len);
35void __inv_icache_page(unsigned long paddr, unsigned long vaddr); 35void __inv_icache_page(unsigned long paddr, unsigned long vaddr);
36void __flush_dcache_page(unsigned long paddr);
36 37
37#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 38#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
38 39
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c
index 3a9ef63b1a97..c854cf95f706 100644
--- a/arch/arc/mm/cache_arc700.c
+++ b/arch/arc/mm/cache_arc700.c
@@ -457,10 +457,10 @@ static void __ic_line_inv_vaddr(unsigned long phy_start, unsigned long vaddr,
457 * Exported APIs 457 * Exported APIs
458 */ 458 */
459 459
460/* TBD: use pg_arch_1 to optimize this */
461void flush_dcache_page(struct page *page) 460void flush_dcache_page(struct page *page)
462{ 461{
463 __dc_line_op((unsigned long)page_address(page), PAGE_SIZE, OP_FLUSH); 462 /* Make a note that dcache is not yet flushed for this page */
463 set_bit(PG_arch_1, &page->flags);
464} 464}
465EXPORT_SYMBOL(flush_dcache_page); 465EXPORT_SYMBOL(flush_dcache_page);
466 466
@@ -570,6 +570,11 @@ void __inv_icache_page(unsigned long paddr, unsigned long vaddr)
570 __ic_line_inv_vaddr(paddr, vaddr, PAGE_SIZE); 570 __ic_line_inv_vaddr(paddr, vaddr, PAGE_SIZE);
571} 571}
572 572
573void __flush_dcache_page(unsigned long paddr)
574{
575 __dc_line_op(paddr, PAGE_SIZE, OP_FLUSH_N_INV);
576}
577
573void flush_icache_all(void) 578void flush_icache_all(void)
574{ 579{
575 unsigned long flags; 580 unsigned long flags;
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 086be526072a..003d69ac6ffa 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -418,9 +418,10 @@ void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
418 local_irq_restore(flags); 418 local_irq_restore(flags);
419} 419}
420 420
421/* arch hook called by core VM at the end of handle_mm_fault( ), 421/*
422 * when a new PTE is entered in Page Tables or an existing one 422 * Called at the end of pagefault, for a userspace mapped page
423 * is modified. We aggresively pre-install a TLB entry 423 * -pre-install the corresponding TLB entry into MMU
424 * -Finalize the delayed D-cache flush (wback+inv kernel mapping)
424 */ 425 */
425void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned, 426void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
426 pte_t *ptep) 427 pte_t *ptep)
@@ -431,8 +432,15 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
431 432
432 /* icache doesn't snoop dcache, thus needs to be made coherent here */ 433 /* icache doesn't snoop dcache, thus needs to be made coherent here */
433 if (vma->vm_flags & VM_EXEC) { 434 if (vma->vm_flags & VM_EXEC) {
434 unsigned long paddr = pte_val(*ptep) & PAGE_MASK; 435 struct page *page = pfn_to_page(pte_pfn(*ptep));
435 __inv_icache_page(paddr, vaddr); 436
437 /* if page was dcache dirty, flush now */
438 int dirty = test_and_clear_bit(PG_arch_1, &page->flags);
439 if (dirty) {
440 unsigned long paddr = pte_val(*ptep) & PAGE_MASK;
441 __flush_dcache_page(paddr);
442 __inv_icache_page(paddr, vaddr);
443 }
436 } 444 }
437} 445}
438 446