Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / arch / xtensa / mm / misc.S
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  */
14
15
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>
22
23
24 /*
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  */
30
31 ENTRY(clear_page)
32
33         abi_entry_default
34
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
46
47         abi_ret_default
48
49 ENDPROC(clear_page)
50
51 /*
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  */
57
58 ENTRY(copy_page)
59
60         abi_entry_default
61
62         __loopi a2, a4, PAGE_SIZE, 32
63
64         l32i    a8, a3, 0
65         l32i    a9, a3, 4
66         s32i    a8, a2, 0
67         s32i    a9, a2, 4
68
69         l32i    a8, a3, 8
70         l32i    a9, a3, 12
71         s32i    a8, a2, 8
72         s32i    a9, a2, 12
73
74         l32i    a8, a3, 16
75         l32i    a9, a3, 20
76         s32i    a8, a2, 16
77         s32i    a9, a2, 20
78
79         l32i    a8, a3, 24
80         l32i    a9, a3, 28
81         s32i    a8, a2, 24
82         s32i    a9, a2, 28
83
84         addi    a2, a2, 32
85         addi    a3, a3, 32
86
87         __endl  a2, a4
88
89         abi_ret_default
90
91 ENDPROC(copy_page)
92
93 #ifdef CONFIG_MMU
94 /*
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  */
105
106 /* TLB miss exceptions are treated special in the following region */
107
108 ENTRY(__tlbtemp_mapping_start)
109
110 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
111
112 /*
113  * clear_page_alias(void *addr, unsigned long paddr)
114  *                     a2              a3
115  */
116
117 ENTRY(clear_page_alias)
118
119         abi_entry_default
120
121         /* Skip setting up a temporary DTLB if not aliased low page. */
122
123         movi    a5, PAGE_OFFSET
124         movi    a6, 0
125         beqz    a3, 1f
126
127         /* Setup a temporary DTLB for the addr. */
128
129         addi    a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
130         mov     a4, a2
131         wdtlb   a6, a2
132         dsync
133
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
145
146         bnez    a6, 1f
147         abi_ret_default
148
149         /* We need to invalidate the temporary idtlb entry, if any. */
150
151 1:      idtlb   a4
152         dsync
153
154         abi_ret_default
155
156 ENDPROC(clear_page_alias)
157
158 /*
159  * copy_page_alias(void *to, void *from,
160  *                      a2        a3
161  *                 unsigned long to_paddr, unsigned long from_paddr)
162  *                               a4                      a5
163  */
164
165 ENTRY(copy_page_alias)
166
167         abi_entry_default
168
169         /* Skip setting up a temporary DTLB for destination if not aliased. */
170
171         movi    a6, 0
172         movi    a7, 0
173         beqz    a4, 1f
174
175         /* Setup a temporary DTLB for destination. */
176
177         addi    a6, a4, (PAGE_KERNEL | _PAGE_HW_WRITE)
178         wdtlb   a6, a2
179         dsync
180
181         /* Skip setting up a temporary DTLB for source if not aliased. */
182
183 1:      beqz    a5, 1f
184
185         /* Setup a temporary DTLB for source. */
186
187         addi    a7, a5, PAGE_KERNEL
188         addi    a8, a3, 1                               # way1
189
190         wdtlb   a7, a8
191         dsync
192
193 1:      __loopi a2, a4, PAGE_SIZE, 32
194
195         l32i    a8, a3, 0
196         l32i    a9, a3, 4
197         s32i    a8, a2, 0
198         s32i    a9, a2, 4
199
200         l32i    a8, a3, 8
201         l32i    a9, a3, 12
202         s32i    a8, a2, 8
203         s32i    a9, a2, 12
204
205         l32i    a8, a3, 16
206         l32i    a9, a3, 20
207         s32i    a8, a2, 16
208         s32i    a9, a2, 20
209
210         l32i    a8, a3, 24
211         l32i    a9, a3, 28
212         s32i    a8, a2, 24
213         s32i    a9, a2, 28
214
215         addi    a2, a2, 32
216         addi    a3, a3, 32
217
218         __endl  a2, a4
219
220         /* We need to invalidate any temporary mapping! */
221
222         bnez    a6, 1f
223         bnez    a7, 2f
224         abi_ret_default
225
226 1:      addi    a2, a2, -PAGE_SIZE
227         idtlb   a2
228         dsync
229         bnez    a7, 2f
230         abi_ret_default
231
232 2:      addi    a3, a3, -PAGE_SIZE+1
233         idtlb   a3
234         dsync
235
236         abi_ret_default
237
238 ENDPROC(copy_page_alias)
239
240 #endif
241
242 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
243
244 /*
245  * void __flush_invalidate_dcache_page_alias (addr, phys)
246  *                                             a2    a3
247  */
248
249 ENTRY(__flush_invalidate_dcache_page_alias)
250
251         abi_entry_default
252
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
258
259         ___flush_invalidate_dcache_page a2 a3
260
261         idtlb   a4
262         dsync
263
264         abi_ret_default
265
266 ENDPROC(__flush_invalidate_dcache_page_alias)
267
268 /*
269  * void __invalidate_dcache_page_alias (addr, phys)
270  *                                       a2    a3
271  */
272
273 ENTRY(__invalidate_dcache_page_alias)
274
275         abi_entry_default
276
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
282
283         ___invalidate_dcache_page a2 a3
284
285         idtlb   a4
286         dsync
287
288         abi_ret_default
289
290 ENDPROC(__invalidate_dcache_page_alias)
291 #endif
292
293 ENTRY(__tlbtemp_mapping_itlb)
294
295 #if (ICACHE_WAY_SIZE > PAGE_SIZE)
296         
297 ENTRY(__invalidate_icache_page_alias)
298
299         abi_entry_default
300
301         addi    a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
302         mov     a4, a2
303         witlb   a6, a2
304         isync
305
306         ___invalidate_icache_page a2 a3
307
308         iitlb   a4
309         isync
310         abi_ret_default
311
312 ENDPROC(__invalidate_icache_page_alias)
313
314 #endif
315
316 /* End of special treatment in tlb miss exception */
317
318 ENTRY(__tlbtemp_mapping_end)
319
320 #endif /* CONFIG_MMU
321
322 /*
323  * void __invalidate_icache_page(ulong start)
324  */
325
326 ENTRY(__invalidate_icache_page)
327
328         abi_entry_default
329
330         ___invalidate_icache_page a2 a3
331         isync
332
333         abi_ret_default
334
335 ENDPROC(__invalidate_icache_page)
336
337 /*
338  * void __invalidate_dcache_page(ulong start)
339  */
340
341 ENTRY(__invalidate_dcache_page)
342
343         abi_entry_default
344
345         ___invalidate_dcache_page a2 a3
346         dsync
347
348         abi_ret_default
349
350 ENDPROC(__invalidate_dcache_page)
351
352 /*
353  * void __flush_invalidate_dcache_page(ulong start)
354  */
355
356 ENTRY(__flush_invalidate_dcache_page)
357
358         abi_entry_default
359
360         ___flush_invalidate_dcache_page a2 a3
361
362         dsync
363         abi_ret_default
364
365 ENDPROC(__flush_invalidate_dcache_page)
366
367 /*
368  * void __flush_dcache_page(ulong start)
369  */
370
371 ENTRY(__flush_dcache_page)
372
373         abi_entry_default
374
375         ___flush_dcache_page a2 a3
376
377         dsync
378         abi_ret_default
379
380 ENDPROC(__flush_dcache_page)
381
382 /*
383  * void __invalidate_icache_range(ulong start, ulong size)
384  */
385
386 ENTRY(__invalidate_icache_range)
387
388         abi_entry_default
389
390         ___invalidate_icache_range a2 a3 a4
391         isync
392
393         abi_ret_default
394
395 ENDPROC(__invalidate_icache_range)
396
397 /*
398  * void __flush_invalidate_dcache_range(ulong start, ulong size)
399  */
400
401 ENTRY(__flush_invalidate_dcache_range)
402
403         abi_entry_default
404
405         ___flush_invalidate_dcache_range a2 a3 a4
406         dsync
407
408         abi_ret_default
409
410 ENDPROC(__flush_invalidate_dcache_range)
411
412 /*
413  * void _flush_dcache_range(ulong start, ulong size)
414  */
415
416 ENTRY(__flush_dcache_range)
417
418         abi_entry_default
419
420         ___flush_dcache_range a2 a3 a4
421         dsync
422
423         abi_ret_default
424
425 ENDPROC(__flush_dcache_range)
426
427 /*
428  * void _invalidate_dcache_range(ulong start, ulong size)
429  */
430
431 ENTRY(__invalidate_dcache_range)
432
433         abi_entry_default
434
435         ___invalidate_dcache_range a2 a3 a4
436
437         abi_ret_default
438
439 ENDPROC(__invalidate_dcache_range)
440
441 /*
442  * void _invalidate_icache_all(void)
443  */
444
445 ENTRY(__invalidate_icache_all)
446
447         abi_entry_default
448
449         ___invalidate_icache_all a2 a3
450         isync
451
452         abi_ret_default
453
454 ENDPROC(__invalidate_icache_all)
455
456 /*
457  * void _flush_invalidate_dcache_all(void)
458  */
459
460 ENTRY(__flush_invalidate_dcache_all)
461
462         abi_entry_default
463
464         ___flush_invalidate_dcache_all a2 a3
465         dsync
466
467         abi_ret_default
468
469 ENDPROC(__flush_invalidate_dcache_all)
470
471 /*
472  * void _invalidate_dcache_all(void)
473  */
474
475 ENTRY(__invalidate_dcache_all)
476
477         abi_entry_default
478
479         ___invalidate_dcache_all a2 a3
480         dsync
481
482         abi_ret_default
483
484 ENDPROC(__invalidate_dcache_all)