xref: /netbsd-src/sys/arch/vax/vax/trap.c (revision 76dfffe33547c37f8bdd446e3e4ab0f3c16cea4b)
1 /*      $NetBSD: trap.c,v 1.24 1996/11/06 20:19:55 cgd 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                 cpu_switch(0);
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(frame->code<0x40000000){
195 				ptep=(u_int *)p->p_addr->u_pcb.P0BR;
196 				pte=&ptep[(frame->code>>PGSHIFT)];
197 			} else if(frame->code>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_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) P0++;
230 			else if(frame->code>0x7fffffff) SYS++;
231 			else P1++;
232 
233 			if(P0){
234 				faultaddr=(u_int)pm->pm_pcb->P0BR+
235 					((testaddr>>PGSHIFT)<<2);
236 			} else if(P1){
237 				faultaddr=(u_int)pm->pm_pcb->P1BR+
238 					((testaddr>>PGSHIFT)<<2);
239 			} else panic("pageflt: PTE fault in SPT\n");
240 
241 			faultaddr&=~PAGE_MASK;
242 			rv = vm_fault(pte_map, faultaddr,
243 				VM_PROT_WRITE|VM_PROT_READ, FALSE);
244 			if (rv != KERN_SUCCESS) {
245 
246 				sig=SIGSEGV;
247 				goto bad;
248 			} else
249 				trapsig=0;
250 		}
251 		addr=(frame->code& ~PAGE_MASK);
252 		if((frame->pc>(unsigned)0x80000000)&&
253 			(frame->code>(unsigned)0x80000000)){
254 			map=kernel_map;
255 		} else {
256 			map= &p->p_vmspace->vm_map;
257 		}
258 		if(frame->trap&T_WRITE) ftype=VM_PROT_WRITE|VM_PROT_READ;
259 		else ftype = VM_PROT_READ;
260 
261 		rv = vm_fault(map, addr, ftype, FALSE);
262 		if (rv != KERN_SUCCESS) {
263 			if(frame->pc>(u_int)0x80000000){
264 				if(p->p_addr->u_pcb.iftrap){
265 					frame->pc=(int)p->p_addr->u_pcb.iftrap;
266 					return;
267 				}
268 				printf("Segv in kernel mode: rv %d\n",rv);
269 				goto faulter;
270 			}
271 			sig=SIGSEGV;
272 		} else trapsig=0;
273 		break;
274 
275 	case T_PTELEN:
276 	case T_PTELEN|T_USER:	/* Page table length exceeded */
277 		pm=&p->p_vmspace->vm_pmap;
278 #ifdef TRAPDEBUG
279 if(faultdebug)printf("trap ptelen type %x, code %x, pc %x, psl %x\n",
280                         frame->trap, frame->code, frame->pc, frame->psl);
281 #endif
282 		if(frame->code<0x40000000){ /* P0 */
283 			int i;
284 
285 			if (p->p_vmspace == 0){
286 				printf("no vmspace in fault\n");
287 				goto faulter;
288 			}
289 			i = p->p_vmspace->vm_tsize + p->p_vmspace->vm_dsize;
290 			if (i > (frame->code >> PAGE_SHIFT)){
291 				pmap_expandp0(pm, i << 1);
292 				trapsig = 0;
293 			} else {
294 				sig = SIGSEGV;
295 			}
296 		} else if (frame->code > 0x7fffffff){ /* System, segv */
297 			sig = SIGSEGV;
298 		} else { /* P1 */
299 			int i;
300 
301 			i = (u_int)(p->p_vmspace->vm_maxsaddr);
302 			if (frame->code < i){
303 				sig = SIGSEGV;
304 			} else {
305 				pmap_expandp1(pm);
306 				trapsig = 0;
307 			}
308 		}
309 		break;
310 
311 	case T_BPTFLT|T_USER:
312 	case T_TRCTRAP|T_USER:
313 		sig = SIGTRAP;
314 		frame->psl &= ~PSL_T;
315 		break;
316 
317 	case T_PRIVINFLT|T_USER:
318 	case T_RESADFLT|T_USER:
319 	case T_RESOPFLT|T_USER:
320 		sig=SIGILL;
321 		break;
322 
323 	case T_ARITHFLT|T_USER:
324 		sig=SIGFPE;
325 		break;
326 
327 	case T_ASTFLT|T_USER:
328 		mtpr(AST_NO,PR_ASTLVL);
329 		trapsig=0;
330 		break;
331 
332 #ifdef DDB
333 	case T_KDBTRAP:
334 		kdb_trap(frame);
335 		return;
336 #endif
337 	}
338 bad:
339 	if (trapsig)
340 		trapsignal(curproc, sig, frame->code);
341 uret:
342 	userret(curproc, frame->pc, frame->psl);
343 };
344 
345 void
346 showstate(p)
347 	struct proc *p;
348 {
349 if(p){
350 	printf("\npid %d, command %s\n",p->p_pid, p->p_comm);
351 	printf("text size %x, data size %x, stack size %x\n",
352 		p->p_vmspace->vm_tsize, p->p_vmspace->vm_dsize,p->p_vmspace->
353 		vm_ssize);
354 	printf("virt text %x, virt data %x, max stack %x\n",
355 		(u_int)p->p_vmspace->vm_taddr, (u_int)p->p_vmspace->vm_daddr,
356 		(u_int)p->p_vmspace->vm_maxsaddr);
357 	printf("kernel uarea %x, end uarea %x\n",(u_int)p->p_addr,
358 		(u_int)p->p_addr + USPACE);
359 } else {
360 	printf("No process\n");
361 }
362 	printf("kernel stack: %x, interrupt stack %x\n",
363 		mfpr(PR_KSP),mfpr(PR_ISP));
364 	printf("P0BR %x, P0LR %x, P1BR %x, P1LR %x\n",
365 		mfpr(PR_P0BR),mfpr(PR_P0LR),mfpr(PR_P1BR),mfpr(PR_P1LR));
366 }
367 
368 void
369 setregs(p, pack, stack, retval)
370         struct proc *p;
371 	struct exec_package *pack;
372         u_long stack;
373         register_t retval[2];
374 {
375 	struct trapframe *exptr;
376 
377 	exptr = p->p_addr->u_pcb.framep;
378 	exptr->pc = pack->ep_entry + 2;
379 	exptr->sp = stack;
380 	retval[0] = retval[1] = 0;
381 }
382 
383 void
384 syscall(frame)
385 	struct	trapframe *frame;
386 {
387 	struct sysent *callp;
388 	int nsys;
389 	int err, rval[2], args[8];
390 	struct trapframe *exptr;
391 	struct proc *p = curproc;
392 
393 #ifdef TRAPDEBUG
394 if(startsysc)printf("trap syscall %s pc %x, psl %x, sp %x, pid %d, frame %x\n",
395                syscallnames[frame->code], frame->pc, frame->psl,frame->sp,
396 		curproc->p_pid,frame);
397 #endif
398 
399 	exptr = p->p_addr->u_pcb.framep = frame;
400 	callp = p->p_emul->e_sysent;
401 	nsys = p->p_emul->e_nsysent;
402 
403 	if(frame->code == SYS___syscall){
404 		int g = *(int *)(frame->ap);
405 
406 		frame->code=*(int *)(frame->ap+4);
407 		frame->ap+=8;
408 		*(int *)(frame->ap)=g-2;
409 	}
410 
411 	if(frame->code<0||frame->code>=nsys)
412 		callp += p->p_emul->e_nosys;
413 	else
414 		callp += frame->code;
415 
416 	rval[0]=0;
417 	rval[1]=frame->r1;
418 	if(callp->sy_narg) {
419 		err = copyin((char*)frame->ap+4, args, callp->sy_argsize);
420 		if (err) {
421 #ifdef KTRACE
422 			if (KTRPOINT(p, KTR_SYSCALL))
423 				ktrsyscall(p->p_tracep, frame->code,
424 				    callp->sy_argsize, args);
425 #endif
426 			goto bad;
427 		}
428 	}
429 #ifdef KTRACE
430 	if (KTRPOINT(p, KTR_SYSCALL))
431 		ktrsyscall(p->p_tracep, frame->code, callp->sy_argsize, args);
432 #endif
433 	err=(*callp->sy_call)(curproc,args,rval);
434 	exptr = curproc->p_addr->u_pcb.framep;
435 
436 #ifdef TRAPDEBUG
437 if(startsysc)
438 	printf("retur %s pc %x, psl %x, sp %x, pid %d, v{rde %d r0 %d, r1 %d, frame %x\n",
439                syscallnames[exptr->code], exptr->pc, exptr->psl,exptr->sp,
440                 curproc->p_pid,err,rval[0],rval[1],exptr);
441 #endif
442 
443 bad:
444 	switch (err) {
445 	case 0:
446 		exptr->r1 = rval[1];
447 		exptr->r0 = rval[0];
448 		exptr->psl &= ~PSL_C;
449 		break;
450 
451 	case EJUSTRETURN:
452 		return;
453 
454 	case ERESTART:
455 		exptr->pc = exptr->pc-2;
456 		break;
457 
458 	default:
459 		exptr->r0 = err;
460 		exptr->psl |= PSL_C;
461 		break;
462 	}
463 	userret(curproc, exptr->pc, exptr->psl);
464 #ifdef KTRACE
465 	if (KTRPOINT(p, KTR_SYSRET))
466 		ktrsysret(p->p_tracep, frame->code, err, rval[0]);
467 #endif
468 }
469 
470 void
471 stray(scb, vec)
472 	int scb, vec;
473 {
474 	printf("stray interrupt scb %d, vec 0x%x\n", scb, vec);
475 }
476 
477 void
478 printstack(loaddr, highaddr)
479 	u_int *loaddr, *highaddr;
480 {
481 	u_int *tmp;
482 
483 	(u_int)tmp = 0xfffffffc & (u_int)loaddr; /* Easy align */
484 
485 	for (;tmp < highaddr;tmp += 4)
486 		printf("%8x:  %8x  %8x  %8x  %8x\n",
487 		    (int)tmp, *tmp, *(tmp + 1), *(tmp + 2), *(tmp + 3));
488 }
489 
490 void
491 showregs(frame)
492 	struct trapframe *frame;
493 {
494 	printf("P0BR %8x   P1BR %8x   P0LR %8x   P1LR %8x\n",
495 	    mfpr(PR_P0BR), mfpr(PR_P1BR), mfpr(PR_P0LR), mfpr(PR_P1LR));
496 	printf("KSP  %8x   ISP  %8x   USP  %8x\n",
497 	    mfpr(PR_KSP), mfpr(PR_ISP), mfpr(PR_USP));
498 	printf("R0   %8x   R1   %8x   R2   %8x   R3   %8x\n",
499 	    frame->r0, frame->r1, frame->r2, frame->r3);
500 	printf("R4   %8x   R5   %8x   R6   %8x   R7   %8x\n",
501 	    frame->r4, frame->r5, frame->r6, frame->r7);
502 	printf("R8   %8x   R9   %8x   R10  %8x   R11  %8x\n",
503 	    frame->r8, frame->r9, frame->r10, frame->r11);
504 	printf("FP   %8x   AP   %8x   PC   %8x   PSL  %8x\n",
505 	    frame->fp, frame->ap, frame->pc, frame->psl);
506 }
507