xref: /netbsd-src/sys/arch/vax/vax/trap.c (revision fdecd6a253f999ae92b139670d9e15cc9df4497c)
1 /*      $NetBSD: trap.c,v 1.27 1997/07/06 22:38:23 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  * 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 
36 
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/proc.h>
40 #include <sys/user.h>
41 #include <sys/syscall.h>
42 #include <sys/systm.h>
43 #include <sys/signalvar.h>
44 #include <sys/exec.h>
45 
46 #include <vm/vm.h>
47 #include <vm/vm_kern.h>
48 #include <vm/vm_page.h>
49 
50 #include <machine/mtpr.h>
51 #include <machine/pte.h>
52 #include <machine/pcb.h>
53 #include <machine/trap.h>
54 #include <machine/pmap.h>
55 
56 #ifdef DDB
57 #include <machine/db_machdep.h>
58 #endif
59 #include <kern/syscalls.c>
60 #ifdef KTRACE
61 #include <sys/ktrace.h>
62 #endif
63 
64 extern 	int want_resched,whichqs;
65 #ifdef TRAPDEBUG
66 volatile int startsysc=0,faultdebug=0;
67 #endif
68 
69 static	void userret __P((struct proc *, u_int, u_int));
70 void	arithflt __P((struct trapframe *));
71 void	syscall __P((struct trapframe *));
72 void	showregs __P((struct trapframe *));
73 void	showstate __P((struct proc *));
74 void	stray __P((int, int));
75 void	printstack __P((u_int *, u_int *));
76 
77 void
78 userret(p, pc, psl)
79 	struct proc *p;
80 	u_int pc, psl;
81 {
82 	int s,sig;
83 
84         while ((sig = CURSIG(p)) !=0)
85                 postsig(sig);
86         p->p_priority = p->p_usrpri;
87         if (want_resched) {
88                 /*
89                  * Since we are curproc, clock will normally just change
90                  * our priority without moving us from one queue to another
91                  * (since the running process is not on a queue.)
92                  * If that happened after we setrunqueue ourselves but before
93 		 * we swtch()'ed, we might not be on the queue indicated by
94                  * our priority.
95                  */
96                 s=splstatclock();
97                 setrunqueue(curproc);
98                 mi_switch();
99                 splx(s);
100                 while ((sig = CURSIG(curproc)) != 0)
101                         postsig(sig);
102         }
103 
104         curpriority = curproc->p_priority;
105 }
106 
107 char *traptypes[]={
108 	"reserved addressing",
109 	"privileged instruction",
110 	"reserved operand",
111 	"breakpoint instruction",
112 	"Nothing",
113 	"system call ",
114 	"arithmetic trap",
115 	"asynchronous system trap",
116 	"page table length fault",
117 	"translation violation fault",
118 	"trace trap",
119 	"compatibility mode fault",
120 	"access violation fault",
121 	"",
122 	"",
123 	"KSP invalid",
124 	"",
125 	"kernel debugger trap"
126 };
127 int no_traps = 18;
128 
129 void
130 arithflt(frame)
131 	struct trapframe *frame;
132 {
133 	u_int	sig, type=frame->trap,trapsig=1,s;
134 	u_int	rv, addr;
135 	struct	proc *p=curproc;
136 	struct	pmap *pm;
137 	vm_map_t map;
138 	vm_prot_t ftype;
139 	extern vm_map_t	pte_map;
140 
141 	if((frame->psl & PSL_U) == PSL_U) {
142 		type|=T_USER;
143 		p->p_addr->u_pcb.framep = frame;
144 	}
145 
146 	type&=~(T_WRITE|T_PTEFETCH);
147 
148 
149 #ifdef TRAPDEBUG
150 if(frame->trap==7) goto fram;
151 if(faultdebug)printf("Trap: type %x, code %x, pc %x, psl %x\n",
152 		frame->trap, frame->code, frame->pc, frame->psl);
153 fram:
154 #endif
155 	switch(type){
156 
157 	default:
158 faulter:
159 #ifdef DDB
160 		kdb_trap(frame);
161 #endif
162 		printf("Trap: type %x, code %x, pc %x, psl %x\n",
163 		    frame->trap, frame->code, frame->pc, frame->psl);
164 		showregs(frame);
165 		panic("trap: adr %x",frame->code);
166 	case T_KSPNOTVAL:
167 		goto faulter;
168 
169 	case T_TRANSFLT|T_USER:
170 	case T_TRANSFLT: /* Translation invalid - may be simul page ref */
171 		if(frame->trap&T_PTEFETCH){
172 			u_int	*ptep, *pte, *pte1;
173 
174 			if(frame->code<0x40000000)
175 				ptep=(u_int *)p->p_addr->u_pcb.P0BR;
176 			else
177 				ptep=(u_int *)p->p_addr->u_pcb.P1BR;
178 			pte1=(u_int *)trunc_page(&ptep[(frame->code
179 				&0x3fffffff)>>PGSHIFT]);
180 			pte=(u_int*)&Sysmap[((u_int)pte1&0x3fffffff)>>PGSHIFT];
181 			if(*pte&PG_SREF){ /* Yes, simulated */
182 				s=splhigh();
183 
184 				*pte|=PG_REF|PG_V;*pte&=~PG_SREF;pte++;
185 				*pte|=PG_REF|PG_V;*pte&=~PG_SREF;
186 				mtpr(0,PR_TBIA);
187 				splx(s);
188 				goto uret;
189 			}
190 		} else {
191 			u_int   *ptep, *pte;
192 
193 			frame->code = trunc_page(frame->code);
194 			if ((u_int)frame->code < (u_int)0x40000000) {
195 				ptep = (u_int *)p->p_addr->u_pcb.P0BR;
196 				pte = &ptep[(frame->code >> PGSHIFT)];
197 			} else if ((u_int)frame->code > (u_int)0x7fffffff) {
198 				pte = (u_int *)&Sysmap[((u_int)frame->code &
199 					0x3fffffff) >> PGSHIFT];
200 			} else {
201 				ptep = (u_int *)p->p_addr->u_pcb.P1BR;
202 				pte = &ptep[(frame->code&0x3fffffff)>>PGSHIFT];
203 			}
204 			if (*pte & PG_SREF) {
205 				s = splhigh();
206 				*pte|=PG_REF|PG_V;*pte&=~PG_SREF;pte++;
207 				*pte|=PG_REF|PG_V;*pte&=~PG_SREF;
208 			/*	mtpr(frame->code,PR_TBIS); */
209 			/*	mtpr(frame->code+NBPG,PR_TBIS); */
210 				mtpr(0,PR_TBIA);
211 				splx(s);
212 				goto uret;
213 			}
214 		}
215 		/* Fall into... */
216 	case T_ACCFLT:
217 	case T_ACCFLT|T_USER:
218 #ifdef TRAPDEBUG
219 if(faultdebug)printf("trap accflt type %x, code %x, pc %x, psl %x\n",
220                         frame->trap, frame->code, frame->pc, frame->psl);
221 #endif
222 		if (!p)
223 			panic("trap: access fault without process");
224 		pm = p->p_vmspace->vm_map.pmap;
225 		if(frame->trap&T_PTEFETCH){
226 			u_int faultaddr,testaddr=(u_int)frame->code&0x3fffffff;
227 			int P0 = 0, P1 = 0, SYS = 0;
228 
229 			if (frame->code == testaddr)
230 				P0++;
231 			else if ((u_int)frame->code > (u_int)0x7fffffff)
232 				SYS++;
233 			else
234 				P1++;
235 
236 			if (P0) {
237 				faultaddr = (u_int)pm->pm_pcb->P0BR +
238 					((testaddr >> PGSHIFT) << 2);
239 			} else if (P1) {
240 				faultaddr= (u_int)pm->pm_pcb->P1BR +
241 					((testaddr >> PGSHIFT) << 2);
242 			} else
243 				panic("pageflt: PTE fault in SPT\n");
244 
245 			faultaddr &= ~PAGE_MASK;
246 			rv = vm_fault(pte_map, faultaddr,
247 				VM_PROT_WRITE|VM_PROT_READ, FALSE);
248 			if (rv != KERN_SUCCESS) {
249 
250 				sig = SIGSEGV;
251 				goto bad;
252 			} else
253 				trapsig = 0;
254 		}
255 		addr=(frame->code& ~PAGE_MASK);
256 		if((frame->pc>(unsigned)0x80000000)&&
257 			(frame->code>(unsigned)0x80000000)){
258 			map=kernel_map;
259 		} else {
260 			map= &p->p_vmspace->vm_map;
261 		}
262 		if(frame->trap&T_WRITE) ftype=VM_PROT_WRITE|VM_PROT_READ;
263 		else ftype = VM_PROT_READ;
264 
265 		rv = vm_fault(map, addr, ftype, FALSE);
266 		if (rv != KERN_SUCCESS) {
267 			if(frame->pc>(u_int)0x80000000){
268 				if(p->p_addr->u_pcb.iftrap){
269 					frame->pc=(int)p->p_addr->u_pcb.iftrap;
270 					return;
271 				}
272 				printf("Segv in kernel mode: rv %d\n",rv);
273 				goto faulter;
274 			}
275 			sig=SIGSEGV;
276 		} else trapsig=0;
277 		break;
278 
279 	case T_PTELEN:
280 	case T_PTELEN|T_USER:	/* Page table length exceeded */
281 		pm = p->p_vmspace->vm_map.pmap;
282 #ifdef TRAPDEBUG
283 if(faultdebug)printf("trap ptelen type %x, code %x, pc %x, psl %x\n",
284                         frame->trap, frame->code, frame->pc, frame->psl);
285 #endif
286 		if ((u_int)frame->code < (u_int)0x40000000) { /* P0 */
287 			int i;
288 
289 			if (p->p_vmspace == 0){
290 				printf("no vmspace in fault\n");
291 				goto faulter;
292 			}
293 			i = p->p_vmspace->vm_tsize + p->p_vmspace->vm_dsize;
294 			if (i > (frame->code >> PAGE_SHIFT)){
295 				pmap_expandp0(pm, i << 1);
296 				trapsig = 0;
297 			} else {
298 				sig = SIGSEGV;
299 			}
300 		} else if ((u_int)frame->code > (u_int)0x7fffffff){ /* System, segv */
301 			sig = SIGSEGV;
302 		} else { /* P1 */
303 			int i;
304 
305 			i = (u_int)(p->p_vmspace->vm_maxsaddr);
306 			if (frame->code < i){
307 				sig = SIGSEGV;
308 			} else {
309 				pmap_expandp1(pm);
310 				trapsig = 0;
311 			}
312 		}
313 		break;
314 
315 	case T_BPTFLT|T_USER:
316 	case T_TRCTRAP|T_USER:
317 		sig = SIGTRAP;
318 		frame->psl &= ~PSL_T;
319 		break;
320 
321 	case T_PRIVINFLT|T_USER:
322 	case T_RESADFLT|T_USER:
323 	case T_RESOPFLT|T_USER:
324 		sig=SIGILL;
325 		break;
326 
327 	case T_ARITHFLT|T_USER:
328 		sig=SIGFPE;
329 		break;
330 
331 	case T_ASTFLT|T_USER:
332 		mtpr(AST_NO,PR_ASTLVL);
333 		trapsig=0;
334 		break;
335 
336 #ifdef DDB
337 	case T_KDBTRAP:
338 		kdb_trap(frame);
339 		return;
340 #endif
341 	}
342 bad:
343 	if (trapsig)
344 		trapsignal(curproc, sig, frame->code);
345 uret:
346 	userret(curproc, frame->pc, frame->psl);
347 };
348 
349 void
350 showstate(p)
351 	struct proc *p;
352 {
353 if(p){
354 	printf("\npid %d, command %s\n",p->p_pid, p->p_comm);
355 	printf("text size %x, data size %x, stack size %x\n",
356 		p->p_vmspace->vm_tsize, p->p_vmspace->vm_dsize,p->p_vmspace->
357 		vm_ssize);
358 	printf("virt text %x, virt data %x, max stack %x\n",
359 		(u_int)p->p_vmspace->vm_taddr, (u_int)p->p_vmspace->vm_daddr,
360 		(u_int)p->p_vmspace->vm_maxsaddr);
361 	printf("kernel uarea %x, end uarea %x\n",(u_int)p->p_addr,
362 		(u_int)p->p_addr + USPACE);
363 } else {
364 	printf("No process\n");
365 }
366 	printf("kernel stack: %x, interrupt stack %x\n",
367 		mfpr(PR_KSP),mfpr(PR_ISP));
368 	printf("P0BR %x, P0LR %x, P1BR %x, P1LR %x\n",
369 		mfpr(PR_P0BR),mfpr(PR_P0LR),mfpr(PR_P1BR),mfpr(PR_P1LR));
370 }
371 
372 void
373 setregs(p, pack, stack, retval)
374         struct proc *p;
375 	struct exec_package *pack;
376         u_long stack;
377         register_t retval[2];
378 {
379 	struct trapframe *exptr;
380 
381 	exptr = p->p_addr->u_pcb.framep;
382 	exptr->pc = pack->ep_entry + 2;
383 	exptr->sp = stack;
384 	retval[0] = retval[1] = 0;
385 }
386 
387 void
388 syscall(frame)
389 	struct	trapframe *frame;
390 {
391 	struct sysent *callp;
392 	int nsys;
393 	int err, rval[2], args[8];
394 	struct trapframe *exptr;
395 	struct proc *p = curproc;
396 
397 #ifdef TRAPDEBUG
398 if(startsysc)printf("trap syscall %s pc %x, psl %x, sp %x, pid %d, frame %x\n",
399                syscallnames[frame->code], frame->pc, frame->psl,frame->sp,
400 		curproc->p_pid,frame);
401 #endif
402 
403 	exptr = p->p_addr->u_pcb.framep = frame;
404 	callp = p->p_emul->e_sysent;
405 	nsys = p->p_emul->e_nsysent;
406 
407 	if(frame->code == SYS___syscall){
408 		int g = *(int *)(frame->ap);
409 
410 		frame->code=*(int *)(frame->ap+4);
411 		frame->ap+=8;
412 		*(int *)(frame->ap)=g-2;
413 	}
414 
415 	if(frame->code<0||frame->code>=nsys)
416 		callp += p->p_emul->e_nosys;
417 	else
418 		callp += frame->code;
419 
420 	rval[0]=0;
421 	rval[1]=frame->r1;
422 	if(callp->sy_narg) {
423 		err = copyin((char*)frame->ap+4, args, callp->sy_argsize);
424 		if (err) {
425 #ifdef KTRACE
426 			if (KTRPOINT(p, KTR_SYSCALL))
427 				ktrsyscall(p->p_tracep, frame->code,
428 				    callp->sy_argsize, args);
429 #endif
430 			goto bad;
431 		}
432 	}
433 #ifdef KTRACE
434 	if (KTRPOINT(p, KTR_SYSCALL))
435 		ktrsyscall(p->p_tracep, frame->code, callp->sy_argsize, args);
436 #endif
437 	err=(*callp->sy_call)(curproc,args,rval);
438 	exptr = curproc->p_addr->u_pcb.framep;
439 
440 #ifdef TRAPDEBUG
441 if(startsysc)
442 	printf("retur %s pc %x, psl %x, sp %x, pid %d, v{rde %d r0 %d, r1 %d, frame %x\n",
443                syscallnames[exptr->code], exptr->pc, exptr->psl,exptr->sp,
444                 curproc->p_pid,err,rval[0],rval[1],exptr);
445 #endif
446 
447 bad:
448 	switch (err) {
449 	case 0:
450 		exptr->r1 = rval[1];
451 		exptr->r0 = rval[0];
452 		exptr->psl &= ~PSL_C;
453 		break;
454 
455 	case EJUSTRETURN:
456 		return;
457 
458 	case ERESTART:
459 		exptr->pc = exptr->pc-2;
460 		break;
461 
462 	default:
463 		exptr->r0 = err;
464 		exptr->psl |= PSL_C;
465 		break;
466 	}
467 	userret(curproc, exptr->pc, exptr->psl);
468 #ifdef KTRACE
469 	if (KTRPOINT(p, KTR_SYSRET))
470 		ktrsysret(p->p_tracep, frame->code, err, rval[0]);
471 #endif
472 }
473 
474 void
475 stray(scb, vec)
476 	int scb, vec;
477 {
478 	printf("stray interrupt scb %d, vec 0x%x\n", scb, vec);
479 }
480 
481 void
482 printstack(loaddr, highaddr)
483 	u_int *loaddr, *highaddr;
484 {
485 	u_int *tmp;
486 
487 	(u_int)tmp = 0xfffffffc & (u_int)loaddr; /* Easy align */
488 
489 	for (;tmp < highaddr;tmp += 4)
490 		printf("%8x:  %8x  %8x  %8x  %8x\n",
491 		    (int)tmp, *tmp, *(tmp + 1), *(tmp + 2), *(tmp + 3));
492 }
493 
494 void
495 showregs(frame)
496 	struct trapframe *frame;
497 {
498 	printf("P0BR %8x   P1BR %8x   P0LR %8x   P1LR %8x\n",
499 	    mfpr(PR_P0BR), mfpr(PR_P1BR), mfpr(PR_P0LR), mfpr(PR_P1LR));
500 	printf("KSP  %8x   ISP  %8x   USP  %8x\n",
501 	    mfpr(PR_KSP), mfpr(PR_ISP), mfpr(PR_USP));
502 	printf("R0   %8x   R1   %8x   R2   %8x   R3   %8x\n",
503 	    frame->r0, frame->r1, frame->r2, frame->r3);
504 	printf("R4   %8x   R5   %8x   R6   %8x   R7   %8x\n",
505 	    frame->r4, frame->r5, frame->r6, frame->r7);
506 	printf("R8   %8x   R9   %8x   R10  %8x   R11  %8x\n",
507 	    frame->r8, frame->r9, frame->r10, frame->r11);
508 	printf("FP   %8x   AP   %8x   PC   %8x   PSL  %8x\n",
509 	    frame->fp, frame->ap, frame->pc, frame->psl);
510 }
511