xref: /netbsd-src/sys/arch/vax/vax/trap.c (revision ce2c90c7c172d95d2402a5b3d96d8f8e6d138a21)
1 /*	$NetBSD: trap.c,v 1.105 2006/07/23 22:06:08 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  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *     This product includes software developed at Ludd, University of Lule}.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33  /* All bugs are subject to removal without further notice */
34 
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.105 2006/07/23 22:06:08 ad Exp $");
37 
38 #include "opt_ddb.h"
39 #include "opt_ktrace.h"
40 #include "opt_multiprocessor.h"
41 
42 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/proc.h>
45 #include <sys/user.h>
46 #include <sys/syscall.h>
47 #include <sys/systm.h>
48 #include <sys/signalvar.h>
49 #include <sys/exec.h>
50 #include <sys/sa.h>
51 #include <sys/savar.h>
52 #include <sys/pool.h>
53 #include <sys/kauth.h>
54 
55 #include <uvm/uvm_extern.h>
56 
57 #include <machine/mtpr.h>
58 #include <machine/pte.h>
59 #include <machine/pcb.h>
60 #include <machine/trap.h>
61 #include <machine/pmap.h>
62 #include <machine/cpu.h>
63 #include <machine/userret.h>
64 
65 #ifdef DDB
66 #include <machine/db_machdep.h>
67 #endif
68 #include <kern/syscalls.c>
69 #ifdef KTRACE
70 #include <sys/ktrace.h>
71 #endif
72 
73 #ifdef TRAPDEBUG
74 volatile int faultdebug = 0;
75 #endif
76 
77 int	cpu_printfataltraps = 0;
78 
79 void	trap (struct trapframe *);
80 
81 const char * const traptypes[]={
82 	"reserved addressing",
83 	"privileged instruction",
84 	"reserved operand",
85 	"breakpoint instruction",
86 	"XFC instruction",
87 	"system call ",
88 	"arithmetic trap",
89 	"asynchronous system trap",
90 	"page table length fault",
91 	"translation violation fault",
92 	"trace trap",
93 	"compatibility mode fault",
94 	"access violation fault",
95 	"",
96 	"",
97 	"KSP invalid",
98 	"",
99 	"kernel debugger trap"
100 };
101 int no_traps = 18;
102 
103 #define USERMODE(framep)   ((((framep)->psl) & (PSL_U)) == PSL_U)
104 #define FAULTCHK						\
105 	if (l->l_addr->u_pcb.iftrap) {				\
106 		frame->pc = (unsigned)l->l_addr->u_pcb.iftrap;	\
107 		frame->psl &= ~PSL_FPD;				\
108 		frame->r0 = EFAULT;/* for copyin/out */		\
109 		frame->r1 = -1; /* for fetch/store */		\
110 		return;						\
111 	}
112 
113 
114 void
115 trap(struct trapframe *frame)
116 {
117 	u_int	sig = 0, type = frame->trap, trapsig = 1, code = 0;
118 	u_int	rv, addr, umode;
119 	struct	lwp *l;
120 	struct	proc *p = NULL;
121 	u_quad_t oticks = 0;
122 	struct vmspace *vm;
123 	struct vm_map *map;
124 	vm_prot_t ftype;
125 
126 	if ((l = curlwp) != NULL)
127 		p = l->l_proc;
128 	uvmexp.traps++;
129 	if ((umode = USERMODE(frame))) {
130 		type |= T_USER;
131 		oticks = p->p_sticks;
132 		l->l_addr->u_pcb.framep = frame;
133 		LWP_CACHE_CREDS(l, p);
134 	}
135 
136 	type&=~(T_WRITE|T_PTEFETCH);
137 
138 
139 #ifdef TRAPDEBUG
140 if(frame->trap==7) goto fram;
141 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n",
142 		frame->trap, frame->code, frame->pc, frame->psl);
143 fram:
144 #endif
145 	switch(type){
146 
147 	default:
148 #ifdef DDB
149 		kdb_trap(frame);
150 #endif
151 		printf("Trap: type %x, code %x, pc %x, psl %x\n",
152 		    (u_int)frame->trap, (u_int)frame->code,
153 		    (u_int)frame->pc, (u_int)frame->psl);
154 		panic("trap");
155 
156 	case T_KSPNOTVAL:
157 		panic("kernel stack invalid");
158 
159 	case T_TRANSFLT|T_USER:
160 	case T_TRANSFLT:
161 		/*
162 		 * BUG! BUG! BUG! BUG! BUG!
163 		 * Due to a hardware bug (at in least KA65x CPUs) a double
164 		 * page table fetch trap will cause a translation fault
165 		 * even if access in the SPT PTE entry specifies 'no access'.
166 		 * In for example section 6.4.2 in VAX Architecture
167 		 * Reference Manual it states that if a page both are invalid
168 		 * and have no access set, a 'access violation fault' occurs.
169 		 * Therefore, we must fall through here...
170 		 */
171 #ifdef nohwbug
172 		panic("translation fault");
173 #endif
174 
175 	case T_PTELEN|T_USER:	/* Page table length exceeded */
176 	case T_ACCFLT|T_USER:
177 		if (frame->code < 0) { /* Check for kernel space */
178 			sig = SIGSEGV;
179 			code = SEGV_ACCERR;
180 			break;
181 		}
182 
183 	case T_PTELEN:
184 	case T_ACCFLT:
185 #ifdef TRAPDEBUG
186 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n",
187 			frame->trap, frame->code, frame->pc, frame->psl);
188 #endif
189 #ifdef DIAGNOSTIC
190 		if (p == 0)
191 			panic("trap: access fault: addr %lx code %lx",
192 			    frame->pc, frame->code);
193 		if (frame->psl & PSL_IS)
194 			panic("trap: pflt on IS");
195 #endif
196 
197 		/*
198 		 * Page tables are allocated in pmap_enter(). We get
199 		 * info from below if it is a page table fault, but
200 		 * UVM may want to map in pages without faults, so
201 		 * because we must check for PTE pages anyway we don't
202 		 * bother doing it here.
203 		 */
204 		addr = trunc_page(frame->code);
205 		if ((umode == 0) && (frame->code < 0)) {
206 			vm = NULL;
207 			map = kernel_map;
208 		} else {
209 			vm = p->p_vmspace;
210 			map = &vm->vm_map;
211 		}
212 
213 		if (frame->trap & T_WRITE)
214 			ftype = VM_PROT_WRITE;
215 		else
216 			ftype = VM_PROT_READ;
217 
218 		if (umode) {
219 			KERNEL_PROC_LOCK(l);
220 			if (l->l_flag & L_SA) {
221 				l->l_savp->savp_faultaddr = (vaddr_t)frame->code;
222 				l->l_flag |= L_SA_PAGEFAULT;
223 			}
224 		} else
225 			KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE);
226 
227 		rv = uvm_fault(map, addr, ftype);
228 		if (rv != 0) {
229 			if (umode == 0) {
230 				KERNEL_UNLOCK();
231 				FAULTCHK;
232 				panic("Segv in kernel mode: pc %x addr %x",
233 				    (u_int)frame->pc, (u_int)frame->code);
234 			}
235 			code = SEGV_ACCERR;
236 			if (rv == ENOMEM) {
237 				printf("UVM: pid %d (%s), uid %d killed: "
238 				       "out of swap\n",
239 				       p->p_pid, p->p_comm,
240 				       l->l_cred ?
241 				       kauth_cred_geteuid(l->l_cred) : -1);
242 				sig = SIGKILL;
243 			} else {
244 				sig = SIGSEGV;
245 				if (rv != EACCES)
246 					code = SEGV_MAPERR;
247 			}
248 		} else {
249 			trapsig = 0;
250 			if (map != kernel_map && (caddr_t)addr >= vm->vm_maxsaddr)
251 				uvm_grow(p, addr);
252 		}
253 		if (umode) {
254 			l->l_flag &= ~L_SA_PAGEFAULT;
255 			KERNEL_PROC_UNLOCK(l);
256 		} else
257 			KERNEL_UNLOCK();
258 		break;
259 
260 	case T_BPTFLT|T_USER:
261 		sig = SIGTRAP;
262 		code = TRAP_BRKPT;
263 		break;
264 	case T_TRCTRAP|T_USER:
265 		sig = SIGTRAP;
266 		code = TRAP_TRACE;
267 		frame->psl &= ~PSL_T;
268 		break;
269 
270 	case T_PRIVINFLT|T_USER:
271 		sig = SIGILL;
272 		code = ILL_PRVOPC;
273 		break;
274 	case T_RESADFLT|T_USER:
275 		sig = SIGILL;
276 		code = ILL_ILLADR;
277 		break;
278 	case T_RESOPFLT|T_USER:
279 		sig = SIGILL;
280 		code = ILL_ILLOPC;
281 		break;
282 
283 	case T_XFCFLT|T_USER:
284 		sig = SIGEMT;
285 		break;
286 
287 	case T_ARITHFLT|T_USER:
288 		sig = SIGFPE;
289 		break;
290 
291 	case T_ASTFLT|T_USER:
292 		mtpr(AST_NO,PR_ASTLVL);
293 		trapsig = 0;
294 		break;
295 
296 #ifdef DDB
297 	case T_BPTFLT: /* Kernel breakpoint */
298 	case T_KDBTRAP:
299 	case T_KDBTRAP|T_USER:
300 	case T_TRCTRAP:
301 		kdb_trap(frame);
302 		return;
303 #endif
304 	}
305 	if (trapsig) {
306 		ksiginfo_t ksi;
307 		if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps)
308 			printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n",
309 			       p->p_pid, l->l_lid, p->p_comm, sig, frame->trap,
310 			       frame->code, frame->pc, frame->psl);
311 		KERNEL_PROC_LOCK(l);
312 		KSI_INIT_TRAP(&ksi);
313 		ksi.ksi_signo = sig;
314 		ksi.ksi_trap = frame->trap;
315 		ksi.ksi_addr = (void *)frame->code;
316 		ksi.ksi_code = code;
317 		trapsignal(l, &ksi);
318 		KERNEL_PROC_UNLOCK(l);
319 	}
320 
321 	if (umode == 0)
322 		return;
323 
324 	userret(l, frame, oticks);
325 }
326 
327 void
328 setregs(struct lwp *l, struct exec_package *pack, u_long stack)
329 {
330 	struct trapframe *exptr;
331 
332 	exptr = l->l_addr->u_pcb.framep;
333 	exptr->pc = pack->ep_entry + 2;
334 	exptr->sp = stack;
335 	exptr->r6 = stack;				/* for ELF */
336 	exptr->r7 = 0;					/* for ELF */
337 	exptr->r8 = 0;					/* for ELF */
338 	exptr->r9 = (u_long) l->l_proc->p_psstr;	/* for ELF */
339 }
340 
341 
342 /*
343  * Start a new LWP
344  */
345 void
346 startlwp(arg)
347 	void *arg;
348 {
349 	int err;
350 	ucontext_t *uc = arg;
351 	struct lwp *l = curlwp;
352 
353 	err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
354 #if DIAGNOSTIC
355 	if (err) {
356 		printf("Error %d from cpu_setmcontext.", err);
357 	}
358 #endif
359 	pool_put(&lwp_uc_pool, uc);
360 
361 	/* XXX - profiling spoiled here */
362 	userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks);
363 }
364 
365 void
366 upcallret(struct lwp *l)
367 {
368 
369 	/* XXX - profiling */
370 	userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks);
371 }
372 
373