]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/arm/arm/cpufunc_asm_armv7.S
MFC r278770, r279114, r279215, r279338, r279543:
[FreeBSD/stable/10.git] / sys / arm / arm / cpufunc_asm_armv7.S
1 /*-
2  * Copyright (c) 2010 Per Odlund <per.odlund@armagedon.se>
3  * Copyright (C) 2011 MARVELL INTERNATIONAL LTD.
4  * All rights reserved.
5  *
6  * Developed by Semihalf.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
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. Neither the name of MARVELL nor the names of contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #include <machine/asm.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <machine/sysreg.h>
37
38         .cpu cortex-a8
39
40 .Lcoherency_level:
41         .word   _C_LABEL(arm_cache_loc)
42 .Lcache_type:
43         .word   _C_LABEL(arm_cache_type)
44 .Lway_mask:
45         .word   0x3ff
46 .Lmax_index:
47         .word   0x7fff
48 .Lpage_mask:
49         .word   0xfff
50
51 #define PT_NOS          (1 << 5)
52 #define PT_S            (1 << 1)
53 #define PT_INNER_NC     0
54 #define PT_INNER_WT     (1 << 0)
55 #define PT_INNER_WB     ((1 << 0) | (1 << 6))
56 #define PT_INNER_WBWA   (1 << 6)
57 #define PT_OUTER_NC     0
58 #define PT_OUTER_WT     (2 << 3)
59 #define PT_OUTER_WB     (3 << 3)
60 #define PT_OUTER_WBWA   (1 << 3)
61         
62 #ifdef SMP
63 #define PT_ATTR (PT_S|PT_INNER_WBWA|PT_OUTER_WBWA|PT_NOS)
64 #else
65 #define PT_ATTR (PT_INNER_WBWA|PT_OUTER_WBWA)
66 #endif
67
68 ENTRY(armv7_setttb)
69         dsb
70         orr     r0, r0, #PT_ATTR
71         mcr     CP15_TTBR0(r0)
72         isb
73 #ifdef SMP
74         mcr     CP15_TLBIALLIS
75 #else
76         mcr     CP15_TLBIALL
77 #endif
78         dsb
79         isb
80         RET
81 END(armv7_setttb)
82
83 ENTRY(armv7_tlb_flushID)
84         dsb
85 #ifdef SMP
86         mcr     CP15_TLBIALLIS
87         mcr     CP15_BPIALLIS
88 #else
89         mcr     CP15_TLBIALL
90         mcr     CP15_BPIALL
91 #endif
92         dsb
93         isb
94         mov     pc, lr
95 END(armv7_tlb_flushID)
96
97 ENTRY(armv7_tlb_flushID_SE)
98         ldr     r1, .Lpage_mask
99         bic     r0, r0, r1
100 #ifdef SMP
101         mcr     CP15_TLBIMVAAIS(r0)
102         mcr     CP15_BPIALLIS
103 #else
104         mcr     CP15_TLBIMVA(r0)
105         mcr     CP15_BPIALL
106 #endif
107         dsb
108         isb
109         mov     pc, lr
110 END(armv7_tlb_flushID_SE)
111
112 /* Based on algorithm from ARM Architecture Reference Manual */
113 ENTRY(armv7_dcache_wbinv_all)
114         stmdb   sp!, {r4, r5, r6, r7, r8, r9}
115
116         /* Get cache level */
117         ldr     r0, .Lcoherency_level
118         ldr     r3, [r0]
119         cmp     r3, #0
120         beq     Finished
121         /* For each cache level */
122         mov     r8, #0
123 Loop1:
124         /* Get cache type for given level */
125         mov     r2, r8, lsl #2
126         add     r2, r2, r2
127         ldr     r0, .Lcache_type
128         ldr     r1, [r0, r2]
129
130         /* Get line size */
131         and     r2, r1, #7
132         add     r2, r2, #4
133
134         /* Get number of ways */
135         ldr     r4, .Lway_mask
136         ands    r4, r4, r1, lsr #3
137         clz     r5, r4
138
139         /* Get max index */
140         ldr     r7, .Lmax_index
141         ands    r7, r7, r1, lsr #13
142 Loop2:
143         mov     r9, r4
144 Loop3:
145         mov     r6, r8, lsl #1
146         orr     r6, r6, r9, lsl r5
147         orr     r6, r6, r7, lsl r2
148
149         /* Clean and invalidate data cache by way/index */
150         mcr     CP15_DCCISW(r6)
151         subs    r9, r9, #1
152         bge     Loop3
153         subs    r7, r7, #1
154         bge     Loop2
155 Skip:
156         add     r8, r8, #1
157         cmp     r3, r8
158         bne Loop1
159 Finished:
160         dsb
161         ldmia   sp!, {r4, r5, r6, r7, r8, r9}
162         RET
163 END(armv7_dcache_wbinv_all)
164
165 ENTRY(armv7_idcache_wbinv_all)
166         stmdb   sp!, {lr}
167         bl armv7_dcache_wbinv_all
168 #ifdef SMP
169         mcr     CP15_ICIALLUIS
170 #else
171         mcr     CP15_ICIALLU
172 #endif
173         dsb
174         isb
175         ldmia   sp!, {lr}
176         RET
177 END(armv7_idcache_wbinv_all)
178
179 /* XXX Temporary set it to 32 for MV cores, however this value should be
180  * get from Cache Type register
181  */
182 .Larmv7_line_size:
183         .word   32
184
185 ENTRY(armv7_dcache_wb_range)
186         ldr     ip, .Larmv7_line_size
187         sub     r3, ip, #1
188         and     r2, r0, r3
189         add     r1, r1, r2
190         bic     r0, r0, r3
191 .Larmv7_wb_next:
192         mcr     CP15_DCCMVAC(r0)
193         add     r0, r0, ip
194         subs    r1, r1, ip
195         bhi     .Larmv7_wb_next
196         dsb                             /* data synchronization barrier */
197         RET
198 END(armv7_dcache_wb_range)
199
200 ENTRY(armv7_dcache_wbinv_range)
201         ldr     ip, .Larmv7_line_size
202         sub     r3, ip, #1
203         and     r2, r0, r3
204         add     r1, r1, r2
205         bic     r0, r0, r3
206 .Larmv7_wbinv_next:
207         mcr     CP15_DCCIMVAC(r0)
208         add     r0, r0, ip
209         subs    r1, r1, ip
210         bhi     .Larmv7_wbinv_next
211         dsb                             /* data synchronization barrier */
212         RET
213 END(armv7_dcache_wbinv_range)
214
215 /*
216  * Note, we must not invalidate everything.  If the range is too big we
217  * must use wb-inv of the entire cache.
218  */
219 ENTRY(armv7_dcache_inv_range)
220         ldr     ip, .Larmv7_line_size
221         sub     r3, ip, #1
222         and     r2, r0, r3
223         add     r1, r1, r2
224         bic     r0, r0, r3
225 .Larmv7_inv_next:
226         mcr     CP15_DCIMVAC(r0)
227         add     r0, r0, ip
228         subs    r1, r1, ip
229         bhi     .Larmv7_inv_next
230         dsb                             /* data synchronization barrier */
231         RET
232 END(armv7_dcache_inv_range)
233
234 ENTRY(armv7_idcache_wbinv_range)
235         ldr     ip, .Larmv7_line_size
236         sub     r3, ip, #1
237         and     r2, r0, r3
238         add     r1, r1, r2
239         bic     r0, r0, r3
240 .Larmv7_id_wbinv_next:
241         mcr     CP15_ICIMVAU(r0)
242         mcr     CP15_DCCIMVAC(r0)
243         add     r0, r0, ip
244         subs    r1, r1, ip
245         bhi     .Larmv7_id_wbinv_next
246         isb                             /* instruction synchronization barrier */
247         dsb                             /* data synchronization barrier */
248         RET
249 END(armv7_idcache_wbinv_range)
250
251 ENTRY_NP(armv7_icache_sync_all)
252 #ifdef SMP
253         mcr     CP15_ICIALLUIS
254 #else
255         mcr     CP15_ICIALLU
256 #endif
257         isb                             /* instruction synchronization barrier */
258         dsb                             /* data synchronization barrier */
259         RET
260 END(armv7_icache_sync_all)
261
262 ENTRY_NP(armv7_icache_sync_range)
263         ldr     ip, .Larmv7_line_size
264 .Larmv7_sync_next:
265         mcr     CP15_ICIMVAU(r0)
266         mcr     CP15_DCCMVAC(r0)
267         add     r0, r0, ip
268         subs    r1, r1, ip
269         bhi     .Larmv7_sync_next
270         isb                             /* instruction synchronization barrier */
271         dsb                             /* data synchronization barrier */
272         RET
273 END(armv7_icache_sync_range)
274
275 ENTRY(armv7_cpu_sleep)
276         dsb                             /* data synchronization barrier */
277         wfi                             /* wait for interrupt */
278         RET
279 END(armv7_cpu_sleep)
280
281 ENTRY(armv7_context_switch)
282         dsb
283         orr     r0, r0, #PT_ATTR
284
285         mcr     CP15_TTBR0(r0)
286         isb
287 #ifdef SMP
288         mcr     CP15_TLBIALLIS
289 #else
290         mcr     CP15_TLBIALL
291 #endif
292         dsb
293         isb
294         RET
295 END(armv7_context_switch)
296
297 ENTRY(armv7_drain_writebuf)
298         dsb
299         RET
300 END(armv7_drain_writebuf)
301
302 ENTRY(armv7_sev)
303         dsb
304         sev
305         nop
306         RET
307 END(armv7_sev)
308
309 ENTRY(armv7_auxctrl)
310         mrc     CP15_ACTLR(r2)
311         bic r3, r2, r0  /* Clear bits */
312         eor r3, r3, r1  /* XOR bits */
313
314         teq r2, r3
315         mcrne   CP15_ACTLR(r3)
316         mov r0, r2
317         RET
318 END(armv7_auxctrl)
319
320 /*
321  * Invalidate all I+D+branch cache.  Used by startup code, which counts
322  * on the fact that only r0-r3,ip are modified and no stack space is used.
323  */
324 ENTRY(armv7_idcache_inv_all)
325         mov     r0, #0
326         mcr     CP15_CSSELR(r0)         @ set cache level to L1
327         mrc     CP15_CCSIDR(r0)
328
329         ubfx    r2, r0, #13, #15        @ get num sets - 1 from CCSIDR
330         ubfx    r3, r0, #3, #10         @ get numways - 1 from CCSIDR
331         clz     r1, r3                  @ number of bits to MSB of way
332         lsl     r3, r3, r1              @ shift into position
333         mov     ip, #1                  @
334         lsl     ip, ip, r1              @ ip now contains the way decr
335
336         ubfx    r0, r0, #0, #3          @ get linesize from CCSIDR
337         add     r0, r0, #4              @ apply bias
338         lsl     r2, r2, r0              @ shift sets by log2(linesize)
339         add     r3, r3, r2              @ merge numsets - 1 with numways - 1
340         sub     ip, ip, r2              @ subtract numsets - 1 from way decr
341         mov     r1, #1
342         lsl     r1, r1, r0              @ r1 now contains the set decr
343         mov     r2, ip                  @ r2 now contains set way decr
344
345         /* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */
346 1:      mcr     CP15_DCISW(r3)          @ invalidate line
347         movs    r0, r3                  @ get current way/set
348         beq     2f                      @ at 0 means we are done.
349         movs    r0, r0, lsl #10         @ clear way bits leaving only set bits
350         subne   r3, r3, r1              @ non-zero?, decrement set #
351         subeq   r3, r3, r2              @ zero?, decrement way # and restore set count
352         b       1b
353
354 2:      dsb                             @ wait for stores to finish
355         mov     r0, #0                  @ and ...
356         mcr     CP15_ICIALLU            @ invalidate instruction+branch cache
357         isb                             @ instruction sync barrier
358         bx      lr                      @ return
359 END(armv7_idcache_inv_all)
360
361 ENTRY_NP(armv7_sleep)
362         dsb
363         wfi
364         bx      lr
365 END(armv7_sleep)
366