| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: trap.c,v 1.1 2014/08/10 05:47:37 matt Exp $ */ | | 1 | /* $NetBSD: trap.c,v 1.2 2017/08/16 22:48:11 nisimura Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Matt Thomas of 3am Software Foundry. | | 8 | * by Matt Thomas of 3am Software Foundry. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -21,27 +21,314 @@ | | | @@ -21,27 +21,314 @@ |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | | | 33 | |
34 | __KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.1 2014/08/10 05:47:37 matt Exp $"); | | 34 | __KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.2 2017/08/16 22:48:11 nisimura Exp $"); |
35 | | | 35 | |
36 | #include <sys/param.h> | | 36 | #include <sys/param.h> |
37 | #include <sys/types.h> | | 37 | #include <sys/types.h> |
38 | #include <sys/cpu.h> | | 38 | #include <sys/cpu.h> |
39 | #include <sys/userret.h> | | 39 | #include <sys/userret.h> |
40 | | | 40 | |
41 | #include <aarch64/locore.h> | | 41 | #include <aarch64/locore.h> |
42 | | | 42 | |
43 | void | | 43 | void |
44 | userret(struct lwp *l, struct trapframe *tf) | | 44 | userret(struct lwp *l, struct trapframe *tf) |
45 | { | | 45 | { |
46 | mi_userret(l); | | 46 | mi_userret(l); |
47 | } | | 47 | } |
| | | 48 | |
| | | 49 | // XXXAARCH64 might be populated in frame.h in future |
| | | 50 | |
| | | 51 | #define FB_X19 0 |
| | | 52 | #define FB_X20 1 |
| | | 53 | #define FB_X21 2 |
| | | 54 | #define FB_X22 3 |
| | | 55 | #define FB_X23 4 |
| | | 56 | #define FB_X24 5 |
| | | 57 | #define FB_X25 6 |
| | | 58 | #define FB_X26 7 |
| | | 59 | #define FB_X27 8 |
| | | 60 | #define FB_X28 9 |
| | | 61 | #define FB_X29 10 |
| | | 62 | #define FB_SP 11 |
| | | 63 | #define FB_LR 12 |
| | | 64 | #define FB_V0 13 |
| | | 65 | #define FB_MAX 14 |
| | | 66 | |
| | | 67 | struct faultbuf { |
| | | 68 | register_t fb_reg[FB_MAX]; |
| | | 69 | }; |
| | | 70 | |
| | | 71 | int cpu_set_onfault(struct faultbuf *, register_t) __returns_twice; |
| | | 72 | void cpu_jump_onfault(struct trapframe *, const struct faultbuf *); |
| | | 73 | void cpu_unset_onfault(void); |
| | | 74 | struct faultbuf *cpu_disable_onfault(void); |
| | | 75 | void cpu_enable_onfault(struct faultbuf *); |
| | | 76 | |
| | | 77 | void |
| | | 78 | cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb) |
| | | 79 | { |
| | | 80 | |
| | | 81 | tf->tf_reg[19] = fb->fb_reg[FB_X19]; |
| | | 82 | tf->tf_reg[20] = fb->fb_reg[FB_X20]; |
| | | 83 | tf->tf_reg[21] = fb->fb_reg[FB_X21]; |
| | | 84 | tf->tf_reg[22] = fb->fb_reg[FB_X22]; |
| | | 85 | tf->tf_reg[23] = fb->fb_reg[FB_X23]; |
| | | 86 | tf->tf_reg[24] = fb->fb_reg[FB_X24]; |
| | | 87 | tf->tf_reg[25] = fb->fb_reg[FB_X25]; |
| | | 88 | tf->tf_reg[26] = fb->fb_reg[FB_X26]; |
| | | 89 | tf->tf_reg[27] = fb->fb_reg[FB_X27]; |
| | | 90 | tf->tf_reg[28] = fb->fb_reg[FB_X28]; |
| | | 91 | tf->tf_reg[29] = fb->fb_reg[FB_X29]; |
| | | 92 | tf->tf_reg[0] = fb->fb_reg[FB_V0]; |
| | | 93 | tf->tf_sp = fb->fb_reg[FB_SP]; |
| | | 94 | tf->tf_lr = fb->fb_reg[FB_LR]; |
| | | 95 | } |
| | | 96 | |
| | | 97 | void |
| | | 98 | cpu_unset_onfault(void) |
| | | 99 | { |
| | | 100 | |
| | | 101 | curlwp->l_md.md_onfault = NULL; |
| | | 102 | } |
| | | 103 | |
| | | 104 | struct faultbuf * |
| | | 105 | cpu_disable_onfault(void) |
| | | 106 | { |
| | | 107 | struct faultbuf * const fb = curlwp->l_md.md_onfault; |
| | | 108 | |
| | | 109 | curlwp->l_md.md_onfault = NULL; |
| | | 110 | return fb; |
| | | 111 | } |
| | | 112 | |
| | | 113 | void |
| | | 114 | cpu_enable_onfault(struct faultbuf *fb) |
| | | 115 | { |
| | | 116 | |
| | | 117 | curlwp->l_md.md_onfault = NULL; |
| | | 118 | } |
| | | 119 | |
| | | 120 | /* |
| | | 121 | * kcopy(9) |
| | | 122 | * int kcopy(const void *src, void *dst, size_t len); |
| | | 123 | * |
| | | 124 | * copy(9) |
| | | 125 | * int copyin(const void *uaddr, void *kaddr, size_t len); |
| | | 126 | * int copyout(const void *kaddr, void *uaddr, size_t len); |
| | | 127 | * int copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done); |
| | | 128 | * int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done); |
| | | 129 | * int copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done); |
| | | 130 | */ |
| | | 131 | |
| | | 132 | int |
| | | 133 | kcopy(const void *kfaddr, void *kdaddr, size_t len) |
| | | 134 | { |
| | | 135 | struct faultbuf fb; |
| | | 136 | int error; |
| | | 137 | |
| | | 138 | if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) { |
| | | 139 | memcpy(kdaddr, kfaddr, len); |
| | | 140 | cpu_unset_onfault(); |
| | | 141 | } |
| | | 142 | return error; |
| | | 143 | } |
| | | 144 | |
| | | 145 | int |
| | | 146 | copyin(const void *uaddr, void *kaddr, size_t len) |
| | | 147 | { |
| | | 148 | struct faultbuf fb; |
| | | 149 | int error; |
| | | 150 | |
| | | 151 | if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) { |
| | | 152 | memcpy(kaddr, uaddr, len); |
| | | 153 | cpu_unset_onfault(); |
| | | 154 | } |
| | | 155 | return error; |
| | | 156 | } |
| | | 157 | |
| | | 158 | int |
| | | 159 | copyout(const void *kaddr, void *uaddr, size_t len) |
| | | 160 | { |
| | | 161 | struct faultbuf fb; |
| | | 162 | int error; |
| | | 163 | |
| | | 164 | if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) { |
| | | 165 | memcpy(uaddr, kaddr, len); |
| | | 166 | cpu_unset_onfault(); |
| | | 167 | } |
| | | 168 | return error; |
| | | 169 | } |
| | | 170 | |
| | | 171 | int |
| | | 172 | copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done) |
| | | 173 | { |
| | | 174 | struct faultbuf fb; |
| | | 175 | int error; |
| | | 176 | |
| | | 177 | if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) { |
| | | 178 | len = strlcpy(kdaddr, kfaddr, len); |
| | | 179 | cpu_unset_onfault(); |
| | | 180 | if (done != NULL) { |
| | | 181 | *done = len; |
| | | 182 | } |
| | | 183 | } |
| | | 184 | return error; |
| | | 185 | } |
| | | 186 | |
| | | 187 | int |
| | | 188 | copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) |
| | | 189 | { |
| | | 190 | struct faultbuf fb; |
| | | 191 | int error; |
| | | 192 | |
| | | 193 | if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) { |
| | | 194 | len = strlcpy(kaddr, uaddr, len); |
| | | 195 | cpu_unset_onfault(); |
| | | 196 | if (done != NULL) { |
| | | 197 | *done = len; |
| | | 198 | } |
| | | 199 | } |
| | | 200 | return error; |
| | | 201 | } |
| | | 202 | |
| | | 203 | int |
| | | 204 | copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done) |
| | | 205 | { |
| | | 206 | struct faultbuf fb; |
| | | 207 | int error; |
| | | 208 | |
| | | 209 | if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) { |
| | | 210 | len = strlcpy(uaddr, kaddr, len); |
| | | 211 | cpu_unset_onfault(); |
| | | 212 | if (done != NULL) { |
| | | 213 | *done = len; |
| | | 214 | } |
| | | 215 | } |
| | | 216 | return error; |
| | | 217 | } |
| | | 218 | |
| | | 219 | /* |
| | | 220 | * fetch(9) |
| | | 221 | * int fubyte(const void *base); |
| | | 222 | * int fusword(const void *base); |
| | | 223 | * int fuswintr(const void *base); |
| | | 224 | * long fuword(const void *base); |
| | | 225 | * |
| | | 226 | * store(9) |
| | | 227 | * int subyte(void *base, int c); |
| | | 228 | * int susword(void *base, short c); |
| | | 229 | * int suswintr(void *base, short c); |
| | | 230 | * int suword(void *base, long c); |
| | | 231 | */ |
| | | 232 | |
| | | 233 | union xubuf { |
| | | 234 | uint8_t b[4]; |
| | | 235 | uint16_t w[2]; |
| | | 236 | uint32_t l[1]; |
| | | 237 | }; |
| | | 238 | |
| | | 239 | static bool |
| | | 240 | fetch_user_data(union xubuf *xu, const void *base, size_t len) |
| | | 241 | { |
| | | 242 | struct faultbuf fb; |
| | | 243 | |
| | | 244 | if (cpu_set_onfault(&fb, 1) == 0) { |
| | | 245 | memcpy(xu->b, base, len); |
| | | 246 | cpu_unset_onfault(); |
| | | 247 | return true; |
| | | 248 | } |
| | | 249 | return false; |
| | | 250 | } |
| | | 251 | |
| | | 252 | int |
| | | 253 | fubyte(const void *base) |
| | | 254 | { |
| | | 255 | union xubuf xu; |
| | | 256 | |
| | | 257 | if (fetch_user_data(&xu, base, sizeof(xu.b[0]))) |
| | | 258 | return xu.b[0]; |
| | | 259 | return -1; |
| | | 260 | } |
| | | 261 | |
| | | 262 | int |
| | | 263 | fusword(const void *base) |
| | | 264 | { |
| | | 265 | union xubuf xu; |
| | | 266 | |
| | | 267 | if (fetch_user_data(&xu, base, sizeof(xu.w[0]))) |
| | | 268 | return xu.w[0]; |
| | | 269 | return -1; |
| | | 270 | } |
| | | 271 | |
| | | 272 | int |
| | | 273 | fuswintr(const void *base) |
| | | 274 | { |
| | | 275 | |
| | | 276 | return -1; |
| | | 277 | } |
| | | 278 | |
| | | 279 | long |
| | | 280 | fuword(const void *base) |
| | | 281 | { |
| | | 282 | union xubuf xu; |
| | | 283 | |
| | | 284 | if (fetch_user_data(&xu, base, sizeof(xu.l[0]))) |
| | | 285 | return xu.l[0]; |
| | | 286 | return -1; |
| | | 287 | } |
| | | 288 | |
| | | 289 | static bool |
| | | 290 | store_user_data(void *base, const union xubuf *xu, size_t len) |
| | | 291 | { |
| | | 292 | struct faultbuf fb; |
| | | 293 | |
| | | 294 | if (cpu_set_onfault(&fb, 1) == 0) { |
| | | 295 | memcpy(base, xu->b, len); |
| | | 296 | cpu_unset_onfault(); |
| | | 297 | return true; |
| | | 298 | } |
| | | 299 | return false; |
| | | 300 | } |
| | | 301 | |
| | | 302 | int |
| | | 303 | subyte(void *base, int c) |
| | | 304 | { |
| | | 305 | union xubuf xu; |
| | | 306 | |
| | | 307 | xu.l[0] = 0; xu.b[0] = c; // { .b[0] = c, .b[1 ... 3] = 0 } |
| | | 308 | return store_user_data(base, &xu, sizeof(xu.b[0])) ? 0 : -1; |
| | | 309 | } |
| | | 310 | |
| | | 311 | int |
| | | 312 | susword(void *base, short c) |
| | | 313 | { |
| | | 314 | union xubuf xu; |
| | | 315 | |
| | | 316 | xu.l[0] = 0; xu.w[0] = c; // { .w[0] = c, .w[1] = 0 } |
| | | 317 | return store_user_data(base, &xu, sizeof(xu.w[0])) ? 0 : -1; |
| | | 318 | } |
| | | 319 | |
| | | 320 | int |
| | | 321 | suswintr(void *base, short c) |
| | | 322 | { |
| | | 323 | |
| | | 324 | return -1; |
| | | 325 | } |
| | | 326 | |
| | | 327 | int |
| | | 328 | suword(void *base, long c) |
| | | 329 | { |
| | | 330 | union xubuf xu; |
| | | 331 | |
| | | 332 | xu.l[0] = c; // { .l[0] = c } |
| | | 333 | return store_user_data(base, &xu, sizeof(xu.l[0])) ? 0 : -1; |
| | | 334 | } |