Wed Aug 16 22:48:11 2017 UTC ()
reimplement copy/fetch/store(9). mostly copied from riscv


(nisimura)
diff -r1.1 -r1.2 src/sys/arch/aarch64/aarch64/trap.c

cvs diff -r1.1 -r1.2 src/sys/arch/aarch64/aarch64/trap.c (expand / switch to unified diff)

--- src/sys/arch/aarch64/aarch64/trap.c 2014/08/10 05:47:37 1.1
+++ src/sys/arch/aarch64/aarch64/trap.c 2017/08/16 22:48:11 1.2
@@ -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
43void 43void
44userret(struct lwp *l, struct trapframe *tf) 44userret(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
 67struct faultbuf {
 68 register_t fb_reg[FB_MAX];
 69};
 70
 71int cpu_set_onfault(struct faultbuf *, register_t) __returns_twice;
 72void cpu_jump_onfault(struct trapframe *, const struct faultbuf *);
 73void cpu_unset_onfault(void);
 74struct faultbuf *cpu_disable_onfault(void);
 75void cpu_enable_onfault(struct faultbuf *);
 76
 77void
 78cpu_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
 97void
 98cpu_unset_onfault(void)
 99{
 100
 101 curlwp->l_md.md_onfault = NULL;
 102}
 103
 104struct faultbuf *
 105cpu_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
 113void
 114cpu_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
 132int
 133kcopy(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
 145int
 146copyin(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
 158int
 159copyout(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
 171int
 172copystr(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
 187int
 188copyinstr(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
 203int
 204copyoutstr(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
 233union xubuf {
 234 uint8_t b[4];
 235 uint16_t w[2];
 236 uint32_t l[1];
 237};
 238
 239static bool
 240fetch_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
 252int
 253fubyte(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
 262int
 263fusword(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
 272int
 273fuswintr(const void *base)
 274{
 275
 276 return -1;
 277}
 278
 279long
 280fuword(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
 289static bool
 290store_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
 302int
 303subyte(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
 311int
 312susword(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
 320int
 321suswintr(void *base, short c)
 322{
 323
 324 return -1;
 325}
 326
 327int
 328suword(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}