Commit | Line | Data |
---|---|---|
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 | |
31 | ENTRY(clear_page) | |
d1538c46 | 32 | |
3f65ce4d | 33 | entry a1, 16 |
3f65ce4d | 34 | |
6656920b CZ |
35 | movi a3, 0 |
36 | __loopi a2, a7, PAGE_SIZE, 32 | |
37 | s32i a3, a2, 0 | |
3f65ce4d CZ |
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 | |
6656920b | 45 | __endla a2, a7, 32 |
3f65ce4d CZ |
46 | |
47 | retw | |
48 | ||
d1538c46 CZ |
49 | ENDPROC(clear_page) |
50 | ||
3f65ce4d | 51 | /* |
6656920b CZ |
52 | * copy_page and copy_user_page are the same for non-cache-aliased configs. |
53 | * | |
3f65ce4d | 54 | * copy_page (void *to, void *from) |
6656920b | 55 | * a2 a3 |
3f65ce4d CZ |
56 | */ |
57 | ||
58 | ENTRY(copy_page) | |
d1538c46 | 59 | |
3f65ce4d | 60 | entry a1, 16 |
3f65ce4d | 61 | |
6656920b CZ |
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 | ||
d1538c46 CZ |
91 | ENDPROC(copy_page) |
92 | ||
e5083a63 | 93 | #ifdef CONFIG_MMU |
6656920b CZ |
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 | /* | |
a91902db MF |
113 | * clear_page_alias(void *addr, unsigned long paddr) |
114 | * a2 a3 | |
6656920b CZ |
115 | */ |
116 | ||
a91902db | 117 | ENTRY(clear_page_alias) |
d1538c46 | 118 | |
6656920b CZ |
119 | entry a1, 32 |
120 | ||
a91902db | 121 | /* Skip setting up a temporary DTLB if not aliased low page. */ |
6656920b | 122 | |
a91902db MF |
123 | movi a5, PAGE_OFFSET |
124 | movi a6, 0 | |
125 | beqz a3, 1f | |
6656920b | 126 | |
a91902db | 127 | /* Setup a temporary DTLB for the addr. */ |
6656920b | 128 | |
a91902db MF |
129 | addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE) |
130 | mov a4, a2 | |
6656920b CZ |
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 | retw | |
148 | ||
149 | /* We need to invalidate the temporary idtlb entry, if any. */ | |
150 | ||
a91902db | 151 | 1: idtlb a4 |
6656920b CZ |
152 | dsync |
153 | ||
154 | retw | |
155 | ||
a91902db | 156 | ENDPROC(clear_page_alias) |
d1538c46 | 157 | |
6656920b | 158 | /* |
a91902db MF |
159 | * copy_page_alias(void *to, void *from, |
160 | * a2 a3 | |
161 | * unsigned long to_paddr, unsigned long from_paddr) | |
162 | * a4 a5 | |
6656920b CZ |
163 | */ |
164 | ||
a91902db | 165 | ENTRY(copy_page_alias) |
6656920b | 166 | |
c4c4594b | 167 | entry a1, 32 |
6656920b | 168 | |
a91902db | 169 | /* Skip setting up a temporary DTLB for destination if not aliased. */ |
6656920b | 170 | |
a91902db MF |
171 | movi a6, 0 |
172 | movi a7, 0 | |
173 | beqz a4, 1f | |
6656920b | 174 | |
a91902db | 175 | /* Setup a temporary DTLB for destination. */ |
6656920b | 176 | |
a91902db | 177 | addi a6, a4, (PAGE_KERNEL | _PAGE_HW_WRITE) |
6656920b CZ |
178 | wdtlb a6, a2 |
179 | dsync | |
180 | ||
a91902db | 181 | /* Skip setting up a temporary DTLB for source if not aliased. */ |
6656920b | 182 | |
a91902db | 183 | 1: beqz a5, 1f |
6656920b | 184 | |
a91902db | 185 | /* Setup a temporary DTLB for source. */ |
6656920b | 186 | |
a91902db | 187 | addi a7, a5, PAGE_KERNEL |
6656920b CZ |
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 | retw | |
225 | ||
226 | 1: addi a2, a2, -PAGE_SIZE | |
227 | idtlb a2 | |
228 | dsync | |
229 | bnez a7, 2f | |
230 | retw | |
231 | ||
232 | 2: addi a3, a3, -PAGE_SIZE+1 | |
233 | idtlb a3 | |
234 | dsync | |
235 | ||
236 | retw | |
237 | ||
a91902db | 238 | ENDPROC(copy_page_alias) |
d1538c46 | 239 | |
6656920b CZ |
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) | |
d1538c46 | 250 | |
6656920b CZ |
251 | entry sp, 16 |
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 | retw | |
265 | ||
d1538c46 | 266 | ENDPROC(__flush_invalidate_dcache_page_alias) |
a91902db MF |
267 | |
268 | /* | |
269 | * void __invalidate_dcache_page_alias (addr, phys) | |
270 | * a2 a3 | |
271 | */ | |
272 | ||
273 | ENTRY(__invalidate_dcache_page_alias) | |
274 | ||
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 | ___invalidate_dcache_page a2 a3 | |
284 | ||
285 | idtlb a4 | |
286 | dsync | |
287 | ||
288 | retw | |
289 | ||
290 | ENDPROC(__invalidate_dcache_page_alias) | |
6656920b CZ |
291 | #endif |
292 | ||
293 | ENTRY(__tlbtemp_mapping_itlb) | |
294 | ||
295 | #if (ICACHE_WAY_SIZE > PAGE_SIZE) | |
296 | ||
297 | ENTRY(__invalidate_icache_page_alias) | |
d1538c46 | 298 | |
6656920b CZ |
299 | entry sp, 16 |
300 | ||
0b2c3afd | 301 | addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE) |
6656920b CZ |
302 | mov a4, a2 |
303 | witlb a6, a2 | |
304 | isync | |
305 | ||
306 | ___invalidate_icache_page a2 a3 | |
307 | ||
308 | iitlb a4 | |
309 | isync | |
3f65ce4d CZ |
310 | retw |
311 | ||
d1538c46 CZ |
312 | ENDPROC(__invalidate_icache_page_alias) |
313 | ||
6656920b CZ |
314 | #endif |
315 | ||
316 | /* End of special treatment in tlb miss exception */ | |
317 | ||
318 | ENTRY(__tlbtemp_mapping_end) | |
d1538c46 | 319 | |
e5083a63 | 320 | #endif /* CONFIG_MMU |
6656920b | 321 | |
3f65ce4d | 322 | /* |
173d6681 | 323 | * void __invalidate_icache_page(ulong start) |
3f65ce4d CZ |
324 | */ |
325 | ||
173d6681 | 326 | ENTRY(__invalidate_icache_page) |
d1538c46 | 327 | |
3f65ce4d | 328 | entry sp, 16 |
3f65ce4d | 329 | |
173d6681 CZ |
330 | ___invalidate_icache_page a2 a3 |
331 | isync | |
3f65ce4d | 332 | |
3f65ce4d CZ |
333 | retw |
334 | ||
d1538c46 CZ |
335 | ENDPROC(__invalidate_icache_page) |
336 | ||
3f65ce4d | 337 | /* |
173d6681 | 338 | * void __invalidate_dcache_page(ulong start) |
3f65ce4d CZ |
339 | */ |
340 | ||
173d6681 | 341 | ENTRY(__invalidate_dcache_page) |
d1538c46 | 342 | |
3f65ce4d | 343 | entry sp, 16 |
3f65ce4d | 344 | |
173d6681 CZ |
345 | ___invalidate_dcache_page a2 a3 |
346 | dsync | |
3f65ce4d | 347 | |
3f65ce4d CZ |
348 | retw |
349 | ||
d1538c46 CZ |
350 | ENDPROC(__invalidate_dcache_page) |
351 | ||
3f65ce4d | 352 | /* |
173d6681 | 353 | * void __flush_invalidate_dcache_page(ulong start) |
3f65ce4d CZ |
354 | */ |
355 | ||
173d6681 | 356 | ENTRY(__flush_invalidate_dcache_page) |
d1538c46 | 357 | |
3f65ce4d | 358 | entry sp, 16 |
3f65ce4d | 359 | |
173d6681 | 360 | ___flush_invalidate_dcache_page a2 a3 |
3f65ce4d | 361 | |
173d6681 | 362 | dsync |
3f65ce4d CZ |
363 | retw |
364 | ||
d1538c46 CZ |
365 | ENDPROC(__flush_invalidate_dcache_page) |
366 | ||
3f65ce4d | 367 | /* |
173d6681 | 368 | * void __flush_dcache_page(ulong start) |
3f65ce4d CZ |
369 | */ |
370 | ||
173d6681 | 371 | ENTRY(__flush_dcache_page) |
d1538c46 | 372 | |
3f65ce4d | 373 | entry sp, 16 |
3f65ce4d | 374 | |
173d6681 | 375 | ___flush_dcache_page a2 a3 |
3f65ce4d | 376 | |
173d6681 | 377 | dsync |
3f65ce4d CZ |
378 | retw |
379 | ||
d1538c46 CZ |
380 | ENDPROC(__flush_dcache_page) |
381 | ||
3f65ce4d | 382 | /* |
173d6681 | 383 | * void __invalidate_icache_range(ulong start, ulong size) |
3f65ce4d CZ |
384 | */ |
385 | ||
173d6681 | 386 | ENTRY(__invalidate_icache_range) |
d1538c46 | 387 | |
3f65ce4d | 388 | entry sp, 16 |
173d6681 CZ |
389 | |
390 | ___invalidate_icache_range a2 a3 a4 | |
391 | isync | |
392 | ||
3f65ce4d CZ |
393 | retw |
394 | ||
d1538c46 CZ |
395 | ENDPROC(__invalidate_icache_range) |
396 | ||
3f65ce4d CZ |
397 | /* |
398 | * void __flush_invalidate_dcache_range(ulong start, ulong size) | |
399 | */ | |
400 | ||
401 | ENTRY(__flush_invalidate_dcache_range) | |
d1538c46 | 402 | |
3f65ce4d | 403 | entry sp, 16 |
3f65ce4d | 404 | |
173d6681 CZ |
405 | ___flush_invalidate_dcache_range a2 a3 a4 |
406 | dsync | |
3f65ce4d | 407 | |
3f65ce4d CZ |
408 | retw |
409 | ||
d1538c46 CZ |
410 | ENDPROC(__flush_invalidate_dcache_range) |
411 | ||
3f65ce4d | 412 | /* |
173d6681 | 413 | * void _flush_dcache_range(ulong start, ulong size) |
3f65ce4d CZ |
414 | */ |
415 | ||
173d6681 | 416 | ENTRY(__flush_dcache_range) |
d1538c46 | 417 | |
3f65ce4d CZ |
418 | entry sp, 16 |
419 | ||
173d6681 | 420 | ___flush_dcache_range a2 a3 a4 |
3f65ce4d | 421 | dsync |
3f65ce4d | 422 | |
3f65ce4d CZ |
423 | retw |
424 | ||
d1538c46 CZ |
425 | ENDPROC(__flush_dcache_range) |
426 | ||
173d6681 CZ |
427 | /* |
428 | * void _invalidate_dcache_range(ulong start, ulong size) | |
429 | */ | |
3f65ce4d | 430 | |
173d6681 | 431 | ENTRY(__invalidate_dcache_range) |
d1538c46 | 432 | |
3f65ce4d CZ |
433 | entry sp, 16 |
434 | ||
173d6681 | 435 | ___invalidate_dcache_range a2 a3 a4 |
3f65ce4d | 436 | |
3f65ce4d CZ |
437 | retw |
438 | ||
d1538c46 CZ |
439 | ENDPROC(__invalidate_dcache_range) |
440 | ||
173d6681 CZ |
441 | /* |
442 | * void _invalidate_icache_all(void) | |
443 | */ | |
3f65ce4d | 444 | |
173d6681 | 445 | ENTRY(__invalidate_icache_all) |
d1538c46 | 446 | |
3f65ce4d CZ |
447 | entry sp, 16 |
448 | ||
173d6681 CZ |
449 | ___invalidate_icache_all a2 a3 |
450 | isync | |
3f65ce4d | 451 | |
3f65ce4d CZ |
452 | retw |
453 | ||
d1538c46 CZ |
454 | ENDPROC(__invalidate_icache_all) |
455 | ||
3f65ce4d | 456 | /* |
173d6681 | 457 | * void _flush_invalidate_dcache_all(void) |
3f65ce4d CZ |
458 | */ |
459 | ||
173d6681 | 460 | ENTRY(__flush_invalidate_dcache_all) |
d1538c46 | 461 | |
3f65ce4d CZ |
462 | entry sp, 16 |
463 | ||
173d6681 CZ |
464 | ___flush_invalidate_dcache_all a2 a3 |
465 | dsync | |
3f65ce4d | 466 | |
3f65ce4d CZ |
467 | retw |
468 | ||
d1538c46 CZ |
469 | ENDPROC(__flush_invalidate_dcache_all) |
470 | ||
173d6681 CZ |
471 | /* |
472 | * void _invalidate_dcache_all(void) | |
473 | */ | |
3f65ce4d | 474 | |
173d6681 | 475 | ENTRY(__invalidate_dcache_all) |
d1538c46 | 476 | |
3f65ce4d CZ |
477 | entry sp, 16 |
478 | ||
173d6681 CZ |
479 | ___invalidate_dcache_all a2 a3 |
480 | dsync | |
3f65ce4d CZ |
481 | |
482 | retw | |
483 | ||
d1538c46 | 484 | ENDPROC(__invalidate_dcache_all) |