Commit 585fa724 authored by Ralf Baechle's avatar Ralf Baechle

[MIPS] Retire flush_icache_page from mm use.

On the 34K the redundant cache operations were causing excessive stalls
resulting in realtime code running on the second VPE missing its deadline.
For all other platforms this patch is just a significant performance
improvment as illustrated by below benchmark numbers.

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
--------- ------------- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
25Kf      2.6.18-rc4     533 0.49 1.16 7.57 33.4 30.5 1.34 12.4 5497 17.K 54.K
25Kf      2.6.18-rc4-p   533 0.49 1.16 6.68 23.0 30.7 1.36 8.55 5030 16.K 48.K
4Kc       2.6.18-rc4      80 4.21 15.0 131. 289. 261. 16.5 258. 18.K 70.K 227K
4Kc       2.6.18-rc4-p    80 4.34 13.1 128. 285. 262. 18.2 258. 12.K 52.K 176K
34Kc      2.6.18-rc4      40 5.01 14.0 61.6 90.0 477. 17.9 94.7 29.K 108K 342K
34Kc      2.6.18-rc4-p    40 4.98 13.9 61.2 89.7 475. 17.6 93.7 8758 44.K 158K
BCM1480   2.6.18-rc4     700 0.28 0.60 3.68 5.92 16.0 0.78 5.08 931. 3163 15.K
BCM1480   2.6.18-rc4-p   700 0.28 0.61 3.65 5.85 16.0 0.79 5.20 395. 1464 8385
TX49-16K  2.6.18-rc3     197 0.73 2.41 19.0 37.8 82.9 2.94 17.5 4438 14.K 56.K
TX49-16K  2.6.18-rc3-p   197 0.73 2.40 19.9 36.3 82.9 2.94 23.4 2577 9103 38.K
TX49-32K  2.6.18-rc3     396 0.36 1.19 6.80 11.8 41.0 1.46 8.17 2738 8465 32.K
TX49-32K  2.6.18-rc3-p   396 0.36 1.19 6.82 10.2 41.0 1.46 8.18 1330 4638 18.K
    
