support.S revision 319202
1/*- 2 * Copyright (c) 2014 Andrew Turner 3 * Copyright (c) 2014-2015 The FreeBSD Foundation 4 * All rights reserved. 5 * 6 * Portions of this software were developed by Andrew Turner 7 * under sponsorship from the FreeBSD Foundation 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32#include <machine/asm.h> 33__FBSDID("$FreeBSD: stable/11/sys/arm64/arm64/support.S 319202 2017-05-30 12:26:36Z andrew $"); 34 35#include <machine/setjmp.h> 36#include <machine/param.h> 37#include <machine/vmparam.h> 38 39#include "assym.s" 40 41/* 42 * One of the fu* or su* functions failed, return -1. 43 */ 44ENTRY(fsu_fault) 45 SET_FAULT_HANDLER(xzr, x1) /* Reset the handler function */ 46 EXIT_USER_ACCESS_CHECK(w0, x1) 47fsu_fault_nopcb: 48 mov x0, #-1 49 ret 50END(fsu_fault) 51 52/* 53 * int casueword32(volatile uint32_t *, uint32_t, uint32_t *, uint32_t) 54 */ 55ENTRY(casueword32) 56 ldr x4, =(VM_MAXUSER_ADDRESS-3) 57 cmp x0, x4 58 b.cs fsu_fault_nopcb 59 adr x6, fsu_fault /* Load the fault handler */ 60 SET_FAULT_HANDLER(x6, x4) /* And set it */ 61 ENTER_USER_ACCESS(w6, x4) 621: ldxr w4, [x0] /* Load-exclusive the data */ 63 cmp w4, w1 /* Compare */ 64 b.ne 2f /* Not equal, exit */ 65 stxr w5, w3, [x0] /* Store the new data */ 66 cbnz w5, 1b /* Retry on failure */ 67 EXIT_USER_ACCESS(w6) 682: SET_FAULT_HANDLER(xzr, x5) /* Reset the fault handler */ 69 str w4, [x2] /* Store the read data */ 70 mov x0, #0 /* Success */ 71 ret /* Return */ 72END(casueword32) 73 74/* 75 * int casueword(volatile u_long *, u_long, u_long *, u_long) 76 */ 77ENTRY(casueword) 78 ldr x4, =(VM_MAXUSER_ADDRESS-7) 79 cmp x0, x4 80 b.cs fsu_fault_nopcb 81 adr x6, fsu_fault /* Load the fault handler */ 82 SET_FAULT_HANDLER(x6, x4) /* And set it */ 83 ENTER_USER_ACCESS(w6, x4) 841: ldxr x4, [x0] /* Load-exclusive the data */ 85 cmp x4, x1 /* Compare */ 86 b.ne 2f /* Not equal, exit */ 87 stxr w5, x3, [x0] /* Store the new data */ 88 cbnz w5, 1b /* Retry on failure */ 89 EXIT_USER_ACCESS(w6) 902: SET_FAULT_HANDLER(xzr, x5) /* Reset the fault handler */ 91 str x4, [x2] /* Store the read data */ 92 mov x0, #0 /* Success */ 93 ret /* Return */ 94END(casueword) 95 96/* 97 * int fubyte(volatile const void *) 98 */ 99ENTRY(fubyte) 100 ldr x1, =VM_MAXUSER_ADDRESS 101 cmp x0, x1 102 b.cs fsu_fault_nopcb 103 adr x6, fsu_fault /* Load the fault handler */ 104 SET_FAULT_HANDLER(x6, x1) /* And set it */ 105 ldtrb w0, [x0] /* Try loading the data */ 106 SET_FAULT_HANDLER(xzr, x1) /* Reset the fault handler */ 107 ret /* Return */ 108END(fubyte) 109 110/* 111 * int fuword(volatile const void *) 112 */ 113ENTRY(fuword16) 114 ldr x1, =(VM_MAXUSER_ADDRESS-1) 115 cmp x0, x1 116 b.cs fsu_fault_nopcb 117 adr x6, fsu_fault /* Load the fault handler */ 118 SET_FAULT_HANDLER(x6, x1) /* And set it */ 119 ldtrh w0, [x0] /* Try loading the data */ 120 SET_FAULT_HANDLER(xzr, x1) /* Reset the fault handler */ 121 ret /* Return */ 122END(fuword16) 123 124/* 125 * int32_t fueword32(volatile const void *, int32_t *) 126 */ 127ENTRY(fueword32) 128 ldr x2, =(VM_MAXUSER_ADDRESS-3) 129 cmp x0, x2 130 b.cs fsu_fault_nopcb 131 adr x6, fsu_fault /* Load the fault handler */ 132 SET_FAULT_HANDLER(x6, x2) /* And set it */ 133 ldtr w0, [x0] /* Try loading the data */ 134 SET_FAULT_HANDLER(xzr, x2) /* Reset the fault handler */ 135 str w0, [x1] /* Save the data in kernel space */ 136 mov w0, #0 /* Success */ 137 ret /* Return */ 138END(fueword32) 139 140/* 141 * long fueword(volatile const void *, int64_t *) 142 * int64_t fueword64(volatile const void *, int64_t *) 143 */ 144ENTRY(fueword) 145EENTRY(fueword64) 146 ldr x2, =(VM_MAXUSER_ADDRESS-7) 147 cmp x0, x2 148 b.cs fsu_fault_nopcb 149 adr x6, fsu_fault /* Load the fault handler */ 150 SET_FAULT_HANDLER(x6, x2) /* And set it */ 151 ldtr x0, [x0] /* Try loading the data */ 152 SET_FAULT_HANDLER(xzr, x2) /* Reset the fault handler */ 153 str x0, [x1] /* Save the data in kernel space */ 154 mov x0, #0 /* Success */ 155 ret /* Return */ 156EEND(fueword64) 157END(fueword) 158 159/* 160 * int subyte(volatile void *, int) 161 */ 162ENTRY(subyte) 163 ldr x2, =VM_MAXUSER_ADDRESS 164 cmp x0, x2 165 b.cs fsu_fault_nopcb 166 adr x6, fsu_fault /* Load the fault handler */ 167 SET_FAULT_HANDLER(x6, x2) /* And set it */ 168 sttrb w1, [x0] /* Try storing the data */ 169 SET_FAULT_HANDLER(xzr, x2) /* Reset the fault handler */ 170 mov x0, #0 /* Success */ 171 ret /* Return */ 172END(subyte) 173 174/* 175 * int suword16(volatile void *, int) 176 */ 177ENTRY(suword16) 178 ldr x2, =(VM_MAXUSER_ADDRESS-1) 179 cmp x0, x2 180 b.cs fsu_fault_nopcb 181 adr x6, fsu_fault /* Load the fault handler */ 182 SET_FAULT_HANDLER(x6, x2) /* And set it */ 183 sttrh w1, [x0] /* Try storing the data */ 184 SET_FAULT_HANDLER(xzr, x2) /* Reset the fault handler */ 185 mov x0, #0 /* Success */ 186 ret /* Return */ 187END(suword16) 188 189/* 190 * int suword32(volatile void *, int) 191 */ 192ENTRY(suword32) 193 ldr x2, =(VM_MAXUSER_ADDRESS-3) 194 cmp x0, x2 195 b.cs fsu_fault_nopcb 196 adr x6, fsu_fault /* Load the fault handler */ 197 SET_FAULT_HANDLER(x6, x2) /* And set it */ 198 sttr w1, [x0] /* Try storing the data */ 199 SET_FAULT_HANDLER(xzr, x2) /* Reset the fault handler */ 200 mov x0, #0 /* Success */ 201 ret /* Return */ 202END(suword32) 203 204/* 205 * int suword(volatile void *, long) 206 */ 207ENTRY(suword) 208EENTRY(suword64) 209 ldr x2, =(VM_MAXUSER_ADDRESS-7) 210 cmp x0, x2 211 b.cs fsu_fault_nopcb 212 adr x6, fsu_fault /* Load the fault handler */ 213 SET_FAULT_HANDLER(x6, x2) /* And set it */ 214 sttr x1, [x0] /* Try storing the data */ 215 SET_FAULT_HANDLER(xzr, x2) /* Reset the fault handler */ 216 mov x0, #0 /* Success */ 217 ret /* Return */ 218EEND(suword64) 219END(suword) 220 221/* 222 * fuswintr and suswintr are just like fusword and susword except that if 223 * the page is not in memory or would cause a trap, then we return an error. 224 * The important thing is to prevent sleep() and switch(). 225 */ 226 227/* 228 * Special handler so the trap code knows not to sleep. 229 */ 230ENTRY(fsu_intr_fault) 231 SET_FAULT_HANDLER(xzr, x1) /* Reset the handler function */ 232 EXIT_USER_ACCESS_CHECK(w0, x1) 233 mov x0, #-1 234 ret 235END(fsu_fault) 236 237/* 238 * int fuswintr(void *) 239 */ 240ENTRY(fuswintr) 241 ldr x1, =(VM_MAXUSER_ADDRESS-3) 242 cmp x0, x1 243 b.cs fsu_fault_nopcb 244 adr x6, fsu_intr_fault /* Load the fault handler */ 245 SET_FAULT_HANDLER(x6, x1) /* And set it */ 246 ldtr w0, [x0] /* Try loading the data */ 247 SET_FAULT_HANDLER(xzr, x1) /* Reset the fault handler */ 248 ret /* Return */ 249END(fuswintr) 250 251/* 252 * int suswintr(void *base, int word) 253 */ 254ENTRY(suswintr) 255 ldr x2, =(VM_MAXUSER_ADDRESS-3) 256 cmp x0, x2 257 b.cs fsu_fault_nopcb 258 adr x6, fsu_intr_fault /* Load the fault handler */ 259 SET_FAULT_HANDLER(x6, x2) /* And set it */ 260 sttr w1, [x0] /* Try storing the data */ 261 SET_FAULT_HANDLER(xzr, x2) /* Reset the fault handler */ 262 mov x0, #0 /* Success */ 263 ret /* Return */ 264END(suswintr) 265 266ENTRY(setjmp) 267 /* Store the stack pointer */ 268 mov x8, sp 269 str x8, [x0], #8 270 271 /* Store the general purpose registers and lr */ 272 stp x19, x20, [x0], #16 273 stp x21, x22, [x0], #16 274 stp x23, x24, [x0], #16 275 stp x25, x26, [x0], #16 276 stp x27, x28, [x0], #16 277 stp x29, lr, [x0], #16 278 279 /* Return value */ 280 mov x0, #0 281 ret 282END(setjmp) 283 284ENTRY(longjmp) 285 /* Restore the stack pointer */ 286 ldr x8, [x0], #8 287 mov sp, x8 288 289 /* Restore the general purpose registers and lr */ 290 ldp x19, x20, [x0], #16 291 ldp x21, x22, [x0], #16 292 ldp x23, x24, [x0], #16 293 ldp x25, x26, [x0], #16 294 ldp x27, x28, [x0], #16 295 ldp x29, lr, [x0], #16 296 297 /* Load the return value */ 298 mov x0, x1 299 ret 300END(longjmp) 301 302/* 303 * pagezero, simple implementation 304 */ 305ENTRY(pagezero_simple) 306 add x1, x0, #PAGE_SIZE 307 3081: 309 stp xzr, xzr, [x0], #0x10 310 stp xzr, xzr, [x0], #0x10 311 stp xzr, xzr, [x0], #0x10 312 stp xzr, xzr, [x0], #0x10 313 cmp x0, x1 314 b.ne 1b 315 ret 316 317END(pagezero_simple) 318 319/* 320 * pagezero, cache assisted 321 */ 322ENTRY(pagezero_cache) 323 add x1, x0, #PAGE_SIZE 324 325 ldr x2, =dczva_line_size 326 ldr x2, [x2] 327 3281: 329 dc zva, x0 330 add x0, x0, x2 331 cmp x0, x1 332 b.ne 1b 333 ret 334 335END(pagezero_cache) 336