diff options
author | Paul Mundt <lethal@linux-sh.org> | 2007-11-05 16:12:32 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2007-11-07 11:14:12 +0900 |
commit | 7747b9a493a197cb4db44c98d25ce6d3d9f586d1 (patch) | |
tree | 636aa0624e6768ef0e8ea02d0692f91dfb51d79f | |
parent | f96691872439ab2071171d4531c4a95b5d493ae5 (diff) |
sh: Wire up clear_user_highpage().
With the kmap_coherent() API in place, this is trivial to implement,
and lets us avoid the cache flush in certain cases.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/sh/mm/pg-sh4.c | 23 | ||||
-rw-r--r-- | include/asm-sh/page.h | 6 |
2 files changed, 29 insertions, 0 deletions
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index 25f5c6f6821d..ede6dd1e3701 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c @@ -9,6 +9,8 @@ #include <linux/mm.h> #include <linux/mutex.h> #include <linux/fs.h> +#include <linux/highmem.h> +#include <linux/module.h> #include <asm/mmu_context.h> #include <asm/cacheflush.h> @@ -79,6 +81,27 @@ void copy_user_page(void *to, void *from, unsigned long address, } } +void copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma) +{ + void *vfrom, *vto; + + __set_bit(PG_mapped, &to->flags); + + vto = kmap_atomic(to, KM_USER1); + vfrom = kmap_coherent(from, vaddr); + copy_page(vto, vfrom); + kunmap_coherent(vfrom); + + if (((vaddr ^ (unsigned long)vto) & CACHE_ALIAS)) + __flush_wback_region(vto, PAGE_SIZE); + + kunmap_atomic(vto, KM_USER1); + /* Make sure this page is cleared on other CPU's too before using it */ + smp_wmb(); +} +EXPORT_SYMBOL(copy_user_highpage); + /* * For SH-4, we have our own implementation for ptep_get_and_clear */ diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index 3aa8b07da47d..5e69de1eacdf 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h @@ -73,10 +73,16 @@ extern void copy_page_nommu(void *to, void *from); #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) struct page; +struct vm_area_struct; extern void clear_user_page(void *to, unsigned long address, struct page *pg); extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg); extern void __clear_user_page(void *to, void *orig_to); extern void __copy_user_page(void *to, void *from, void *orig_to); +#ifdef CONFIG_CPU_SH4 +extern void copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); +#define __HAVE_ARCH_COPY_USER_HIGHPAGE +#endif #else #define clear_user_page(page, vaddr, pg) clear_page(page) #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) |