]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/arm/arm/cpufunc_asm_xscale_c3.S
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / arm / arm / cpufunc_asm_xscale_c3.S
1 /*      $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $  */
2
3 /*-
4  * Copyright (c) 2007 Olivier Houchard
5  * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
6  * All rights reserved.
7  *
8  * Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed for the NetBSD Project by
21  *      Wasabi Systems, Inc.
22  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
23  *    or promote products derived from this software without specific prior
24  *    written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  */
39
40 /*-
41  * Copyright (c) 2001 Matt Thomas.
42  * Copyright (c) 1997,1998 Mark Brinicombe.
43  * Copyright (c) 1997 Causality Limited
44  * All rights reserved.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. All advertising materials mentioning features or use of this software
55  *    must display the following acknowledgement:
56  *      This product includes software developed by Causality Limited.
57  * 4. The name of Causality Limited may not be used to endorse or promote
58  *    products derived from this software without specific prior written
59  *    permission.
60  *
61  * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
62  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
64  * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
65  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
66  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
67  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71  * SUCH DAMAGE.
72  *
73  * XScale core 3 assembly functions for CPU / MMU / TLB specific operations
74  */
75
76 #include <machine/asm.h>
77 __FBSDID("$FreeBSD$");
78
79 /*
80  * Size of the XScale core D-cache.
81  */
82 #define DCACHE_SIZE             0x00008000
83
84 .Lblock_userspace_access:
85         .word   _C_LABEL(block_userspace_access)
86
87 /*
88  * CPWAIT -- Canonical method to wait for CP15 update.
89  * From: Intel 80200 manual, section 2.3.3.
90  *
91  * NOTE: Clobbers the specified temp reg.
92  */
93 #define CPWAIT_BRANCH                                                    \
94         sub     pc, pc, #4
95
96 #define CPWAIT(tmp)                                                      \
97         mrc     p15, 0, tmp, c2, c0, 0  /* arbitrary read of CP15 */    ;\
98         mov     tmp, tmp                /* wait for it to complete */   ;\
99         CPWAIT_BRANCH                   /* branch to next insn */
100
101 #define CPWAIT_AND_RETURN_SHIFTER       lsr #32
102
103 #define CPWAIT_AND_RETURN(tmp)                                           \
104         mrc     p15, 0, tmp, c2, c0, 0  /* arbitrary read of CP15 */    ;\
105         /* Wait for it to complete and branch to the return address */   \
106         sub     pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER
107
108 #define ARM_USE_L2_CACHE
109
110 #define L2_CACHE_SIZE           0x80000
111 #define L2_CACHE_WAYS           8
112 #define L2_CACHE_LINE_SIZE      32
113 #define L2_CACHE_SETS           (L2_CACHE_SIZE / \
114     (L2_CACHE_WAYS * L2_CACHE_LINE_SIZE))
115
116 #define L1_DCACHE_SIZE          32 * 1024
117 #define L1_DCACHE_WAYS          4
118 #define L1_DCACHE_LINE_SIZE     32
119 #define L1_DCACHE_SETS          (L1_DCACHE_SIZE / \
120     (L1_DCACHE_WAYS * L1_DCACHE_LINE_SIZE))
121 #ifdef CACHE_CLEAN_BLOCK_INTR
122 #define XSCALE_CACHE_CLEAN_BLOCK                                        \
123         stmfd   sp!, {r4}                                       ;       \
124         mrs     r4, cpsr_all                                    ;       \
125         orr     r0, r4, #(I32_bit | F32_bit)                    ;       \
126         msr     cpsr_all, r0
127
128 #define XSCALE_CACHE_CLEAN_UNBLOCK                                      \
129         msr     cpsr_all, r4                                    ;       \
130         ldmfd   sp!, {r4}
131 #else
132 #define XSCALE_CACHE_CLEAN_BLOCK                                        \
133         stmfd   sp!, {r4}                                       ;       \
134         ldr     r4, .Lblock_userspace_access                    ;       \
135         ldr     ip, [r4]                                        ;       \
136         orr     r0, ip, #1                                      ;       \
137         str     r0, [r4]        
138
139 #define XSCALE_CACHE_CLEAN_UNBLOCK                                      \
140         str     ip, [r3]                                        ;       \
141         ldmfd   sp!, {r4}
142 #endif /* CACHE_CLEAN_BLOCK_INTR */
143
144
145 ENTRY_NP(xscalec3_cache_syncI)
146 ENTRY_NP(xscalec3_cache_purgeID)
147         mcr     p15, 0, r0, c7, c5, 0   /* flush I cache (D cleaned below) */
148 ENTRY_NP(xscalec3_cache_cleanID)
149 ENTRY_NP(xscalec3_cache_purgeD)
150 ENTRY(xscalec3_cache_cleanD)
151
152         XSCALE_CACHE_CLEAN_BLOCK
153         mov     r0, #0
154 1:
155         mov     r1, r0, asl #30
156         mov     r2, #0
157 2:
158         orr     r3, r1, r2, asl #5
159         mcr     p15, 0, r3, c7, c14, 2  /* clean and invalidate */
160         add     r2, r2, #1
161         cmp     r2, #L1_DCACHE_SETS
162         bne     2b
163         add     r0, r0, #1
164         cmp     r0, #4
165         bne     1b
166         CPWAIT(r0)
167         XSCALE_CACHE_CLEAN_UNBLOCK
168         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
169
170         RET
171 END(xscalec3_cache_syncI)
172 END(xscalec3_cache_purgeID)
173 END(xscalec3_cache_cleanID)
174 END(xscalec3_cache_purgeD)
175 END(xscalec3_cache_cleanD)
176
177 ENTRY(xscalec3_cache_purgeID_rng)
178
179         cmp     r1, #0x4000
180         bcs     _C_LABEL(xscalec3_cache_cleanID)
181         and     r2, r0, #0x1f
182         add     r1, r1, r2
183         bic     r0, r0, #0x1f
184
185 1:      mcr     p15, 0, r0, c7, c14, 1  /* clean/invalidate L1 D cache entry */
186         nop
187         mcr     p15, 0, r0, c7, c5, 1   /* flush I cache single entry */
188         add     r0, r0, #32
189         subs    r1, r1, #32
190         bhi     1b
191
192         CPWAIT(r0)
193
194         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
195
196         CPWAIT_AND_RETURN(r0)
197 END(xscalec3_cache_purgeID_rng)
198
199 ENTRY(xscalec3_cache_syncI_rng)
200         cmp     r1, #0x4000
201         bcs     _C_LABEL(xscalec3_cache_syncI)
202
203         and     r2, r0, #0x1f
204         add     r1, r1, r2
205         bic     r0, r0, #0x1f
206
207 1:      mcr     p15, 0, r0, c7, c10, 1  /* clean D cache entry */
208         mcr     p15, 0, r0, c7, c5, 1   /* flush I cache single entry */
209         add     r0, r0, #32
210         subs    r1, r1, #32
211         bhi     1b
212
213         CPWAIT(r0)
214
215         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
216
217         CPWAIT_AND_RETURN(r0)
218 END(xscalec3_cache_syncI_rng)
219         
220 ENTRY(xscalec3_cache_purgeD_rng)
221
222         cmp     r1, #0x4000
223         bcs     _C_LABEL(xscalec3_cache_cleanID)
224         and     r2, r0, #0x1f
225         add     r1, r1, r2
226         bic     r0, r0, #0x1f
227
228 1:      mcr     p15, 0, r0, c7, c14, 1  /* Clean and invalidate D cache entry */
229         add     r0, r0, #32
230         subs    r1, r1, #32
231         bhi     1b
232
233         CPWAIT(r0)
234
235         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
236
237         CPWAIT_AND_RETURN(r0)
238 END(xscalec3_cache_purgeD_rng)
239
240 ENTRY(xscalec3_cache_cleanID_rng)
241 ENTRY(xscalec3_cache_cleanD_rng)
242
243         cmp     r1, #0x4000
244         bcs     _C_LABEL(xscalec3_cache_cleanID)
245         and     r2, r0, #0x1f
246         add     r1, r1, r2
247         bic     r0, r0, #0x1f
248
249 1:      mcr     p15, 0, r0, c7, c10, 1  /* clean L1 D cache entry */
250         nop
251         add     r0, r0, #32
252         subs    r1, r1, #32
253         bhi     1b
254
255         CPWAIT(r0)
256
257         mcr     p15, 0, r0, c7, c10, 4  /* drain write buffer */
258
259         CPWAIT_AND_RETURN(r0)
260 END(xscalec3_cache_cleanID_rng)
261 END(xscalec3_cache_cleanD_rng)
262
263 ENTRY(xscalec3_l2cache_purge)
264         /* Clean-up the L2 cache */
265         mcr     p15, 0, r0, c7, c10, 5  /* Data memory barrier */
266         mov     r0, #0
267 1:
268         mov     r1, r0, asl #29
269         mov     r2, #0
270 2:
271         orr     r3, r1, r2, asl #5
272         mcr     p15, 1, r3, c7, c15, 2
273         add     r2, r2, #1
274         cmp     r2, #L2_CACHE_SETS
275         bne     2b
276         add     r0, r0, #1
277         cmp     r0, #8
278         bne     1b
279         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
280
281         CPWAIT(r0)
282         mcr     p15, 0, r0, c7, c10, 5  /* Data memory barrier */
283         RET
284 END(xscalec3_l2cache_purge)
285
286 ENTRY(xscalec3_l2cache_clean_rng)
287         mcr     p15, 0, r0, c7, c10, 5  /* Data memory barrier */
288
289         and     r2, r0, #0x1f
290         add     r1, r1, r2
291         bic     r0, r0, #0x1f
292
293 1:      mcr     p15, 1, r0, c7, c11, 1  /* Clean L2 D cache entry */
294         add     r0, r0, #32
295         subs    r1, r1, #32
296         bhi     1b
297
298
299         CPWAIT(r0)
300
301         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
302         mcr     p15, 0, r0, c7, c10, 5
303
304         CPWAIT_AND_RETURN(r0)
305 END(xscalec3_l2cache_clean_rng)
306
307 ENTRY(xscalec3_l2cache_purge_rng)
308
309         mcr     p15, 0, r0, c7, c10, 5  /* Data memory barrier */
310
311         and     r2, r0, #0x1f
312         add     r1, r1, r2
313         bic     r0, r0, #0x1f
314
315 1:      mcr     p15, 1, r0, c7, c11, 1  /* Clean L2 D cache entry */
316         mcr     p15, 1, r0, c7, c7, 1   /* Invalidate L2 D cache entry */
317         add     r0, r0, #32
318         subs    r1, r1, #32
319         bhi     1b
320
321         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
322         mcr     p15, 0, r0, c7, c10, 5
323
324         CPWAIT_AND_RETURN(r0)
325 END(xscalec3_l2cache_purge_rng)
326
327 ENTRY(xscalec3_l2cache_flush_rng)
328         mcr     p15, 0, r0, c7, c10, 5  /* Data memory barrier */
329
330         and     r2, r0, #0x1f
331         add     r1, r1, r2
332         bic     r0, r0, #0x1f
333
334 1:      mcr     p15, 1, r0, c7, c7, 1   /* Invalidate L2 cache line */
335         add     r0, r0, #32
336         subs    r1, r1, #32
337         bhi     1b
338         mcr     p15, 0, r0, c7, c10, 4          @ data write barrier
339         mcr     p15, 0, r0, c7, c10, 5
340         CPWAIT_AND_RETURN(r0)
341 END(xscalec3_l2cache_flush_rng)
342
343 /*
344  * Functions to set the MMU Translation Table Base register
345  *
346  * We need to clean and flush the cache as it uses virtual
347  * addresses that are about to change.
348  */
349 ENTRY(xscalec3_setttb)
350 #ifdef CACHE_CLEAN_BLOCK_INTR
351         mrs     r3, cpsr_all
352         orr     r1, r3, #(I32_bit | F32_bit)
353         msr     cpsr_all, r1
354 #else
355         ldr     r3, .Lblock_userspace_access
356         ldr     r2, [r3]
357         orr     r1, r2, #1
358         str     r1, [r3]
359 #endif
360         stmfd   sp!, {r0-r3, lr}
361         bl      _C_LABEL(xscalec3_cache_cleanID)
362         mcr     p15, 0, r0, c7, c5, 0   /* invalidate I$ and BTB */
363         mcr     p15, 0, r0, c7, c10, 4  /* drain write and fill buffer */
364
365         CPWAIT(r0)
366
367         ldmfd   sp!, {r0-r3, lr}
368
369 #ifdef ARM_USE_L2_CACHE
370         orr     r0, r0, #0x18   /* cache the page table in L2 */
371 #endif
372         /* Write the TTB */
373         mcr     p15, 0, r0, c2, c0, 0
374
375         /* If we have updated the TTB we must flush the TLB */
376         mcr     p15, 0, r0, c8, c7, 0   /* invalidate I+D TLB */
377
378         CPWAIT(r0)
379
380 #ifdef CACHE_CLEAN_BLOCK_INTR
381         msr     cpsr_all, r3
382 #else
383         str     r2, [r3]
384 #endif
385         RET
386 END(xscalec3_setttb)
387
388 /*
389  * Context switch.
390  *
391  * These is the CPU-specific parts of the context switcher cpu_switch()
392  * These functions actually perform the TTB reload.
393  *
394  * NOTE: Special calling convention
395  *      r1, r4-r13 must be preserved
396  */
397 ENTRY(xscalec3_context_switch)
398         /*
399          * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
400          * Thus the data cache will contain only kernel data and the
401          * instruction cache will contain only kernel code, and all
402          * kernel mappings are shared by all processes.
403          */
404 #ifdef ARM_USE_L2_CACHE
405         orr     r0, r0, #0x18   /* Cache the page table in L2 */
406 #endif
407         /* Write the TTB */
408         mcr     p15, 0, r0, c2, c0, 0
409
410         /* If we have updated the TTB we must flush the TLB */
411         mcr     p15, 0, r0, c8, c7, 0   /* flush the I+D tlb */
412
413         CPWAIT_AND_RETURN(r0)
414 END(xscalec3_context_switch)
415