Merge branch 'topic/asoc' into for-linus
[linux-block.git] / arch / xtensa / mm / misc.S
CommitLineData
3f65ce4d
CZ
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 *
6656920b 10 * Copyright (C) 2001 - 2007 Tensilica Inc.
3f65ce4d
CZ
11 *
12 * Chris Zankel <chris@zankel.net>
13 */
14
3f65ce4d
CZ
15
16#include <linux/linkage.h>
17#include <asm/page.h>
18#include <asm/pgtable.h>
173d6681
CZ
19#include <asm/asmmacro.h>
20#include <asm/cacheasm.h>
6656920b
CZ
21#include <asm/tlbflush.h>
22
3f65ce4d 23
6656920b
CZ
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 */
3f65ce4d
CZ
30
31ENTRY(clear_page)
32 entry a1, 16
3f65ce4d 33
6656920b
CZ
34 movi a3, 0
35 __loopi a2, a7, PAGE_SIZE, 32
36 s32i a3, a2, 0
3f65ce4d
CZ
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
6656920b 44 __endla a2, a7, 32
3f65ce4d
CZ
45
46 retw
47
48/*
6656920b
CZ
49 * copy_page and copy_user_page are the same for non-cache-aliased configs.
50 *
3f65ce4d 51 * copy_page (void *to, void *from)
6656920b 52 * a2 a3
3f65ce4d
CZ
53 */
54
55ENTRY(copy_page)
56 entry a1, 16
3f65ce4d 57
6656920b
CZ
58 __loopi a2, a4, PAGE_SIZE, 32
59
60 l32i a8, a3, 0
61 l32i a9, a3, 4
62 s32i a8, a2, 0
63 s32i a9, a2, 4
64
65 l32i a8, a3, 8
66 l32i a9, a3, 12
67 s32i a8, a2, 8
68 s32i a9, a2, 12
69
70 l32i a8, a3, 16
71 l32i a9, a3, 20
72 s32i a8, a2, 16
73 s32i a9, a2, 20
74
75 l32i a8, a3, 24
76 l32i a9, a3, 28
77 s32i a8, a2, 24
78 s32i a9, a2, 28
79
80 addi a2, a2, 32
81 addi a3, a3, 32
82
83 __endl a2, a4
84
85 retw
86
e5083a63 87#ifdef CONFIG_MMU
6656920b
CZ
88/*
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 */
99
100/* TLB miss exceptions are treated special in the following region */
101
102ENTRY(__tlbtemp_mapping_start)
103
104#if (DCACHE_WAY_SIZE > PAGE_SIZE)
105
106/*
107 * clear_user_page (void *addr, unsigned long vaddr, struct page *page)
108 * a2 a3 a4
109 */
110
111ENTRY(clear_user_page)
112 entry a1, 32
113
114 /* Mark page dirty and determine alias. */
115
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
124
125 /* Skip setting up a temporary DTLB if not aliased. */
126
127 beqz a6, 1f
128
129 /* Invalidate kernel page. */
130
131 mov a10, a2
132 call8 __invalidate_dcache_page
133
134 /* Setup a temporary DTLB with the color of the VPN */
135
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'
140
141 wdtlb a6, a2
142 dsync
143
1441: 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
155
156 bnez a6, 1f
157 retw
158
159 /* We need to invalidate the temporary idtlb entry, if any. */
160
1611: addi a2, a2, -PAGE_SIZE
162 idtlb a2
163 dsync
164
165 retw
166
167/*
168 * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
169 * a2 a3 a4 a5
170 */
171
172ENTRY(copy_user_page)
173
174 entry a1, 32
175
176 /* Mark page dirty and determine alias for destination. */
177
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)
189
190 beqz a6, 1f
191
192 /* Invalidate dcache */
193
194 mov a10, a2
195 call8 __invalidate_dcache_page
196
197 /* Setup a temporary DTLB with a matching color. */
198
199 movi a8, TLBTEMP_BASE_1 # base
200 add a6, a2, a5 # ppn
201 add a2, a8, a4 # add 'color'
202
203 wdtlb a6, a2
204 dsync
205
206 /* Skip setting up a temporary DTLB for destination if not aliased. */
207
2081: beqz a7, 1f
209
210 /* Setup a temporary DTLB with a matching color. */
211
212 movi a8, TLBTEMP_BASE_2 # base
213 add a7, a3, a5 # ppn
214 add a3, a8, a4
215 addi a8, a3, 1 # way1
216
217 wdtlb a7, a8
218 dsync
219
2201: __loopi a2, a4, PAGE_SIZE, 32
221
222 l32i a8, a3, 0
223 l32i a9, a3, 4
224 s32i a8, a2, 0
225 s32i a9, a2, 4
226
227 l32i a8, a3, 8
228 l32i a9, a3, 12
229 s32i a8, a2, 8
230 s32i a9, a2, 12
231
232 l32i a8, a3, 16
233 l32i a9, a3, 20
234 s32i a8, a2, 16
235 s32i a9, a2, 20
236
237 l32i a8, a3, 24
238 l32i a9, a3, 28
239 s32i a8, a2, 24
240 s32i a9, a2, 28
241
242 addi a2, a2, 32
243 addi a3, a3, 32
244
245 __endl a2, a4
246
247 /* We need to invalidate any temporary mapping! */
248
249 bnez a6, 1f
250 bnez a7, 2f
251 retw
252
2531: addi a2, a2, -PAGE_SIZE
254 idtlb a2
255 dsync
256 bnez a7, 2f
257 retw
258
2592: addi a3, a3, -PAGE_SIZE+1
260 idtlb a3
261 dsync
262
263 retw
264
265#endif
266
267#if (DCACHE_WAY_SIZE > PAGE_SIZE)
268
269/*
270 * void __flush_invalidate_dcache_page_alias (addr, phys)
271 * a2 a3
272 */
273
274ENTRY(__flush_invalidate_dcache_page_alias)
275 entry sp, 16
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 ___flush_invalidate_dcache_page a2 a3
284
285 idtlb a4
286 dsync
287
288 retw
289
290#endif
291
292ENTRY(__tlbtemp_mapping_itlb)
293
294#if (ICACHE_WAY_SIZE > PAGE_SIZE)
295
296ENTRY(__invalidate_icache_page_alias)
297 entry sp, 16
298
0b2c3afd 299 addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
6656920b
CZ
300 mov a4, a2
301 witlb a6, a2
302 isync
303
304 ___invalidate_icache_page a2 a3
305
306 iitlb a4
307 isync
3f65ce4d
CZ
308 retw
309
6656920b
CZ
310#endif
311
312/* End of special treatment in tlb miss exception */
313
314ENTRY(__tlbtemp_mapping_end)
e5083a63 315#endif /* CONFIG_MMU
6656920b 316
3f65ce4d 317/*
173d6681 318 * void __invalidate_icache_page(ulong start)
3f65ce4d
CZ
319 */
320
173d6681 321ENTRY(__invalidate_icache_page)
3f65ce4d 322 entry sp, 16
3f65ce4d 323
173d6681
CZ
324 ___invalidate_icache_page a2 a3
325 isync
3f65ce4d 326
3f65ce4d
CZ
327 retw
328
329/*
173d6681 330 * void __invalidate_dcache_page(ulong start)
3f65ce4d
CZ
331 */
332
173d6681 333ENTRY(__invalidate_dcache_page)
3f65ce4d 334 entry sp, 16
3f65ce4d 335
173d6681
CZ
336 ___invalidate_dcache_page a2 a3
337 dsync
3f65ce4d 338
3f65ce4d
CZ
339 retw
340
341/*
173d6681 342 * void __flush_invalidate_dcache_page(ulong start)
3f65ce4d
CZ
343 */
344
173d6681 345ENTRY(__flush_invalidate_dcache_page)
3f65ce4d 346 entry sp, 16
3f65ce4d 347
173d6681 348 ___flush_invalidate_dcache_page a2 a3
3f65ce4d 349
173d6681 350 dsync
3f65ce4d
CZ
351 retw
352
353/*
173d6681 354 * void __flush_dcache_page(ulong start)
3f65ce4d
CZ
355 */
356
173d6681 357ENTRY(__flush_dcache_page)
3f65ce4d 358 entry sp, 16
3f65ce4d 359
173d6681 360 ___flush_dcache_page a2 a3
3f65ce4d 361
173d6681 362 dsync
3f65ce4d
CZ
363 retw
364
3f65ce4d 365/*
173d6681 366 * void __invalidate_icache_range(ulong start, ulong size)
3f65ce4d
CZ
367 */
368
173d6681 369ENTRY(__invalidate_icache_range)
3f65ce4d 370 entry sp, 16
173d6681
CZ
371
372 ___invalidate_icache_range a2 a3 a4
373 isync
374
3f65ce4d
CZ
375 retw
376
377/*
378 * void __flush_invalidate_dcache_range(ulong start, ulong size)
379 */
380
381ENTRY(__flush_invalidate_dcache_range)
382 entry sp, 16
3f65ce4d 383
173d6681
CZ
384 ___flush_invalidate_dcache_range a2 a3 a4
385 dsync
3f65ce4d 386
3f65ce4d
CZ
387 retw
388
389/*
173d6681 390 * void _flush_dcache_range(ulong start, ulong size)
3f65ce4d
CZ
391 */
392
173d6681 393ENTRY(__flush_dcache_range)
3f65ce4d
CZ
394 entry sp, 16
395
173d6681 396 ___flush_dcache_range a2 a3 a4
3f65ce4d 397 dsync
3f65ce4d 398
3f65ce4d
CZ
399 retw
400
173d6681
CZ
401/*
402 * void _invalidate_dcache_range(ulong start, ulong size)
403 */
3f65ce4d 404
173d6681 405ENTRY(__invalidate_dcache_range)
3f65ce4d
CZ
406 entry sp, 16
407
173d6681 408 ___invalidate_dcache_range a2 a3 a4
3f65ce4d 409
3f65ce4d
CZ
410 retw
411
173d6681
CZ
412/*
413 * void _invalidate_icache_all(void)
414 */
3f65ce4d 415
173d6681 416ENTRY(__invalidate_icache_all)
3f65ce4d
CZ
417 entry sp, 16
418
173d6681
CZ
419 ___invalidate_icache_all a2 a3
420 isync
3f65ce4d 421
3f65ce4d
CZ
422 retw
423
3f65ce4d 424/*
173d6681 425 * void _flush_invalidate_dcache_all(void)
3f65ce4d
CZ
426 */
427
173d6681 428ENTRY(__flush_invalidate_dcache_all)
3f65ce4d
CZ
429 entry sp, 16
430
173d6681
CZ
431 ___flush_invalidate_dcache_all a2 a3
432 dsync
3f65ce4d 433
3f65ce4d
CZ
434 retw
435
173d6681
CZ
436/*
437 * void _invalidate_dcache_all(void)
438 */
3f65ce4d 439
173d6681 440ENTRY(__invalidate_dcache_all)
3f65ce4d
CZ
441 entry sp, 16
442
173d6681
CZ
443 ___invalidate_dcache_all a2 a3
444 dsync
3f65ce4d
CZ
445
446 retw
447