ARM: LPC32xx: Fix reset function
[cascardo/linux.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         entry   a1, 16
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         retw
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         entry   a1, 16
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         retw
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_user_page (void *addr, unsigned long vaddr, struct page *page)
114  *                     a2              a3                 a4
115  */
116
117 ENTRY(clear_user_page)
118
119         entry   a1, 32
120
121         /* Mark page dirty and determine alias. */
122
123         movi    a7, (1 << PG_ARCH_1)
124         l32i    a5, a4, PAGE_FLAGS
125         xor     a6, a2, a3
126         extui   a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
127         extui   a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
128         or      a5, a5, a7
129         slli    a3, a3, PAGE_SHIFT
130         s32i    a5, a4, PAGE_FLAGS
131
132         /* Skip setting up a temporary DTLB if not aliased. */
133
134         beqz    a6, 1f
135
136         /* Invalidate kernel page. */
137
138         mov     a10, a2
139         call8   __invalidate_dcache_page
140
141         /* Setup a temporary DTLB with the color of the VPN */
142
143         movi    a4, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff
144         movi    a5, TLBTEMP_BASE_1                      # virt
145         add     a6, a2, a4                              # ppn
146         add     a2, a5, a3                              # add 'color'
147
148         wdtlb   a6, a2
149         dsync
150
151 1:      movi    a3, 0
152         __loopi a2, a7, PAGE_SIZE, 32
153         s32i    a3, a2, 0
154         s32i    a3, a2, 4
155         s32i    a3, a2, 8
156         s32i    a3, a2, 12
157         s32i    a3, a2, 16
158         s32i    a3, a2, 20
159         s32i    a3, a2, 24
160         s32i    a3, a2, 28
161         __endla a2, a7, 32
162
163         bnez    a6, 1f
164         retw
165
166         /* We need to invalidate the temporary idtlb entry, if any. */
167
168 1:      addi    a2, a2, -PAGE_SIZE
169         idtlb   a2
170         dsync
171
172         retw
173
174 ENDPROC(clear_user_page)
175
176 /*
177  * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
178  *                    a2          a3            a4                  a5
179  */
180
181 ENTRY(copy_user_page)
182
183         entry   a1, 32
184
185         /* Mark page dirty and determine alias for destination. */
186
187         movi    a8, (1 << PG_ARCH_1)
188         l32i    a9, a5, PAGE_FLAGS
189         xor     a6, a2, a4
190         xor     a7, a3, a4
191         extui   a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER
192         extui   a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
193         extui   a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER
194         or      a9, a9, a8
195         slli    a4, a4, PAGE_SHIFT
196         s32i    a9, a5, PAGE_FLAGS
197         movi    a5, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff
198
199         beqz    a6, 1f
200
201         /* Invalidate dcache */
202
203         mov     a10, a2
204         call8   __invalidate_dcache_page
205
206         /* Setup a temporary DTLB with a matching color. */
207
208         movi    a8, TLBTEMP_BASE_1                      # base
209         add     a6, a2, a5                              # ppn
210         add     a2, a8, a4                              # add 'color'
211
212         wdtlb   a6, a2
213         dsync
214
215         /* Skip setting up a temporary DTLB for destination if not aliased. */
216
217 1:      beqz    a7, 1f
218
219         /* Setup a temporary DTLB with a matching color. */
220
221         movi    a8, TLBTEMP_BASE_2                      # base
222         add     a7, a3, a5                              # ppn
223         add     a3, a8, a4
224         addi    a8, a3, 1                               # way1
225
226         wdtlb   a7, a8
227         dsync
228
229 1:      __loopi a2, a4, PAGE_SIZE, 32
230
231         l32i    a8, a3, 0
232         l32i    a9, a3, 4
233         s32i    a8, a2, 0
234         s32i    a9, a2, 4
235
236         l32i    a8, a3, 8
237         l32i    a9, a3, 12
238         s32i    a8, a2, 8
239         s32i    a9, a2, 12
240
241         l32i    a8, a3, 16
242         l32i    a9, a3, 20
243         s32i    a8, a2, 16
244         s32i    a9, a2, 20
245
246         l32i    a8, a3, 24
247         l32i    a9, a3, 28
248         s32i    a8, a2, 24
249         s32i    a9, a2, 28
250
251         addi    a2, a2, 32
252         addi    a3, a3, 32
253
254         __endl  a2, a4
255
256         /* We need to invalidate any temporary mapping! */
257
258         bnez    a6, 1f
259         bnez    a7, 2f
260         retw
261
262 1:      addi    a2, a2, -PAGE_SIZE
263         idtlb   a2
264         dsync
265         bnez    a7, 2f
266         retw
267
268 2:      addi    a3, a3, -PAGE_SIZE+1
269         idtlb   a3
270         dsync
271
272         retw
273
274 ENDPROC(copy_user_page)
275
276 #endif
277
278 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
279
280 /*
281  * void __flush_invalidate_dcache_page_alias (addr, phys)
282  *                                             a2    a3
283  */
284
285 ENTRY(__flush_invalidate_dcache_page_alias)
286
287         entry   sp, 16
288
289         movi    a7, 0                   # required for exception handler
290         addi    a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
291         mov     a4, a2
292         wdtlb   a6, a2
293         dsync
294
295         ___flush_invalidate_dcache_page a2 a3
296
297         idtlb   a4
298         dsync
299
300         retw
301
302 ENDPROC(__flush_invalidate_dcache_page_alias)
303 #endif
304
305 ENTRY(__tlbtemp_mapping_itlb)
306
307 #if (ICACHE_WAY_SIZE > PAGE_SIZE)
308         
309 ENTRY(__invalidate_icache_page_alias)
310
311         entry   sp, 16
312
313         addi    a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
314         mov     a4, a2
315         witlb   a6, a2
316         isync
317
318         ___invalidate_icache_page a2 a3
319
320         iitlb   a4
321         isync
322         retw
323
324 ENDPROC(__invalidate_icache_page_alias)
325
326 #endif
327
328 /* End of special treatment in tlb miss exception */
329
330 ENTRY(__tlbtemp_mapping_end)
331
332 #endif /* CONFIG_MMU
333
334 /*
335  * void __invalidate_icache_page(ulong start)
336  */
337
338 ENTRY(__invalidate_icache_page)
339
340         entry   sp, 16
341
342         ___invalidate_icache_page a2 a3
343         isync
344
345         retw
346
347 ENDPROC(__invalidate_icache_page)
348
349 /*
350  * void __invalidate_dcache_page(ulong start)
351  */
352
353 ENTRY(__invalidate_dcache_page)
354
355         entry   sp, 16
356
357         ___invalidate_dcache_page a2 a3
358         dsync
359
360         retw
361
362 ENDPROC(__invalidate_dcache_page)
363
364 /*
365  * void __flush_invalidate_dcache_page(ulong start)
366  */
367
368 ENTRY(__flush_invalidate_dcache_page)
369
370         entry   sp, 16
371
372         ___flush_invalidate_dcache_page a2 a3
373
374         dsync
375         retw
376
377 ENDPROC(__flush_invalidate_dcache_page)
378
379 /*
380  * void __flush_dcache_page(ulong start)
381  */
382
383 ENTRY(__flush_dcache_page)
384
385         entry   sp, 16
386
387         ___flush_dcache_page a2 a3
388
389         dsync
390         retw
391
392 ENDPROC(__flush_dcache_page)
393
394 /*
395  * void __invalidate_icache_range(ulong start, ulong size)
396  */
397
398 ENTRY(__invalidate_icache_range)
399
400         entry   sp, 16
401
402         ___invalidate_icache_range a2 a3 a4
403         isync
404
405         retw
406
407 ENDPROC(__invalidate_icache_range)
408
409 /*
410  * void __flush_invalidate_dcache_range(ulong start, ulong size)
411  */
412
413 ENTRY(__flush_invalidate_dcache_range)
414
415         entry   sp, 16
416
417         ___flush_invalidate_dcache_range a2 a3 a4
418         dsync
419
420         retw
421
422 ENDPROC(__flush_invalidate_dcache_range)
423
424 /*
425  * void _flush_dcache_range(ulong start, ulong size)
426  */
427
428 ENTRY(__flush_dcache_range)
429
430         entry   sp, 16
431
432         ___flush_dcache_range a2 a3 a4
433         dsync
434
435         retw
436
437 ENDPROC(__flush_dcache_range)
438
439 /*
440  * void _invalidate_dcache_range(ulong start, ulong size)
441  */
442
443 ENTRY(__invalidate_dcache_range)
444
445         entry   sp, 16
446
447         ___invalidate_dcache_range a2 a3 a4
448
449         retw
450
451 ENDPROC(__invalidate_dcache_range)
452
453 /*
454  * void _invalidate_icache_all(void)
455  */
456
457 ENTRY(__invalidate_icache_all)
458
459         entry   sp, 16
460
461         ___invalidate_icache_all a2 a3
462         isync
463
464         retw
465
466 ENDPROC(__invalidate_icache_all)
467
468 /*
469  * void _flush_invalidate_dcache_all(void)
470  */
471
472 ENTRY(__flush_invalidate_dcache_all)
473
474         entry   sp, 16
475
476         ___flush_invalidate_dcache_all a2 a3
477         dsync
478
479         retw
480
481 ENDPROC(__flush_invalidate_dcache_all)
482
483 /*
484  * void _invalidate_dcache_all(void)
485  */
486
487 ENTRY(__invalidate_dcache_all)
488
489         entry   sp, 16
490
491         ___invalidate_dcache_all a2 a3
492         dsync
493
494         retw
495
496 ENDPROC(__invalidate_dcache_all)