1 /* $NetBSD: trap.c,v 1.138 2023/10/05 19:41:06 ad Exp $ */
2
3 /*
4 * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /* All bugs are subject to removal without further notice */
29
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.138 2023/10/05 19:41:06 ad Exp $");
32
33 #include "opt_ddb.h"
34 #include "opt_multiprocessor.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/cpu.h>
39 #include <sys/exec.h>
40 #include <sys/kauth.h>
41 #include <sys/proc.h>
42 #include <sys/signalvar.h>
43
44 #include <uvm/uvm_extern.h>
45
46 #include <machine/trap.h>
47 #include <machine/userret.h>
48
49 #ifdef DDB
50 #include <machine/db_machdep.h>
51 #endif
52 #include <vax/vax/db_disasm.h>
53 #include <kern/syscalls.c>
54 #include <sys/ktrace.h>
55
56 #ifdef TRAPDEBUG
57 volatile int faultdebug = 0;
58 #endif
59
60 int cpu_printfataltraps = 0;
61
62 void trap (struct trapframe *);
63
64 const char * const traptypes[]={
65 "reserved addressing",
66 "privileged instruction",
67 "reserved operand",
68 "breakpoint instruction",
69 "XFC instruction",
70 "system call ",
71 "arithmetic trap",
72 "asynchronous system trap",
73 "page table length fault",
74 "translation violation fault",
75 "trace trap",
76 "compatibility mode fault",
77 "access violation fault",
78 "",
79 "",
80 "KSP invalid",
81 "",
82 "kernel debugger trap"
83 };
84 int no_traps = 18;
85
86 #define USERMODE_P(tf) ((((tf)->tf_psl) & (PSL_U)) == PSL_U)
87
88 void
trap(struct trapframe * tf)89 trap(struct trapframe *tf)
90 {
91 u_int sig = 0, type = tf->tf_trap, code = 0;
92 u_int rv, addr;
93 bool trapsig = true;
94 const bool usermode = USERMODE_P(tf);
95 struct lwp * const l = curlwp;
96 struct proc * const p = l->l_proc;
97 struct pcb * const pcb = lwp_getpcb(l);
98 u_quad_t oticks = 0;
99 struct vmspace *vm;
100 struct vm_map *map;
101 vm_prot_t ftype;
102 void *onfault = pcb->pcb_onfault;
103
104 KASSERT(p != NULL);
105 curcpu()->ci_data.cpu_ntrap++;
106 if (usermode) {
107 type |= T_USER;
108 oticks = p->p_sticks;
109 l->l_md.md_utf = tf;
110 }
111
112 type &= ~(T_WRITE|T_PTEFETCH);
113
114
115 #ifdef TRAPDEBUG
116 if(tf->tf_trap==7) goto fram;
117 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n",
118 tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl);
119 fram:
120 #endif
121 switch (type) {
122
123 default:
124 #ifdef DDB
125 kdb_trap(tf);
126 #endif
127 panic("trap: type %x, code %x, pc %x, psl %x",
128 (u_int)tf->tf_trap, (u_int)tf->tf_code,
129 (u_int)tf->tf_pc, (u_int)tf->tf_psl);
130
131 case T_KSPNOTVAL:
132 panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)",
133 p->p_pid, l->l_lid, l->l_name ? l->l_name : "??",
134 mfpr(PR_KSP), (u_int)tf->tf_pc, pcb,
135 (u_int)tf->tf_fp, (u_int)tf->tf_psl);
136
137 case T_TRANSFLT|T_USER:
138 case T_TRANSFLT:
139 /*
140 * BUG! BUG! BUG! BUG! BUG!
141 * Due to a hardware bug (at in least KA65x CPUs) a double
142 * page table fetch trap will cause a translation fault
143 * even if access in the SPT PTE entry specifies 'no access'.
144 * In for example section 6.4.2 in VAX Architecture
145 * Reference Manual it states that if a page both are invalid
146 * and have no access set, a 'access violation fault' occurs.
147 * Therefore, we must fall through here...
148 */
149 #ifdef nohwbug
150 panic("translation fault");
151 #endif
152
153 case T_PTELEN|T_USER: /* Page table length exceeded */
154 case T_ACCFLT|T_USER:
155 if (tf->tf_code < 0) { /* Check for kernel space */
156 sig = SIGSEGV;
157 code = SEGV_ACCERR;
158 break;
159 }
160
161 case T_PTELEN:
162 #ifndef MULTIPROCESSOR
163 /*
164 * If we referred to an address beyond the end of the system
165 * page table, it may be due to a failed CAS
166 * restartable-atomic-sequence. If it is, restart it at the
167 * beginning and restart.
168 */
169 {
170 extern const uint8_t cas32_ras_start[], cas32_ras_end[];
171 if (tf->tf_code == CASMAGIC
172 && tf->tf_pc >= (uintptr_t) cas32_ras_start
173 && tf->tf_pc < (uintptr_t) cas32_ras_end) {
174 tf->tf_pc = (uintptr_t) cas32_ras_start;
175 trapsig = false;
176 break;
177 }
178 }
179 /* FALLTHROUGH */
180 #endif
181 case T_ACCFLT:
182 #ifdef TRAPDEBUG
183 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n",
184 tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl);
185 #endif
186 #ifdef DIAGNOSTIC
187 if (p == 0)
188 panic("trap: access fault: addr %lx code %lx",
189 tf->tf_pc, tf->tf_code);
190 if (tf->tf_psl & PSL_IS)
191 panic("trap: pflt on IS");
192 #endif
193
194 /*
195 * Page tables are allocated in pmap_enter(). We get
196 * info from below if it is a page table fault, but
197 * UVM may want to map in pages without faults, so
198 * because we must check for PTE pages anyway we don't
199 * bother doing it here.
200 */
201 addr = trunc_page(tf->tf_code);
202 if (!usermode && (tf->tf_code < 0)) {
203 vm = NULL;
204 map = kernel_map;
205
206 } else {
207 vm = p->p_vmspace;
208 map = &vm->vm_map;
209 }
210
211 if (tf->tf_trap & T_WRITE)
212 ftype = VM_PROT_WRITE;
213 else
214 ftype = VM_PROT_READ;
215
216 pcb->pcb_onfault = NULL;
217 rv = uvm_fault(map, addr, ftype);
218 pcb->pcb_onfault = onfault;
219 if (rv != 0) {
220 if (!usermode) {
221 if (onfault) {
222 pcb->pcb_onfault = NULL;
223 tf->tf_pc = (unsigned)onfault;
224 tf->tf_psl &= ~PSL_FPD;
225 tf->tf_r0 = rv;
226 return;
227 }
228 printf("r0=%08lx r1=%08lx r2=%08lx r3=%08lx ",
229 tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3);
230 printf("r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n",
231 tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7);
232 printf(
233 "r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n",
234 tf->tf_r8, tf->tf_r9, tf->tf_r10,
235 tf->tf_r11);
236 printf("ap=%08lx fp=%08lx sp=%08lx pc=%08lx\n",
237 tf->tf_ap, tf->tf_fp, tf->tf_sp, tf->tf_pc);
238 panic("SEGV in kernel mode: pc %#lx addr %#lx",
239 tf->tf_pc, tf->tf_code);
240 }
241 switch (rv) {
242 case ENOMEM:
243 printf("UVM: pid %d (%s), uid %d killed: "
244 "out of swap\n",
245 p->p_pid, p->p_comm,
246 l->l_cred ?
247 kauth_cred_geteuid(l->l_cred) : -1);
248 sig = SIGKILL;
249 code = SI_NOINFO;
250 break;
251 case EINVAL:
252 code = BUS_ADRERR;
253 sig = SIGBUS;
254 break;
255 case EACCES:
256 code = SEGV_ACCERR;
257 sig = SIGSEGV;
258 break;
259 default:
260 code = SEGV_MAPERR;
261 sig = SIGSEGV;
262 break;
263 }
264 } else {
265 trapsig = false;
266 if (map != kernel_map && addr > 0
267 && (void *)addr >= vm->vm_maxsaddr)
268 uvm_grow(p, addr);
269 }
270 break;
271
272 case T_BPTFLT|T_USER:
273 sig = SIGTRAP;
274 code = TRAP_BRKPT;
275 break;
276 case T_TRCTRAP|T_USER:
277 sig = SIGTRAP;
278 code = TRAP_TRACE;
279 tf->tf_psl &= ~PSL_T;
280 break;
281
282 case T_PRIVINFLT|T_USER:
283 sig = SIGILL;
284 code = ILL_PRVOPC;
285 break;
286 case T_RESADFLT|T_USER:
287 sig = SIGILL;
288 code = ILL_ILLADR;
289 break;
290 case T_RESOPFLT|T_USER:
291 sig = SIGILL;
292 code = ILL_ILLOPC;
293 break;
294
295 case T_XFCFLT|T_USER:
296 sig = SIGEMT;
297 break;
298
299 case T_ARITHFLT|T_USER:
300 sig = SIGFPE;
301 switch (tf->tf_code) {
302 case ATRP_INTOVF: code = FPE_INTOVF; break;
303 case ATRP_INTDIV: code = FPE_INTDIV; break;
304 case ATRP_FLTOVF: code = FPE_FLTOVF; break;
305 case ATRP_FLTDIV: code = FPE_FLTDIV; break;
306 case ATRP_FLTUND: code = FPE_FLTUND; break;
307 case ATRP_DECOVF: code = FPE_INTOVF; break;
308 case ATRP_FLTSUB: code = FPE_FLTSUB; break;
309 case AFLT_FLTDIV: code = FPE_FLTDIV; break;
310 case AFLT_FLTUND: code = FPE_FLTUND; break;
311 case AFLT_FLTOVF: code = FPE_FLTOVF; break;
312 default: code = FPE_FLTINV; break;
313 }
314 break;
315
316 case T_ASTFLT|T_USER:
317 pcb->P0LR = (pcb->P0LR & ~AST_MASK) | AST_PCB;
318 mtpr(AST_NO,PR_ASTLVL);
319 trapsig = false;
320 break;
321
322 #ifdef DDB
323 case T_BPTFLT: /* Kernel breakpoint */
324 case T_KDBTRAP:
325 case T_KDBTRAP|T_USER:
326 case T_TRCTRAP:
327 kdb_trap(tf);
328 return;
329 #endif
330 }
331 if (trapsig) {
332 ksiginfo_t ksi;
333 if ((sig == SIGSEGV || sig == SIGILL)
334 && cpu_printfataltraps
335 && (p->p_slflag & PSL_TRACED) == 0
336 && !sigismember(&p->p_sigctx.ps_sigcatch, sig))
337 printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n",
338 p->p_pid, l->l_lid, p->p_comm, sig, tf->tf_trap,
339 tf->tf_code, tf->tf_pc, tf->tf_psl);
340 KSI_INIT_TRAP(&ksi);
341 ksi.ksi_signo = sig;
342 ksi.ksi_trap = tf->tf_trap;
343 ksi.ksi_addr = (void *)tf->tf_code;
344 ksi.ksi_code = code;
345
346 /*
347 * Arithmetic exceptions can be of two kinds:
348 * - traps (codes 1..7), where pc points to the
349 * next instruction to execute.
350 * - faults (codes 8..10), where pc points to the
351 * faulting instruction.
352 * In the latter case, we need to advance pc by ourselves
353 * to prevent a signal loop.
354 *
355 * XXX this is gross -- miod
356 */
357 if (type == (T_ARITHFLT | T_USER) && (tf->tf_code & 8))
358 tf->tf_pc = skip_opcode(tf->tf_pc);
359
360 trapsignal(l, &ksi);
361 }
362
363 if (!usermode)
364 return;
365
366 userret(l, tf, oticks);
367 }
368
369 void
setregs(struct lwp * l,struct exec_package * pack,vaddr_t stack)370 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
371 {
372 struct trapframe * const tf = l->l_md.md_utf;
373
374 tf->tf_pc = pack->ep_entry + 2;
375 tf->tf_sp = stack;
376 tf->tf_r6 = stack; /* for ELF */
377 tf->tf_r7 = 0; /* for ELF */
378 tf->tf_r8 = 0; /* for ELF */
379 tf->tf_r9 = l->l_proc->p_psstrp; /* for ELF */
380 }
381
382
383 /*
384 * Start a new LWP
385 */
386 void
startlwp(void * arg)387 startlwp(void *arg)
388 {
389 ucontext_t * const uc = arg;
390 lwp_t * const l = curlwp;
391 int error __diagused;
392
393 error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
394 KASSERT(error == 0);
395
396 kmem_free(uc, sizeof(ucontext_t));
397 /* XXX - profiling spoiled here */
398 userret(l, l->l_md.md_utf, l->l_proc->p_sticks);
399 }
400