diff options
-rw-r--r-- | arch/arc/include/asm/cacheflush.h | 1 | ||||
-rw-r--r-- | arch/arc/mm/cache_arc700.c | 9 | ||||
-rw-r--r-- | arch/arc/mm/tlb.c | 18 |
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); | |||
33 | void flush_icache_range(unsigned long start, unsigned long end); | 33 | void flush_icache_range(unsigned long start, unsigned long end); |
34 | void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len); | 34 | void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len); |
35 | void __inv_icache_page(unsigned long paddr, unsigned long vaddr); | 35 | void __inv_icache_page(unsigned long paddr, unsigned long vaddr); |
36 | void __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 */ | ||
461 | void flush_dcache_page(struct page *page) | 460 | void 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 | } |
465 | EXPORT_SYMBOL(flush_dcache_page); | 465 | EXPORT_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 | ||
573 | void __flush_dcache_page(unsigned long paddr) | ||
574 | { | ||
575 | __dc_line_op(paddr, PAGE_SIZE, OP_FLUSH_N_INV); | ||
576 | } | ||
577 | |||
573 | void flush_icache_all(void) | 578 | void 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 | */ |
425 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned, | 426 | void 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 | ||