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)
35 __loopi a2, a7, PAGE_SIZE, 32
49 * copy_page and copy_user_page are the same for non-cache-aliased configs.
51 * copy_page (void *to, void *from)
58 __loopi a2, a4, PAGE_SIZE, 32
89 * 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.
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.
100 /* TLB miss exceptions are treated special in the following region */
102 ENTRY(__tlbtemp_mapping_start)
104 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
107 * clear_user_page (void *addr, unsigned long vaddr, struct page *page)
111 ENTRY(clear_user_page)
114 /* Mark page dirty and determine alias. */
116 movi a7, (1 << PG_ARCH_1)
117 l32i a5, a4, PAGE_FLAGS
119 extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
120 extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
122 slli a3, a3, PAGE_SHIFT
123 s32i a5, a4, PAGE_FLAGS
125 /* Skip setting up a temporary DTLB if not aliased. */
129 /* Invalidate kernel page. */
132 call8 __invalidate_dcache_page
134 /* Setup a temporary DTLB with the color of the VPN */
136 movi a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
137 movi a5, TLBTEMP_BASE_1 # virt
139 add a2, a5, a3 # add 'color'
145 __loopi a2, a7, PAGE_SIZE, 32
159 /* We need to invalidate the temporary idtlb entry, if any. */
161 1: addi a2, a2, -PAGE_SIZE
168 * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
172 ENTRY(copy_user_page)
176 /* Mark page dirty and determine alias for destination. */
178 movi a8, (1 << PG_ARCH_1)
179 l32i a9, a5, PAGE_FLAGS
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
186 slli a4, a4, PAGE_SHIFT
187 s32i a9, a5, PAGE_FLAGS
188 movi a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
192 /* Invalidate dcache */
195 call8 __invalidate_dcache_page
197 /* Setup a temporary DTLB with a matching color. */
199 movi a8, TLBTEMP_BASE_1 # base
201 add a2, a8, a4 # add 'color'
206 /* Skip setting up a temporary DTLB for destination if not aliased. */
210 /* Setup a temporary DTLB with a matching color. */
212 movi a8, TLBTEMP_BASE_2 # base
215 addi a8, a3, 1 # way1
220 1: __loopi a2, a4, PAGE_SIZE, 32
247 /* We need to invalidate any temporary mapping! */
253 1: addi a2, a2, -PAGE_SIZE
259 2: addi a3, a3, -PAGE_SIZE+1
267 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
270 * void __flush_invalidate_dcache_page_alias (addr, phys)
274 ENTRY(__flush_invalidate_dcache_page_alias)
277 movi a7, 0 # required for exception handler
278 addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
283 ___flush_invalidate_dcache_page a2 a3
292 ENTRY(__tlbtemp_mapping_itlb)
294 #if (ICACHE_WAY_SIZE > PAGE_SIZE)
296 ENTRY(__invalidate_icache_page_alias)
299 addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
304 ___invalidate_icache_page a2 a3
312 /* End of special treatment in tlb miss exception */
314 ENTRY(__tlbtemp_mapping_end)
318 * void __invalidate_icache_page(ulong start)
321 ENTRY(__invalidate_icache_page)
324 ___invalidate_icache_page a2 a3
330 * void __invalidate_dcache_page(ulong start)
333 ENTRY(__invalidate_dcache_page)
336 ___invalidate_dcache_page a2 a3
342 * void __flush_invalidate_dcache_page(ulong start)
345 ENTRY(__flush_invalidate_dcache_page)
348 ___flush_invalidate_dcache_page a2 a3
354 * void __flush_dcache_page(ulong start)
357 ENTRY(__flush_dcache_page)
360 ___flush_dcache_page a2 a3
366 * void __invalidate_icache_range(ulong start, ulong size)
369 ENTRY(__invalidate_icache_range)
372 ___invalidate_icache_range a2 a3 a4
378 * void __flush_invalidate_dcache_range(ulong start, ulong size)
381 ENTRY(__flush_invalidate_dcache_range)
384 ___flush_invalidate_dcache_range a2 a3 a4
390 * void _flush_dcache_range(ulong start, ulong size)
393 ENTRY(__flush_dcache_range)
396 ___flush_dcache_range a2 a3 a4
402 * void _invalidate_dcache_range(ulong start, ulong size)
405 ENTRY(__invalidate_dcache_range)
408 ___invalidate_dcache_range a2 a3 a4
413 * void _invalidate_icache_all(void)
416 ENTRY(__invalidate_icache_all)
419 ___invalidate_icache_all a2 a3
425 * void _flush_invalidate_dcache_all(void)
428 ENTRY(__flush_invalidate_dcache_all)
431 ___flush_invalidate_dcache_all a2 a3
437 * void _invalidate_dcache_all(void)
440 ENTRY(__invalidate_dcache_all)
443 ___invalidate_dcache_all a2 a3