1 /* $NetBSD: cpufunc_asm_sa1.S,v 1.8 2002/08/17 16:36:32 thorpej Exp $ */
4 * Copyright (c) 1997,1998 Mark Brinicombe.
5 * Copyright (c) 1997 Causality Limited
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Causality Limited.
19 * 4. The name of Causality Limited may not be used to endorse or promote
20 * products derived from this software without specific prior written
23 * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
24 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SA-1 assembly functions for CPU / MMU / TLB specific operations
39 #include <machine/asm.h>
40 __FBSDID("$FreeBSD$");
42 .Lblock_userspace_access:
43 .word _C_LABEL(block_userspace_access)
46 * Functions to set the MMU Translation Table Base register
48 * We need to clean and flush the cache as it uses virtual
49 * addresses that are about to change.
52 mrc p15, 0, r0, c2, c0, 0
54 #ifdef CACHE_CLEAN_BLOCK_INTR
56 orr r1, r3, #(I32_bit | F32_bit)
59 ldr r3, .Lblock_userspace_access
64 stmfd sp!, {r0-r3, lr}
65 bl _C_LABEL(sa1_cache_cleanID)
66 ldmfd sp!, {r0-r3, lr}
67 mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */
68 mcr p15, 0, r0, c7, c10, 4 /* drain write and fill buffer */
71 mcr p15, 0, r0, c2, c0, 0
73 /* If we have updated the TTB we must flush the TLB */
74 mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLB */
76 /* The cleanID above means we only need to flush the I cache here */
77 mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */
79 /* Make sure that pipeline is emptied */
82 #ifdef CACHE_CLEAN_BLOCK_INTR
94 ENTRY(sa1_tlb_flushID_SE)
95 mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */
96 mcr p15, 0, r0, c8, c5, 0 /* flush I tlb */
98 END(sa1_tlb_flushID_SE)
103 ENTRY(sa1_cache_flushID)
104 mcr p15, 0, r0, c7, c7, 0 /* flush I+D cache */
106 END(sa1_cache_flushID)
108 ENTRY(sa1_cache_flushI)
109 mcr p15, 0, r0, c7, c5, 0 /* flush I cache */
111 END(sa1_cache_flushI)
113 ENTRY(sa1_cache_flushD)
114 mcr p15, 0, r0, c7, c6, 0 /* flush D cache */
116 END(sa1_cache_flushD)
118 ENTRY(sa1_cache_flushD_SE)
119 mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
121 END(sa1_cache_flushD_SE)
123 ENTRY(sa1_cache_cleanD_E)
124 mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
126 END(sa1_cache_cleanD_E)
129 * Information for the SA-1 cache clean/purge functions:
131 * * Virtual address of the memory region to use
132 * * Size of memory region
136 .global _C_LABEL(sa1_cache_clean_addr)
137 _C_LABEL(sa1_cache_clean_addr):
140 .global _C_LABEL(sa1_cache_clean_size)
141 _C_LABEL(sa1_cache_clean_size):
142 #if defined(CPU_SA1100) || defined(CPU_SA1110)
150 .Lsa1_cache_clean_addr:
151 .word _C_LABEL(sa1_cache_clean_addr)
152 .Lsa1_cache_clean_size:
153 .word _C_LABEL(sa1_cache_clean_size)
155 #ifdef CACHE_CLEAN_BLOCK_INTR
156 #define SA1_CACHE_CLEAN_BLOCK \
158 orr r0, r3, #(I32_bit | F32_bit) ; \
161 #define SA1_CACHE_CLEAN_UNBLOCK \
164 #define SA1_CACHE_CLEAN_BLOCK \
165 ldr r3, .Lblock_userspace_access ; \
170 #define SA1_CACHE_CLEAN_UNBLOCK \
172 #endif /* CACHE_CLEAN_BLOCK_INTR */
174 #ifdef DOUBLE_CACHE_CLEAN_BANK
175 #define SA1_DOUBLE_CACHE_CLEAN_BANK \
179 #define SA1_DOUBLE_CACHE_CLEAN_BANK /* nothing */
180 #endif /* DOUBLE_CACHE_CLEAN_BANK */
182 #define SA1_CACHE_CLEAN_PROLOGUE \
183 SA1_CACHE_CLEAN_BLOCK ; \
184 ldr r2, .Lsa1_cache_clean_addr ; \
185 ldmia r2, {r0, r1} ; \
186 SA1_DOUBLE_CACHE_CLEAN_BANK
188 #define SA1_CACHE_CLEAN_EPILOGUE \
189 SA1_CACHE_CLEAN_UNBLOCK
191 ENTRY_NP(sa1_cache_syncI)
192 ENTRY_NP(sa1_cache_purgeID)
193 mcr p15, 0, r0, c7, c5, 0 /* flush I cache (D cleaned below) */
194 ENTRY_NP(sa1_cache_cleanID)
195 ENTRY_NP(sa1_cache_purgeD)
196 ENTRY(sa1_cache_cleanD)
197 SA1_CACHE_CLEAN_PROLOGUE
203 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
205 SA1_CACHE_CLEAN_EPILOGUE
208 END(sa1_cache_purgeID)
209 END(sa1_cache_cleanID)
210 END(sa1_cache_purgeD)
211 END(sa1_cache_cleanD)
213 ENTRY(sa1_cache_purgeID_E)
214 mcr p15, 0, r0, c7, c10, 1 /* clean dcache entry */
215 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
216 mcr p15, 0, r0, c7, c5, 0 /* flush I cache */
217 mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
219 END(sa1_cache_purgeID_E)
221 ENTRY(sa1_cache_purgeD_E)
222 mcr p15, 0, r0, c7, c10, 1 /* clean dcache entry */
223 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
224 mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
226 END(sa1_cache_purgeD_E)
231 /* sa1_cache_syncI is identical to sa1_cache_purgeID */
233 ENTRY(sa1_cache_cleanID_rng)
234 ENTRY(sa1_cache_cleanD_rng)
236 bcs _C_LABEL(sa1_cache_cleanID)
242 1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
247 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
249 END(sa1_cache_cleanID_rng)
250 END(sa1_cache_cleanD_rng)
252 ENTRY(sa1_cache_purgeID_rng)
254 bcs _C_LABEL(sa1_cache_purgeID)
260 1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
261 mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
266 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
267 mcr p15, 0, r0, c7, c5, 0 /* flush I cache */
269 END(sa1_cache_purgeID_rng)
271 ENTRY(sa1_cache_purgeD_rng)
273 bcs _C_LABEL(sa1_cache_purgeD)
279 1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
280 mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */
285 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
287 END(sa1_cache_purgeD_rng)
289 ENTRY(sa1_cache_syncI_rng)
291 bcs _C_LABEL(sa1_cache_syncI)
297 1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */
302 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
303 mcr p15, 0, r0, c7, c5, 0 /* flush I cache */
306 END(sa1_cache_syncI_rng)
311 * These is the CPU-specific parts of the context switcher cpu_switch()
312 * These functions actually perform the TTB reload.
314 * NOTE: Special calling convention
315 * r1, r4-r13 must be preserved
317 #if defined(CPU_SA110)
318 ENTRY(sa110_context_switch)
320 * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
321 * Thus the data cache will contain only kernel data and the
322 * instruction cache will contain only kernel code, and all
323 * kernel mappings are shared by all processes.
327 mcr p15, 0, r0, c2, c0, 0
329 /* If we have updated the TTB we must flush the TLB */
330 mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */
332 /* Make sure that pipeline is emptied */
336 END(sa110_context_switch)