mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
[linux/fpc-iii.git] / arch / xtensa / mm / misc.S
blob11a01c3e9cea91ece949e93c0c7776bdb4826170
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)
33         entry   a1, 16
35         movi    a3, 0
36         __loopi a2, a7, PAGE_SIZE, 32
37         s32i    a3, a2, 0
38         s32i    a3, a2, 4
39         s32i    a3, a2, 8
40         s32i    a3, a2, 12
41         s32i    a3, a2, 16
42         s32i    a3, a2, 20
43         s32i    a3, a2, 24
44         s32i    a3, a2, 28
45         __endla a2, a7, 32
47         retw
49 ENDPROC(clear_page)
52  * copy_page and copy_user_page are the same for non-cache-aliased configs.
53  *
54  * copy_page (void *to, void *from)
55  *               a2          a3
56  */
58 ENTRY(copy_page)
60         entry   a1, 16
62         __loopi a2, a4, PAGE_SIZE, 32
64         l32i    a8, a3, 0
65         l32i    a9, a3, 4
66         s32i    a8, a2, 0
67         s32i    a9, a2, 4
69         l32i    a8, a3, 8
70         l32i    a9, a3, 12
71         s32i    a8, a2, 8
72         s32i    a9, a2, 12
74         l32i    a8, a3, 16
75         l32i    a9, a3, 20
76         s32i    a8, a2, 16
77         s32i    a9, a2, 20
79         l32i    a8, a3, 24
80         l32i    a9, a3, 28
81         s32i    a8, a2, 24
82         s32i    a9, a2, 28
84         addi    a2, a2, 32
85         addi    a3, a3, 32
87         __endl  a2, a4
89         retw
91 ENDPROC(copy_page)
93 #ifdef CONFIG_MMU
95  * If we have to deal with cache aliasing, we use temporary memory mappings
96  * to ensure that the source and destination pages have the same color as
97  * the virtual address. We use way 0 and 1 for temporary mappings in such cases.
98  *
99  * The temporary DTLB entries shouldn't be flushed by interrupts, but are
100  * flushed by preemptive task switches. Special code in the 
101  * fast_second_level_miss handler re-established the temporary mapping. 
102  * It requires that the PPNs for the destination and source addresses are
103  * in a6, and a7, respectively.
104  */
106 /* TLB miss exceptions are treated special in the following region */
108 ENTRY(__tlbtemp_mapping_start)
110 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
113  * clear_page_alias(void *addr, unsigned long paddr)
114  *                     a2              a3
115  */
117 ENTRY(clear_page_alias)
119         entry   a1, 32
121         /* Skip setting up a temporary DTLB if not aliased low page. */
123         movi    a5, PAGE_OFFSET
124         movi    a6, 0
125         beqz    a3, 1f
127         /* Setup a temporary DTLB for the addr. */
129         addi    a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
130         mov     a4, a2
131         wdtlb   a6, a2
132         dsync
134 1:      movi    a3, 0
135         __loopi a2, a7, PAGE_SIZE, 32
136         s32i    a3, a2, 0
137         s32i    a3, a2, 4
138         s32i    a3, a2, 8
139         s32i    a3, a2, 12
140         s32i    a3, a2, 16
141         s32i    a3, a2, 20
142         s32i    a3, a2, 24
143         s32i    a3, a2, 28
144         __endla a2, a7, 32
146         bnez    a6, 1f
147         retw
149         /* We need to invalidate the temporary idtlb entry, if any. */
151 1:      idtlb   a4
152         dsync
154         retw
156 ENDPROC(clear_page_alias)
159  * copy_page_alias(void *to, void *from,
160  *                      a2        a3
161  *                 unsigned long to_paddr, unsigned long from_paddr)
162  *                               a4                      a5
163  */
165 ENTRY(copy_page_alias)
167         entry   a1, 32
169         /* Skip setting up a temporary DTLB for destination if not aliased. */
171         movi    a6, 0
172         movi    a7, 0
173         beqz    a4, 1f
175         /* Setup a temporary DTLB for destination. */
177         addi    a6, a4, (PAGE_KERNEL | _PAGE_HW_WRITE)
178         wdtlb   a6, a2
179         dsync
181         /* Skip setting up a temporary DTLB for source if not aliased. */
183 1:      beqz    a5, 1f
185         /* Setup a temporary DTLB for source. */
187         addi    a7, a5, PAGE_KERNEL
188         addi    a8, a3, 1                               # way1
190         wdtlb   a7, a8
191         dsync
193 1:      __loopi a2, a4, PAGE_SIZE, 32
195         l32i    a8, a3, 0
196         l32i    a9, a3, 4
197         s32i    a8, a2, 0
198         s32i    a9, a2, 4
200         l32i    a8, a3, 8
201         l32i    a9, a3, 12
202         s32i    a8, a2, 8
203         s32i    a9, a2, 12
205         l32i    a8, a3, 16
206         l32i    a9, a3, 20
207         s32i    a8, a2, 16
208         s32i    a9, a2, 20
210         l32i    a8, a3, 24
211         l32i    a9, a3, 28
212         s32i    a8, a2, 24
213         s32i    a9, a2, 28
215         addi    a2, a2, 32
216         addi    a3, a3, 32
218         __endl  a2, a4
220         /* We need to invalidate any temporary mapping! */
222         bnez    a6, 1f
223         bnez    a7, 2f
224         retw
226 1:      addi    a2, a2, -PAGE_SIZE
227         idtlb   a2
228         dsync
229         bnez    a7, 2f
230         retw
232 2:      addi    a3, a3, -PAGE_SIZE+1
233         idtlb   a3
234         dsync
236         retw
238 ENDPROC(copy_page_alias)
240 #endif
242 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
245  * void __flush_invalidate_dcache_page_alias (addr, phys)
246  *                                             a2    a3
247  */
249 ENTRY(__flush_invalidate_dcache_page_alias)
251         entry   sp, 16
253         movi    a7, 0                   # required for exception handler
254         addi    a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
255         mov     a4, a2
256         wdtlb   a6, a2
257         dsync
259         ___flush_invalidate_dcache_page a2 a3
261         idtlb   a4
262         dsync
264         retw
266 ENDPROC(__flush_invalidate_dcache_page_alias)
269  * void __invalidate_dcache_page_alias (addr, phys)
270  *                                       a2    a3
271  */
273 ENTRY(__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         ___invalidate_dcache_page a2 a3
285         idtlb   a4
286         dsync
288         retw
290 ENDPROC(__invalidate_dcache_page_alias)
291 #endif
293 ENTRY(__tlbtemp_mapping_itlb)
295 #if (ICACHE_WAY_SIZE > PAGE_SIZE)
296         
297 ENTRY(__invalidate_icache_page_alias)
299         entry   sp, 16
301         addi    a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
302         mov     a4, a2
303         witlb   a6, a2
304         isync
306         ___invalidate_icache_page a2 a3
308         iitlb   a4
309         isync
310         retw
312 ENDPROC(__invalidate_icache_page_alias)
314 #endif
316 /* End of special treatment in tlb miss exception */
318 ENTRY(__tlbtemp_mapping_end)
320 #endif /* CONFIG_MMU
323  * void __invalidate_icache_page(ulong start)
324  */
326 ENTRY(__invalidate_icache_page)
328         entry   sp, 16
330         ___invalidate_icache_page a2 a3
331         isync
333         retw
335 ENDPROC(__invalidate_icache_page)
338  * void __invalidate_dcache_page(ulong start)
339  */
341 ENTRY(__invalidate_dcache_page)
343         entry   sp, 16
345         ___invalidate_dcache_page a2 a3
346         dsync
348         retw
350 ENDPROC(__invalidate_dcache_page)
353  * void __flush_invalidate_dcache_page(ulong start)
354  */
356 ENTRY(__flush_invalidate_dcache_page)
358         entry   sp, 16
360         ___flush_invalidate_dcache_page a2 a3
362         dsync
363         retw
365 ENDPROC(__flush_invalidate_dcache_page)
368  * void __flush_dcache_page(ulong start)
369  */
371 ENTRY(__flush_dcache_page)
373         entry   sp, 16
375         ___flush_dcache_page a2 a3
377         dsync
378         retw
380 ENDPROC(__flush_dcache_page)
383  * void __invalidate_icache_range(ulong start, ulong size)
384  */
386 ENTRY(__invalidate_icache_range)
388         entry   sp, 16
390         ___invalidate_icache_range a2 a3 a4
391         isync
393         retw
395 ENDPROC(__invalidate_icache_range)
398  * void __flush_invalidate_dcache_range(ulong start, ulong size)
399  */
401 ENTRY(__flush_invalidate_dcache_range)
403         entry   sp, 16
405         ___flush_invalidate_dcache_range a2 a3 a4
406         dsync
408         retw
410 ENDPROC(__flush_invalidate_dcache_range)
413  * void _flush_dcache_range(ulong start, ulong size)
414  */
416 ENTRY(__flush_dcache_range)
418         entry   sp, 16
420         ___flush_dcache_range a2 a3 a4
421         dsync
423         retw
425 ENDPROC(__flush_dcache_range)
428  * void _invalidate_dcache_range(ulong start, ulong size)
429  */
431 ENTRY(__invalidate_dcache_range)
433         entry   sp, 16
435         ___invalidate_dcache_range a2 a3 a4
437         retw
439 ENDPROC(__invalidate_dcache_range)
442  * void _invalidate_icache_all(void)
443  */
445 ENTRY(__invalidate_icache_all)
447         entry   sp, 16
449         ___invalidate_icache_all a2 a3
450         isync
452         retw
454 ENDPROC(__invalidate_icache_all)
457  * void _flush_invalidate_dcache_all(void)
458  */
460 ENTRY(__flush_invalidate_dcache_all)
462         entry   sp, 16
464         ___flush_invalidate_dcache_all a2 a3
465         dsync
467         retw
469 ENDPROC(__flush_invalidate_dcache_all)
472  * void _invalidate_dcache_all(void)
473  */
475 ENTRY(__invalidate_dcache_all)
477         entry   sp, 16
479         ___invalidate_dcache_all a2 a3
480         dsync
482         retw
484 ENDPROC(__invalidate_dcache_all)