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