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