xref: /linux/arch/xtensa/mm/misc.S (revision 3d0fe49454652117522f60bfbefb978ba0e5300b)
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 *
10 * Copyright (C) 2001 - 2007 Tensilica Inc.
11 *
12 * Chris Zankel	<chris@zankel.net>
13 */
14
15
16#include <linux/linkage.h>
17#include <linux/pgtable.h>
18#include <asm/page.h>
19#include <asm/asmmacro.h>
20#include <asm/cacheasm.h>
21#include <asm/tlbflush.h>
22
23
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 */
30
31ENTRY(clear_page)
32
33	abi_entry_default
34
35	movi	a3, 0
36	__loopi	a2, a7, PAGE_SIZE, 32
37	s32i	a3, a2, 0
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
45	__endla	a2, a7, 32
46
47	abi_ret_default
48
49ENDPROC(clear_page)
50EXPORT_SYMBOL(clear_page)
51
52/*
53 * copy_page and copy_user_page are the same for non-cache-aliased configs.
54 *
55 * copy_page (void *to, void *from)
56 *               a2          a3
57 */
58
59ENTRY(copy_page)
60
61	abi_entry_default
62
63	__loopi a2, a4, PAGE_SIZE, 32
64
65	l32i    a8, a3, 0
66	l32i    a9, a3, 4
67	s32i    a8, a2, 0
68	s32i    a9, a2, 4
69
70	l32i    a8, a3, 8
71	l32i    a9, a3, 12
72	s32i    a8, a2, 8
73	s32i    a9, a2, 12
74
75	l32i    a8, a3, 16
76	l32i    a9, a3, 20
77	s32i    a8, a2, 16
78	s32i    a9, a2, 20
79
80	l32i    a8, a3, 24
81	l32i    a9, a3, 28
82	s32i    a8, a2, 24
83	s32i    a9, a2, 28
84
85	addi    a2, a2, 32
86	addi    a3, a3, 32
87
88	__endl  a2, a4
89
90	abi_ret_default
91
92ENDPROC(copy_page)
93EXPORT_SYMBOL(copy_page)
94
95#ifdef CONFIG_MMU
96/*
97 * If we have to deal with cache aliasing, we use temporary memory mappings
98 * to ensure that the source and destination pages have the same color as
99 * the virtual address. We use way 0 and 1 for temporary mappings in such cases.
100 *
101 * The temporary DTLB entries shouldn't be flushed by interrupts, but are
102 * flushed by preemptive task switches. Special code in the
103 * fast_second_level_miss handler re-established the temporary mapping.
104 * It requires that the PPNs for the destination and source addresses are
105 * in a6, and a7, respectively.
106 */
107
108/* TLB miss exceptions are treated special in the following region */
109
110ENTRY(__tlbtemp_mapping_start)
111
112#if (DCACHE_WAY_SIZE > PAGE_SIZE)
113
114/*
115 * clear_page_alias(void *addr, unsigned long paddr)
116 *                     a2              a3
117 */
118
119ENTRY(clear_page_alias)
120
121	abi_entry_default
122
123	movi	a5, PAGE_OFFSET
124	addi	a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
125	mov	a4, a2
126	wdtlb	a6, a2
127	dsync
128
129	movi	a3, 0
130	__loopi	a2, a7, PAGE_SIZE, 32
131	s32i	a3, a2, 0
132	s32i	a3, a2, 4
133	s32i	a3, a2, 8
134	s32i	a3, a2, 12
135	s32i	a3, a2, 16
136	s32i	a3, a2, 20
137	s32i	a3, a2, 24
138	s32i	a3, a2, 28
139	__endla	a2, a7, 32
140
141	/* We need to invalidate the temporary dtlb entry. */
142
143	idtlb	a4
144	dsync
145
146	abi_ret_default
147
148ENDPROC(clear_page_alias)
149
150/*
151 * copy_page_alias(void *to, void *from,
152 *			a2	  a3
153 *                 unsigned long to_paddr, unsigned long from_paddr)
154 *	        		 a4			 a5
155 */
156
157ENTRY(copy_page_alias)
158
159	abi_entry_default
160
161	/* Setup a temporary DTLB for destination. */
162
163	addi	a6, a4, (PAGE_KERNEL | _PAGE_HW_WRITE)
164	wdtlb	a6, a2
165	dsync
166
167	/* Setup a temporary DTLB for source. */
168
169	addi	a7, a5, PAGE_KERNEL
170	addi	a8, a3, 1				# way1
171
172	wdtlb	a7, a8
173	dsync
174
1751:	__loopi a2, a4, PAGE_SIZE, 32
176
177	l32i    a8, a3, 0
178	l32i    a9, a3, 4
179	s32i    a8, a2, 0
180	s32i    a9, a2, 4
181
182	l32i    a8, a3, 8
183	l32i    a9, a3, 12
184	s32i    a8, a2, 8
185	s32i    a9, a2, 12
186
187	l32i    a8, a3, 16
188	l32i    a9, a3, 20
189	s32i    a8, a2, 16
190	s32i    a9, a2, 20
191
192	l32i    a8, a3, 24
193	l32i    a9, a3, 28
194	s32i    a8, a2, 24
195	s32i    a9, a2, 28
196
197	addi    a2, a2, 32
198	addi    a3, a3, 32
199
200	__endl  a2, a4
201
202	/* We need to invalidate any temporary mapping! */
203
204	addi	a2, a2, -PAGE_SIZE
205	idtlb	a2
206	dsync
207
208	addi	a3, a3, -PAGE_SIZE+1
209	idtlb	a3
210	dsync
211
212	abi_ret_default
213
214ENDPROC(copy_page_alias)
215
216#endif
217
218#if (DCACHE_WAY_SIZE > PAGE_SIZE)
219
220/*
221 * void __flush_invalidate_dcache_page_alias (addr, phys)
222 *                                             a2    a3
223 */
224
225ENTRY(__flush_invalidate_dcache_page_alias)
226
227	abi_entry_default
228
229	movi	a7, 0			# required for exception handler
230	addi	a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
231	mov	a4, a2
232	wdtlb	a6, a2
233	dsync
234
235	___flush_invalidate_dcache_page a2 a3
236
237	idtlb	a4
238	dsync
239
240	abi_ret_default
241
242ENDPROC(__flush_invalidate_dcache_page_alias)
243
244/*
245 * void __invalidate_dcache_page_alias (addr, phys)
246 *                                       a2    a3
247 */
248
249ENTRY(__invalidate_dcache_page_alias)
250
251	abi_entry_default
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	___invalidate_dcache_page a2 a3
260
261	idtlb	a4
262	dsync
263
264	abi_ret_default
265
266ENDPROC(__invalidate_dcache_page_alias)
267#endif
268
269ENTRY(__tlbtemp_mapping_itlb)
270
271#if (ICACHE_WAY_SIZE > PAGE_SIZE)
272
273ENTRY(__invalidate_icache_page_alias)
274
275	abi_entry_default
276
277	addi	a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
278	mov	a4, a2
279	witlb	a6, a2
280	isync
281
282	___invalidate_icache_page a2 a3
283
284	iitlb	a4
285	isync
286	abi_ret_default
287
288ENDPROC(__invalidate_icache_page_alias)
289
290#endif
291
292/* End of special treatment in tlb miss exception */
293
294ENTRY(__tlbtemp_mapping_end)
295
296#endif /* CONFIG_MMU
297
298/*
299 * void __invalidate_icache_page(ulong start)
300 */
301
302ENTRY(__invalidate_icache_page)
303
304	abi_entry_default
305
306	___invalidate_icache_page a2 a3
307	isync
308
309	abi_ret_default
310
311ENDPROC(__invalidate_icache_page)
312
313/*
314 * void __invalidate_dcache_page(ulong start)
315 */
316
317ENTRY(__invalidate_dcache_page)
318
319	abi_entry_default
320
321	___invalidate_dcache_page a2 a3
322	dsync
323
324	abi_ret_default
325
326ENDPROC(__invalidate_dcache_page)
327
328/*
329 * void __flush_invalidate_dcache_page(ulong start)
330 */
331
332ENTRY(__flush_invalidate_dcache_page)
333
334	abi_entry_default
335
336	___flush_invalidate_dcache_page a2 a3
337
338	dsync
339	abi_ret_default
340
341ENDPROC(__flush_invalidate_dcache_page)
342
343/*
344 * void __flush_dcache_page(ulong start)
345 */
346
347ENTRY(__flush_dcache_page)
348
349	abi_entry_default
350
351	___flush_dcache_page a2 a3
352
353	dsync
354	abi_ret_default
355
356ENDPROC(__flush_dcache_page)
357
358/*
359 * void __invalidate_icache_range(ulong start, ulong size)
360 */
361
362ENTRY(__invalidate_icache_range)
363
364	abi_entry_default
365
366	___invalidate_icache_range a2 a3 a4
367	isync
368
369	abi_ret_default
370
371ENDPROC(__invalidate_icache_range)
372EXPORT_SYMBOL(__invalidate_icache_range)
373
374/*
375 * void __flush_invalidate_dcache_range(ulong start, ulong size)
376 */
377
378ENTRY(__flush_invalidate_dcache_range)
379
380	abi_entry_default
381
382	___flush_invalidate_dcache_range a2 a3 a4
383	dsync
384
385	abi_ret_default
386
387ENDPROC(__flush_invalidate_dcache_range)
388
389/*
390 * void _flush_dcache_range(ulong start, ulong size)
391 */
392
393ENTRY(__flush_dcache_range)
394
395	abi_entry_default
396
397	___flush_dcache_range a2 a3 a4
398	dsync
399
400	abi_ret_default
401
402ENDPROC(__flush_dcache_range)
403EXPORT_SYMBOL(__flush_dcache_range)
404
405/*
406 * void _invalidate_dcache_range(ulong start, ulong size)
407 */
408
409ENTRY(__invalidate_dcache_range)
410
411	abi_entry_default
412
413	___invalidate_dcache_range a2 a3 a4
414
415	abi_ret_default
416
417ENDPROC(__invalidate_dcache_range)
418EXPORT_SYMBOL(__invalidate_dcache_range)
419
420/*
421 * void _invalidate_icache_all(void)
422 */
423
424ENTRY(__invalidate_icache_all)
425
426	abi_entry_default
427
428	___invalidate_icache_all a2 a3
429	isync
430
431	abi_ret_default
432
433ENDPROC(__invalidate_icache_all)
434
435/*
436 * void _flush_invalidate_dcache_all(void)
437 */
438
439ENTRY(__flush_invalidate_dcache_all)
440
441	abi_entry_default
442
443	___flush_invalidate_dcache_all a2 a3
444	dsync
445
446	abi_ret_default
447
448ENDPROC(__flush_invalidate_dcache_all)
449
450/*
451 * void _invalidate_dcache_all(void)
452 */
453
454ENTRY(__invalidate_dcache_all)
455
456	abi_entry_default
457
458	___invalidate_dcache_all a2 a3
459	dsync
460
461	abi_ret_default
462
463ENDPROC(__invalidate_dcache_all)
464