Home | History | Annotate | Line # | Download | only in aarch64
trap.c revision 1.3
      1 /* $NetBSD: trap.c,v 1.3 2017/08/25 22:23:59 nisimura Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2014 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Matt Thomas of 3am Software Foundry.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     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
     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
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 
     34 __KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.3 2017/08/25 22:23:59 nisimura Exp $");
     35 
     36 #include <sys/param.h>
     37 #include <sys/types.h>
     38 #include <sys/cpu.h>
     39 #include <sys/proc.h>
     40 #include <sys/userret.h>
     41 #include <sys/systm.h>
     42 
     43 #include <sys/signal.h>
     44 #include <sys/signalvar.h>
     45 #include <sys/siginfo.h>
     46 
     47 #include <aarch64/locore.h>
     48 
     49 static void
     50 dump_trapframe(struct trapframe *tf, void (*pr)(const char *, ...))
     51 {
     52 	(*pr)("trapframe @ %p:\n", tf);
     53 	(*pr)("esr=%016"PRIxREGISTER
     54 	    ",  pc=%016"PRIxREGISTER
     55 	    ",  lr=%016"PRIxREGISTER
     56 	    ",  sp=%016"PRIxREGISTER"\n",
     57 	    tf->tf_esr, tf->tf_pc, tf->tf_lr, tf->tf_sp);
     58 	(*pr)(" x0=%016"PRIxREGISTER
     59 	    ",  x1=%016"PRIxREGISTER
     60 	    ",  x2=%016"PRIxREGISTER
     61 	    ",  x3=%016"PRIxREGISTER"\n",
     62 	    tf->tf_reg[0], tf->tf_reg[1], tf->tf_reg[2], tf->tf_reg[3]);
     63 	(*pr)(" x4=%016"PRIxREGISTER
     64 	    ",  x5=%016"PRIxREGISTER
     65 	    ",  x6=%016"PRIxREGISTER
     66 	    ",  x7=%016"PRIxREGISTER"\n",
     67 	    tf->tf_reg[4], tf->tf_reg[5], tf->tf_reg[6], tf->tf_reg[7]);
     68 	(*pr)(" x8=%016"PRIxREGISTER
     69 	    ",  x9=%016"PRIxREGISTER
     70 	    ", x10=%016"PRIxREGISTER
     71 	    ", x11=%016"PRIxREGISTER"\n",
     72 	    tf->tf_reg[8], tf->tf_reg[9], tf->tf_reg[10], tf->tf_reg[11]);
     73 	(*pr)("x12=%016"PRIxREGISTER
     74 	    ", x13=%016"PRIxREGISTER
     75 	    ", x14=%016"PRIxREGISTER
     76 	    ", x15=%016"PRIxREGISTER"\n",
     77 	    tf->tf_reg[12], tf->tf_reg[13], tf->tf_reg[14], tf->tf_reg[15]);
     78 	(*pr)("x16=%016"PRIxREGISTER
     79 	    ", x17=%016"PRIxREGISTER
     80 	    ", x18=%016"PRIxREGISTER
     81 	    ", x19=%016"PRIxREGISTER"\n",
     82 	    tf->tf_reg[16], tf->tf_reg[17], tf->tf_reg[18], tf->tf_reg[19]);
     83 	(*pr)("x20=%016"PRIxREGISTER
     84 	    ", x21=%016"PRIxREGISTER
     85 	    ", x22=%016"PRIxREGISTER
     86 	    ", x23=%016"PRIxREGISTER"\n",
     87 	    tf->tf_reg[20], tf->tf_reg[21], tf->tf_reg[22], tf->tf_reg[23]);
     88 	(*pr)("x24=%016"PRIxREGISTER
     89 	    ", x25=%016"PRIxREGISTER
     90 	    ", x26=%016"PRIxREGISTER
     91 	    ", x27=%016"PRIxREGISTER"\n",
     92 	    tf->tf_reg[24], tf->tf_reg[25], tf->tf_reg[26], tf->tf_reg[27]);
     93 	(*pr)("x28=%016"PRIxREGISTER
     94 	    ", x29=%016"PRIxREGISTER
     95 	    ", x30=%016"PRIxREGISTER"\n",
     96 	    tf->tf_reg[28], tf->tf_reg[29], tf->tf_reg[30]);
     97 }
     98 
     99 void
    100 userret(struct lwp *l, struct trapframe *tf)
    101 {
    102 	mi_userret(l);
    103 }
    104 
    105 void
    106 trap(struct trapframe *tf, int reason)
    107 {
    108 	struct lwp * const l = curlwp;
    109 	size_t code = tf->tf_esr & 0xffff;
    110 	bool usertrap_p = tf->tf_esr & 01;
    111 	bool ok = true;
    112 	ksiginfo_t ksi;
    113 
    114 	code = code;
    115 	dump_trapframe(tf, printf);
    116 
    117 	if (usertrap_p) {
    118 		if (!ok)
    119 			(*l->l_proc->p_emul->e_trapsignal)(l, &ksi);
    120 		userret(l, tf);
    121 	}
    122 	else if (!ok) {
    123 		dump_trapframe(tf, printf);
    124 		panic("%s: fatal kernel trap", __func__);
    125 	}
    126 }
    127 
    128 void
    129 interrupt(struct trapframe *tf)
    130 {
    131 }
    132 
    133 // XXXAARCH64 might be populated in frame.h in future
    134 
    135 #define FB_X19	0
    136 #define FB_X20	1
    137 #define FB_X21	2
    138 #define FB_X22	3
    139 #define FB_X23	4
    140 #define FB_X24	5
    141 #define FB_X25	6
    142 #define FB_X26	7
    143 #define FB_X27	8
    144 #define FB_X28	9
    145 #define FB_X29	10
    146 #define FB_LR	11
    147 #define FB_SP	12
    148 #define FB_V0	13
    149 #define FB_MAX	14
    150 
    151 struct faultbuf {
    152 	register_t fb_reg[FB_MAX];
    153 };
    154 
    155 int	cpu_set_onfault(struct faultbuf *, register_t) __returns_twice;
    156 void	cpu_jump_onfault(struct trapframe *, const struct faultbuf *);
    157 void	cpu_unset_onfault(void);
    158 struct faultbuf *cpu_disable_onfault(void);
    159 void	cpu_enable_onfault(struct faultbuf *);
    160 
    161 void
    162 cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb)
    163 {
    164 
    165 	tf->tf_reg[19] = fb->fb_reg[FB_X19];
    166 	tf->tf_reg[20] = fb->fb_reg[FB_X20];
    167 	tf->tf_reg[21] = fb->fb_reg[FB_X21];
    168 	tf->tf_reg[22] = fb->fb_reg[FB_X22];
    169 	tf->tf_reg[23] = fb->fb_reg[FB_X23];
    170 	tf->tf_reg[24] = fb->fb_reg[FB_X24];
    171 	tf->tf_reg[25] = fb->fb_reg[FB_X25];
    172 	tf->tf_reg[26] = fb->fb_reg[FB_X26];
    173 	tf->tf_reg[27] = fb->fb_reg[FB_X27];
    174 	tf->tf_reg[28] = fb->fb_reg[FB_X28];
    175 	tf->tf_reg[29] = fb->fb_reg[FB_X29];
    176 	tf->tf_reg[0] = fb->fb_reg[FB_V0];
    177 	tf->tf_sp = fb->fb_reg[FB_SP];
    178 	tf->tf_lr = fb->fb_reg[FB_LR];
    179 }
    180 
    181 void
    182 cpu_unset_onfault(void)
    183 {
    184 
    185 	curlwp->l_md.md_onfault = NULL;
    186 }
    187 
    188 struct faultbuf *
    189 cpu_disable_onfault(void)
    190 {
    191 	struct faultbuf * const fb = curlwp->l_md.md_onfault;
    192 
    193 	curlwp->l_md.md_onfault = NULL;
    194 	return fb;
    195 }
    196 
    197 void
    198 cpu_enable_onfault(struct faultbuf *fb)
    199 {
    200 
    201 	curlwp->l_md.md_onfault = NULL;
    202 }
    203 
    204 /*
    205  * kcopy(9)
    206  * int kcopy(const void *src, void *dst, size_t len);
    207  *
    208  * copy(9)
    209  * int copyin(const void *uaddr, void *kaddr, size_t len);
    210  * int copyout(const void *kaddr, void *uaddr, size_t len);
    211  * int copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done);
    212  * int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done);
    213  * int copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done);
    214  */
    215 
    216 int
    217 kcopy(const void *kfaddr, void *kdaddr, size_t len)
    218 {
    219 	struct faultbuf fb;
    220 	int error;
    221 
    222 	if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
    223 		memcpy(kdaddr, kfaddr, len);
    224 		cpu_unset_onfault();
    225 	}
    226 	return error;
    227 }
    228 
    229 int
    230 copyin(const void *uaddr, void *kaddr, size_t len)
    231 {
    232 	struct faultbuf fb;
    233 	int error;
    234 
    235 	if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
    236 		memcpy(kaddr, uaddr, len);
    237 		cpu_unset_onfault();
    238 	}
    239 	return error;
    240 }
    241 
    242 int
    243 copyout(const void *kaddr, void *uaddr, size_t len)
    244 {
    245 	struct faultbuf fb;
    246 	int error;
    247 
    248 	if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
    249 		memcpy(uaddr, kaddr, len);
    250 		cpu_unset_onfault();
    251 	}
    252 	return error;
    253 }
    254 
    255 int
    256 copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done)
    257 {
    258 	struct faultbuf fb;
    259 	int error;
    260 
    261 	if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
    262 		len = strlcpy(kdaddr, kfaddr, len);
    263 		cpu_unset_onfault();
    264 		if (done != NULL) {
    265 			*done = len;
    266 		}
    267 	}
    268 	return error;
    269 }
    270 
    271 int
    272 copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
    273 {
    274 	struct faultbuf fb;
    275 	int error;
    276 
    277 	if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
    278 		len = strlcpy(kaddr, uaddr, len);
    279 		cpu_unset_onfault();
    280 		if (done != NULL) {
    281 			*done = len;
    282 		}
    283 	}
    284 	return error;
    285 }
    286 
    287 int
    288 copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done)
    289 {
    290 	struct faultbuf fb;
    291 	int error;
    292 
    293 	if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
    294 		len = strlcpy(uaddr, kaddr, len);
    295 		cpu_unset_onfault();
    296 		if (done != NULL) {
    297 			*done = len;
    298 		}
    299 	}
    300 	return error;
    301 }
    302 
    303 /*
    304  * fetch(9)
    305  * int fubyte(const void *base);
    306  * int fusword(const void *base);
    307  * int fuswintr(const void *base);
    308  * long fuword(const void *base);
    309  *
    310  * store(9)
    311  * int subyte(void *base, int c);
    312  * int susword(void *base, short c);
    313  * int suswintr(void *base, short c);
    314  * int suword(void *base, long c);
    315  */
    316 
    317 union xubuf {
    318 	uint8_t b[4];
    319 	uint16_t w[2];
    320 	uint32_t l[1];
    321 };
    322 
    323 static bool
    324 fetch_user_data(union xubuf *xu, const void *base, size_t len)
    325 {
    326 	struct faultbuf fb;
    327 
    328 	if (cpu_set_onfault(&fb, 1) == 0) {
    329 		memcpy(xu->b, base, len);
    330 		cpu_unset_onfault();
    331 		return true;
    332 	}
    333 	return false;
    334 }
    335 
    336 int
    337 fubyte(const void *base)
    338 {
    339 	union xubuf xu;
    340 
    341 	if (fetch_user_data(&xu, base, sizeof(xu.b[0])))
    342 		return xu.b[0];
    343 	return -1;
    344 }
    345 
    346 int
    347 fusword(const void *base)
    348 {
    349 	union xubuf xu;
    350 
    351 	if (fetch_user_data(&xu, base, sizeof(xu.w[0])))
    352 		return xu.w[0];
    353 	return -1;
    354 }
    355 
    356 int
    357 fuswintr(const void *base)
    358 {
    359 
    360 	return -1;
    361 }
    362 
    363 long
    364 fuword(const void *base)
    365 {
    366 	union xubuf xu;
    367 
    368 	if (fetch_user_data(&xu, base, sizeof(xu.l[0])))
    369 		return xu.l[0];
    370 	return -1;
    371 }
    372 
    373 static bool
    374 store_user_data(void *base, const union xubuf *xu, size_t len)
    375 {
    376 	struct faultbuf fb;
    377 
    378 	if (cpu_set_onfault(&fb, 1) == 0) {
    379 		memcpy(base, xu->b, len);
    380 		cpu_unset_onfault();
    381 		return true;
    382 	}
    383 	return false;
    384 }
    385 
    386 int
    387 subyte(void *base, int c)
    388 {
    389 	union xubuf xu;
    390 
    391 	xu.l[0] = 0; xu.b[0] = c; // { .b[0] = c, .b[1 ... 3] = 0 }
    392 	return store_user_data(base, &xu, sizeof(xu.b[0])) ? 0 : -1;
    393 }
    394 
    395 int
    396 susword(void *base, short c)
    397 {
    398 	union xubuf xu;
    399 
    400 	xu.l[0] = 0; xu.w[0] = c; // { .w[0] = c, .w[1] = 0 }
    401 	return store_user_data(base, &xu, sizeof(xu.w[0])) ? 0 : -1;
    402 }
    403 
    404 int
    405 suswintr(void *base, short c)
    406 {
    407 
    408 	return -1;
    409 }
    410 
    411 int
    412 suword(void *base, long c)
    413 {
    414 	union xubuf xu;
    415 
    416 	xu.l[0] = c; // { .l[0] = c }
    417 	return store_user_data(base, &xu, sizeof(xu.l[0])) ? 0 : -1;
    418 }
    419