aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/mm
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-04-16 04:40:48 -0400
committerVineet Gupta <vgupta@synopsys.com>2013-05-07 09:38:15 -0400
commiteacd0e950dc2100af54f2a94ae29105bf48ab921 (patch)
treee9721c56d69fee98dd5539d78de1e037822facf6 /arch/arc/mm
parent764531cc5a9261de9f74fd85c30dfb7837af2797 (diff)
ARC: [mm] Lazy D-cache flush (non aliasing VIPT)
flush_dcache_page( ) is MM hook to ensure that a page has consistent views between kernel and userspace. Thus it is called when * kernel writes to a page which at some later point could get mapped to userspace (so kernel mapping needs to be flushed-n-inv) * kernel is about to read from a page with possible userspace mappings (so userspace mappings needs to be made coherent with kernel ones) However for Non aliasing VIPT dcache, any userspace mapping will always be congruent to kernel mapping. Thus d-cache need need not be flushed at all (or delayed indefinitely). The only reason it does need to be flushed is when mapping code pages. Since icache doesn't snoop dcache, those dirty dcache lines need to be written back to memory and icache line invalidated so that icache lines fetch will get the right data. Decent gains on LMBench fork/exec/sh and File I/O micro-benchmarks. (1) FPGA @ 80 MHZ Processor, Processes - times in microseconds - smaller is better ------------------------------------------------------------------------------ Host OS Mhz null null open slct sig sig fork exec sh call I/O stat clos TCP inst hndl proc proc proc --------- ------------- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- 3.9-rc6-a Linux 3.9.0-r 80 4.79 8.72 66.7 116. 239. 8.39 30.4 4798 14.K 34.K 3.9-rc6-b Linux 3.9.0-r 80 4.79 8.62 65.4 111. 239. 8.35 29.0 3995 12.K 30.K 3.9-rc7-c Linux 3.9.0-r 80 4.79 9.00 66.1 106. 239. 8.61 30.4 2858 10.K 24.K ^^^^ ^^^^ ^^^ File & VM system latencies in microseconds - smaller is better ------------------------------------------------------------------------------- Host OS 0K File 10K File Mmap Prot Page 100fd Create Delete Create Delete Latency Fault Fault selct --------- ------------- ------ ------ ------ ------ ------- ----- ------- ----- 3.9-rc6-a Linux 3.9.0-r 317.8 204.2 1122.3 375.1 3522.0 4.288 20.7 126.8 3.9-rc6-b Linux 3.9.0-r 298.7 223.0 1141.6 367.8 3531.0 4.866 20.9 126.4 3.9-rc7-c Linux 3.9.0-r 278.4 179.2 862.1 339.3 3705.0 3.223 20.3 126.6 ^^^^^ ^^^^^ ^^^^^ ^^^^ (2) Customer Silicon @ 500 MHz (166 MHz mem) ------------------------------------------------------------------------------ Host OS Mhz null null open slct sig sig fork exec sh call I/O stat clos TCP inst hndl proc proc proc --------- ------------- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- abilis-ba Linux 3.9.0-r 497 0.71 1.38 4.58 12.0 35.5 1.40 3.89 2070 5525 13.K abilis-ca Linux 3.9.0-r 497 0.71 1.40 4.61 11.8 35.6 1.37 3.92 1411 4317 10.K ^^^^ ^^^^ ^^^ Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/mm')
-rw-r--r--arch/arc/mm/cache_arc700.c9
-rw-r--r--arch/arc/mm/tlb.c18
2 files changed, 20 insertions, 7 deletions
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