xref: /netbsd-src/sys/arch/vax/vax/trap.c (revision cac8e449158efc7261bebc8657cbb0125a2cfdde)
1 /*	$NetBSD: trap.c,v 1.114 2008/05/21 14:07:29 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.114 2008/05/21 14:07:29 ad Exp $");
37 
38 #include "opt_ddb.h"
39 #include "opt_multiprocessor.h"
40 
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <sys/proc.h>
44 #include <sys/user.h>
45 #include <sys/syscall.h>
46 #include <sys/systm.h>
47 #include <sys/signalvar.h>
48 #include <sys/exec.h>
49 #include <sys/pool.h>
50 #include <sys/kauth.h>
51 
52 #include <uvm/uvm_extern.h>
53 
54 #include <machine/mtpr.h>
55 #include <machine/pte.h>
56 #include <machine/pcb.h>
57 #include <machine/trap.h>
58 #include <machine/pmap.h>
59 #include <machine/cpu.h>
60 #include <machine/userret.h>
61 
62 #ifdef DDB
63 #include <machine/db_machdep.h>
64 #endif
65 #include <kern/syscalls.c>
66 #include <sys/ktrace.h>
67 
68 #ifdef TRAPDEBUG
69 volatile int faultdebug = 0;
70 #endif
71 
72 int	cpu_printfataltraps = 0;
73 
74 void	trap (struct trapframe *);
75 
76 const char * const traptypes[]={
77 	"reserved addressing",
78 	"privileged instruction",
79 	"reserved operand",
80 	"breakpoint instruction",
81 	"XFC instruction",
82 	"system call ",
83 	"arithmetic trap",
84 	"asynchronous system trap",
85 	"page table length fault",
86 	"translation violation fault",
87 	"trace trap",
88 	"compatibility mode fault",
89 	"access violation fault",
90 	"",
91 	"",
92 	"KSP invalid",
93 	"",
94 	"kernel debugger trap"
95 };
96 int no_traps = 18;
97 
98 #define USERMODE_P(framep)   ((((framep)->psl) & (PSL_U)) == PSL_U)
99 #define FAULTCHK						\
100 	if (l->l_addr->u_pcb.iftrap) {				\
101 		frame->pc = (unsigned)l->l_addr->u_pcb.iftrap;	\
102 		frame->psl &= ~PSL_FPD;				\
103 		frame->r0 = EFAULT;/* for copyin/out */		\
104 		frame->r1 = -1; /* for fetch/store */		\
105 		return;						\
106 	}
107 
108 
109 void
110 trap(struct trapframe *frame)
111 {
112 	u_int	sig = 0, type = frame->trap, code = 0;
113 	u_int	rv, addr;
114 	bool trapsig = true;
115 	const bool usermode = USERMODE_P(frame);;
116 	struct	lwp *l;
117 	struct	proc *p;
118 	u_quad_t oticks = 0;
119 	struct vmspace *vm;
120 	struct vm_map *map;
121 	vm_prot_t ftype;
122 
123 	l = curlwp;
124 	KASSERT(l != NULL);
125 	p = l->l_proc;
126 	KASSERT(p != NULL);
127 	uvmexp.traps++;
128 	if (usermode) {
129 		type |= T_USER;
130 		oticks = p->p_sticks;
131 		l->l_addr->u_pcb.framep = frame;
132 		LWP_CACHE_CREDS(l, p);
133 	}
134 
135 	type &= ~(T_WRITE|T_PTEFETCH);
136 
137 
138 #ifdef TRAPDEBUG
139 if(frame->trap==7) goto fram;
140 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n",
141 		frame->trap, frame->code, frame->pc, frame->psl);
142 fram:
143 #endif
144 	switch (type) {
145 
146 	default:
147 #ifdef DDB
148 		kdb_trap(frame);
149 #endif
150 		panic("trap: type %x, code %x, pc %x, psl %x",
151 		    (u_int)frame->trap, (u_int)frame->code,
152 		    (u_int)frame->pc, (u_int)frame->psl);
153 
154 	case T_KSPNOTVAL:
155 		panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)",
156 		    p->p_pid, l->l_lid, l->l_name ? l->l_name : "??",
157 		    mfpr(PR_KSP), (u_int)frame->pc, l->l_addr,
158 		    (u_int)frame->fp, (u_int)frame->psl);
159 
160 	case T_TRANSFLT|T_USER:
161 	case T_TRANSFLT:
162 		/*
163 		 * BUG! BUG! BUG! BUG! BUG!
164 		 * Due to a hardware bug (at in least KA65x CPUs) a double
165 		 * page table fetch trap will cause a translation fault
166 		 * even if access in the SPT PTE entry specifies 'no access'.
167 		 * In for example section 6.4.2 in VAX Architecture
168 		 * Reference Manual it states that if a page both are invalid
169 		 * and have no access set, a 'access violation fault' occurs.
170 		 * Therefore, we must fall through here...
171 		 */
172 #ifdef nohwbug
173 		panic("translation fault");
174 #endif
175 
176 	case T_PTELEN|T_USER:	/* Page table length exceeded */
177 	case T_ACCFLT|T_USER:
178 		if (frame->code < 0) { /* Check for kernel space */
179 			sig = SIGSEGV;
180 			code = SEGV_ACCERR;
181 			break;
182 		}
183 
184 	case T_PTELEN:
185 	case T_ACCFLT:
186 #ifdef TRAPDEBUG
187 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n",
188 			frame->trap, frame->code, frame->pc, frame->psl);
189 #endif
190 #ifdef DIAGNOSTIC
191 		if (p == 0)
192 			panic("trap: access fault: addr %lx code %lx",
193 			    frame->pc, frame->code);
194 		if (frame->psl & PSL_IS)
195 			panic("trap: pflt on IS");
196 #endif
197 
198 		/*
199 		 * Page tables are allocated in pmap_enter(). We get
200 		 * info from below if it is a page table fault, but
201 		 * UVM may want to map in pages without faults, so
202 		 * because we must check for PTE pages anyway we don't
203 		 * bother doing it here.
204 		 */
205 		addr = trunc_page(frame->code);
206 		if (!usermode && (frame->code < 0)) {
207 			vm = NULL;
208 			map = kernel_map;
209 
210 		} else {
211 			vm = p->p_vmspace;
212 			map = &vm->vm_map;
213 		}
214 
215 		if (frame->trap & T_WRITE)
216 			ftype = VM_PROT_WRITE;
217 		else
218 			ftype = VM_PROT_READ;
219 
220 		rv = uvm_fault(map, addr, ftype);
221 		if (rv != 0) {
222 			if (!usermode) {
223 				FAULTCHK;
224 				panic("Segv in kernel mode: pc %x addr %x",
225 				    (u_int)frame->pc, (u_int)frame->code);
226 			}
227 			code = SEGV_ACCERR;
228 			if (rv == ENOMEM) {
229 				printf("UVM: pid %d (%s), uid %d killed: "
230 				       "out of swap\n",
231 				       p->p_pid, p->p_comm,
232 				       l->l_cred ?
233 				       kauth_cred_geteuid(l->l_cred) : -1);
234 				sig = SIGKILL;
235 			} else {
236 				sig = SIGSEGV;
237 				if (rv != EACCES)
238 					code = SEGV_MAPERR;
239 			}
240 		} else {
241 			trapsig = false;
242 			if (map != kernel_map && addr > 0
243 			    && (void *)addr >= vm->vm_maxsaddr)
244 				uvm_grow(p, addr);
245 		}
246 		break;
247 
248 	case T_BPTFLT|T_USER:
249 		sig = SIGTRAP;
250 		code = TRAP_BRKPT;
251 		break;
252 	case T_TRCTRAP|T_USER:
253 		sig = SIGTRAP;
254 		code = TRAP_TRACE;
255 		frame->psl &= ~PSL_T;
256 		break;
257 
258 	case T_PRIVINFLT|T_USER:
259 		sig = SIGILL;
260 		code = ILL_PRVOPC;
261 		break;
262 	case T_RESADFLT|T_USER:
263 		sig = SIGILL;
264 		code = ILL_ILLADR;
265 		break;
266 	case T_RESOPFLT|T_USER:
267 		sig = SIGILL;
268 		code = ILL_ILLOPC;
269 		break;
270 
271 	case T_XFCFLT|T_USER:
272 		sig = SIGEMT;
273 		break;
274 
275 	case T_ARITHFLT|T_USER:
276 		sig = SIGFPE;
277 		break;
278 
279 	case T_ASTFLT|T_USER:
280 		mtpr(AST_NO,PR_ASTLVL);
281 		trapsig = false;
282 		break;
283 
284 #ifdef DDB
285 	case T_BPTFLT: /* Kernel breakpoint */
286 	case T_KDBTRAP:
287 	case T_KDBTRAP|T_USER:
288 	case T_TRCTRAP:
289 		kdb_trap(frame);
290 		return;
291 #endif
292 	}
293 	if (trapsig) {
294 		ksiginfo_t ksi;
295 		if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps)
296 			printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n",
297 			       p->p_pid, l->l_lid, p->p_comm, sig, frame->trap,
298 			       frame->code, frame->pc, frame->psl);
299 		KSI_INIT_TRAP(&ksi);
300 		ksi.ksi_signo = sig;
301 		ksi.ksi_trap = frame->trap;
302 		ksi.ksi_addr = (void *)frame->code;
303 		ksi.ksi_code = code;
304 		trapsignal(l, &ksi);
305 	}
306 
307 	if (!usermode)
308 		return;
309 
310 	userret(l, frame, oticks);
311 }
312 
313 void
314 setregs(struct lwp *l, struct exec_package *pack, u_long stack)
315 {
316 	struct trapframe *exptr;
317 
318 	exptr = l->l_addr->u_pcb.framep;
319 	exptr->pc = pack->ep_entry + 2;
320 	exptr->sp = stack;
321 	exptr->r6 = stack;				/* for ELF */
322 	exptr->r7 = 0;					/* for ELF */
323 	exptr->r8 = 0;					/* for ELF */
324 	exptr->r9 = (u_long) l->l_proc->p_psstr;	/* for ELF */
325 }
326 
327 
328 /*
329  * Start a new LWP
330  */
331 void
332 startlwp(void *arg)
333 {
334 	int err;
335 	ucontext_t *uc = arg;
336 	struct lwp *l = curlwp;
337 
338 	err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
339 #if DIAGNOSTIC
340 	if (err) {
341 		printf("Error %d from cpu_setmcontext.", err);
342 	}
343 #endif
344 	pool_put(&lwp_uc_pool, uc);
345 
346 	/* XXX - profiling spoiled here */
347 	userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks);
348 }
349