xref: /netbsd-src/sys/arch/vax/vax/trap.c (revision ce0bb6e8d2e560ecacbe865a848624f94498063b)
1 /*      $NetBSD: trap.c,v 1.8 1995/03/30 21:25:45 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 "vm/vm.h"
45 #include "vm/vm_kern.h"
46 #include "vm/vm_page.h"
47 #include "vax/include/mtpr.h"
48 #include "vax/include/pte.h"
49 #include "vax/include/pcb.h"
50 #include "vax/include/trap.h"
51 #include "vax/include/pmap.h"
52 #include "kern/syscalls.c"
53 
54 
55 extern 	int want_resched,whichqs;
56 volatile int startsysc=0,ovalidstart=0,faultdebug=0,haltfault=0;
57 
58 
59 userret(p, pc, psl)
60 	struct proc *p;
61 	u_int pc, psl;
62 {
63 	int s,sig;
64 
65         while ((sig = CURSIG(p)) !=0)
66                 postsig(sig);
67         p->p_priority = p->p_usrpri;
68         if (want_resched) {
69                 /*
70                  * Since we are curproc, clock will normally just change
71                  * our priority without moving us from one queue to another
72                  * (since the running process is not on a queue.)
73                  * If that happened after we setrq ourselves but before we
74                  * swtch()'ed, we might not be on the queue indicated by
75                  * our priority.
76                  */
77                 s=splstatclock();
78                 setrunqueue(curproc);
79                 cpu_switch();
80                 splx(s);
81                 while ((sig = CURSIG(curproc)) != 0)
82                         postsig(sig);
83         }
84 
85         curpriority = curproc->p_priority;
86 }
87 
88 char *traptypes[]={
89 	"reserved addressing",
90 	"privileged instruction",
91 	"reserved operand",
92 	"breakpoint instruction",
93 	"Nothing",
94 	"system call ",
95 	"arithmetic trap",
96 	"asynchronous system trap",
97 	"page table length fault",
98 	"translation violation fault",
99 	"trace trap",
100 	"compatibility mode fault",
101 	"access violation fault",
102 };
103 
104 arithflt(frame)
105 	struct trapframe *frame;
106 {
107 	u_int	sig, type=frame->trap,trapsig=1,s;
108 	u_int	rv, addr,*i,j;
109 	struct	proc *p=curproc;
110 	struct	pmap *pm;
111 	vm_map_t map;
112 	vm_prot_t ftype;
113 	extern vm_map_t	pte_map;
114 
115 	if((frame->psl & PSL_U) == PSL_U)
116 		type|=T_USER;
117 
118 	type&=~(T_WRITE|T_PTEFETCH);
119 	switch(type){
120 
121 	default:
122 faulter:
123 		if(frame->trap<12)
124 			printf("\nKernel fault: %s. Stack dump:\n\n",
125 				traptypes[frame->trap]);
126 		else
127 			printf("\nKernel fault: %d. Stack dump:\n\n",
128 				frame->trap);
129 		printf("FP %8x AP %8x R0 %8x R1 %8x\n",frame->fp,
130 			frame->ap, frame->r0, frame->r1);
131 		printf("R2 %8x R3 %8x R4 %8x R5 %8x\n",frame->r2,frame->r3,
132 			frame->r4,frame->r5);
133 		printf("TRAP %2x CODE %6x PC %8x PSL %8x\n",frame->trap,
134 			frame->code, frame->pc, frame->psl);
135 			i=(u_int*)&(frame->psl);
136 		printf("(RET PC) %8x, (RET PSL) %8x\n",i[1],i[2]);
137 		for(j=3;j<15;j+=4)
138 			printf("%8x %8x %8x %8x\n",i[j],i[j+1],i[j+2],
139 				i[j+3]);
140 		asm("halt");
141 		printf("trap type %x, code %x, pc %x, psl %x\n",
142 			frame->trap, frame->code, frame->pc, frame->psl);
143 		showstate(curproc);
144 		asm("halt");
145 		panic("trap");
146 
147 	case T_TRANSFLT|T_USER:
148 	case T_TRANSFLT: /* Translation invalid - may be simul page ref */
149 		if(frame->trap&T_PTEFETCH){
150 			u_int	*ptep, *pte, *pte1;
151 
152 			if(frame->code<0x40000000)
153 				ptep=(u_int *)p->p_addr->u_pcb.P0BR;
154 			else
155 				ptep=(u_int *)p->p_addr->u_pcb.P1BR;
156 			pte1=(u_int *)trunc_page(&ptep[(frame->code
157 				&0x3fffffff)>>PG_SHIFT]);
158 			pte=(u_int*)&Sysmap[((u_int)pte1&0x3fffffff)>>PG_SHIFT];
159 			if(*pte&PG_SREF){ /* Yes, simulated */
160 				s=splhigh();
161 
162 				*pte|=PG_REF|PG_V;*pte&=~PG_SREF;pte++;
163 				*pte|=PG_REF|PG_V;*pte&=~PG_SREF;
164 				mtpr(0,PR_TBIA);
165 				splx(s);
166 				goto uret;
167 			}
168 		} else {
169 			u_int   *ptep, *pte;
170 
171 			frame->code=trunc_page(frame->code);
172 			if(frame->code<0x40000000){
173 				ptep=(u_int *)p->p_addr->u_pcb.P0BR;
174 				pte=&ptep[(frame->code>>PG_SHIFT)];
175 			} else if(frame->code>0x7fffffff){
176 				pte=(u_int *)&Sysmap[((u_int)frame->code&
177 					0x3fffffff)>>PG_SHIFT];
178 			} else {
179 				ptep=(u_int *)p->p_addr->u_pcb.P1BR;
180 				pte=&ptep[(frame->code&0x3fffffff)>>PG_SHIFT];
181 			}
182 			if(*pte&PG_SREF){
183 				s=splhigh();
184 				*pte|=PG_REF|PG_V;*pte&=~PG_SREF;pte++;
185 				*pte|=PG_REF|PG_V;*pte&=~PG_SREF;
186 			/*	mtpr(frame->code,PR_TBIS); */
187 			/*	mtpr(frame->code+NBPG,PR_TBIS); */
188 				mtpr(0,PR_TBIA);
189 				splx(s);
190 				goto uret;
191 			}
192 		}
193 		/* Fall into... */
194 	case T_ACCFLT:
195 	case T_ACCFLT|T_USER:
196         {u_int tmpo=frame->code&0x7fffff00;
197          u_int tmpp=frame->pc&0x7fffff00;
198 	 extern u_int sigsida;
199 
200         if((tmpo==0x7fffe000)&&(tmpp==0x7fffe000)){
201                 u_int *hej=(u_int *)(mfpr(PR_P1BR)+0x7fffc0);
202 /*		printf("Faultar sigsida: pid %d\n", p->p_pid); */
203                 *hej=0xf8000000|(sigsida>>PG_SHIFT);
204                 mtpr(0x7fffe000,PR_TBIS);
205                 return;
206         }}
207 if(faultdebug)printf("trap accflt type %x, code %x, pc %x, psl %x\n",
208                         frame->trap, frame->code, frame->pc, frame->psl);
209 
210 		if(!p) panic("trap: access fault without process");
211 		pm=&p->p_vmspace->vm_pmap;
212 		if(frame->trap&T_PTEFETCH){
213 			u_int faultaddr,testaddr=(u_int)frame->code&0x3fffffff;
214 			int P0=0,P1=0,SYS=0;
215 
216 			if(frame->code==testaddr) P0++;
217 			else if(frame->code>0x7fffffff) SYS++;
218 			else P1++;
219 
220 			if(P0){
221 				faultaddr=(u_int)pm->pm_pcb->P0BR+
222 					((testaddr>>PG_SHIFT)<<2);
223 			} else if(P1){
224 				faultaddr=(u_int)pm->pm_pcb->P1BR+
225 					((testaddr>>PG_SHIFT)<<2);
226 			} else panic("pageflt: PTE fault in SPT\n");
227 
228 			faultaddr&=~PAGE_MASK;
229 			rv = vm_fault(pte_map, faultaddr,
230 				VM_PROT_WRITE|VM_PROT_READ, FALSE);
231 			if (rv != KERN_SUCCESS) {
232 
233 				sig=SIGSEGV;
234 			} else trapsig=0;
235 /*			return; /* We don't know if it was a trap only for PTE*/
236 			break;
237 		}
238 		addr=(frame->code& ~PAGE_MASK);
239 		if((frame->pc>(unsigned)0x80000000)&&
240 			(frame->code>(unsigned)0x80000000)){
241 			map=kernel_map;
242 		} else {
243 			map= &p->p_vmspace->vm_map;
244 		}
245 		if(frame->trap&T_WRITE) ftype=VM_PROT_WRITE|VM_PROT_READ;
246 		else ftype = VM_PROT_READ;
247 
248 		rv = vm_fault(map, addr, ftype, FALSE);
249 		if (rv != KERN_SUCCESS) {
250 			if(frame->pc>(u_int)0x80000000){
251 				if(p->p_addr->u_pcb.iftrap){
252 					frame->pc=p->p_addr->u_pcb.iftrap;
253 					return;
254 				}
255 				printf("Segv in kernel mode: rv %d\n",rv);
256 				goto faulter;
257 			}
258 			sig=SIGSEGV;
259 		} else trapsig=0;
260 		break;
261 
262 	case T_PTELEN:
263 	case T_PTELEN|T_USER:	/* Page table length exceeded */
264 		pm=&p->p_vmspace->vm_pmap;
265 if(faultdebug)printf("trap ptelen type %x, code %x, pc %x, psl %x\n",
266                         frame->trap, frame->code, frame->pc, frame->psl);
267 		if(frame->code<0x40000000){ /* P0 */
268 			int i=p->p_vmspace->vm_tsize+p->p_vmspace->vm_dsize;
269 			if(i>(frame->code>>PAGE_SHIFT)){
270 				pmap_expandp0(pm,i<<1);
271 				trapsig=0;
272 			} else {
273 				sig=SIGSEGV;
274 			}
275 		} else if(frame->code>0x7fffffff){ /* System, segv */
276 			sig=SIGSEGV;
277 		} else { /* P1 */
278 			int i=(u_int)(p->p_vmspace->vm_maxsaddr);
279 			if(frame->code<i){
280 				sig=SIGSEGV;
281 			} else {
282 				pmap_expandp1(pm);
283 				trapsig=0;
284 			}
285 		}
286 		break;
287 
288 	case T_PRIVINFLT|T_USER:
289 	case T_RESADFLT|T_USER:
290 	case T_RESOPFLT|T_USER:
291 		sig=SIGILL;
292 		break;
293 
294 	case T_ARITHFLT|T_USER:
295 		sig=SIGFPE;
296 		break;
297 
298 	case T_ASTFLT|T_USER:
299 		mtpr(AST_NO,PR_ASTLVL);
300 		trapsig=0;
301 		break;
302 	}
303 	if(trapsig) trapsignal(curproc, sig, frame->code);
304 uret:
305 	userret(curproc, frame->pc, frame->psl);
306 };
307 
308 showstate(p)
309 	struct proc *p;
310 {
311 if(p){
312 	printf("\npid %d, command %s\n",p->p_pid, p->p_comm);
313 	printf("text size %x, data size %x, stack size %x\n",
314 		p->p_vmspace->vm_tsize, p->p_vmspace->vm_dsize,p->p_vmspace->
315 		vm_ssize);
316 	printf("virt text %x, virt data %x, max stack %x\n",
317 		p->p_vmspace->vm_taddr,p->p_vmspace->vm_daddr,
318 		p->p_vmspace->vm_maxsaddr);
319 	printf("user pte p0br %x, user stack addr %x\n",
320 		p->p_vmspace->vm_pmap.pm_pcb->P0BR, mfpr(PR_USP));
321 } else {
322 	printf("No process\n");
323 }
324 	printf("kernel stack: %x, interrupt stack %x\n",
325 		mfpr(PR_KSP),mfpr(PR_ISP));
326 	printf("P0BR %x, P0LR %x, P1BR %x, P1LR %x\n",
327 		mfpr(PR_P0BR),mfpr(PR_P0LR),mfpr(PR_P1BR),mfpr(PR_P1LR));
328 }
329 
330 setregs(p,pack,stack,retval)
331         struct proc *p;
332         int pack,stack,retval[2]; /* Not all are ints... */
333 {
334 	struct trapframe *exptr;
335 
336 	exptr=p->p_addr->u_pcb.framep;
337 	exptr->pc=pack+2;
338 	mtpr(stack,PR_USP);
339 }
340 
341 syscall(frame)
342 	struct	trapframe *frame;
343 {
344 	struct sysent *callp;
345 	int err,rval[2],args[8],sig;
346 	struct trapframe *exptr;
347 	struct proc *p=curproc;
348 
349 if(startsysc)printf("trap syscall %s pc %x, psl %x, ap %x, pid %d\n",
350                syscallnames[frame->code], frame->pc, frame->psl,frame->ap,
351 		curproc->p_pid);
352 
353 	p->p_addr->u_pcb.framep=frame;
354 
355 	if(frame->code==SYS___syscall){
356 		int g=*(int *)(frame->ap);
357 
358 		frame->code=*(int *)(frame->ap+4);
359 		frame->ap+=8;
360 		*(int *)(frame->ap)=g-2;
361 if(startsysc){
362 		printf("SYS___syscall: ap %x\n",frame->ap);
363 		asm("halt");
364 		}
365 	}
366 
367 	if(frame->code<0||frame->code>=nsysent)
368 		callp= &sysent[0];
369 	else
370 		callp= &sysent[frame->code];
371 
372 	rval[0]=0;
373 	rval[1]=frame->r1;
374 	if(callp->sy_narg)
375 		copyin((char*)frame->ap+4, args, callp->sy_argsize);
376 
377 	err=(*callp->sy_call)(curproc,args,rval);
378 	exptr=curproc->p_addr->u_pcb.framep;
379 
380 if(startsysc)
381 	printf("retur %s pc %x, psl %x, ap %x, pid %d, v{rde %d r0 %d, r1 %d\n",
382                syscallnames[exptr->code], exptr->pc, exptr->psl,exptr->ap,
383                 curproc->p_pid,err,rval[0],rval[1]);
384 
385 	switch(err){
386 	case 0:
387 		exptr->r1=rval[1];
388 		exptr->r0=rval[0];
389 		exptr->psl &= ~PSL_C;
390 		break;
391 	case EJUSTRETURN:
392 		return;
393 	case ERESTART:
394 		exptr->pc=exptr->pc-2;
395 		break;
396 	default:
397 		exptr->r0=err;
398 		exptr->psl |= PSL_C;
399 		break;
400 	}
401 	userret(curproc, exptr->pc, exptr->psl);
402 }
403 
404 stray(scb, vec){
405 	printf("stray interrupt scb %d, vec 0x%x\n", scb, vec);
406 }
407 
408 struct inta {
409 	char pushr[2];	/* pushr $3f */
410 	char pushl[2];	/* pushl $? */
411 	char nop;	/* nop, for foolish gcc */
412 	char calls[3];	/* $1,? */
413 	u_int hoppaddr; /* jump for calls */
414 	char popr[2];	/* popr $0x3f */
415 	char rei;	/* rei */
416 } intasm = {0xbb, 0x3f, 0xdd, 0, 1, 0xfb, 1, 0xef, 0, 0xba, 0x3f, 2};
417 
418 u_int
419 settrap(plats, nyrut,arg)
420 	u_int plats;  /* Pointer to place to copy interrupt routine */
421 	u_int nyrut;  /* Pointer to new routine to jump to */
422 	u_int arg;    /* arg number to pass to routine. */
423 {
424 	struct inta *introut;
425 
426 	introut=(void *)((plats&0xfffffffc)+4);
427 	bcopy(&intasm, introut, sizeof(struct inta));
428 	introut->pushl[1]=arg;
429 	introut->hoppaddr=nyrut-(u_int)&introut->popr[0];
430 	return (u_int)introut;
431 }
432