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