ARM: 7409/1: Do not call flush_cache_user_range with mmap_sem held
[linux/fpc-iii.git] / arch / xtensa / mm / misc.S
blobb048406d87568cb23a5fd14d7dd215dd51f6f6dc
1 /*
2  * arch/xtensa/mm/misc.S
3  *
4  * Miscellaneous assembly functions.
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file "COPYING" in the main directory of this archive
8  * for more details.
9  *
10  * Copyright (C) 2001 - 2007 Tensilica Inc.
11  *
12  * Chris Zankel <chris@zankel.net>
13  */
16 #include <linux/linkage.h>
17 #include <asm/page.h>
18 #include <asm/pgtable.h>
19 #include <asm/asmmacro.h>
20 #include <asm/cacheasm.h>
21 #include <asm/tlbflush.h>
25  * clear_page and clear_user_page are the same for non-cache-aliased configs.
26  *
27  * clear_page (unsigned long page)
28  *                    a2
29  */
31 ENTRY(clear_page)
32         entry   a1, 16
34         movi    a3, 0
35         __loopi a2, a7, PAGE_SIZE, 32
36         s32i    a3, a2, 0
37         s32i    a3, a2, 4
38         s32i    a3, a2, 8
39         s32i    a3, a2, 12
40         s32i    a3, a2, 16
41         s32i    a3, a2, 20
42         s32i    a3, a2, 24
43         s32i    a3, a2, 28
44         __endla a2, a7, 32
46         retw
49  * copy_page and copy_user_page are the same for non-cache-aliased configs.
50  *
51  * copy_page (void *to, void *from)
52  *               a2          a3
53  */
55 ENTRY(copy_page)
56         entry   a1, 16
58         __loopi a2, a4, PAGE_SIZE, 32
60         l32i    a8, a3, 0
61         l32i    a9, a3, 4
62         s32i    a8, a2, 0
63         s32i    a9, a2, 4
65         l32i    a8, a3, 8
66         l32i    a9, a3, 12
67         s32i    a8, a2, 8
68         s32i    a9, a2, 12
70         l32i    a8, a3, 16
71         l32i    a9, a3, 20
72         s32i    a8, a2, 16
73         s32i    a9, a2, 20
75         l32i    a8, a3, 24
76         l32i    a9, a3, 28
77         s32i    a8, a2, 24
78         s32i    a9, a2, 28
80         addi    a2, a2, 32
81         addi    a3, a3, 32
83         __endl  a2, a4
85         retw
87 #ifdef CONFIG_MMU
89  * If we have to deal with cache aliasing, we use temporary memory mappings
90  * to ensure that the source and destination pages have the same color as
91  * the virtual address. We use way 0 and 1 for temporary mappings in such cases.
92  *
93  * The temporary DTLB entries shouldn't be flushed by interrupts, but are
94  * flushed by preemptive task switches. Special code in the 
95  * fast_second_level_miss handler re-established the temporary mapping. 
96  * It requires that the PPNs for the destination and source addresses are
97  * in a6, and a7, respectively.
98  */
100 /* TLB miss exceptions are treated special in the following region */
102 ENTRY(__tlbtemp_mapping_start)
104 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
107  * clear_user_page (void *addr, unsigned long vaddr, struct page *page)
108  *                     a2              a3                 a4
109  */
111 ENTRY(clear_user_page)
112         entry   a1, 32
114         /* Mark page dirty and determine alias. */
116         movi    a7, (1 << PG_ARCH_1)
117         l32i    a5, a4, PAGE_FLAGS
118         xor     a6, a2, a3
119         extui   a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
120         extui   a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
121         or      a5, a5, a7
122         slli    a3, a3, PAGE_SHIFT
123         s32i    a5, a4, PAGE_FLAGS
125         /* Skip setting up a temporary DTLB if not aliased. */
127         beqz    a6, 1f
129         /* Invalidate kernel page. */
131         mov     a10, a2
132         call8   __invalidate_dcache_page
134         /* Setup a temporary DTLB with the color of the VPN */
136         movi    a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
137         movi    a5, TLBTEMP_BASE_1                      # virt
138         add     a6, a2, a4                              # ppn
139         add     a2, a5, a3                              # add 'color'
141         wdtlb   a6, a2
142         dsync
144 1:      movi    a3, 0
145         __loopi a2, a7, PAGE_SIZE, 32
146         s32i    a3, a2, 0
147         s32i    a3, a2, 4
148         s32i    a3, a2, 8
149         s32i    a3, a2, 12
150         s32i    a3, a2, 16
151         s32i    a3, a2, 20
152         s32i    a3, a2, 24
153         s32i    a3, a2, 28
154         __endla a2, a7, 32
156         bnez    a6, 1f
157         retw
159         /* We need to invalidate the temporary idtlb entry, if any. */
161 1:      addi    a2, a2, -PAGE_SIZE
162         idtlb   a2
163         dsync
165         retw
168  * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
169  *                    a2          a3            a4                  a5
170  */
172 ENTRY(copy_user_page)
174         entry   a1, 32 
176         /* Mark page dirty and determine alias for destination. */
178         movi    a8, (1 << PG_ARCH_1)
179         l32i    a9, a5, PAGE_FLAGS
180         xor     a6, a2, a4
181         xor     a7, a3, a4
182         extui   a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER
183         extui   a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
184         extui   a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER
185         or      a9, a9, a8
186         slli    a4, a4, PAGE_SHIFT
187         s32i    a9, a5, PAGE_FLAGS
188         movi    a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
190         beqz    a6, 1f
192         /* Invalidate dcache */
194         mov     a10, a2
195         call8   __invalidate_dcache_page
197         /* Setup a temporary DTLB with a matching color. */
199         movi    a8, TLBTEMP_BASE_1                      # base
200         add     a6, a2, a5                              # ppn
201         add     a2, a8, a4                              # add 'color'
203         wdtlb   a6, a2
204         dsync
206         /* Skip setting up a temporary DTLB for destination if not aliased. */
208 1:      beqz    a7, 1f
210         /* Setup a temporary DTLB with a matching color. */
212         movi    a8, TLBTEMP_BASE_2                      # base
213         add     a7, a3, a5                              # ppn
214         add     a3, a8, a4
215         addi    a8, a3, 1                               # way1
217         wdtlb   a7, a8
218         dsync
220 1:      __loopi a2, a4, PAGE_SIZE, 32
222         l32i    a8, a3, 0
223         l32i    a9, a3, 4
224         s32i    a8, a2, 0
225         s32i    a9, a2, 4
227         l32i    a8, a3, 8
228         l32i    a9, a3, 12
229         s32i    a8, a2, 8
230         s32i    a9, a2, 12
232         l32i    a8, a3, 16
233         l32i    a9, a3, 20
234         s32i    a8, a2, 16
235         s32i    a9, a2, 20
237         l32i    a8, a3, 24
238         l32i    a9, a3, 28
239         s32i    a8, a2, 24
240         s32i    a9, a2, 28
242         addi    a2, a2, 32
243         addi    a3, a3, 32
245         __endl  a2, a4
247         /* We need to invalidate any temporary mapping! */
249         bnez    a6, 1f
250         bnez    a7, 2f
251         retw
253 1:      addi    a2, a2, -PAGE_SIZE
254         idtlb   a2
255         dsync
256         bnez    a7, 2f
257         retw
259 2:      addi    a3, a3, -PAGE_SIZE+1
260         idtlb   a3
261         dsync
263         retw
265 #endif
267 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
270  * void __flush_invalidate_dcache_page_alias (addr, phys)
271  *                                             a2    a3
272  */
274 ENTRY(__flush_invalidate_dcache_page_alias)
275         entry   sp, 16
277         movi    a7, 0                   # required for exception handler
278         addi    a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
279         mov     a4, a2
280         wdtlb   a6, a2
281         dsync
283         ___flush_invalidate_dcache_page a2 a3
285         idtlb   a4
286         dsync
288         retw
290 #endif
292 ENTRY(__tlbtemp_mapping_itlb)
294 #if (ICACHE_WAY_SIZE > PAGE_SIZE)
295         
296 ENTRY(__invalidate_icache_page_alias)
297         entry   sp, 16
299         addi    a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
300         mov     a4, a2
301         witlb   a6, a2
302         isync
304         ___invalidate_icache_page a2 a3
306         iitlb   a4
307         isync
308         retw
310 #endif
312 /* End of special treatment in tlb miss exception */
314 ENTRY(__tlbtemp_mapping_end)
315 #endif /* CONFIG_MMU
318  * void __invalidate_icache_page(ulong start)
319  */
321 ENTRY(__invalidate_icache_page)
322         entry   sp, 16
324         ___invalidate_icache_page a2 a3
325         isync
327         retw
330  * void __invalidate_dcache_page(ulong start)
331  */
333 ENTRY(__invalidate_dcache_page)
334         entry   sp, 16
336         ___invalidate_dcache_page a2 a3
337         dsync
339         retw
342  * void __flush_invalidate_dcache_page(ulong start)
343  */
345 ENTRY(__flush_invalidate_dcache_page)
346         entry   sp, 16
348         ___flush_invalidate_dcache_page a2 a3
350         dsync
351         retw
354  * void __flush_dcache_page(ulong start)
355  */
357 ENTRY(__flush_dcache_page)
358         entry   sp, 16
360         ___flush_dcache_page a2 a3
362         dsync
363         retw
366  * void __invalidate_icache_range(ulong start, ulong size)
367  */
369 ENTRY(__invalidate_icache_range)
370         entry   sp, 16
372         ___invalidate_icache_range a2 a3 a4
373         isync
375         retw
378  * void __flush_invalidate_dcache_range(ulong start, ulong size)
379  */
381 ENTRY(__flush_invalidate_dcache_range)
382         entry   sp, 16
384         ___flush_invalidate_dcache_range a2 a3 a4
385         dsync
387         retw
390  * void _flush_dcache_range(ulong start, ulong size)
391  */
393 ENTRY(__flush_dcache_range)
394         entry   sp, 16
396         ___flush_dcache_range a2 a3 a4
397         dsync
399         retw
402  * void _invalidate_dcache_range(ulong start, ulong size)
403  */
405 ENTRY(__invalidate_dcache_range)
406         entry   sp, 16
408         ___invalidate_dcache_range a2 a3 a4
410         retw
413  * void _invalidate_icache_all(void)
414  */
416 ENTRY(__invalidate_icache_all)
417         entry   sp, 16
419         ___invalidate_icache_all a2 a3
420         isync
422         retw
425  * void _flush_invalidate_dcache_all(void)
426  */
428 ENTRY(__flush_invalidate_dcache_all)
429         entry   sp, 16
431         ___flush_invalidate_dcache_all a2 a3
432         dsync
434         retw
437  * void _invalidate_dcache_all(void)
438  */
440 ENTRY(__invalidate_dcache_all)
441         entry   sp, 16
443         ___invalidate_dcache_all a2 a3
444         dsync
446         retw