xref: /netbsd-src/sys/arch/vax/vax/trap.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: trap.c,v 1.135 2017/05/22 16:53:05 ragge 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.135 2017/05/22 16:53:05 ragge 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
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 		LWP_CACHE_CREDS(l, p);
111 	}
112 
113 	type &= ~(T_WRITE|T_PTEFETCH);
114 
115 
116 #ifdef TRAPDEBUG
117 if(tf->tf_trap==7) goto fram;
118 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n",
119 		tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl);
120 fram:
121 #endif
122 	switch (type) {
123 
124 	default:
125 #ifdef DDB
126 		kdb_trap(tf);
127 #endif
128 		panic("trap: type %x, code %x, pc %x, psl %x",
129 		    (u_int)tf->tf_trap, (u_int)tf->tf_code,
130 		    (u_int)tf->tf_pc, (u_int)tf->tf_psl);
131 
132 	case T_KSPNOTVAL:
133 		panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)",
134 		    p->p_pid, l->l_lid, l->l_name ? l->l_name : "??",
135 		    mfpr(PR_KSP), (u_int)tf->tf_pc, pcb,
136 		    (u_int)tf->tf_fp, (u_int)tf->tf_psl);
137 
138 	case T_TRANSFLT|T_USER:
139 	case T_TRANSFLT:
140 		/*
141 		 * BUG! BUG! BUG! BUG! BUG!
142 		 * Due to a hardware bug (at in least KA65x CPUs) a double
143 		 * page table fetch trap will cause a translation fault
144 		 * even if access in the SPT PTE entry specifies 'no access'.
145 		 * In for example section 6.4.2 in VAX Architecture
146 		 * Reference Manual it states that if a page both are invalid
147 		 * and have no access set, a 'access violation fault' occurs.
148 		 * Therefore, we must fall through here...
149 		 */
150 #ifdef nohwbug
151 		panic("translation fault");
152 #endif
153 
154 	case T_PTELEN|T_USER:	/* Page table length exceeded */
155 	case T_ACCFLT|T_USER:
156 		if (tf->tf_code < 0) { /* Check for kernel space */
157 			sig = SIGSEGV;
158 			code = SEGV_ACCERR;
159 			break;
160 		}
161 
162 	case T_PTELEN:
163 #ifndef MULTIPROCESSOR
164 		/*
165 		 * If we referred to an address beyond the end of the system
166 		 * page table, it may be due to a failed CAS
167 		 * restartable-atomic-sequence.  If it is, restart it at the
168 		 * beginning and restart.
169 		 */
170 		{
171 			extern const uint8_t cas32_ras_start[], cas32_ras_end[];
172 			if (tf->tf_code == CASMAGIC
173 			    && tf->tf_pc >= (uintptr_t) cas32_ras_start
174 			    && tf->tf_pc < (uintptr_t) cas32_ras_end) {
175 				tf->tf_pc = (uintptr_t) cas32_ras_start;
176 				trapsig = false;
177 				break;
178 			}
179 		}
180 		/* FALLTHROUGH */
181 #endif
182 	case T_ACCFLT:
183 #ifdef TRAPDEBUG
184 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n",
185 			tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl);
186 #endif
187 #ifdef DIAGNOSTIC
188 		if (p == 0)
189 			panic("trap: access fault: addr %lx code %lx",
190 			    tf->tf_pc, tf->tf_code);
191 		if (tf->tf_psl & PSL_IS)
192 			panic("trap: pflt on IS");
193 #endif
194 
195 		/*
196 		 * Page tables are allocated in pmap_enter(). We get
197 		 * info from below if it is a page table fault, but
198 		 * UVM may want to map in pages without faults, so
199 		 * because we must check for PTE pages anyway we don't
200 		 * bother doing it here.
201 		 */
202 		addr = trunc_page(tf->tf_code);
203 		if (!usermode && (tf->tf_code < 0)) {
204 			vm = NULL;
205 			map = kernel_map;
206 
207 		} else {
208 			vm = p->p_vmspace;
209 			map = &vm->vm_map;
210 		}
211 
212 		if (tf->tf_trap & T_WRITE)
213 			ftype = VM_PROT_WRITE;
214 		else
215 			ftype = VM_PROT_READ;
216 
217 		pcb->pcb_onfault = NULL;
218 		rv = uvm_fault(map, addr, ftype);
219 		pcb->pcb_onfault = onfault;
220 		if (rv != 0) {
221 			if (!usermode) {
222 				if (onfault) {
223 					pcb->pcb_onfault = NULL;
224 					tf->tf_pc = (unsigned)onfault;
225 					tf->tf_psl &= ~PSL_FPD;
226 					tf->tf_r0 = rv;
227 					return;
228 				}
229 				printf("r0=%08lx r1=%08lx r2=%08lx r3=%08lx ",
230 				    tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3);
231 				printf("r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n",
232 				    tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7);
233 				printf(
234 				    "r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n",
235 				    tf->tf_r8, tf->tf_r9, tf->tf_r10,
236 				    tf->tf_r11);
237 				printf("ap=%08lx fp=%08lx sp=%08lx pc=%08lx\n",
238 				    tf->tf_ap, tf->tf_fp, tf->tf_sp, tf->tf_pc);
239 				panic("SEGV in kernel mode: pc %#lx addr %#lx",
240 				    tf->tf_pc, tf->tf_code);
241 			}
242 			switch (rv) {
243 			case ENOMEM:
244 				printf("UVM: pid %d (%s), uid %d killed: "
245 				       "out of swap\n",
246 				       p->p_pid, p->p_comm,
247 				       l->l_cred ?
248 				       kauth_cred_geteuid(l->l_cred) : -1);
249 				sig = SIGKILL;
250 				code = SI_NOINFO;
251 				break;
252 			case EINVAL:
253 				code = BUS_ADRERR;
254 				sig = SIGBUS;
255 				break;
256 			case EACCES:
257 				code = SEGV_ACCERR;
258 				sig = SIGSEGV;
259 				break;
260 			default:
261 				code = SEGV_MAPERR;
262 				sig = SIGSEGV;
263 				break;
264 			}
265 		} else {
266 			trapsig = false;
267 			if (map != kernel_map && addr > 0
268 			    && (void *)addr >= vm->vm_maxsaddr)
269 				uvm_grow(p, addr);
270 		}
271 		break;
272 
273 	case T_BPTFLT|T_USER:
274 		sig = SIGTRAP;
275 		code = TRAP_BRKPT;
276 		break;
277 	case T_TRCTRAP|T_USER:
278 		sig = SIGTRAP;
279 		code = TRAP_TRACE;
280 		tf->tf_psl &= ~PSL_T;
281 		break;
282 
283 	case T_PRIVINFLT|T_USER:
284 		sig = SIGILL;
285 		code = ILL_PRVOPC;
286 		break;
287 	case T_RESADFLT|T_USER:
288 		sig = SIGILL;
289 		code = ILL_ILLADR;
290 		break;
291 	case T_RESOPFLT|T_USER:
292 		sig = SIGILL;
293 		code = ILL_ILLOPC;
294 		break;
295 
296 	case T_XFCFLT|T_USER:
297 		sig = SIGEMT;
298 		break;
299 
300 	case T_ARITHFLT|T_USER:
301 		sig = SIGFPE;
302 		switch (tf->tf_code) {
303 		case ATRP_INTOVF: code = FPE_INTOVF; break;
304 		case ATRP_INTDIV: code = FPE_INTDIV; break;
305 		case ATRP_FLTOVF: code = FPE_FLTOVF; break;
306 		case ATRP_FLTDIV: code = FPE_FLTDIV; break;
307 		case ATRP_FLTUND: code = FPE_FLTUND; break;
308 		case ATRP_DECOVF: code = FPE_INTOVF; break;
309 		case ATRP_FLTSUB: code = FPE_FLTSUB; break;
310 		case AFLT_FLTDIV: code = FPE_FLTDIV; break;
311 		case AFLT_FLTUND: code = FPE_FLTUND; break;
312 		case AFLT_FLTOVF: code = FPE_FLTOVF; break;
313 		default:	  code = FPE_FLTINV; break;
314 		}
315 		break;
316 
317 	case T_ASTFLT|T_USER:
318 		mtpr(AST_NO,PR_ASTLVL);
319 		trapsig = false;
320 		if (curcpu()->ci_want_resched)
321 			preempt();
322 		break;
323 
324 #ifdef DDB
325 	case T_BPTFLT: /* Kernel breakpoint */
326 	case T_KDBTRAP:
327 	case T_KDBTRAP|T_USER:
328 	case T_TRCTRAP:
329 		kdb_trap(tf);
330 		return;
331 #endif
332 	}
333 	if (trapsig) {
334 		ksiginfo_t ksi;
335 		if ((sig == SIGSEGV || sig == SIGILL)
336 		    && cpu_printfataltraps
337 		    && (p->p_slflag & PSL_TRACED) == 0
338 		    && !sigismember(&p->p_sigctx.ps_sigcatch, sig))
339 			printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n",
340 			       p->p_pid, l->l_lid, p->p_comm, sig, tf->tf_trap,
341 			       tf->tf_code, tf->tf_pc, tf->tf_psl);
342 		KSI_INIT_TRAP(&ksi);
343 		ksi.ksi_signo = sig;
344 		ksi.ksi_trap = tf->tf_trap;
345 		ksi.ksi_addr = (void *)tf->tf_code;
346 		ksi.ksi_code = code;
347 
348 		/*
349 		 * Arithmetic exceptions can be of two kinds:
350 		 * - traps (codes 1..7), where pc points to the
351 		 *   next instruction to execute.
352 		 * - faults (codes 8..10), where pc points to the
353 		 *   faulting instruction.
354 		 * In the latter case, we need to advance pc by ourselves
355 		 * to prevent a signal loop.
356 		 *
357 		 * XXX this is gross -- miod
358 		 */
359 		if (type == (T_ARITHFLT | T_USER) && (tf->tf_code & 8))
360 			tf->tf_pc = skip_opcode(tf->tf_pc);
361 
362 		trapsignal(l, &ksi);
363 	}
364 
365 	if (!usermode)
366 		return;
367 
368 	userret(l, tf, oticks);
369 }
370 
371 void
372 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
373 {
374 	struct trapframe * const tf = l->l_md.md_utf;
375 
376 	tf->tf_pc = pack->ep_entry + 2;
377 	tf->tf_sp = stack;
378 	tf->tf_r6 = stack;				/* for ELF */
379 	tf->tf_r7 = 0;				/* for ELF */
380 	tf->tf_r8 = 0;				/* for ELF */
381 	tf->tf_r9 = l->l_proc->p_psstrp;		/* for ELF */
382 }
383 
384 
385 /*
386  * Start a new LWP
387  */
388 void
389 startlwp(void *arg)
390 {
391 	ucontext_t * const uc = arg;
392 	lwp_t * const l = curlwp;
393 	int error __diagused;
394 
395 	error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
396 	KASSERT(error == 0);
397 
398 	kmem_free(uc, sizeof(ucontext_t));
399 	/* XXX - profiling spoiled here */
400 	userret(l, l->l_md.md_utf, l->l_proc->p_sticks);
401 }
402