blob: b048406d87568cb23a5fd14d7dd215dd51f6f6dc [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)
32 entry a1, 16
Chris Zankel3f65ce42005-06-23 22:01:24 -070033
Chris Zankel66569202007-08-22 10:14:51 -070034 movi a3, 0
35 __loopi a2, a7, PAGE_SIZE, 32
36 s32i a3, a2, 0
Chris Zankel3f65ce42005-06-23 22:01:24 -070037 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
Chris Zankel66569202007-08-22 10:14:51 -070044 __endla a2, a7, 32
Chris Zankel3f65ce42005-06-23 22:01:24 -070045
46 retw
47
48/*
Chris Zankel66569202007-08-22 10:14:51 -070049 * copy_page and copy_user_page are the same for non-cache-aliased configs.
50 *
Chris Zankel3f65ce42005-06-23 22:01:24 -070051 * copy_page (void *to, void *from)
Chris Zankel66569202007-08-22 10:14:51 -070052 * a2 a3
Chris Zankel3f65ce42005-06-23 22:01:24 -070053 */
54
55ENTRY(copy_page)
56 entry a1, 16
Chris Zankel3f65ce42005-06-23 22:01:24 -070057
Chris Zankel66569202007-08-22 10:14:51 -070058 __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
Chris Zankel3f65ce42005-06-23 22:01:24 -070084
85 retw
86
Johannes Weinere5083a62009-03-04 16:21:31 +010087#ifdef CONFIG_MMU
Chris Zankel3f65ce42005-06-23 22:01:24 -070088/*
Chris Zankel66569202007-08-22 10:14:51 -070089 * 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
Chris Zankel0b2c3af2008-02-12 10:11:45 -0800299 addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
Chris Zankel66569202007-08-22 10:14:51 -0700300 mov a4, a2
301 witlb a6, a2
302 isync
303
304 ___invalidate_icache_page a2 a3
305
306 iitlb a4
307 isync
308 retw
309
310#endif
311
312/* End of special treatment in tlb miss exception */
313
314ENTRY(__tlbtemp_mapping_end)
Johannes Weinere5083a62009-03-04 16:21:31 +0100315#endif /* CONFIG_MMU
Chris Zankel66569202007-08-22 10:14:51 -0700316
317/*
Chris Zankel3f65ce42005-06-23 22:01:24 -0700318 * void __invalidate_icache_page(ulong start)
319 */
320
321ENTRY(__invalidate_icache_page)
322 entry sp, 16
Chris Zankel173d66812006-12-10 02:18:48 -0800323
324 ___invalidate_icache_page a2 a3
325 isync
326
Chris Zankel3f65ce42005-06-23 22:01:24 -0700327 retw
328
329/*
330 * void __invalidate_dcache_page(ulong start)
331 */
332
333ENTRY(__invalidate_dcache_page)
334 entry sp, 16
Chris Zankel3f65ce42005-06-23 22:01:24 -0700335
Chris Zankel173d66812006-12-10 02:18:48 -0800336 ___invalidate_dcache_page a2 a3
337 dsync
Chris Zankel3f65ce42005-06-23 22:01:24 -0700338
Chris Zankel3f65ce42005-06-23 22:01:24 -0700339 retw
340
341/*
342 * void __flush_invalidate_dcache_page(ulong start)
343 */
344
345ENTRY(__flush_invalidate_dcache_page)
346 entry sp, 16
Chris Zankel173d66812006-12-10 02:18:48 -0800347
348 ___flush_invalidate_dcache_page a2 a3
349
350 dsync
351 retw
352
353/*
354 * void __flush_dcache_page(ulong start)
355 */
356
357ENTRY(__flush_dcache_page)
358 entry sp, 16
359
360 ___flush_dcache_page a2 a3
361
362 dsync
363 retw
364
Chris Zankel173d66812006-12-10 02:18:48 -0800365/*
366 * void __invalidate_icache_range(ulong start, ulong size)
367 */
368
369ENTRY(__invalidate_icache_range)
370 entry sp, 16
371
372 ___invalidate_icache_range a2 a3 a4
373 isync
374
Chris Zankel3f65ce42005-06-23 22:01:24 -0700375 retw
376
377/*
378 * void __flush_invalidate_dcache_range(ulong start, ulong size)
379 */
380
381ENTRY(__flush_invalidate_dcache_range)
382 entry sp, 16
Chris Zankel173d66812006-12-10 02:18:48 -0800383
384 ___flush_invalidate_dcache_range a2 a3 a4
385 dsync
386
Chris Zankel3f65ce42005-06-23 22:01:24 -0700387 retw
388
389/*
Chris Zankel173d66812006-12-10 02:18:48 -0800390 * void _flush_dcache_range(ulong start, ulong size)
391 */
392
393ENTRY(__flush_dcache_range)
394 entry sp, 16
395
396 ___flush_dcache_range a2 a3 a4
397 dsync
398
399 retw
400
401/*
402 * void _invalidate_dcache_range(ulong start, ulong size)
403 */
404
405ENTRY(__invalidate_dcache_range)
406 entry sp, 16
407
408 ___invalidate_dcache_range a2 a3 a4
409
Chris Zankel173d66812006-12-10 02:18:48 -0800410 retw
411
412/*
413 * void _invalidate_icache_all(void)
414 */
415
416ENTRY(__invalidate_icache_all)
417 entry sp, 16
418
419 ___invalidate_icache_all a2 a3
420 isync
421
422 retw
423
424/*
425 * void _flush_invalidate_dcache_all(void)
426 */
427
428ENTRY(__flush_invalidate_dcache_all)
429 entry sp, 16
430
431 ___flush_invalidate_dcache_all a2 a3
432 dsync
433
434 retw
435
436/*
437 * void _invalidate_dcache_all(void)
Chris Zankel3f65ce42005-06-23 22:01:24 -0700438 */
439
440ENTRY(__invalidate_dcache_all)
441 entry sp, 16
Chris Zankel3f65ce42005-06-23 22:01:24 -0700442
Chris Zankel173d66812006-12-10 02:18:48 -0800443 ___invalidate_dcache_all a2 a3
Chris Zankel3f65ce42005-06-23 22:01:24 -0700444 dsync
Chris Zankel3f65ce42005-06-23 22:01:24 -0700445
446 retw
447