cpufunc_asm_armv8.S revision 1.8 1 /* $NetBSD: cpufunc_asm_armv8.S,v 1.8 2021/02/11 08:35:11 ryo Exp $ */
2
3 /*-
4 * Copyright (c) 2014 Robin Randhawa
5 * Copyright (c) 2015 The FreeBSD Foundation
6 * All rights reserved.
7 *
8 * Portions of this software were developed by Andrew Turner
9 * under sponsorship from the FreeBSD Foundation
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE 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 THE 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 * $FreeBSD: head/sys/arm64/arm64/cpufunc_asm.S 313347 2017-02-06 17:50:09Z andrew $
33 */
34
35 #include "opt_cputypes.h"
36 #include "opt_gprof.h"
37 #include "opt_multiprocessor.h"
38 #include <aarch64/asm.h>
39
40 .text
41 .align 2
42
43 /*
44 * Macro to handle the cache. This takes the start address in x0, length
45 * in x1. It will corrupt x2-x5.
46 */
47 .macro cache_handle_range dcop = "", icop = ""
48 mrs x3, ctr_el0
49 mov x4, #4 /* size of word */
50 .ifnb \dcop
51 ubfx x2, x3, #16, #4 /* x2 = D cache shift */
52 lsl x2, x4, x2 /* x2 = D cache line size */
53 .endif
54 .ifnb \icop
55 and x3, x3, #15 /* x3 = I cache shift */
56 lsl x3, x4, x3 /* x3 = I cache line size */
57 .endif
58 .ifnb \dcop
59 sub x4, x2, #1 /* Get the address mask */
60 and x4, x0, x4 /* Get the low bits of the address */
61 add x5, x1, x4 /* Add these to the size */
62 bic x4, x0, x4 /* Clear the low bit of the address */
63 1:
64 dc \dcop, x4
65 add x4, x4, x2 /* Move to the next line */
66 subs x5, x5, x2 /* Reduce the size */
67 b.hi 1b /* Check if we are done */
68 dsb ish
69 .endif
70 .ifnb \icop
71 sub x4, x3, #1 /* Get the address mask */
72 and x4, x0, x4 /* Get the low bits of the address */
73 add x5, x1, x4 /* Add these to the size */
74 bic x4, x0, x4 /* Clear the low bit of the address */
75 1:
76 ic \icop, x4
77 add x4, x4, x3 /* Move to the next line */
78 subs x5, x5, x3 /* Reduce the size */
79 b.hi 1b /* Check if we are done */
80 dsb ish
81 isb
82 .endif
83 .endm
84
85
86 ENTRY(aarch64_nullop)
87 ret
88 END(aarch64_nullop)
89
90 ENTRY(aarch64_cpuid)
91 mrs x0, midr_el1
92 ret
93 END(aarch64_cpuid)
94
95 /*
96 * void aarch64_dcache_wb_range(vaddr_t, vsize_t)
97 */
98 ENTRY(aarch64_dcache_wb_range)
99 cache_handle_range dcop = cvac
100 ret
101 END(aarch64_dcache_wb_range)
102
103 /*
104 * void aarch64_dcache_wbinv_range(vaddr_t, vsize_t)
105 */
106 ENTRY(aarch64_dcache_wbinv_range)
107 cache_handle_range dcop = civac
108 ret
109 END(aarch64_dcache_wbinv_range)
110
111 /*
112 * void aarch64_dcache_inv_range(vaddr_t, vsize_t)
113 *
114 * Note, we must not invalidate everything. If the range is too big we
115 * must use wb-inv of the entire cache.
116 */
117 ENTRY(aarch64_dcache_inv_range)
118 cache_handle_range dcop = ivac
119 ret
120 END(aarch64_dcache_inv_range)
121
122 /*
123 * void aarch64_idcache_wbinv_range(vaddr_t, vsize_t)
124 */
125 ENTRY(aarch64_idcache_wbinv_range)
126 cache_handle_range dcop = civac, icop = ivau
127 ret
128 END(aarch64_idcache_wbinv_range)
129
130 /*
131 * void aarch64_icache_sync_range(vaddr_t, vsize_t)
132 */
133 ENTRY(aarch64_icache_sync_range)
134 cache_handle_range dcop = cvau, icop = ivau
135 ret
136 END(aarch64_icache_sync_range)
137
138 /*
139 * void aarch64_icache_inv_range(vaddr_t, vsize_t)
140 */
141 ENTRY(aarch64_icache_inv_range)
142 cache_handle_range icop = ivau
143 ret
144 END(aarch64_icache_inv_range)
145
146 /*
147 * void aarch64_icache_barrier_range(vaddr_t, vsize_t)
148 */
149 ENTRY(aarch64_icache_barrier_range)
150 dsb ishst
151 isb
152 ret
153 END(aarch64_icache_barrier_range)
154
155 /*
156 * void aarch64_icache_inv_all(void)
157 */
158 ENTRY(aarch64_icache_inv_all)
159 dsb ish
160 #ifdef MULTIPROCESSOR
161 ic ialluis
162 #else
163 ic iallu
164 #endif
165 dsb ish
166 isb
167 ret
168 END(aarch64_icache_inv_all)
169
170
171
172 ENTRY(aarch64_drain_writebuf)
173 dsb sy
174 ret
175 END(aarch64_drain_writebuf)
176
177
178 /*
179 * TLB ops
180 */
181
182 /* void aarch64_set_ttbr0(uint64_t ttbr0) */
183 ENTRY(aarch64_set_ttbr0)
184 dsb ish
185 msr ttbr0_el1, x0
186 dsb ish
187 isb
188 ret
189 END(aarch64_set_ttbr0)
190
191 #ifdef CPU_THUNDERX
192 /*
193 * Cavium erratum 27456
194 * void aarch64_set_ttbr0_thunderx(uint64_t ttbr0)
195 */
196 ENTRY(aarch64_set_ttbr0_thunderx)
197 dsb ish
198 msr ttbr0_el1, x0
199 isb
200 ic iallu
201 dsb nsh
202 isb
203 ret
204 END(aarch64_set_ttbr0_thunderx)
205 #endif /* CPU_THUNDERX */
206
207 /* void aarch64_tlbi_all(void) */
208 ENTRY(aarch64_tlbi_all)
209 dsb ishst
210 #ifdef MULTIPROCESSOR
211 tlbi vmalle1is
212 #else
213 tlbi vmalle1
214 #endif
215 dsb ish
216 isb
217 ret
218 END(aarch64_tlbi_all)
219
220 /* void aarch64_tlbi_by_asid(int asid) */
221 ENTRY(aarch64_tlbi_by_asid)
222 /* x8 = bit 63[ASID]48, 47[RES0]0 */
223 lsl x8, x0, #48
224 dsb ishst
225 #ifdef MULTIPROCESSOR
226 tlbi aside1is, x8
227 #else
228 tlbi aside1, x8
229 #endif
230 dsb ish
231 isb
232 ret
233 END(aarch64_tlbi_by_asid)
234
235 /* aarch64_tlbi_by_va(vaddr_t va) */
236 ENTRY(aarch64_tlbi_by_va)
237 /* x8 = bit 63[RES0]44, 43[VA(55:12)]0 */
238 ubfx x8, x0, #12, #44
239 dsb ishst
240 #ifdef MULTIPROCESSOR
241 tlbi vaae1is, x8
242 #else
243 tlbi vaae1, x8
244 #endif
245 dsb ish
246 isb
247 ret
248 END(aarch64_tlbi_by_va)
249
250 /* aarch64_tlbi_by_va_ll(vaddr_t va) */
251 ENTRY(aarch64_tlbi_by_va_ll)
252 /* x8 = bit 63[RES0]44, 43[VA(55:12)]0 */
253 ubfx x8, x0, #12, #44
254 dsb ishst
255 #ifdef MULTIPROCESSOR
256 tlbi vaale1is, x8
257 #else
258 tlbi vaale1, x8
259 #endif
260 dsb ish
261 isb
262 ret
263 END(aarch64_tlbi_by_va_ll)
264
265 /* aarch64_tlbi_by_asid_va(int asid, vaddr_t va) */
266 ENTRY(aarch64_tlbi_by_asid_va)
267 /* x8 = bit 63[ASID]48, 47[RES0]44, 43[VA(55:12)]0 */
268 lsl x8, x0, #48
269 bfxil x8, x1, #12, #44
270 dsb ishst
271 #ifdef MULTIPROCESSOR
272 tlbi vae1is, x8
273 #else
274 tlbi vae1, x8
275 #endif
276 dsb ish
277 isb
278 ret
279 END(aarch64_tlbi_by_asid_va)
280
281 /* aarch64_tlbi_by_asid_va_ll(int asid, vaddr_t va) */
282 ENTRY(aarch64_tlbi_by_asid_va_ll)
283 /* x8 = bit 63[ASID]48, 47[RES0]44, 43[VA(55:12)]0 */
284 lsl x8, x0, #48
285 bfxil x8, x1, #12, #44
286 dsb ishst
287 #ifdef MULTIPROCESSOR
288 tlbi vale1is, x8
289 #else
290 tlbi vale1, x8
291 #endif
292 dsb ish
293 isb
294 ret
295 END(aarch64_tlbi_by_asid_va_ll)
296