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
88 * If we have to deal with cache aliasing, we use temporary memory mappings
89 * to ensure that the source and destination pages have the same color as
90 * the virtual address. We use way 0 and 1 for temporary mappings in such cases.
92 * The temporary DTLB entries shouldn't be flushed by interrupts, but are
93 * flushed by preemptive task switches. Special code in the
94 * fast_second_level_miss handler re-established the temporary mapping.
95 * It requires that the PPNs for the destination and source addresses are
96 * in a6, and a7, respectively.
99 /* TLB miss exceptions are treated special in the following region */
101 ENTRY(__tlbtemp_mapping_start)
103 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
106 * clear_user_page (void *addr, unsigned long vaddr, struct page *page)
110 ENTRY(clear_user_page)
113 /* Mark page dirty and determine alias. */
115 movi a7, (1 << PG_ARCH_1)
116 l32i a5, a4, PAGE_FLAGS
118 extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
119 extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
121 slli a3, a3, PAGE_SHIFT
122 s32i a5, a4, PAGE_FLAGS
124 /* Skip setting up a temporary DTLB if not aliased. */
128 /* Invalidate kernel page. */
131 call8 __invalidate_dcache_page
133 /* Setup a temporary DTLB with the color of the VPN */
135 movi a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
136 movi a5, TLBTEMP_BASE_1 # virt
138 add a2, a5, a3 # add 'color'
144 __loopi a2, a7, PAGE_SIZE, 32
158 /* We need to invalidate the temporary idtlb entry, if any. */
160 1: addi a2, a2, -PAGE_SIZE
167 * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
171 ENTRY(copy_user_page)
175 /* Mark page dirty and determine alias for destination. */
177 movi a8, (1 << PG_ARCH_1)
178 l32i a9, a5, PAGE_FLAGS
181 extui a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER
182 extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
183 extui a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER
185 slli a4, a4, PAGE_SHIFT
186 s32i a9, a5, PAGE_FLAGS
187 movi a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
191 /* Invalidate dcache */
194 call8 __invalidate_dcache_page
196 /* Setup a temporary DTLB with a matching color. */
198 movi a8, TLBTEMP_BASE_1 # base
200 add a2, a8, a4 # add 'color'
205 /* Skip setting up a temporary DTLB for destination if not aliased. */
209 /* Setup a temporary DTLB with a matching color. */
211 movi a8, TLBTEMP_BASE_2 # base
214 addi a8, a3, 1 # way1
219 1: __loopi a2, a4, PAGE_SIZE, 32
246 /* We need to invalidate any temporary mapping! */
252 1: addi a2, a2, -PAGE_SIZE
258 2: addi a3, a3, -PAGE_SIZE+1
266 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
269 * void __flush_invalidate_dcache_page_alias (addr, phys)
273 ENTRY(__flush_invalidate_dcache_page_alias)
276 movi a7, 0 # required for exception handler
277 addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
282 ___flush_invalidate_dcache_page a2 a3
291 ENTRY(__tlbtemp_mapping_itlb)
293 #if (ICACHE_WAY_SIZE > PAGE_SIZE)
295 ENTRY(__invalidate_icache_page_alias)
298 addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
303 ___invalidate_icache_page a2 a3
311 /* End of special treatment in tlb miss exception */
313 ENTRY(__tlbtemp_mapping_end)
316 * void __invalidate_icache_page(ulong start)
319 ENTRY(__invalidate_icache_page)
322 ___invalidate_icache_page a2 a3
328 * void __invalidate_dcache_page(ulong start)
331 ENTRY(__invalidate_dcache_page)
334 ___invalidate_dcache_page a2 a3
340 * void __flush_invalidate_dcache_page(ulong start)
343 ENTRY(__flush_invalidate_dcache_page)
346 ___flush_invalidate_dcache_page a2 a3
352 * void __flush_dcache_page(ulong start)
355 ENTRY(__flush_dcache_page)
358 ___flush_dcache_page a2 a3
364 * void __invalidate_icache_range(ulong start, ulong size)
367 ENTRY(__invalidate_icache_range)
370 ___invalidate_icache_range a2 a3 a4
376 * void __flush_invalidate_dcache_range(ulong start, ulong size)
379 ENTRY(__flush_invalidate_dcache_range)
382 ___flush_invalidate_dcache_range a2 a3 a4
388 * void _flush_dcache_range(ulong start, ulong size)
391 ENTRY(__flush_dcache_range)
394 ___flush_dcache_range a2 a3 a4
400 * void _invalidate_dcache_range(ulong start, ulong size)
403 ENTRY(__invalidate_dcache_range)
406 ___invalidate_dcache_range a2 a3 a4
411 * void _invalidate_icache_all(void)
414 ENTRY(__invalidate_icache_all)
417 ___invalidate_icache_all a2 a3
423 * void _flush_invalidate_dcache_all(void)
426 ENTRY(__flush_invalidate_dcache_all)
429 ___flush_invalidate_dcache_all a2 a3
435 * void _invalidate_dcache_all(void)
438 ENTRY(__invalidate_dcache_all)
441 ___invalidate_dcache_all a2 a3