aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm/pg-sh4.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/mm/pg-sh4.c')
-rw-r--r--arch/sh/mm/pg-sh4.c75
1 files changed, 52 insertions, 23 deletions
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index 25f5c6f6821d..8c7a9ca79879 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -9,6 +9,8 @@
9#include <linux/mm.h> 9#include <linux/mm.h>
10#include <linux/mutex.h> 10#include <linux/mutex.h>
11#include <linux/fs.h> 11#include <linux/fs.h>
12#include <linux/highmem.h>
13#include <linux/module.h>
12#include <asm/mmu_context.h> 14#include <asm/mmu_context.h>
13#include <asm/cacheflush.h> 15#include <asm/cacheflush.h>
14 16
@@ -50,34 +52,61 @@ static inline void kunmap_coherent(struct page *page)
50void clear_user_page(void *to, unsigned long address, struct page *page) 52void clear_user_page(void *to, unsigned long address, struct page *page)
51{ 53{
52 __set_bit(PG_mapped, &page->flags); 54 __set_bit(PG_mapped, &page->flags);
53 if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) 55
54 clear_page(to); 56 clear_page(to);
55 else { 57 if ((((address & PAGE_MASK) ^ (unsigned long)to) & CACHE_ALIAS))
56 void *vto = kmap_coherent(page, address); 58 __flush_wback_region(to, PAGE_SIZE);
57 __clear_user_page(vto, to);
58 kunmap_coherent(vto);
59 }
60} 59}
61 60
62/* 61void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
63 * copy_user_page 62 unsigned long vaddr, void *dst, const void *src,
64 * @to: P1 address 63 unsigned long len)
65 * @from: P1 address
66 * @address: U0 address to be mapped
67 * @page: page (virt_to_page(to))
68 */
69void copy_user_page(void *to, void *from, unsigned long address,
70 struct page *page)
71{ 64{
65 void *vto;
66
72 __set_bit(PG_mapped, &page->flags); 67 __set_bit(PG_mapped, &page->flags);
73 if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) 68
74 copy_page(to, from); 69 vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
75 else { 70 memcpy(vto, src, len);
76 void *vfrom = kmap_coherent(page, address); 71 kunmap_coherent(vto);
77 __copy_user_page(vfrom, from, to); 72
78 kunmap_coherent(vfrom); 73 if (vma->vm_flags & VM_EXEC)
79 } 74 flush_cache_page(vma, vaddr, page_to_pfn(page));
75}
76
77void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
78 unsigned long vaddr, void *dst, const void *src,
79 unsigned long len)
80{
81 void *vfrom;
82
83 __set_bit(PG_mapped, &page->flags);
84
85 vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
86 memcpy(dst, vfrom, len);
87 kunmap_coherent(vfrom);
88}
89
90void copy_user_highpage(struct page *to, struct page *from,
91 unsigned long vaddr, struct vm_area_struct *vma)
92{
93 void *vfrom, *vto;
94
95 __set_bit(PG_mapped, &to->flags);
96
97 vto = kmap_atomic(to, KM_USER1);
98 vfrom = kmap_coherent(from, vaddr);
99 copy_page(vto, vfrom);
100 kunmap_coherent(vfrom);
101
102 if (((vaddr ^ (unsigned long)vto) & CACHE_ALIAS))
103 __flush_wback_region(vto, PAGE_SIZE);
104
105 kunmap_atomic(vto, KM_USER1);
106 /* Make sure this page is cleared on other CPU's too before using it */
107 smp_wmb();
80} 108}
109EXPORT_SYMBOL(copy_user_highpage);
81 110
82/* 111/*
83 * For SH-4, we have our own implementation for ptep_get_and_clear 112 * For SH-4, we have our own implementation for ptep_get_and_clear