xref: /netbsd-src/sys/arch/vax/vax/trap.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /*	$NetBSD: trap.c,v 1.136 2019/11/21 19:24:02 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.136 2019/11/21 19:24:02 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
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 		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
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
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