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