Commit c2ed00d8 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] PA-RISC Cache flush optimisation

Cache flush optimization for UP/SMP; remove hardcoded threshold
for selecting whole cache vs region flush

From: Randolph Chung <tausq@parisc-linux.org>
Signed-off-by: default avatarMatthew Wilcox <willy@parisc-linux.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 8953e802
...@@ -55,6 +55,11 @@ flush_data_cache(void) ...@@ -55,6 +55,11 @@ flush_data_cache(void)
{ {
on_each_cpu((void (*)(void *))flush_data_cache_local, NULL, 1, 1); on_each_cpu((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
} }
void
flush_instruction_cache(void)
{
on_each_cpu((void (*)(void *))flush_instruction_cache_local, NULL, 1, 1);
}
#endif #endif
void void
...@@ -327,3 +332,35 @@ void clear_user_page_asm(void *page, unsigned long vaddr) ...@@ -327,3 +332,35 @@ void clear_user_page_asm(void *page, unsigned long vaddr)
__clear_user_page_asm(page, vaddr); __clear_user_page_asm(page, vaddr);
purge_tlb_end(); purge_tlb_end();
} }
#define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
int parisc_cache_flush_threshold = FLUSH_THRESHOLD;
void parisc_setup_cache_timing(void)
{
unsigned long rangetime, alltime;
extern char _text; /* start of kernel code, defined by linker */
extern char _end; /* end of BSS, defined by linker */
unsigned long size;
alltime = mfctl(16);
flush_data_cache();
alltime = mfctl(16) - alltime;
size = (unsigned long)(&_end - _text);
rangetime = mfctl(16);
flush_kernel_dcache_range((unsigned long)&_text, size);
rangetime = mfctl(16) - rangetime;
printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
alltime, size, rangetime);
/* Racy, but if we see an intermediate value, it's ok too... */
parisc_cache_flush_threshold = size * alltime / rangetime;
parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1);
if (!parisc_cache_flush_threshold)
parisc_cache_flush_threshold = FLUSH_THRESHOLD;
printk("Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
}
...@@ -307,6 +307,8 @@ static int __init parisc_init(void) ...@@ -307,6 +307,8 @@ static int __init parisc_init(void)
boot_cpu_data.cpu_hz / 1000000, boot_cpu_data.cpu_hz / 1000000,
boot_cpu_data.cpu_hz % 1000000 ); boot_cpu_data.cpu_hz % 1000000 );
parisc_setup_cache_timing();
/* These are in a non-obvious order, will fix when we have an iotree */ /* These are in a non-obvious order, will fix when we have an iotree */
#if defined(CONFIG_IOSAPIC) #if defined(CONFIG_IOSAPIC)
iosapic_init(); iosapic_init();
......
...@@ -34,6 +34,7 @@ extern void flush_data_cache_local(void); /* flushes local data-cache only */ ...@@ -34,6 +34,7 @@ extern void flush_data_cache_local(void); /* flushes local data-cache only */
extern void flush_instruction_cache_local(void); /* flushes local code-cache only */ extern void flush_instruction_cache_local(void); /* flushes local code-cache only */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
extern void flush_data_cache(void); /* flushes data-cache only (all processors) */ extern void flush_data_cache(void); /* flushes data-cache only (all processors) */
extern void flush_instruction_cache(void); /* flushes i-cache only (all processors) */
#else #else
#define flush_data_cache flush_data_cache_local #define flush_data_cache flush_data_cache_local
#define flush_instruction_cache flush_instruction_cache_local #define flush_instruction_cache flush_instruction_cache_local
......
...@@ -33,36 +33,25 @@ static inline void flush_cache_all(void) ...@@ -33,36 +33,25 @@ static inline void flush_cache_all(void)
#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()
/* The following value needs to be tuned and probably scaled with the extern int parisc_cache_flush_threshold;
* cache size. void parisc_setup_cache_timing(void);
*/
#define FLUSH_THRESHOLD 0x80000
static inline void static inline void
flush_user_dcache_range(unsigned long start, unsigned long end) flush_user_dcache_range(unsigned long start, unsigned long end)
{ {
#ifdef CONFIG_SMP if ((end - start) < parisc_cache_flush_threshold)
flush_user_dcache_range_asm(start,end);
#else
if ((end - start) < FLUSH_THRESHOLD)
flush_user_dcache_range_asm(start,end); flush_user_dcache_range_asm(start,end);
else else
flush_data_cache(); flush_data_cache();
#endif
} }
static inline void static inline void
flush_user_icache_range(unsigned long start, unsigned long end) flush_user_icache_range(unsigned long start, unsigned long end)
{ {
#ifdef CONFIG_SMP if ((end - start) < parisc_cache_flush_threshold)
flush_user_icache_range_asm(start,end);
#else
if ((end - start) < FLUSH_THRESHOLD)
flush_user_icache_range_asm(start,end); flush_user_icache_range_asm(start,end);
else else
flush_instruction_cache(); flush_instruction_cache();
#endif
} }
extern void flush_dcache_page(struct page *page); extern void flush_dcache_page(struct page *page);
......
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