xref: /netbsd-src/sys/arch/vax/vax/trap.c (revision ae9172d6cd9432a6a1a56760d86b32c57a66c39c)
1 /*      $NetBSD: trap.c,v 1.5 1994/11/25 19:10:06 ragge Exp $     */
2 
3 #define SCHEDDEBUG
4 #undef FAULTDEBUG
5 /*
6  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *     This product includes software developed at Ludd, University of Lule}.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35  /* All bugs are subject to removal without further notice */
36 
37 
38 
39 #include "sys/types.h"
40 #include "sys/param.h"
41 #include "sys/proc.h"
42 #include "sys/user.h"
43 #include "sys/syscall.h"
44 #include "sys/systm.h"
45 #include "sys/signalvar.h"
46 #include "vm/vm.h"
47 #include "vm/vm_kern.h"
48 #include "vm/vm_page.h"
49 #include "vax/include/mtpr.h"
50 #include "vax/include/pte.h"
51 #include "vax/include/pcb.h"
52 #include "vax/include/trap.h"
53 #include "vax/include/pmap.h"
54 #include "kern/syscalls.c"
55 
56 
57 extern 	int want_resched,whichqs;
58 volatile int startsysc=0,ovalidstart=0,faultdebug=0,haltfault=0;
59 
60 
61 userret(p, pc, psl)
62 	struct proc *p;
63 	u_int pc, psl;
64 {
65 	int s,sig;
66 
67         while ((sig = CURSIG(p)) !=0)
68                 postsig(sig);
69         p->p_priority = p->p_usrpri;
70         if (want_resched) {
71                 /*
72                  * Since we are curproc, clock will normally just change
73                  * our priority without moving us from one queue to another
74                  * (since the running process is not on a queue.)
75                  * If that happened after we setrq ourselves but before we
76                  * swtch()'ed, we might not be on the queue indicated by
77                  * our priority.
78                  */
79                 s=splstatclock();
80                 setrunqueue(curproc);
81                 cpu_switch();
82                 splx(s);
83                 while ((sig = CURSIG(curproc)) != 0)
84                         postsig(sig);
85         }
86 
87         curpriority = curproc->p_priority;
88 }
89 
90 struct pagef {
91         u_int     ps;
92         u_int     pc;
93 	u_int	vaddr;
94 	u_int	code;
95 };
96 
97 pageflt(pagef)
98 	struct pagef *pagef;
99 {
100 	struct	proc *p;
101 	struct	pmap *pm;
102 	u_int	P0=0, P1=0, SYS=0;
103         int rv;
104         vm_map_t map;
105         vm_prot_t ftype;
106         unsigned addr,sig;
107         extern vm_map_t kernel_map,pte_map;
108 	extern u_int sigsida,pv_table,v_cmap;
109 
110 if(faultdebug)printf("pageflt: pagef %x, pc %x, psl %x, vaddr %x, code %x\n",
111 		pagef, pagef->pc, pagef->ps, pagef->vaddr, pagef->code);
112 
113 if((pagef->vaddr>pv_table)&&(pagef->vaddr<v_cmap)){
114 printf("pv_table: pagef %x, pc %x, psl %x, vaddr %x, code %x\n",
115 		pagef, pagef->pc, pagef->ps, pagef->vaddr, pagef->code);
116 		asm("halt");
117 }
118 	p=curproc;
119 	pm=&p->p_vmspace->vm_pmap;
120 
121 if(faultdebug&&curproc){printf("p: %x, p->p_vmspace %x, p->p_vmspace->vm_pmap %x\n",
122 		p,p->p_vmspace, p->p_vmspace->vm_pmap);
123 		printf("&p->p_vmspace->vm_pmap %x, pm %x\n",
124 			&p->p_vmspace->vm_pmap, pm);
125 }
126 
127 
128 
129 
130 if(!pm){
131 	printf("Error in trap: null pmap\n");
132 	asm("halt");
133 }
134 
135 	if(pagef->vaddr<0x40000000) P0++;
136 	else if(pagef->vaddr<(u_int)0x80000000) P1++;
137 	else SYS++;
138 
139 /* XXX Where does this page become marked invalid??? */
140 
141 	if((pagef->vaddr==0x7fffe000)&&(pagef->pc==0x7fffe000)){
142 		u_int *hej=(u_int *)(mfpr(PR_P1BR)+0x7fffc0);
143 		*hej=0xf8000000|(sigsida>>PG_SHIFT);
144 		return;
145 	}
146 	if(pagef->code&1){ /* PTE length violation */
147 		if(P0){
148 
149 /*
150  * This is weird! We should know how much ptes we need to alloc
151  * for text,  data and bss in the executable file!
152  */
153 
154 			pmap_expandp0(pm);
155 
156 		} else if(P1){
157 			pmap_expandp1(pm);
158 		} else panic("pageflt: Length violation in SPT\n");
159 		return; /* Len fault, must return */
160 	}
161 	if(pagef->code&2){ /* pte reference fault */
162 		u_int faultaddr,testaddr=(u_int)pagef->vaddr&0x3fffffff;
163 
164 		if(P0){
165 			faultaddr=(u_int)pm->pm_pcb->P0BR+
166 				((testaddr>>PG_SHIFT)<<2);
167 		} else if(P1){
168 			faultaddr=(u_int)pm->pm_pcb->P1BR+
169 				((testaddr>>PG_SHIFT)<<2);
170 		} else panic("pageflt: PTE fault in SPT\n");
171 
172                 rv = vm_fault(pte_map, faultaddr, VM_PROT_WRITE|VM_PROT_READ,
173 			FALSE);
174                 if (rv != KERN_SUCCESS) {
175                         printf("ptefault - ]t skogen... :(  %d code %x\n",
176 				rv,pagef->code);
177                         printf("pc: 0x %x, vaddr 0x %x, code %d\n",
178                         pagef->pc,pagef->vaddr,pagef->code);
179                         showstate(p);
180                         asm("halt");
181 
182                         sig=SIGSEGV;
183                         trapsignal(p, sig, pagef->vaddr);
184                 }
185 		return; /* We don't know if it was a trap only for PTE */
186 	}
187         addr=(pagef->vaddr& ~PAGE_MASK);
188         if((pagef->pc>(unsigned)0x80000000)&&
189                 (pagef->vaddr>(unsigned)0x80000000)){
190                 map=kernel_map;
191         } else {
192                 map= &p->p_vmspace->vm_map;
193         }
194         if(pagef->code&4) ftype=VM_PROT_WRITE|VM_PROT_READ;
195         else ftype = VM_PROT_READ;
196 
197         rv = vm_fault(map, addr, ftype, FALSE);
198         if (rv != KERN_SUCCESS) {
199                 printf("pagefault - ]t helvete... :(  %d code %x\n",rv,
200 			pagef->code);
201                 printf("pc: 0x %x, vaddr 0x %x\n",pagef->pc,pagef->vaddr);
202                 showstate(p);
203                 asm("halt");
204 		if(pagef->pc>(u_int)0x80000000) panic("segv in kernel mode");
205                 sig=SIGSEGV;
206                 trapsignal(p, sig, pagef->vaddr);
207         }
208 	if(pagef->pc<(u_int)0x80000000) userret(p, pagef->pc, pagef->ps);
209 if(haltfault) asm("halt");
210 }
211 
212 char *traptypes[]={
213 	"reserved addressing",
214 	"privileged instruction",
215 	"reserved operand",
216 	"breakpoint instruction",
217 	"Nothing",
218 	"system call (kcall)",
219 	"arithmetic trap",
220 	"asynchronous system trap",
221 	"Access control violation fault",
222 	"translation fault",
223 	"trace trap",
224 	"compatibility mode fault",
225 };
226 
227 struct	arithframe {
228 	u_int	type;
229 	u_int	code;
230 	u_int	pc;
231 	u_int	psl;
232 };
233 
234 arithflt(frame)
235 	struct arithframe *frame;
236 {
237 	u_int	sig, type=frame->type;
238 
239 printf("trapfault: %s, code %x, pc %x, psl %x\n",traptypes[type],
240 		frame->code, frame->pc, frame->psl);
241 asm("halt");
242 	if((frame->psl & PSL_U) == PSL_U)
243 		type|=T_USER;
244 
245 	switch(type){
246 
247 	default:
248 		printf("trap type %x, code %x, pc %x, psl %x\n",
249 			frame->type, frame->code, frame->pc, frame->psl);
250 		showstate(curproc);
251 		asm("halt");
252 		panic("trap");
253 
254 	case T_PRIVINFLT|T_USER:
255 	case T_RESADFLT|T_USER:
256 	case T_RESOPFLT|T_USER:
257 		sig=SIGILL;
258 		break;
259 
260 	case T_ARITHFLT|T_USER:
261 		sig=SIGFPE;
262 		break;
263 
264 
265 	}
266 
267 	trapsignal(curproc, sig, frame->code);
268 	userret(curproc, frame->pc, frame->psl);
269 };
270 
271 /*
272  * astint() forces rescheduling of processes. Called by the fancy
273  * hardware supported Asynchronous System Trap on VAXen :)
274  */
275 astint(psl){
276 	mtpr(AST_NO,PR_ASTLVL); /* Turn off AST's */
277 	if(!(psl&PSL_U)) return;
278 /*		panic("astint: AST from kernel space"); */
279 	splclock(); /* We want no interrupts now */
280 	if(whichqs&&want_resched){
281 		setrunqueue(curproc);
282 		cpu_switch();
283 	}
284 }
285 
286 
287 showstate(p)
288 	struct proc *p;
289 {
290 	printf("\npid %d, command %s\n",p->p_pid, p->p_comm);
291 	printf("text size %x, data size %x, stack size %x\n",
292 		p->p_vmspace->vm_tsize, p->p_vmspace->vm_dsize,p->p_vmspace->
293 		vm_ssize);
294 	printf("virt text %x, virt data %x, max stack %x\n",
295 		p->p_vmspace->vm_taddr,p->p_vmspace->vm_daddr,
296 		p->p_vmspace->vm_maxsaddr);
297 	printf("user pte p0br %x, user stack addr %x\n",
298 		p->p_vmspace->vm_pmap.pm_pcb->P0BR, mfpr(PR_USP));
299 	printf("P0BR %x, P0LR %x, P1BR %x, P1LR %x\n",
300 		mfpr(PR_P0BR),mfpr(PR_P0LR),mfpr(PR_P1BR),mfpr(PR_P1LR));
301 }
302 
303 setregs(p,pack,stack,retval)
304         struct proc *p;
305         int pack,stack,retval[2]; /* Not all are ints... */
306 {
307 	struct sysc_frame *exptr;
308 
309 	exptr=(struct sysc_frame *)mfpr(PR_SSP);
310 	exptr->pc=pack+2;
311 	mtpr(stack,PR_USP);
312 #if 0
313         printf("Setregs: pid %d, pack %x, stack %x, execptr %x\n",
314                 p->p_pid,pack,stack,exptr);
315 #endif
316 }
317 
318 syscall(frame)
319 	struct	sysc_frame *frame;
320 {
321 	struct sysent *callp;
322 	int err,rval[2],args[8],narg,sig;
323 	struct sysc_frame *exptr;
324 
325 	mtpr(frame,PR_SSP); /* Save frame pointer here, foolish but simple! */
326 	if(frame->type<0||frame->type>=nsysent)
327 		callp= &sysent[0];
328 	else
329 		callp= &sysent[frame->type];
330 
331 	rval[0]=0;
332 	rval[1]=frame->r1;
333 	narg=callp->sy_narg * sizeof(int);
334 	if((narg=callp->sy_narg*4)!=0)
335 		copyin((char*)frame->ap+4, args, narg);
336 if(startsysc)printf("%s: pid %d, args %x, callp->sy_call %x\n",syscallnames[frame->type],
337 		curproc->p_pid, args, callp->sy_call);
338 if(startsysc)if(!strcmp("fork",syscallnames[frame->type])){
339 	printf("frame %x, narg %d\n",frame,narg);}
340 if(startsysc)if(!strcmp("execve",syscallnames[frame->type]))
341 		printf("syscall: execptr %x\n",frame);
342 if(startsysc) if(!strcmp("break",syscallnames[frame->type])){
343 	printf("brek: narg %d, frame->ap+4 %x,r3 %x\n",narg,frame->ap+4,
344 		frame->r3);}
345 	err=(*callp->sy_call)(curproc,args,rval);
346 	exptr=(struct sysc_frame *)
347 		mfpr(PR_SSP); /* Might have changed after fork */
348 if(startsysc)printf("return pid %d, call %s, err %d rval %d, %d, r3 %x\n",
349 	curproc->p_pid, syscallnames[exptr->type],err,rval[0],rval[1],
350 		exptr->r3);
351 /* if(!strcmp("fork",syscallnames[exptr->type])){
352 	printf("frame %x, narg %d\n",exptr,narg); asm("halt");} */
353 	switch(err){
354 	case 0:
355 		exptr->r1=rval[1];
356 		exptr->r0=rval[0];
357 		exptr->psl &= ~PSL_C;
358 		break;
359 	case EJUSTRETURN:
360 		return;
361 	case ERESTART:
362 		exptr->pc=exptr->pc-2;
363 		break;
364 	default:
365 		exptr->r0=err;
366 		exptr->psl |= PSL_C;
367 		break;
368 	}
369 
370         while ((sig = CURSIG(curproc)) !=0)
371                 postsig(sig);
372         curproc->p_priority = curproc->p_usrpri;
373         if (want_resched) {
374                 /*
375                  * Since we are curproc, clock will normally just change
376                  * our priority without moving us from one queue to another
377                  * (since the running process is not on a queue.)
378                  * If that happened after we setrq ourselves but before we
379                  * swtch()'ed, we might not be on the queue indicated by
380                  * our priority.
381                  */
382                 (void) splstatclock();
383                 setrunqueue(curproc);
384                 cpu_switch();
385                 spl0(); /* XXX - Is this right? -gwr */
386                 while ((sig = CURSIG(curproc)) != 0)
387                         postsig(sig);
388         }
389 
390         curpriority = curproc->p_priority;
391 }
392