parisc: fixes and cleanups in page cache flushing (1/4)
This is the first patch in a series of 4, with which the page cache flushing of
parisc will gets fixed and enhanced. This even fixes the nasty "minifail" bug
(http://wiki.parisc-linux.org/TestCases?highlight=%28minifail%29) which
prevented parisc to stay an official debian port. Basically the flush in
copy_user_page together with the TLB patch from commit
7139bc1579
is what fixes the minifail bug.
This patch still uses the TMPALIAS approach. The new copy_user_page
implementation calls flush_dcache_page_asm to flush the user dcache page
(crucial for minifail fix) via a kernel TMPALIAS mapping. After that, it just
copies the page using the kernel mapping. It does a final flush if needed.
Generally it is hard to avoid doing some cache flushes using the kernel mapping
(e.g., copy_to_user_page and copy_from_user_page).
This patch depends on a subsequent change to pacache.S implementing
clear_page_asm and copy_page_asm. These are optimized routines to clear and
copy a page. The calls in clear_user_page and copy_user_page could be replaced
by calls to memset and memcpy, respectively. I tested prefetch optimizations
in clear_page_asm and copy_page_asm but didn't see any significant performance
improvement on rp3440. I'm not sure if these are routines are significantly
faster than memset and/or memcpy, but they are there for further performance
evaluation.
Signed-off-by: John David Anglin <dave.anglin@bell.net>
Signed-off-by: Helge Deller <deller@gmx.de>
Este cometimento está contido em:

cometido por
Helge Deller

ascendente
93c3e913e1
cometimento
7633453978
@@ -329,17 +329,6 @@ EXPORT_SYMBOL(flush_kernel_dcache_page_asm);
|
||||
EXPORT_SYMBOL(flush_data_cache_local);
|
||||
EXPORT_SYMBOL(flush_kernel_icache_range_asm);
|
||||
|
||||
void clear_user_page_asm(void *page, unsigned long vaddr)
|
||||
{
|
||||
unsigned long flags;
|
||||
/* This function is implemented in assembly in pacache.S */
|
||||
extern void __clear_user_page_asm(void *page, unsigned long vaddr);
|
||||
|
||||
purge_tlb_start(flags);
|
||||
__clear_user_page_asm(page, vaddr);
|
||||
purge_tlb_end(flags);
|
||||
}
|
||||
|
||||
#define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
|
||||
int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD;
|
||||
|
||||
@@ -373,20 +362,9 @@ void __init parisc_setup_cache_timing(void)
|
||||
printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
|
||||
}
|
||||
|
||||
extern void purge_kernel_dcache_page(unsigned long);
|
||||
extern void clear_user_page_asm(void *page, unsigned long vaddr);
|
||||
|
||||
void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
purge_kernel_dcache_page((unsigned long)page);
|
||||
purge_tlb_start(flags);
|
||||
pdtlb_kernel(page);
|
||||
purge_tlb_end(flags);
|
||||
clear_user_page_asm(page, vaddr);
|
||||
}
|
||||
EXPORT_SYMBOL(clear_user_page);
|
||||
extern void purge_kernel_dcache_page_asm(unsigned long);
|
||||
extern void clear_user_page_asm(void *, unsigned long);
|
||||
extern void copy_user_page_asm(void *, void *, unsigned long);
|
||||
|
||||
void flush_kernel_dcache_page_addr(void *addr)
|
||||
{
|
||||
@@ -399,11 +377,26 @@ void flush_kernel_dcache_page_addr(void *addr)
|
||||
}
|
||||
EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
|
||||
|
||||
void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
|
||||
struct page *pg)
|
||||
void clear_user_page(void *vto, unsigned long vaddr, struct page *page)
|
||||
{
|
||||
/* no coherency needed (all in kmap/kunmap) */
|
||||
copy_user_page_asm(vto, vfrom);
|
||||
clear_page_asm(vto);
|
||||
if (!parisc_requires_coherency())
|
||||
flush_kernel_dcache_page_asm(vto);
|
||||
}
|
||||
EXPORT_SYMBOL(clear_user_page);
|
||||
|
||||
void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
|
||||
struct page *pg)
|
||||
{
|
||||
/* Copy using kernel mapping. No coherency is needed
|
||||
(all in kmap/kunmap) on machines that don't support
|
||||
non-equivalent aliasing. However, the `from' page
|
||||
needs to be flushed before it can be accessed through
|
||||
the kernel mapping. */
|
||||
preempt_disable();
|
||||
flush_dcache_page_asm(__pa(vfrom), vaddr);
|
||||
preempt_enable();
|
||||
copy_page_asm(vto, vfrom);
|
||||
if (!parisc_requires_coherency())
|
||||
flush_kernel_dcache_page_asm(vto);
|
||||
}
|
||||
|
Criar uma nova questão referindo esta
Bloquear um utilizador