![Vineet Gupta](/assets/img/avatar_default.png)
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>
76 lines
2.6 KiB
C
76 lines
2.6 KiB
C
/*
|
|
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* vineetg: May 2011: for Non-aliasing VIPT D-cache following can be NOPs
|
|
* -flush_cache_dup_mm (fork)
|
|
* -likewise for flush_cache_mm (exit/execve)
|
|
* -likewise for flush_cache_{range,page} (munmap, exit, COW-break)
|
|
*
|
|
* vineetg: April 2008
|
|
* -Added a critical CacheLine flush to copy_to_user_page( ) which
|
|
* was causing gdbserver to not setup breakpoints consistently
|
|
*/
|
|
|
|
#ifndef _ASM_CACHEFLUSH_H
|
|
#define _ASM_CACHEFLUSH_H
|
|
|
|
#include <linux/mm.h>
|
|
|
|
/*
|
|
* Semantically we need this because icache doesn't snoop dcache/dma.
|
|
* However ARC Cache flush requires paddr as well as vaddr, latter not available
|
|
* in the flush_icache_page() API. So we no-op it but do the equivalent work
|
|
* in update_mmu_cache()
|
|
*/
|
|
#define flush_icache_page(vma, page)
|
|
|
|
void flush_cache_all(void);
|
|
|
|
void flush_icache_range(unsigned long start, unsigned long end);
|
|
void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len);
|
|
void __inv_icache_page(unsigned long paddr, unsigned long vaddr);
|
|
void __flush_dcache_page(unsigned long paddr);
|
|
|
|
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
|
|
|
void flush_dcache_page(struct page *page);
|
|
|
|
void dma_cache_wback_inv(unsigned long start, unsigned long sz);
|
|
void dma_cache_inv(unsigned long start, unsigned long sz);
|
|
void dma_cache_wback(unsigned long start, unsigned long sz);
|
|
|
|
#define flush_dcache_mmap_lock(mapping) do { } while (0)
|
|
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
|
|
|
/* TBD: optimize this */
|
|
#define flush_cache_vmap(start, end) flush_cache_all()
|
|
#define flush_cache_vunmap(start, end) flush_cache_all()
|
|
|
|
/*
|
|
* VM callbacks when entire/range of user-space V-P mappings are
|
|
* torn-down/get-invalidated
|
|
*
|
|
* Currently we don't support D$ aliasing configs for our VIPT caches
|
|
* NOPS for VIPT Cache with non-aliasing D$ configurations only
|
|
*/
|
|
#define flush_cache_dup_mm(mm) /* called on fork */
|
|
#define flush_cache_mm(mm) /* called on munmap/exit */
|
|
#define flush_cache_range(mm, u_vstart, u_vend)
|
|
#define flush_cache_page(vma, u_vaddr, pfn) /* PF handling/COW-break */
|
|
|
|
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
|
|
do { \
|
|
memcpy(dst, src, len); \
|
|
if (vma->vm_flags & VM_EXEC) \
|
|
__sync_icache_dcache((unsigned long)(dst), vaddr, len); \
|
|
} while (0)
|
|
|
|
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
|
|
memcpy(dst, src, len); \
|
|
|
|
#endif
|