Original patch by me with enhancements by Atsushi Nemoto.
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
Signed-off-by: default avatarAtsushi Nemoto <anemo@mba.ocn.ne.jp>
parent 13fdd31a
...@@ -335,7 +335,7 @@ void __init r3k_cache_init(void) ...@@ -335,7 +335,7 @@ void __init r3k_cache_init(void)
flush_cache_mm = r3k_flush_cache_mm; flush_cache_mm = r3k_flush_cache_mm;
flush_cache_range = r3k_flush_cache_range; flush_cache_range = r3k_flush_cache_range;
flush_cache_page = r3k_flush_cache_page; flush_cache_page = r3k_flush_cache_page;
flush_icache_page = r3k_flush_icache_page; __flush_icache_page = r3k_flush_icache_page;
flush_icache_range = r3k_flush_icache_range; flush_icache_range = r3k_flush_icache_range;
flush_cache_sigtramp = r3k_flush_cache_sigtramp; flush_cache_sigtramp = r3k_flush_cache_sigtramp;
......
...@@ -1291,7 +1291,7 @@ void __init r4k_cache_init(void) ...@@ -1291,7 +1291,7 @@ void __init r4k_cache_init(void)
__flush_cache_all = r4k___flush_cache_all; __flush_cache_all = r4k___flush_cache_all;
flush_cache_mm = r4k_flush_cache_mm; flush_cache_mm = r4k_flush_cache_mm;
flush_cache_page = r4k_flush_cache_page; flush_cache_page = r4k_flush_cache_page;
flush_icache_page = r4k_flush_icache_page; __flush_icache_page = r4k_flush_icache_page;
flush_cache_range = r4k_flush_cache_range; flush_cache_range = r4k_flush_cache_range;
flush_cache_sigtramp = r4k_flush_cache_sigtramp; flush_cache_sigtramp = r4k_flush_cache_sigtramp;
......
...@@ -520,7 +520,7 @@ void sb1_cache_init(void) ...@@ -520,7 +520,7 @@ void sb1_cache_init(void)
/* These routines are for Icache coherence with the Dcache */ /* These routines are for Icache coherence with the Dcache */
flush_icache_range = sb1_flush_icache_range; flush_icache_range = sb1_flush_icache_range;
flush_icache_page = sb1_flush_icache_page; __flush_icache_page = sb1_flush_icache_page;
flush_icache_all = __sb1_flush_icache_all; /* local only */ flush_icache_all = __sb1_flush_icache_all; /* local only */
/* This implies an Icache flush too, so can't be nop'ed */ /* This implies an Icache flush too, so can't be nop'ed */
......
...@@ -382,7 +382,7 @@ void __init tx39_cache_init(void) ...@@ -382,7 +382,7 @@ void __init tx39_cache_init(void)
flush_cache_mm = (void *) tx39h_flush_icache_all; flush_cache_mm = (void *) tx39h_flush_icache_all;
flush_cache_range = (void *) tx39h_flush_icache_all; flush_cache_range = (void *) tx39h_flush_icache_all;
flush_cache_page = (void *) tx39h_flush_icache_all; flush_cache_page = (void *) tx39h_flush_icache_all;
flush_icache_page = (void *) tx39h_flush_icache_all; __flush_icache_page = (void *) tx39h_flush_icache_all;
flush_icache_range = (void *) tx39h_flush_icache_all; flush_icache_range = (void *) tx39h_flush_icache_all;
flush_cache_sigtramp = (void *) tx39h_flush_icache_all; flush_cache_sigtramp = (void *) tx39h_flush_icache_all;
...@@ -408,7 +408,7 @@ void __init tx39_cache_init(void) ...@@ -408,7 +408,7 @@ void __init tx39_cache_init(void)
flush_cache_mm = tx39_flush_cache_mm; flush_cache_mm = tx39_flush_cache_mm;
flush_cache_range = tx39_flush_cache_range; flush_cache_range = tx39_flush_cache_range;
flush_cache_page = tx39_flush_cache_page; flush_cache_page = tx39_flush_cache_page;
flush_icache_page = tx39_flush_icache_page; __flush_icache_page = tx39_flush_icache_page;
flush_icache_range = tx39_flush_icache_range; flush_icache_range = tx39_flush_icache_range;
flush_cache_sigtramp = tx39_flush_cache_sigtramp; flush_cache_sigtramp = tx39_flush_cache_sigtramp;
......
...@@ -25,7 +25,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, ...@@ -25,7 +25,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
unsigned long pfn); unsigned long pfn);
void (*flush_icache_range)(unsigned long start, unsigned long end); void (*flush_icache_range)(unsigned long start, unsigned long end);
void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page); void (*__flush_icache_page)(struct vm_area_struct *vma, struct page *page);
/* MIPS specific cache operations */ /* MIPS specific cache operations */
void (*flush_cache_sigtramp)(unsigned long addr); void (*flush_cache_sigtramp)(unsigned long addr);
...@@ -70,6 +70,8 @@ void __flush_dcache_page(struct page *page) ...@@ -70,6 +70,8 @@ void __flush_dcache_page(struct page *page)
struct address_space *mapping = page_mapping(page); struct address_space *mapping = page_mapping(page);
unsigned long addr; unsigned long addr;
if (PageHighMem(page))
return;
if (mapping && !mapping_mapped(mapping)) { if (mapping && !mapping_mapped(mapping)) {
SetPageDcacheDirty(page); SetPageDcacheDirty(page);
return; return;
...@@ -91,16 +93,16 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address, ...@@ -91,16 +93,16 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address,
{ {
struct page *page; struct page *page;
unsigned long pfn, addr; unsigned long pfn, addr;
int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc;
pfn = pte_pfn(pte); pfn = pte_pfn(pte);
if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page_mapping(page)) && if (unlikely(!pfn_valid(pfn)))
Page_dcache_dirty(page)) { return;
if (pages_do_alias((unsigned long)page_address(page), page = pfn_to_page(pfn);
address & PAGE_MASK)) { if (page_mapping(page) && Page_dcache_dirty(page)) {
addr = (unsigned long) page_address(page); addr = (unsigned long) page_address(page);
if (exec || pages_do_alias(addr, address & PAGE_MASK))
flush_data_cache_page(addr); flush_data_cache_page(addr);
}
ClearPageDcacheDirty(page); ClearPageDcacheDirty(page);
} }
} }
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
* - flush_cache_range(vma, start, end) flushes a range of pages * - flush_cache_range(vma, start, end) flushes a range of pages
* - flush_icache_range(start, end) flush a range of instructions * - flush_icache_range(start, end) flush a range of instructions
* - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache * - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
* - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
* *
* MIPS specific flush operations: * MIPS specific flush operations:
* *
...@@ -39,7 +38,7 @@ extern void __flush_dcache_page(struct page *page); ...@@ -39,7 +38,7 @@ extern void __flush_dcache_page(struct page *page);
static inline void flush_dcache_page(struct page *page) static inline void flush_dcache_page(struct page *page)
{ {
if (cpu_has_dc_aliases) if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
__flush_dcache_page(page); __flush_dcache_page(page);
} }
...@@ -47,8 +46,13 @@ static inline void flush_dcache_page(struct page *page) ...@@ -47,8 +46,13 @@ static inline void flush_dcache_page(struct page *page)
#define flush_dcache_mmap_lock(mapping) do { } while (0) #define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0)
extern void (*flush_icache_page)(struct vm_area_struct *vma, extern void (*__flush_icache_page)(struct vm_area_struct *vma,
struct page *page); struct page *page);
static inline void flush_icache_page(struct vm_area_struct *vma,
struct page *page)
{
}
extern void (*flush_icache_range)(unsigned long start, unsigned long end); extern void (*flush_icache_range)(unsigned long start, unsigned long end);
#define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vmap(start, end) flush_cache_all()
#define flush_cache_vunmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all()
...@@ -60,7 +64,7 @@ static inline void copy_to_user_page(struct vm_area_struct *vma, ...@@ -60,7 +64,7 @@ static inline void copy_to_user_page(struct vm_area_struct *vma,
if (cpu_has_dc_aliases) if (cpu_has_dc_aliases)
flush_cache_page(vma, vaddr, page_to_pfn(page)); flush_cache_page(vma, vaddr, page_to_pfn(page));
memcpy(dst, src, len); memcpy(dst, src, len);
flush_icache_page(vma, page); __flush_icache_page(vma, page);
} }
static inline void copy_from_user_page(struct vm_area_struct *vma, static inline void copy_from_user_page(struct vm_area_struct *vma,
......
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/cpu-features.h>
extern void clear_page(void * page); extern void clear_page(void * page);
extern void copy_page(void * to, void * from); extern void copy_page(void * to, void * from);
...@@ -53,7 +55,7 @@ static inline void clear_user_page(void *addr, unsigned long vaddr, ...@@ -53,7 +55,7 @@ static inline void clear_user_page(void *addr, unsigned long vaddr,
extern void (*flush_data_cache_page)(unsigned long addr); extern void (*flush_data_cache_page)(unsigned long addr);
clear_page(addr); clear_page(addr);
if (pages_do_alias((unsigned long) addr, vaddr)) if (pages_do_alias((unsigned long) addr, vaddr & PAGE_MASK))
flush_data_cache_page((unsigned long)addr); flush_data_cache_page((unsigned long)addr);
} }
...@@ -63,7 +65,8 @@ static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, ...@@ -63,7 +65,8 @@ static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
extern void (*flush_data_cache_page)(unsigned long addr); extern void (*flush_data_cache_page)(unsigned long addr);
copy_page(vto, vfrom); copy_page(vto, vfrom);
if (pages_do_alias((unsigned long)vto, vaddr)) if (!cpu_has_ic_fills_f_dc ||
pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
flush_data_cache_page((unsigned long)vto); flush_data_cache_page((unsigned long)vto);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment