xref: /openbmc/linux/arch/xtensa/mm/misc.S (revision b868a02e)
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)
50
51/*
52 * copy_page and copy_user_page are the same for non-cache-aliased configs.
53 *
54 * copy_page (void *to, void *from)
55 *               a2          a3
56 */
57
58ENTRY(copy_page)
59
60	abi_entry_default
61
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	abi_ret_default
90
91ENDPROC(copy_page)
92
93#ifdef CONFIG_MMU
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
108ENTRY(__tlbtemp_mapping_start)
109
110#if (DCACHE_WAY_SIZE > PAGE_SIZE)
111
112/*
113 * clear_page_alias(void *addr, unsigned long paddr)
114 *                     a2              a3
115 */
116
117ENTRY(clear_page_alias)
118
119	abi_entry_default
120
121	movi	a5, PAGE_OFFSET
122	addi	a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
123	mov	a4, a2
124	wdtlb	a6, a2
125	dsync
126
127	movi	a3, 0
128	__loopi	a2, a7, PAGE_SIZE, 32
129	s32i	a3, a2, 0
130	s32i	a3, a2, 4
131	s32i	a3, a2, 8
132	s32i	a3, a2, 12
133	s32i	a3, a2, 16
134	s32i	a3, a2, 20
135	s32i	a3, a2, 24
136	s32i	a3, a2, 28
137	__endla	a2, a7, 32
138
139	/* We need to invalidate the temporary dtlb entry. */
140
141	idtlb	a4
142	dsync
143
144	abi_ret_default
145
146ENDPROC(clear_page_alias)
147
148/*
149 * copy_page_alias(void *to, void *from,
150 *			a2	  a3
151 *                 unsigned long to_paddr, unsigned long from_paddr)
152 *	        		 a4			 a5
153 */
154
155ENTRY(copy_page_alias)
156
157	abi_entry_default
158
159	/* Setup a temporary DTLB for destination. */
160
161	addi	a6, a4, (PAGE_KERNEL | _PAGE_HW_WRITE)
162	wdtlb	a6, a2
163	dsync
164
165	/* Setup a temporary DTLB for source. */
166
167	addi	a7, a5, PAGE_KERNEL
168	addi	a8, a3, 1				# way1
169
170	wdtlb	a7, a8
171	dsync
172
1731:	__loopi a2, a4, PAGE_SIZE, 32
174
175	l32i    a8, a3, 0
176	l32i    a9, a3, 4
177	s32i    a8, a2, 0
178	s32i    a9, a2, 4
179
180	l32i    a8, a3, 8
181	l32i    a9, a3, 12
182	s32i    a8, a2, 8
183	s32i    a9, a2, 12
184
185	l32i    a8, a3, 16
186	l32i    a9, a3, 20
187	s32i    a8, a2, 16
188	s32i    a9, a2, 20
189
190	l32i    a8, a3, 24
191	l32i    a9, a3, 28
192	s32i    a8, a2, 24
193	s32i    a9, a2, 28
194
195	addi    a2, a2, 32
196	addi    a3, a3, 32
197
198	__endl  a2, a4
199
200	/* We need to invalidate any temporary mapping! */
201
202	addi	a2, a2, -PAGE_SIZE
203	idtlb	a2
204	dsync
205
206	addi	a3, a3, -PAGE_SIZE+1
207	idtlb	a3
208	dsync
209
210	abi_ret_default
211
212ENDPROC(copy_page_alias)
213
214#endif
215
216#if (DCACHE_WAY_SIZE > PAGE_SIZE)
217
218/*
219 * void __flush_invalidate_dcache_page_alias (addr, phys)
220 *                                             a2    a3
221 */
222
223ENTRY(__flush_invalidate_dcache_page_alias)
224
225	abi_entry_default
226
227	movi	a7, 0			# required for exception handler
228	addi	a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
229	mov	a4, a2
230	wdtlb	a6, a2
231	dsync
232
233	___flush_invalidate_dcache_page a2 a3
234
235	idtlb	a4
236	dsync
237
238	abi_ret_default
239
240ENDPROC(__flush_invalidate_dcache_page_alias)
241
242/*
243 * void __invalidate_dcache_page_alias (addr, phys)
244 *                                       a2    a3
245 */
246
247ENTRY(__invalidate_dcache_page_alias)
248
249	abi_entry_default
250
251	movi	a7, 0			# required for exception handler
252	addi	a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
253	mov	a4, a2
254	wdtlb	a6, a2
255	dsync
256
257	___invalidate_dcache_page a2 a3
258
259	idtlb	a4
260	dsync
261
262	abi_ret_default
263
264ENDPROC(__invalidate_dcache_page_alias)
265#endif
266
267ENTRY(__tlbtemp_mapping_itlb)
268
269#if (ICACHE_WAY_SIZE > PAGE_SIZE)
270
271ENTRY(__invalidate_icache_page_alias)
272
273	abi_entry_default
274
275	addi	a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
276	mov	a4, a2
277	witlb	a6, a2
278	isync
279
280	___invalidate_icache_page a2 a3
281
282	iitlb	a4
283	isync
284	abi_ret_default
285
286ENDPROC(__invalidate_icache_page_alias)
287
288#endif
289
290/* End of special treatment in tlb miss exception */
291
292ENTRY(__tlbtemp_mapping_end)
293
294#endif /* CONFIG_MMU
295
296/*
297 * void __invalidate_icache_page(ulong start)
298 */
299
300ENTRY(__invalidate_icache_page)
301
302	abi_entry_default
303
304	___invalidate_icache_page a2 a3
305	isync
306
307	abi_ret_default
308
309ENDPROC(__invalidate_icache_page)
310
311/*
312 * void __invalidate_dcache_page(ulong start)
313 */
314
315ENTRY(__invalidate_dcache_page)
316
317	abi_entry_default
318
319	___invalidate_dcache_page a2 a3
320	dsync
321
322	abi_ret_default
323
324ENDPROC(__invalidate_dcache_page)
325
326/*
327 * void __flush_invalidate_dcache_page(ulong start)
328 */
329
330ENTRY(__flush_invalidate_dcache_page)
331
332	abi_entry_default
333
334	___flush_invalidate_dcache_page a2 a3
335
336	dsync
337	abi_ret_default
338
339ENDPROC(__flush_invalidate_dcache_page)
340
341/*
342 * void __flush_dcache_page(ulong start)
343 */
344
345ENTRY(__flush_dcache_page)
346
347	abi_entry_default
348
349	___flush_dcache_page a2 a3
350
351	dsync
352	abi_ret_default
353
354ENDPROC(__flush_dcache_page)
355
356/*
357 * void __invalidate_icache_range(ulong start, ulong size)
358 */
359
360ENTRY(__invalidate_icache_range)
361
362	abi_entry_default
363
364	___invalidate_icache_range a2 a3 a4
365	isync
366
367	abi_ret_default
368
369ENDPROC(__invalidate_icache_range)
370
371/*
372 * void __flush_invalidate_dcache_range(ulong start, ulong size)
373 */
374
375ENTRY(__flush_invalidate_dcache_range)
376
377	abi_entry_default
378
379	___flush_invalidate_dcache_range a2 a3 a4
380	dsync
381
382	abi_ret_default
383
384ENDPROC(__flush_invalidate_dcache_range)
385
386/*
387 * void _flush_dcache_range(ulong start, ulong size)
388 */
389
390ENTRY(__flush_dcache_range)
391
392	abi_entry_default
393
394	___flush_dcache_range a2 a3 a4
395	dsync
396
397	abi_ret_default
398
399ENDPROC(__flush_dcache_range)
400
401/*
402 * void _invalidate_dcache_range(ulong start, ulong size)
403 */
404
405ENTRY(__invalidate_dcache_range)
406
407	abi_entry_default
408
409	___invalidate_dcache_range a2 a3 a4
410
411	abi_ret_default
412
413ENDPROC(__invalidate_dcache_range)
414
415/*
416 * void _invalidate_icache_all(void)
417 */
418
419ENTRY(__invalidate_icache_all)
420
421	abi_entry_default
422
423	___invalidate_icache_all a2 a3
424	isync
425
426	abi_ret_default
427
428ENDPROC(__invalidate_icache_all)
429
430/*
431 * void _flush_invalidate_dcache_all(void)
432 */
433
434ENTRY(__flush_invalidate_dcache_all)
435
436	abi_entry_default
437
438	___flush_invalidate_dcache_all a2 a3
439	dsync
440
441	abi_ret_default
442
443ENDPROC(__flush_invalidate_dcache_all)
444
445/*
446 * void _invalidate_dcache_all(void)
447 */
448
449ENTRY(__invalidate_dcache_all)
450
451	abi_entry_default
452
453	___invalidate_dcache_all a2 a3
454	dsync
455
456	abi_ret_default
457
458ENDPROC(__invalidate_dcache_all)
459