blob: d97ed1ba7b0addd36d81782469ead96889535fc0 [file] [log] [blame]
Chris Zankel3f65ce42005-06-23 22:01:24 -07001/*
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 *
Chris Zankel66569202007-08-22 10:14:51 -070010 * Copyright (C) 2001 - 2007 Tensilica Inc.
Chris Zankel3f65ce42005-06-23 22:01:24 -070011 *
12 * Chris Zankel <chris@zankel.net>
13 */
14
Chris Zankel3f65ce42005-06-23 22:01:24 -070015
16#include <linux/linkage.h>
17#include <asm/page.h>
18#include <asm/pgtable.h>
Chris Zankel173d66812006-12-10 02:18:48 -080019#include <asm/asmmacro.h>
20#include <asm/cacheasm.h>
Chris Zankel66569202007-08-22 10:14:51 -070021#include <asm/tlbflush.h>
Chris Zankel3f65ce42005-06-23 22:01:24 -070022
Chris Zankel66569202007-08-22 10:14:51 -070023
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 */
Chris Zankel3f65ce42005-06-23 22:01:24 -070030
31ENTRY(clear_page)
Chris Zankeld1538c42012-11-16 16:16:20 -080032
Chris Zankel3f65ce42005-06-23 22:01:24 -070033 entry a1, 16
Chris Zankel3f65ce42005-06-23 22:01:24 -070034
Chris Zankel66569202007-08-22 10:14:51 -070035 movi a3, 0
36 __loopi a2, a7, PAGE_SIZE, 32
37 s32i a3, a2, 0
Chris Zankel3f65ce42005-06-23 22:01:24 -070038 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
Chris Zankel66569202007-08-22 10:14:51 -070045 __endla a2, a7, 32
Chris Zankel3f65ce42005-06-23 22:01:24 -070046
47 retw
48
Chris Zankeld1538c42012-11-16 16:16:20 -080049ENDPROC(clear_page)
50
Chris Zankel3f65ce42005-06-23 22:01:24 -070051/*
Chris Zankel66569202007-08-22 10:14:51 -070052 * copy_page and copy_user_page are the same for non-cache-aliased configs.
53 *
Chris Zankel3f65ce42005-06-23 22:01:24 -070054 * copy_page (void *to, void *from)
Chris Zankel66569202007-08-22 10:14:51 -070055 * a2 a3
Chris Zankel3f65ce42005-06-23 22:01:24 -070056 */
57
58ENTRY(copy_page)
Chris Zankeld1538c42012-11-16 16:16:20 -080059
Chris Zankel3f65ce42005-06-23 22:01:24 -070060 entry a1, 16
Chris Zankel3f65ce42005-06-23 22:01:24 -070061
Chris Zankel66569202007-08-22 10:14:51 -070062 __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
Chris Zankel3f65ce42005-06-23 22:01:24 -070088
89 retw
90
Chris Zankeld1538c42012-11-16 16:16:20 -080091ENDPROC(copy_page)
92
Johannes Weinere5083a62009-03-04 16:21:31 +010093#ifdef CONFIG_MMU
Chris Zankel3f65ce42005-06-23 22:01:24 -070094/*
Chris Zankel66569202007-08-22 10:14:51 -070095 * 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
108ENTRY(__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
117ENTRY(clear_user_page)
Chris Zankeld1538c42012-11-16 16:16:20 -0800118
Chris Zankel66569202007-08-22 10:14:51 -0700119 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_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
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
1511: 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
1681: addi a2, a2, -PAGE_SIZE
169 idtlb a2
170 dsync
171
172 retw
173
Chris Zankeld1538c42012-11-16 16:16:20 -0800174ENDPROC(clear_user_page)
175
Chris Zankel66569202007-08-22 10:14:51 -0700176/*
177 * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
178 * a2 a3 a4 a5
179 */
180
181ENTRY(copy_user_page)
182
Chris Zankelc4c45942012-11-28 16:53:51 -0800183 entry a1, 32
Chris Zankel66569202007-08-22 10:14:51 -0700184
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_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
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
2171: 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
2291: __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
2621: addi a2, a2, -PAGE_SIZE
263 idtlb a2
264 dsync
265 bnez a7, 2f
266 retw
267
2682: addi a3, a3, -PAGE_SIZE+1
269 idtlb a3
270 dsync
271
272 retw
273
Chris Zankeld1538c42012-11-16 16:16:20 -0800274ENDPROC(copy_user_page)
275
Chris Zankel66569202007-08-22 10:14:51 -0700276#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
285ENTRY(__flush_invalidate_dcache_page_alias)
Chris Zankeld1538c42012-11-16 16:16:20 -0800286
Chris Zankel66569202007-08-22 10:14:51 -0700287 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
Chris Zankeld1538c42012-11-16 16:16:20 -0800302ENDPROC(__flush_invalidate_dcache_page_alias)
Chris Zankel66569202007-08-22 10:14:51 -0700303#endif
304
305ENTRY(__tlbtemp_mapping_itlb)
306
307#if (ICACHE_WAY_SIZE > PAGE_SIZE)
308
309ENTRY(__invalidate_icache_page_alias)
Chris Zankeld1538c42012-11-16 16:16:20 -0800310
Chris Zankel66569202007-08-22 10:14:51 -0700311 entry sp, 16
312
Chris Zankel0b2c3af2008-02-12 10:11:45 -0800313 addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
Chris Zankel66569202007-08-22 10:14:51 -0700314 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
Chris Zankeld1538c42012-11-16 16:16:20 -0800324ENDPROC(__invalidate_icache_page_alias)
325
Chris Zankel66569202007-08-22 10:14:51 -0700326#endif
327
328/* End of special treatment in tlb miss exception */
329
330ENTRY(__tlbtemp_mapping_end)
Chris Zankeld1538c42012-11-16 16:16:20 -0800331
Johannes Weinere5083a62009-03-04 16:21:31 +0100332#endif /* CONFIG_MMU
Chris Zankel66569202007-08-22 10:14:51 -0700333
334/*
Chris Zankel3f65ce42005-06-23 22:01:24 -0700335 * void __invalidate_icache_page(ulong start)
336 */
337
338ENTRY(__invalidate_icache_page)
Chris Zankeld1538c42012-11-16 16:16:20 -0800339
Chris Zankel3f65ce42005-06-23 22:01:24 -0700340 entry sp, 16
Chris Zankel173d66812006-12-10 02:18:48 -0800341
342 ___invalidate_icache_page a2 a3
343 isync
344
Chris Zankel3f65ce42005-06-23 22:01:24 -0700345 retw
346
Chris Zankeld1538c42012-11-16 16:16:20 -0800347ENDPROC(__invalidate_icache_page)
348
Chris Zankel3f65ce42005-06-23 22:01:24 -0700349/*
350 * void __invalidate_dcache_page(ulong start)
351 */
352
353ENTRY(__invalidate_dcache_page)
Chris Zankeld1538c42012-11-16 16:16:20 -0800354
Chris Zankel3f65ce42005-06-23 22:01:24 -0700355 entry sp, 16
Chris Zankel3f65ce42005-06-23 22:01:24 -0700356
Chris Zankel173d66812006-12-10 02:18:48 -0800357 ___invalidate_dcache_page a2 a3
358 dsync
Chris Zankel3f65ce42005-06-23 22:01:24 -0700359
Chris Zankel3f65ce42005-06-23 22:01:24 -0700360 retw
361
Chris Zankeld1538c42012-11-16 16:16:20 -0800362ENDPROC(__invalidate_dcache_page)
363
Chris Zankel3f65ce42005-06-23 22:01:24 -0700364/*
365 * void __flush_invalidate_dcache_page(ulong start)
366 */
367
368ENTRY(__flush_invalidate_dcache_page)
Chris Zankeld1538c42012-11-16 16:16:20 -0800369
Chris Zankel3f65ce42005-06-23 22:01:24 -0700370 entry sp, 16
Chris Zankel173d66812006-12-10 02:18:48 -0800371
372 ___flush_invalidate_dcache_page a2 a3
373
374 dsync
375 retw
376
Chris Zankeld1538c42012-11-16 16:16:20 -0800377ENDPROC(__flush_invalidate_dcache_page)
378
Chris Zankel173d66812006-12-10 02:18:48 -0800379/*
380 * void __flush_dcache_page(ulong start)
381 */
382
383ENTRY(__flush_dcache_page)
Chris Zankeld1538c42012-11-16 16:16:20 -0800384
Chris Zankel173d66812006-12-10 02:18:48 -0800385 entry sp, 16
386
387 ___flush_dcache_page a2 a3
388
389 dsync
390 retw
391
Chris Zankeld1538c42012-11-16 16:16:20 -0800392ENDPROC(__flush_dcache_page)
393
Chris Zankel173d66812006-12-10 02:18:48 -0800394/*
395 * void __invalidate_icache_range(ulong start, ulong size)
396 */
397
398ENTRY(__invalidate_icache_range)
Chris Zankeld1538c42012-11-16 16:16:20 -0800399
Chris Zankel173d66812006-12-10 02:18:48 -0800400 entry sp, 16
401
402 ___invalidate_icache_range a2 a3 a4
403 isync
404
Chris Zankel3f65ce42005-06-23 22:01:24 -0700405 retw
406
Chris Zankeld1538c42012-11-16 16:16:20 -0800407ENDPROC(__invalidate_icache_range)
408
Chris Zankel3f65ce42005-06-23 22:01:24 -0700409/*
410 * void __flush_invalidate_dcache_range(ulong start, ulong size)
411 */
412
413ENTRY(__flush_invalidate_dcache_range)
Chris Zankeld1538c42012-11-16 16:16:20 -0800414
Chris Zankel3f65ce42005-06-23 22:01:24 -0700415 entry sp, 16
Chris Zankel173d66812006-12-10 02:18:48 -0800416
417 ___flush_invalidate_dcache_range a2 a3 a4
418 dsync
419
Chris Zankel3f65ce42005-06-23 22:01:24 -0700420 retw
421
Chris Zankeld1538c42012-11-16 16:16:20 -0800422ENDPROC(__flush_invalidate_dcache_range)
423
Chris Zankel3f65ce42005-06-23 22:01:24 -0700424/*
Chris Zankel173d66812006-12-10 02:18:48 -0800425 * void _flush_dcache_range(ulong start, ulong size)
426 */
427
428ENTRY(__flush_dcache_range)
Chris Zankeld1538c42012-11-16 16:16:20 -0800429
Chris Zankel173d66812006-12-10 02:18:48 -0800430 entry sp, 16
431
432 ___flush_dcache_range a2 a3 a4
433 dsync
434
435 retw
436
Chris Zankeld1538c42012-11-16 16:16:20 -0800437ENDPROC(__flush_dcache_range)
438
Chris Zankel173d66812006-12-10 02:18:48 -0800439/*
440 * void _invalidate_dcache_range(ulong start, ulong size)
441 */
442
443ENTRY(__invalidate_dcache_range)
Chris Zankeld1538c42012-11-16 16:16:20 -0800444
Chris Zankel173d66812006-12-10 02:18:48 -0800445 entry sp, 16
446
447 ___invalidate_dcache_range a2 a3 a4
448
Chris Zankel173d66812006-12-10 02:18:48 -0800449 retw
450
Chris Zankeld1538c42012-11-16 16:16:20 -0800451ENDPROC(__invalidate_dcache_range)
452
Chris Zankel173d66812006-12-10 02:18:48 -0800453/*
454 * void _invalidate_icache_all(void)
455 */
456
457ENTRY(__invalidate_icache_all)
Chris Zankeld1538c42012-11-16 16:16:20 -0800458
Chris Zankel173d66812006-12-10 02:18:48 -0800459 entry sp, 16
460
461 ___invalidate_icache_all a2 a3
462 isync
463
464 retw
465
Chris Zankeld1538c42012-11-16 16:16:20 -0800466ENDPROC(__invalidate_icache_all)
467
Chris Zankel173d66812006-12-10 02:18:48 -0800468/*
469 * void _flush_invalidate_dcache_all(void)
470 */
471
472ENTRY(__flush_invalidate_dcache_all)
Chris Zankeld1538c42012-11-16 16:16:20 -0800473
Chris Zankel173d66812006-12-10 02:18:48 -0800474 entry sp, 16
475
476 ___flush_invalidate_dcache_all a2 a3
477 dsync
478
479 retw
480
Chris Zankeld1538c42012-11-16 16:16:20 -0800481ENDPROC(__flush_invalidate_dcache_all)
482
Chris Zankel173d66812006-12-10 02:18:48 -0800483/*
484 * void _invalidate_dcache_all(void)
Chris Zankel3f65ce42005-06-23 22:01:24 -0700485 */
486
487ENTRY(__invalidate_dcache_all)
Chris Zankeld1538c42012-11-16 16:16:20 -0800488
Chris Zankel3f65ce42005-06-23 22:01:24 -0700489 entry sp, 16
Chris Zankel3f65ce42005-06-23 22:01:24 -0700490
Chris Zankel173d66812006-12-10 02:18:48 -0800491 ___invalidate_dcache_all a2 a3
Chris Zankel3f65ce42005-06-23 22:01:24 -0700492 dsync
Chris Zankel3f65ce42005-06-23 22:01:24 -0700493
494 retw
495
Chris Zankeld1538c42012-11-16 16:16:20 -0800496ENDPROC(__invalidate_dcache_all)