2 * arch/xtensa/mm/misc.S
4 * Miscellaneous assembly functions.
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
10 * Copyright (C) 2001 - 2007 Tensilica Inc.
12 * Chris Zankel <chris@zankel.net>
16 #include <linux/linkage.h>
18 #include <asm/pgtable.h>
19 #include <asm/asmmacro.h>
20 #include <asm/cacheasm.h>
21 #include <asm/tlbflush.h>
25 * clear_page and clear_user_page are the same for non-cache-aliased configs.
27 * clear_page (unsigned long page)
36 __loopi a2, a7, PAGE_SIZE, 32
52 * copy_page and copy_user_page are the same for non-cache-aliased configs.
54 * copy_page (void *to, void *from)
62 __loopi a2, a4, PAGE_SIZE, 32
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.
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.
106 /* TLB miss exceptions are treated special in the following region */
108 ENTRY(__tlbtemp_mapping_start)
110 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
113 * clear_user_page (void *addr, unsigned long vaddr, struct page *page)
117 ENTRY(clear_user_page)
121 /* Mark page dirty and determine alias. */
123 movi a7, (1 << PG_ARCH_1)
124 l32i a5, a4, PAGE_FLAGS
126 extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
127 extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
129 slli a3, a3, PAGE_SHIFT
130 s32i a5, a4, PAGE_FLAGS
132 /* Skip setting up a temporary DTLB if not aliased. */
136 /* Invalidate kernel page. */
139 call8 __invalidate_dcache_page
141 /* Setup a temporary DTLB with the color of the VPN */
143 movi a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
144 movi a5, TLBTEMP_BASE_1 # virt
146 add a2, a5, a3 # add 'color'
152 __loopi a2, a7, PAGE_SIZE, 32
166 /* We need to invalidate the temporary idtlb entry, if any. */
168 1: addi a2, a2, -PAGE_SIZE
174 ENDPROC(clear_user_page)
177 * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
181 ENTRY(copy_user_page)
185 /* Mark page dirty and determine alias for destination. */
187 movi a8, (1 << PG_ARCH_1)
188 l32i a9, a5, PAGE_FLAGS
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
195 slli a4, a4, PAGE_SHIFT
196 s32i a9, a5, PAGE_FLAGS
197 movi a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
201 /* Invalidate dcache */
204 call8 __invalidate_dcache_page
206 /* Setup a temporary DTLB with a matching color. */
208 movi a8, TLBTEMP_BASE_1 # base
210 add a2, a8, a4 # add 'color'
215 /* Skip setting up a temporary DTLB for destination if not aliased. */
219 /* Setup a temporary DTLB with a matching color. */
221 movi a8, TLBTEMP_BASE_2 # base
224 addi a8, a3, 1 # way1
229 1: __loopi a2, a4, PAGE_SIZE, 32
256 /* We need to invalidate any temporary mapping! */
262 1: addi a2, a2, -PAGE_SIZE
268 2: addi a3, a3, -PAGE_SIZE+1
274 ENDPROC(copy_user_page)
278 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
281 * void __flush_invalidate_dcache_page_alias (addr, phys)
285 ENTRY(__flush_invalidate_dcache_page_alias)
289 movi a7, 0 # required for exception handler
290 addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
295 ___flush_invalidate_dcache_page a2 a3
302 ENDPROC(__flush_invalidate_dcache_page_alias)
305 ENTRY(__tlbtemp_mapping_itlb)
307 #if (ICACHE_WAY_SIZE > PAGE_SIZE)
309 ENTRY(__invalidate_icache_page_alias)
313 addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
318 ___invalidate_icache_page a2 a3
324 ENDPROC(__invalidate_icache_page_alias)
328 /* End of special treatment in tlb miss exception */
330 ENTRY(__tlbtemp_mapping_end)
335 * void __invalidate_icache_page(ulong start)
338 ENTRY(__invalidate_icache_page)
342 ___invalidate_icache_page a2 a3
347 ENDPROC(__invalidate_icache_page)
350 * void __invalidate_dcache_page(ulong start)
353 ENTRY(__invalidate_dcache_page)
357 ___invalidate_dcache_page a2 a3
362 ENDPROC(__invalidate_dcache_page)
365 * void __flush_invalidate_dcache_page(ulong start)
368 ENTRY(__flush_invalidate_dcache_page)
372 ___flush_invalidate_dcache_page a2 a3
377 ENDPROC(__flush_invalidate_dcache_page)
380 * void __flush_dcache_page(ulong start)
383 ENTRY(__flush_dcache_page)
387 ___flush_dcache_page a2 a3
392 ENDPROC(__flush_dcache_page)
395 * void __invalidate_icache_range(ulong start, ulong size)
398 ENTRY(__invalidate_icache_range)
402 ___invalidate_icache_range a2 a3 a4
407 ENDPROC(__invalidate_icache_range)
410 * void __flush_invalidate_dcache_range(ulong start, ulong size)
413 ENTRY(__flush_invalidate_dcache_range)
417 ___flush_invalidate_dcache_range a2 a3 a4
422 ENDPROC(__flush_invalidate_dcache_range)
425 * void _flush_dcache_range(ulong start, ulong size)
428 ENTRY(__flush_dcache_range)
432 ___flush_dcache_range a2 a3 a4
437 ENDPROC(__flush_dcache_range)
440 * void _invalidate_dcache_range(ulong start, ulong size)
443 ENTRY(__invalidate_dcache_range)
447 ___invalidate_dcache_range a2 a3 a4
451 ENDPROC(__invalidate_dcache_range)
454 * void _invalidate_icache_all(void)
457 ENTRY(__invalidate_icache_all)
461 ___invalidate_icache_all a2 a3
466 ENDPROC(__invalidate_icache_all)
469 * void _flush_invalidate_dcache_all(void)
472 ENTRY(__flush_invalidate_dcache_all)
476 ___flush_invalidate_dcache_all a2 a3
481 ENDPROC(__flush_invalidate_dcache_all)
484 * void _invalidate_dcache_all(void)
487 ENTRY(__invalidate_dcache_all)
491 ___invalidate_dcache_all a2 a3
496 ENDPROC(__invalidate_dcache_all)