trap.c revision 1.2 1 1.2 nisimura /* $NetBSD: trap.c,v 1.2 2017/08/16 22:48:11 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.2 nisimura __KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.2 2017/08/16 22:48:11 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.1 matt #include <sys/userret.h>
40 1.1 matt
41 1.1 matt #include <aarch64/locore.h>
42 1.1 matt
43 1.1 matt void
44 1.1 matt userret(struct lwp *l, struct trapframe *tf)
45 1.1 matt {
46 1.1 matt mi_userret(l);
47 1.1 matt }
48 1.2 nisimura
49 1.2 nisimura // XXXAARCH64 might be populated in frame.h in future
50 1.2 nisimura
51 1.2 nisimura #define FB_X19 0
52 1.2 nisimura #define FB_X20 1
53 1.2 nisimura #define FB_X21 2
54 1.2 nisimura #define FB_X22 3
55 1.2 nisimura #define FB_X23 4
56 1.2 nisimura #define FB_X24 5
57 1.2 nisimura #define FB_X25 6
58 1.2 nisimura #define FB_X26 7
59 1.2 nisimura #define FB_X27 8
60 1.2 nisimura #define FB_X28 9
61 1.2 nisimura #define FB_X29 10
62 1.2 nisimura #define FB_SP 11
63 1.2 nisimura #define FB_LR 12
64 1.2 nisimura #define FB_V0 13
65 1.2 nisimura #define FB_MAX 14
66 1.2 nisimura
67 1.2 nisimura struct faultbuf {
68 1.2 nisimura register_t fb_reg[FB_MAX];
69 1.2 nisimura };
70 1.2 nisimura
71 1.2 nisimura int cpu_set_onfault(struct faultbuf *, register_t) __returns_twice;
72 1.2 nisimura void cpu_jump_onfault(struct trapframe *, const struct faultbuf *);
73 1.2 nisimura void cpu_unset_onfault(void);
74 1.2 nisimura struct faultbuf *cpu_disable_onfault(void);
75 1.2 nisimura void cpu_enable_onfault(struct faultbuf *);
76 1.2 nisimura
77 1.2 nisimura void
78 1.2 nisimura cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb)
79 1.2 nisimura {
80 1.2 nisimura
81 1.2 nisimura tf->tf_reg[19] = fb->fb_reg[FB_X19];
82 1.2 nisimura tf->tf_reg[20] = fb->fb_reg[FB_X20];
83 1.2 nisimura tf->tf_reg[21] = fb->fb_reg[FB_X21];
84 1.2 nisimura tf->tf_reg[22] = fb->fb_reg[FB_X22];
85 1.2 nisimura tf->tf_reg[23] = fb->fb_reg[FB_X23];
86 1.2 nisimura tf->tf_reg[24] = fb->fb_reg[FB_X24];
87 1.2 nisimura tf->tf_reg[25] = fb->fb_reg[FB_X25];
88 1.2 nisimura tf->tf_reg[26] = fb->fb_reg[FB_X26];
89 1.2 nisimura tf->tf_reg[27] = fb->fb_reg[FB_X27];
90 1.2 nisimura tf->tf_reg[28] = fb->fb_reg[FB_X28];
91 1.2 nisimura tf->tf_reg[29] = fb->fb_reg[FB_X29];
92 1.2 nisimura tf->tf_reg[0] = fb->fb_reg[FB_V0];
93 1.2 nisimura tf->tf_sp = fb->fb_reg[FB_SP];
94 1.2 nisimura tf->tf_lr = fb->fb_reg[FB_LR];
95 1.2 nisimura }
96 1.2 nisimura
97 1.2 nisimura void
98 1.2 nisimura cpu_unset_onfault(void)
99 1.2 nisimura {
100 1.2 nisimura
101 1.2 nisimura curlwp->l_md.md_onfault = NULL;
102 1.2 nisimura }
103 1.2 nisimura
104 1.2 nisimura struct faultbuf *
105 1.2 nisimura cpu_disable_onfault(void)
106 1.2 nisimura {
107 1.2 nisimura struct faultbuf * const fb = curlwp->l_md.md_onfault;
108 1.2 nisimura
109 1.2 nisimura curlwp->l_md.md_onfault = NULL;
110 1.2 nisimura return fb;
111 1.2 nisimura }
112 1.2 nisimura
113 1.2 nisimura void
114 1.2 nisimura cpu_enable_onfault(struct faultbuf *fb)
115 1.2 nisimura {
116 1.2 nisimura
117 1.2 nisimura curlwp->l_md.md_onfault = NULL;
118 1.2 nisimura }
119 1.2 nisimura
120 1.2 nisimura /*
121 1.2 nisimura * kcopy(9)
122 1.2 nisimura * int kcopy(const void *src, void *dst, size_t len);
123 1.2 nisimura *
124 1.2 nisimura * copy(9)
125 1.2 nisimura * int copyin(const void *uaddr, void *kaddr, size_t len);
126 1.2 nisimura * int copyout(const void *kaddr, void *uaddr, size_t len);
127 1.2 nisimura * int copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done);
128 1.2 nisimura * int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done);
129 1.2 nisimura * int copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done);
130 1.2 nisimura */
131 1.2 nisimura
132 1.2 nisimura int
133 1.2 nisimura kcopy(const void *kfaddr, void *kdaddr, size_t len)
134 1.2 nisimura {
135 1.2 nisimura struct faultbuf fb;
136 1.2 nisimura int error;
137 1.2 nisimura
138 1.2 nisimura if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
139 1.2 nisimura memcpy(kdaddr, kfaddr, len);
140 1.2 nisimura cpu_unset_onfault();
141 1.2 nisimura }
142 1.2 nisimura return error;
143 1.2 nisimura }
144 1.2 nisimura
145 1.2 nisimura int
146 1.2 nisimura copyin(const void *uaddr, void *kaddr, size_t len)
147 1.2 nisimura {
148 1.2 nisimura struct faultbuf fb;
149 1.2 nisimura int error;
150 1.2 nisimura
151 1.2 nisimura if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
152 1.2 nisimura memcpy(kaddr, uaddr, len);
153 1.2 nisimura cpu_unset_onfault();
154 1.2 nisimura }
155 1.2 nisimura return error;
156 1.2 nisimura }
157 1.2 nisimura
158 1.2 nisimura int
159 1.2 nisimura copyout(const void *kaddr, void *uaddr, size_t len)
160 1.2 nisimura {
161 1.2 nisimura struct faultbuf fb;
162 1.2 nisimura int error;
163 1.2 nisimura
164 1.2 nisimura if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
165 1.2 nisimura memcpy(uaddr, kaddr, len);
166 1.2 nisimura cpu_unset_onfault();
167 1.2 nisimura }
168 1.2 nisimura return error;
169 1.2 nisimura }
170 1.2 nisimura
171 1.2 nisimura int
172 1.2 nisimura copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done)
173 1.2 nisimura {
174 1.2 nisimura struct faultbuf fb;
175 1.2 nisimura int error;
176 1.2 nisimura
177 1.2 nisimura if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
178 1.2 nisimura len = strlcpy(kdaddr, kfaddr, len);
179 1.2 nisimura cpu_unset_onfault();
180 1.2 nisimura if (done != NULL) {
181 1.2 nisimura *done = len;
182 1.2 nisimura }
183 1.2 nisimura }
184 1.2 nisimura return error;
185 1.2 nisimura }
186 1.2 nisimura
187 1.2 nisimura int
188 1.2 nisimura copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
189 1.2 nisimura {
190 1.2 nisimura struct faultbuf fb;
191 1.2 nisimura int error;
192 1.2 nisimura
193 1.2 nisimura if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
194 1.2 nisimura len = strlcpy(kaddr, uaddr, len);
195 1.2 nisimura cpu_unset_onfault();
196 1.2 nisimura if (done != NULL) {
197 1.2 nisimura *done = len;
198 1.2 nisimura }
199 1.2 nisimura }
200 1.2 nisimura return error;
201 1.2 nisimura }
202 1.2 nisimura
203 1.2 nisimura int
204 1.2 nisimura copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done)
205 1.2 nisimura {
206 1.2 nisimura struct faultbuf fb;
207 1.2 nisimura int error;
208 1.2 nisimura
209 1.2 nisimura if ((error = cpu_set_onfault(&fb, EFAULT)) == 0) {
210 1.2 nisimura len = strlcpy(uaddr, kaddr, len);
211 1.2 nisimura cpu_unset_onfault();
212 1.2 nisimura if (done != NULL) {
213 1.2 nisimura *done = len;
214 1.2 nisimura }
215 1.2 nisimura }
216 1.2 nisimura return error;
217 1.2 nisimura }
218 1.2 nisimura
219 1.2 nisimura /*
220 1.2 nisimura * fetch(9)
221 1.2 nisimura * int fubyte(const void *base);
222 1.2 nisimura * int fusword(const void *base);
223 1.2 nisimura * int fuswintr(const void *base);
224 1.2 nisimura * long fuword(const void *base);
225 1.2 nisimura *
226 1.2 nisimura * store(9)
227 1.2 nisimura * int subyte(void *base, int c);
228 1.2 nisimura * int susword(void *base, short c);
229 1.2 nisimura * int suswintr(void *base, short c);
230 1.2 nisimura * int suword(void *base, long c);
231 1.2 nisimura */
232 1.2 nisimura
233 1.2 nisimura union xubuf {
234 1.2 nisimura uint8_t b[4];
235 1.2 nisimura uint16_t w[2];
236 1.2 nisimura uint32_t l[1];
237 1.2 nisimura };
238 1.2 nisimura
239 1.2 nisimura static bool
240 1.2 nisimura fetch_user_data(union xubuf *xu, const void *base, size_t len)
241 1.2 nisimura {
242 1.2 nisimura struct faultbuf fb;
243 1.2 nisimura
244 1.2 nisimura if (cpu_set_onfault(&fb, 1) == 0) {
245 1.2 nisimura memcpy(xu->b, base, len);
246 1.2 nisimura cpu_unset_onfault();
247 1.2 nisimura return true;
248 1.2 nisimura }
249 1.2 nisimura return false;
250 1.2 nisimura }
251 1.2 nisimura
252 1.2 nisimura int
253 1.2 nisimura fubyte(const void *base)
254 1.2 nisimura {
255 1.2 nisimura union xubuf xu;
256 1.2 nisimura
257 1.2 nisimura if (fetch_user_data(&xu, base, sizeof(xu.b[0])))
258 1.2 nisimura return xu.b[0];
259 1.2 nisimura return -1;
260 1.2 nisimura }
261 1.2 nisimura
262 1.2 nisimura int
263 1.2 nisimura fusword(const void *base)
264 1.2 nisimura {
265 1.2 nisimura union xubuf xu;
266 1.2 nisimura
267 1.2 nisimura if (fetch_user_data(&xu, base, sizeof(xu.w[0])))
268 1.2 nisimura return xu.w[0];
269 1.2 nisimura return -1;
270 1.2 nisimura }
271 1.2 nisimura
272 1.2 nisimura int
273 1.2 nisimura fuswintr(const void *base)
274 1.2 nisimura {
275 1.2 nisimura
276 1.2 nisimura return -1;
277 1.2 nisimura }
278 1.2 nisimura
279 1.2 nisimura long
280 1.2 nisimura fuword(const void *base)
281 1.2 nisimura {
282 1.2 nisimura union xubuf xu;
283 1.2 nisimura
284 1.2 nisimura if (fetch_user_data(&xu, base, sizeof(xu.l[0])))
285 1.2 nisimura return xu.l[0];
286 1.2 nisimura return -1;
287 1.2 nisimura }
288 1.2 nisimura
289 1.2 nisimura static bool
290 1.2 nisimura store_user_data(void *base, const union xubuf *xu, size_t len)
291 1.2 nisimura {
292 1.2 nisimura struct faultbuf fb;
293 1.2 nisimura
294 1.2 nisimura if (cpu_set_onfault(&fb, 1) == 0) {
295 1.2 nisimura memcpy(base, xu->b, len);
296 1.2 nisimura cpu_unset_onfault();
297 1.2 nisimura return true;
298 1.2 nisimura }
299 1.2 nisimura return false;
300 1.2 nisimura }
301 1.2 nisimura
302 1.2 nisimura int
303 1.2 nisimura subyte(void *base, int c)
304 1.2 nisimura {
305 1.2 nisimura union xubuf xu;
306 1.2 nisimura
307 1.2 nisimura xu.l[0] = 0; xu.b[0] = c; // { .b[0] = c, .b[1 ... 3] = 0 }
308 1.2 nisimura return store_user_data(base, &xu, sizeof(xu.b[0])) ? 0 : -1;
309 1.2 nisimura }
310 1.2 nisimura
311 1.2 nisimura int
312 1.2 nisimura susword(void *base, short c)
313 1.2 nisimura {
314 1.2 nisimura union xubuf xu;
315 1.2 nisimura
316 1.2 nisimura xu.l[0] = 0; xu.w[0] = c; // { .w[0] = c, .w[1] = 0 }
317 1.2 nisimura return store_user_data(base, &xu, sizeof(xu.w[0])) ? 0 : -1;
318 1.2 nisimura }
319 1.2 nisimura
320 1.2 nisimura int
321 1.2 nisimura suswintr(void *base, short c)
322 1.2 nisimura {
323 1.2 nisimura
324 1.2 nisimura return -1;
325 1.2 nisimura }
326 1.2 nisimura
327 1.2 nisimura int
328 1.2 nisimura suword(void *base, long c)
329 1.2 nisimura {
330 1.2 nisimura union xubuf xu;
331 1.2 nisimura
332 1.2 nisimura xu.l[0] = c; // { .l[0] = c }
333 1.2 nisimura return store_user_data(base, &xu, sizeof(xu.l[0])) ? 0 : -1;
334 1.2 nisimura }
335