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 | /* | |
113 | * clear_user_page (void *addr, unsigned long vaddr, struct page *page) | |
114 | * a2 a3 a4 | |
115 | */ | |
116 | ||
117 | ENTRY(clear_user_page) | |
d1538c46 | 118 | |
6656920b CZ |
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 | ||
ff384905 | 143 | movi a4, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff |
6656920b CZ |
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 | ||
d1538c46 CZ |
174 | ENDPROC(clear_user_page) |
175 | ||
6656920b CZ |
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 | ||
c4c4594b | 183 | entry a1, 32 |
6656920b CZ |
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 | |
ff384905 | 197 | movi a5, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff |
6656920b CZ |
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 | ||
d1538c46 CZ |
274 | ENDPROC(copy_user_page) |
275 | ||
6656920b CZ |
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) | |
d1538c46 | 286 | |
6656920b CZ |
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 | ||
d1538c46 | 302 | ENDPROC(__flush_invalidate_dcache_page_alias) |
6656920b CZ |
303 | #endif |
304 | ||
305 | ENTRY(__tlbtemp_mapping_itlb) | |
306 | ||
307 | #if (ICACHE_WAY_SIZE > PAGE_SIZE) | |
308 | ||
309 | ENTRY(__invalidate_icache_page_alias) | |
d1538c46 | 310 | |
6656920b CZ |
311 | entry sp, 16 |
312 | ||
0b2c3afd | 313 | addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE) |
6656920b CZ |
314 | mov a4, a2 |
315 | witlb a6, a2 | |
316 | isync | |
317 | ||
318 | ___invalidate_icache_page a2 a3 | |
319 | ||
320 | iitlb a4 | |
321 | isync | |
3f65ce4d CZ |
322 | retw |
323 | ||
d1538c46 CZ |
324 | ENDPROC(__invalidate_icache_page_alias) |
325 | ||
6656920b CZ |
326 | #endif |
327 | ||
328 | /* End of special treatment in tlb miss exception */ | |
329 | ||
330 | ENTRY(__tlbtemp_mapping_end) | |
d1538c46 | 331 | |
e5083a63 | 332 | #endif /* CONFIG_MMU |
6656920b | 333 | |
3f65ce4d | 334 | /* |
173d6681 | 335 | * void __invalidate_icache_page(ulong start) |
3f65ce4d CZ |
336 | */ |
337 | ||
173d6681 | 338 | ENTRY(__invalidate_icache_page) |
d1538c46 | 339 | |
3f65ce4d | 340 | entry sp, 16 |
3f65ce4d | 341 | |
173d6681 CZ |
342 | ___invalidate_icache_page a2 a3 |
343 | isync | |
3f65ce4d | 344 | |
3f65ce4d CZ |
345 | retw |
346 | ||
d1538c46 CZ |
347 | ENDPROC(__invalidate_icache_page) |
348 | ||
3f65ce4d | 349 | /* |
173d6681 | 350 | * void __invalidate_dcache_page(ulong start) |
3f65ce4d CZ |
351 | */ |
352 | ||
173d6681 | 353 | ENTRY(__invalidate_dcache_page) |
d1538c46 | 354 | |
3f65ce4d | 355 | entry sp, 16 |
3f65ce4d | 356 | |
173d6681 CZ |
357 | ___invalidate_dcache_page a2 a3 |
358 | dsync | |
3f65ce4d | 359 | |
3f65ce4d CZ |
360 | retw |
361 | ||
d1538c46 CZ |
362 | ENDPROC(__invalidate_dcache_page) |
363 | ||
3f65ce4d | 364 | /* |
173d6681 | 365 | * void __flush_invalidate_dcache_page(ulong start) |
3f65ce4d CZ |
366 | */ |
367 | ||
173d6681 | 368 | ENTRY(__flush_invalidate_dcache_page) |
d1538c46 | 369 | |
3f65ce4d | 370 | entry sp, 16 |
3f65ce4d | 371 | |
173d6681 | 372 | ___flush_invalidate_dcache_page a2 a3 |
3f65ce4d | 373 | |
173d6681 | 374 | dsync |
3f65ce4d CZ |
375 | retw |
376 | ||
d1538c46 CZ |
377 | ENDPROC(__flush_invalidate_dcache_page) |
378 | ||
3f65ce4d | 379 | /* |
173d6681 | 380 | * void __flush_dcache_page(ulong start) |
3f65ce4d CZ |
381 | */ |
382 | ||
173d6681 | 383 | ENTRY(__flush_dcache_page) |
d1538c46 | 384 | |
3f65ce4d | 385 | entry sp, 16 |
3f65ce4d | 386 | |
173d6681 | 387 | ___flush_dcache_page a2 a3 |
3f65ce4d | 388 | |
173d6681 | 389 | dsync |
3f65ce4d CZ |
390 | retw |
391 | ||
d1538c46 CZ |
392 | ENDPROC(__flush_dcache_page) |
393 | ||
3f65ce4d | 394 | /* |
173d6681 | 395 | * void __invalidate_icache_range(ulong start, ulong size) |
3f65ce4d CZ |
396 | */ |
397 | ||
173d6681 | 398 | ENTRY(__invalidate_icache_range) |
d1538c46 | 399 | |
3f65ce4d | 400 | entry sp, 16 |
173d6681 CZ |
401 | |
402 | ___invalidate_icache_range a2 a3 a4 | |
403 | isync | |
404 | ||
3f65ce4d CZ |
405 | retw |
406 | ||
d1538c46 CZ |
407 | ENDPROC(__invalidate_icache_range) |
408 | ||
3f65ce4d CZ |
409 | /* |
410 | * void __flush_invalidate_dcache_range(ulong start, ulong size) | |
411 | */ | |
412 | ||
413 | ENTRY(__flush_invalidate_dcache_range) | |
d1538c46 | 414 | |
3f65ce4d | 415 | entry sp, 16 |
3f65ce4d | 416 | |
173d6681 CZ |
417 | ___flush_invalidate_dcache_range a2 a3 a4 |
418 | dsync | |
3f65ce4d | 419 | |
3f65ce4d CZ |
420 | retw |
421 | ||
d1538c46 CZ |
422 | ENDPROC(__flush_invalidate_dcache_range) |
423 | ||
3f65ce4d | 424 | /* |
173d6681 | 425 | * void _flush_dcache_range(ulong start, ulong size) |
3f65ce4d CZ |
426 | */ |
427 | ||
173d6681 | 428 | ENTRY(__flush_dcache_range) |
d1538c46 | 429 | |
3f65ce4d CZ |
430 | entry sp, 16 |
431 | ||
173d6681 | 432 | ___flush_dcache_range a2 a3 a4 |
3f65ce4d | 433 | dsync |
3f65ce4d | 434 | |
3f65ce4d CZ |
435 | retw |
436 | ||
d1538c46 CZ |
437 | ENDPROC(__flush_dcache_range) |
438 | ||
173d6681 CZ |
439 | /* |
440 | * void _invalidate_dcache_range(ulong start, ulong size) | |
441 | */ | |
3f65ce4d | 442 | |
173d6681 | 443 | ENTRY(__invalidate_dcache_range) |
d1538c46 | 444 | |
3f65ce4d CZ |
445 | entry sp, 16 |
446 | ||
173d6681 | 447 | ___invalidate_dcache_range a2 a3 a4 |
3f65ce4d | 448 | |
3f65ce4d CZ |
449 | retw |
450 | ||
d1538c46 CZ |
451 | ENDPROC(__invalidate_dcache_range) |
452 | ||
173d6681 CZ |
453 | /* |
454 | * void _invalidate_icache_all(void) | |
455 | */ | |
3f65ce4d | 456 | |
173d6681 | 457 | ENTRY(__invalidate_icache_all) |
d1538c46 | 458 | |
3f65ce4d CZ |
459 | entry sp, 16 |
460 | ||
173d6681 CZ |
461 | ___invalidate_icache_all a2 a3 |
462 | isync | |
3f65ce4d | 463 | |
3f65ce4d CZ |
464 | retw |
465 | ||
d1538c46 CZ |
466 | ENDPROC(__invalidate_icache_all) |
467 | ||
3f65ce4d | 468 | /* |
173d6681 | 469 | * void _flush_invalidate_dcache_all(void) |
3f65ce4d CZ |
470 | */ |
471 | ||
173d6681 | 472 | ENTRY(__flush_invalidate_dcache_all) |
d1538c46 | 473 | |
3f65ce4d CZ |
474 | entry sp, 16 |
475 | ||
173d6681 CZ |
476 | ___flush_invalidate_dcache_all a2 a3 |
477 | dsync | |
3f65ce4d | 478 | |
3f65ce4d CZ |
479 | retw |
480 | ||
d1538c46 CZ |
481 | ENDPROC(__flush_invalidate_dcache_all) |
482 | ||
173d6681 CZ |
483 | /* |
484 | * void _invalidate_dcache_all(void) | |
485 | */ | |
3f65ce4d | 486 | |
173d6681 | 487 | ENTRY(__invalidate_dcache_all) |
d1538c46 | 488 | |
3f65ce4d CZ |
489 | entry sp, 16 |
490 | ||
173d6681 CZ |
491 | ___invalidate_dcache_all a2 a3 |
492 | dsync | |
3f65ce4d CZ |
493 | |
494 | retw | |
495 | ||
d1538c46 | 496 | ENDPROC(__invalidate_dcache_all) |