diff options
-rw-r--r-- | arch/sh/mm/clear_page.S | 45 | ||||
-rw-r--r-- | arch/sh/mm/copy_page.S | 61 | ||||
-rw-r--r-- | arch/sh/mm/pg-sh4.c | 75 | ||||
-rw-r--r-- | include/asm-sh/cacheflush.h | 18 | ||||
-rw-r--r-- | include/asm-sh/page.h | 11 |
5 files changed, 73 insertions, 137 deletions
diff --git a/arch/sh/mm/clear_page.S b/arch/sh/mm/clear_page.S index 8a706131e521..7a7c81ee3f01 100644 --- a/arch/sh/mm/clear_page.S +++ b/arch/sh/mm/clear_page.S | |||
@@ -150,48 +150,3 @@ ENTRY(__clear_user) | |||
150 | .long 8b, .Lbad_clear_user | 150 | .long 8b, .Lbad_clear_user |
151 | .long 9b, .Lbad_clear_user | 151 | .long 9b, .Lbad_clear_user |
152 | .previous | 152 | .previous |
153 | |||
154 | #if defined(CONFIG_CPU_SH4) | ||
155 | /* | ||
156 | * __clear_user_page | ||
157 | * @to: P3 address (with same color) | ||
158 | * @orig_to: P1 address | ||
159 | * | ||
160 | * void __clear_user_page(void *to, void *orig_to) | ||
161 | */ | ||
162 | |||
163 | /* | ||
164 | * r0 --- scratch | ||
165 | * r4 --- to | ||
166 | * r5 --- orig_to | ||
167 | * r6 --- to + PAGE_SIZE | ||
168 | */ | ||
169 | ENTRY(__clear_user_page) | ||
170 | mov.l .Lpsz,r0 | ||
171 | mov r4,r6 | ||
172 | add r0,r6 | ||
173 | mov #0,r0 | ||
174 | ! | ||
175 | 1: ocbi @r5 | ||
176 | add #32,r5 | ||
177 | movca.l r0,@r4 | ||
178 | mov r4,r1 | ||
179 | add #32,r4 | ||
180 | mov.l r0,@-r4 | ||
181 | mov.l r0,@-r4 | ||
182 | mov.l r0,@-r4 | ||
183 | mov.l r0,@-r4 | ||
184 | mov.l r0,@-r4 | ||
185 | mov.l r0,@-r4 | ||
186 | mov.l r0,@-r4 | ||
187 | add #28,r4 | ||
188 | cmp/eq r6,r4 | ||
189 | bf/s 1b | ||
190 | ocbwb @r1 | ||
191 | ! | ||
192 | rts | ||
193 | nop | ||
194 | .Lpsz: .long PAGE_SIZE | ||
195 | |||
196 | #endif | ||
197 | |||
diff --git a/arch/sh/mm/copy_page.S b/arch/sh/mm/copy_page.S index 3d8409daa4be..40685018b952 100644 --- a/arch/sh/mm/copy_page.S +++ b/arch/sh/mm/copy_page.S | |||
@@ -68,67 +68,6 @@ ENTRY(copy_page_slow) | |||
68 | rts | 68 | rts |
69 | nop | 69 | nop |
70 | 70 | ||
71 | #if defined(CONFIG_CPU_SH4) | ||
72 | /* | ||
73 | * __copy_user_page | ||
74 | * @to: P1 address (with same color) | ||
75 | * @from: P1 address | ||
76 | * @orig_to: P1 address | ||
77 | * | ||
78 | * void __copy_user_page(void *to, void *from, void *orig_to) | ||
79 | */ | ||
80 | |||
81 | /* | ||
82 | * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch | ||
83 | * r8 --- from + PAGE_SIZE | ||
84 | * r9 --- orig_to | ||
85 | * r10 --- to | ||
86 | * r11 --- from | ||
87 | */ | ||
88 | ENTRY(__copy_user_page) | ||
89 | mov.l r8,@-r15 | ||
90 | mov.l r9,@-r15 | ||
91 | mov.l r10,@-r15 | ||
92 | mov.l r11,@-r15 | ||
93 | mov r4,r10 | ||
94 | mov r5,r11 | ||
95 | mov r6,r9 | ||
96 | mov r5,r8 | ||
97 | mov.l .Lpsz,r0 | ||
98 | add r0,r8 | ||
99 | ! | ||
100 | 1: ocbi @r9 | ||
101 | add #32,r9 | ||
102 | mov.l @r11+,r0 | ||
103 | mov.l @r11+,r1 | ||
104 | mov.l @r11+,r2 | ||
105 | mov.l @r11+,r3 | ||
106 | mov.l @r11+,r4 | ||
107 | mov.l @r11+,r5 | ||
108 | mov.l @r11+,r6 | ||
109 | mov.l @r11+,r7 | ||
110 | movca.l r0,@r10 | ||
111 | mov r10,r0 | ||
112 | add #32,r10 | ||
113 | mov.l r7,@-r10 | ||
114 | mov.l r6,@-r10 | ||
115 | mov.l r5,@-r10 | ||
116 | mov.l r4,@-r10 | ||
117 | mov.l r3,@-r10 | ||
118 | mov.l r2,@-r10 | ||
119 | mov.l r1,@-r10 | ||
120 | ocbwb @r0 | ||
121 | cmp/eq r11,r8 | ||
122 | bf/s 1b | ||
123 | add #28,r10 | ||
124 | ! | ||
125 | mov.l @r15+,r11 | ||
126 | mov.l @r15+,r10 | ||
127 | mov.l @r15+,r9 | ||
128 | mov.l @r15+,r8 | ||
129 | rts | ||
130 | nop | ||
131 | #endif | ||
132 | .align 2 | 71 | .align 2 |
133 | .Lpsz: .long PAGE_SIZE | 72 | .Lpsz: .long PAGE_SIZE |
134 | /* | 73 | /* |
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) | |||
50 | void clear_user_page(void *to, unsigned long address, struct page *page) | 52 | void 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 | /* | 61 | void 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 | */ | ||
69 | void 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 | |||
77 | void 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 | |||
90 | void 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 | } |
109 | EXPORT_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 |
diff --git a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h index aa558da08471..b91246153b7e 100644 --- a/include/asm-sh/cacheflush.h +++ b/include/asm-sh/cacheflush.h | |||
@@ -43,21 +43,31 @@ extern void __flush_purge_region(void *start, int size); | |||
43 | extern void __flush_invalidate_region(void *start, int size); | 43 | extern void __flush_invalidate_region(void *start, int size); |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #define flush_cache_vmap(start, end) flush_cache_all() | 46 | #ifdef CONFIG_CPU_SH4 |
47 | #define flush_cache_vunmap(start, end) flush_cache_all() | 47 | extern void copy_to_user_page(struct vm_area_struct *vma, |
48 | struct page *page, unsigned long vaddr, void *dst, const void *src, | ||
49 | unsigned long len); | ||
48 | 50 | ||
49 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | 51 | extern void copy_from_user_page(struct vm_area_struct *vma, |
52 | struct page *page, unsigned long vaddr, void *dst, const void *src, | ||
53 | unsigned long len); | ||
54 | #else | ||
55 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | ||
50 | do { \ | 56 | do { \ |
51 | flush_cache_page(vma, vaddr, page_to_pfn(page));\ | 57 | flush_cache_page(vma, vaddr, page_to_pfn(page));\ |
52 | memcpy(dst, src, len); \ | 58 | memcpy(dst, src, len); \ |
53 | flush_icache_user_range(vma, page, vaddr, len); \ | 59 | flush_icache_user_range(vma, page, vaddr, len); \ |
54 | } while (0) | 60 | } while (0) |
55 | 61 | ||
56 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | 62 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ |
57 | do { \ | 63 | do { \ |
58 | flush_cache_page(vma, vaddr, page_to_pfn(page));\ | 64 | flush_cache_page(vma, vaddr, page_to_pfn(page));\ |
59 | memcpy(dst, src, len); \ | 65 | memcpy(dst, src, len); \ |
60 | } while (0) | 66 | } while (0) |
67 | #endif | ||
68 | |||
69 | #define flush_cache_vmap(start, end) flush_cache_all() | ||
70 | #define flush_cache_vunmap(start, end) flush_cache_all() | ||
61 | 71 | ||
62 | #define HAVE_ARCH_UNMAPPED_AREA | 72 | #define HAVE_ARCH_UNMAPPED_AREA |
63 | 73 | ||
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index 3aa8b07da47d..d00a8fde7c7f 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h | |||
@@ -73,10 +73,13 @@ extern void copy_page_nommu(void *to, void *from); | |||
73 | #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ | 73 | #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ |
74 | (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) | 74 | (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) |
75 | struct page; | 75 | struct page; |
76 | extern void clear_user_page(void *to, unsigned long address, struct page *pg); | 76 | struct vm_area_struct; |
77 | extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg); | 77 | extern void clear_user_page(void *to, unsigned long address, struct page *page); |
78 | extern void __clear_user_page(void *to, void *orig_to); | 78 | #ifdef CONFIG_CPU_SH4 |
79 | extern void __copy_user_page(void *to, void *from, void *orig_to); | 79 | extern void copy_user_highpage(struct page *to, struct page *from, |
80 | unsigned long vaddr, struct vm_area_struct *vma); | ||
81 | #define __HAVE_ARCH_COPY_USER_HIGHPAGE | ||
82 | #endif | ||
80 | #else | 83 | #else |
81 | #define clear_user_page(page, vaddr, pg) clear_page(page) | 84 | #define clear_user_page(page, vaddr, pg) clear_page(page) |
82 | #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) | 85 | #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) |