1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1992 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department, Ralph Campbell, Sony Corp. and Kazumasa Utashiro 9 * of Software Research Associates, Inc. 10 * 11 * %sccs.include.redist.c% 12 * 13 * from: Utah $Hdr: trap.c 1.32 91/04/06$ 14 * 15 * @(#)trap.c 7.1 (Berkeley) 06/04/92 16 */ 17 18 #include "../include/fix_machine_type.h" 19 #include "param.h" 20 #include "systm.h" 21 #include "proc.h" 22 #include "kernel.h" 23 #include "signalvar.h" 24 #include "user.h" 25 #include "buf.h" 26 #ifdef KTRACE 27 #include "ktrace.h" 28 #endif 29 #include "net/netisr.h" 30 31 #include "../include/trap.h" 32 #include "../include/psl.h" 33 #include "../include/reg.h" 34 #include "../include/cpu.h" 35 #include "../include/pte.h" 36 #include "../include/mips_opcode.h" 37 #include "../include/adrsmap.h" 38 #if defined(DS3100) || defined(DS5000) 39 #include "clockreg.h" 40 #endif 41 42 #include "vm/vm.h" 43 #include "vm/vm_kern.h" 44 #include "vm/vm_page.h" 45 46 #ifdef news3400 47 #include "lp.h" 48 #include "bm.h" 49 #include "ms.h" 50 #include "en.h" 51 #include "../hbdev/dmac_0448.h" 52 #include "../sio/scc.h" 53 #endif 54 55 /* 56 * This is a kludge to allow X windows to work. 57 */ 58 #define X_KLUGE 59 60 #ifdef X_KLUGE 61 #define USER_MAP_ADDR 0x4000 62 #define NPTES 300 63 static pt_entry_t UserMapPtes[NPTES]; 64 static unsigned nUserMapPtes; 65 static pid_t UserMapPid; 66 #endif 67 68 struct proc *machFPCurProcPtr; /* pointer to last proc to use FP */ 69 70 extern void MachKernGenException(); 71 extern void MachUserGenException(); 72 extern void MachKernIntr(); 73 extern void MachUserIntr(); 74 extern void MachTLBModException(); 75 extern void MachTLBMissException(); 76 extern void MemErrorInterrupt(); 77 extern unsigned MachEmulateBranch(); 78 79 void (*machExceptionTable[])() = { 80 /* 81 * The kernel exception handlers. 82 */ 83 MachKernIntr, /* external interrupt */ 84 MachKernGenException, /* TLB modification */ 85 MachTLBMissException, /* TLB miss (load or instr. fetch) */ 86 MachTLBMissException, /* TLB miss (store) */ 87 MachKernGenException, /* address error (load or I-fetch) */ 88 MachKernGenException, /* address error (store) */ 89 MachKernGenException, /* bus error (I-fetch) */ 90 MachKernGenException, /* bus error (load or store) */ 91 MachKernGenException, /* system call */ 92 MachKernGenException, /* breakpoint */ 93 MachKernGenException, /* reserved instruction */ 94 MachKernGenException, /* coprocessor unusable */ 95 MachKernGenException, /* arithmetic overflow */ 96 MachKernGenException, /* reserved */ 97 MachKernGenException, /* reserved */ 98 MachKernGenException, /* reserved */ 99 /* 100 * The user exception handlers. 101 */ 102 MachUserIntr, 103 MachUserGenException, 104 MachUserGenException, 105 MachUserGenException, 106 MachUserGenException, 107 MachUserGenException, 108 MachUserGenException, 109 MachUserGenException, 110 MachUserGenException, 111 MachUserGenException, 112 MachUserGenException, 113 MachUserGenException, 114 MachUserGenException, 115 MachUserGenException, 116 MachUserGenException, 117 MachUserGenException, 118 }; 119 120 char *trap_type[] = { 121 "external interrupt", 122 "TLB modification", 123 "TLB miss (load or instr. fetch)", 124 "TLB miss (store)", 125 "address error (load or I-fetch)", 126 "address error (store)", 127 "bus error (I-fetch)", 128 "bus error (load or store)", 129 "system call", 130 "breakpoint", 131 "reserved instruction", 132 "coprocessor unusable", 133 "arithmetic overflow", 134 "reserved 13", 135 "reserved 14", 136 "reserved 15", 137 }; 138 139 #ifdef DEBUG 140 #define TRAPSIZE 10 141 struct trapdebug { /* trap history buffer for debugging */ 142 u_int status; 143 u_int cause; 144 u_int vadr; 145 u_int pc; 146 u_int ra; 147 u_int code; 148 } trapdebug[TRAPSIZE], *trp = trapdebug; 149 #endif 150 151 /* 152 * Handle an exception. 153 * Called from MachKernGenException() or MachUserGenException() 154 * when a processor trap occurs. 155 * In the case of a kernel trap, we return the pc where to resume if 156 * ((struct pcb *)UADDR)->pcb_onfault is set, otherwise, return old pc. 157 */ 158 unsigned 159 trap(statusReg, causeReg, vadr, pc, args) 160 unsigned statusReg; /* status register at time of the exception */ 161 unsigned causeReg; /* cause register at time of exception */ 162 unsigned vadr; /* address (if any) the fault occured on */ 163 unsigned pc; /* program counter where to continue */ 164 { 165 register int type, i; 166 unsigned ucode = 0; 167 register struct proc *p = curproc; 168 struct timeval syst; 169 vm_prot_t ftype; 170 extern unsigned onfault_table[]; 171 172 #ifdef DEBUG 173 trp->status = statusReg; 174 trp->cause = causeReg; 175 trp->vadr = vadr; 176 trp->pc = pc; 177 trp->ra = !USERMODE(statusReg) ? ((int *)&args)[19] : 178 p->p_md.md_regs[RA]; 179 trp->code = 0; 180 if (++trp == &trapdebug[TRAPSIZE]) 181 trp = trapdebug; 182 #endif 183 184 cnt.v_trap++; 185 type = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT; 186 if (USERMODE(statusReg)) { 187 type |= T_USER; 188 syst = p->p_stime; 189 } 190 191 /* 192 * Enable hardware interrupts if they were on before. 193 * We only respond to software interrupts when returning to user mode. 194 */ 195 if (statusReg & MACH_SR_INT_ENA_PREV) 196 splx((statusReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR); 197 198 switch (type) { 199 case T_TLB_MOD: 200 if ((int)vadr < 0) { 201 register pt_entry_t *pte; 202 register unsigned entry; 203 #ifndef ATTR 204 register vm_offset_t pa; 205 #endif 206 207 pte = kvtopte(vadr); 208 entry = pte->pt_entry; 209 if (entry & PG_RO) { 210 /* write to read only page in the kernel */ 211 ftype = VM_PROT_WRITE; 212 goto kernel_fault; 213 } 214 entry |= PG_M; 215 pte->pt_entry = entry; 216 vadr &= PG_FRAME; 217 printf("trap: TLBupdate hi %x lo %x i %x\n", vadr, 218 entry, MachTLBUpdate(vadr, entry)); /* XXX */ 219 #ifdef ATTR 220 pmap_attributes[atop(entry - KERNBASE)] |= PMAP_ATTR_MOD; 221 #else 222 pa = entry & PG_FRAME; 223 if (!IS_VM_PHYSADDR(pa)) 224 panic("trap: kmod"); 225 PHYS_TO_VM_PAGE(pa)->clean = FALSE; 226 #endif 227 return (pc); 228 } 229 /* FALLTHROUGH */ 230 231 case T_TLB_MOD+T_USER: 232 { 233 pmap_hash_t hp; 234 #ifndef ATTR 235 vm_offset_t pa; 236 #endif 237 #ifdef DIAGNOSTIC 238 extern pmap_hash_t zero_pmap_hash; 239 extern pmap_t cur_pmap; 240 241 if (cur_pmap->pm_hash == zero_pmap_hash) 242 panic("tlbmod"); 243 #endif 244 hp = &((pmap_hash_t)PMAP_HASH_UADDR)[PMAP_HASH(vadr)]; 245 if (hp->low & PG_RO) { 246 ftype = VM_PROT_WRITE; 247 goto dofault; 248 } 249 hp->low |= PG_M; 250 printf("trap: TLBupdate hi %x lo %x i %x\n", hp->high, hp->low, 251 MachTLBUpdate(hp->high, hp->low)); /* XXX */ 252 #ifdef ATTR 253 pmap_attributes[atop(hp->low - KERNBASE)] |= PMAP_ATTR_MOD; 254 #else 255 pa = hp->low & PG_FRAME; 256 if (!IS_VM_PHYSADDR(pa)) 257 panic("trap: umod"); 258 PHYS_TO_VM_PAGE(pa)->clean = FALSE; 259 #endif 260 if (!USERMODE(statusReg)) 261 return (pc); 262 goto out; 263 } 264 265 case T_TLB_LD_MISS: 266 case T_TLB_ST_MISS: 267 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ; 268 if ((int)vadr < 0) { 269 register vm_offset_t va; 270 int rv; 271 272 kernel_fault: 273 va = trunc_page((vm_offset_t)vadr); 274 rv = vm_fault(kernel_map, va, ftype, FALSE); 275 if (rv == KERN_SUCCESS) 276 return (pc); 277 if (i = ((struct pcb *)UADDR)->pcb_onfault) { 278 ((struct pcb *)UADDR)->pcb_onfault = 0; 279 return (onfault_table[i]); 280 } 281 goto err; 282 } 283 goto dofault; 284 285 case T_TLB_LD_MISS+T_USER: 286 ftype = VM_PROT_READ; 287 goto dofault; 288 289 case T_TLB_ST_MISS+T_USER: 290 ftype = VM_PROT_WRITE; 291 dofault: 292 { 293 register vm_offset_t va; 294 register struct vmspace *vm = p->p_vmspace; 295 register vm_map_t map = &vm->vm_map; 296 int rv; 297 298 #ifdef X_KLUGE 299 if (p->p_pid == UserMapPid && 300 (va = pmax_btop(vadr - USER_MAP_ADDR)) < nUserMapPtes) { 301 register pt_entry_t *pte; 302 303 pte = &UserMapPtes[va]; 304 MachTLBWriteRandom((vadr & PG_FRAME) | 305 (vm->vm_pmap.pm_tlbpid << VMMACH_TLB_PID_SHIFT), 306 pte->pt_entry); 307 return (pc); 308 } 309 #endif 310 va = trunc_page((vm_offset_t)vadr); 311 rv = vm_fault(map, va, ftype, FALSE); 312 if (rv != KERN_SUCCESS) { 313 printf("vm_fault(%x, %x, %x, 0) -> %x ADR %x PC %x RA %x\n", 314 map, va, ftype, rv, vadr, pc, 315 !USERMODE(statusReg) ? ((int *)&args)[19] : 316 p->p_md.md_regs[RA]); /* XXX */ 317 printf("\tpid %d %s PC %x RA %x\n", p->p_pid, 318 p->p_comm, p->p_md.md_regs[PC], 319 p->p_md.md_regs[RA]); /* XXX */ 320 #ifdef DEBUG 321 trapDump("vm_fault"); 322 #endif 323 } 324 /* 325 * If this was a stack access we keep track of the maximum 326 * accessed stack size. Also, if vm_fault gets a protection 327 * failure it is due to accessing the stack region outside 328 * the current limit and we need to reflect that as an access 329 * error. 330 */ 331 if ((caddr_t)va >= vm->vm_maxsaddr) { 332 if (rv == KERN_SUCCESS) { 333 unsigned nss; 334 335 nss = clrnd(btoc(USRSTACK-(unsigned)va)); 336 if (nss > vm->vm_ssize) 337 vm->vm_ssize = nss; 338 } else if (rv == KERN_PROTECTION_FAILURE) 339 rv = KERN_INVALID_ADDRESS; 340 } 341 if (rv == KERN_SUCCESS) { 342 if (!USERMODE(statusReg)) 343 return (pc); 344 goto out; 345 } 346 if (!USERMODE(statusReg)) { 347 if (i = ((struct pcb *)UADDR)->pcb_onfault) { 348 ((struct pcb *)UADDR)->pcb_onfault = 0; 349 return (onfault_table[i]); 350 } 351 goto err; 352 } 353 ucode = vadr; 354 i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; 355 break; 356 } 357 358 case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */ 359 if (vadr == KERNBASE) { 360 struct args { 361 int i[1]; 362 } args; 363 int rval[2]; 364 365 /* 366 * Assume a signal handler is trying to return 367 * (see sendsig() and sigreturn()). We have to 368 * pop the sigframe struct to get the address of 369 * the sigcontext. 370 */ 371 args.i[0] = p->p_md.md_regs[SP] + 4 * sizeof(int); 372 (void) sigreturn(curproc, &args, rval); 373 goto out; 374 } 375 /* FALLTHROUGH */ 376 377 case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */ 378 case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to cpu */ 379 case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to cpu */ 380 i = SIGSEGV; 381 break; 382 383 case T_SYSCALL+T_USER: 384 { 385 register int *locr0 = p->p_md.md_regs; 386 register struct sysent *callp; 387 unsigned int code; 388 int numsys; 389 struct args { 390 int i[8]; 391 } args; 392 int rval[2]; 393 struct sysent *systab; 394 extern int nsysent; 395 #ifdef ULTRIXCOMPAT 396 extern struct sysent ultrixsysent[]; 397 extern int ultrixnsysent; 398 #endif 399 400 cnt.v_syscall++; 401 /* compute next PC after syscall instruction */ 402 if ((int)causeReg < 0) 403 locr0[PC] = MachEmulateBranch(locr0, pc, 0, 0); 404 else 405 locr0[PC] += 4; 406 systab = sysent; 407 numsys = nsysent; 408 #ifdef ULTRIXCOMPAT 409 if (p->p_md.md_flags & MDP_ULTRIX) { 410 systab = ultrixsysent; 411 numsys = ultrixnsysent; 412 } 413 #endif 414 code = locr0[V0]; 415 #ifdef COMPAT_NEWSOS 416 #define SYSCALL_BSDOFFSET 1000 417 if (code >= SYSCALL_BSDOFFSET) 418 code -= SYSCALL_BSDOFFSET; 419 #endif 420 if (code == 0) { /* indir */ 421 code = locr0[A0]; 422 #ifdef COMPAT_NEWSOS 423 if (code >= SYSCALL_BSDOFFSET) 424 code -= SYSCALL_BSDOFFSET; 425 #endif 426 if (code >= numsys) 427 callp = &systab[0]; /* indir (illegal) */ 428 else 429 callp = &systab[code]; 430 i = callp->sy_narg; 431 args.i[0] = locr0[A1]; 432 args.i[1] = locr0[A2]; 433 args.i[2] = locr0[A3]; 434 if (i > 3) { 435 i = copyin((caddr_t)(locr0[SP] + 436 3 * sizeof(int)), 437 (caddr_t)&args.i[3], 438 (u_int)(i - 3) * sizeof(int)); 439 if (i) { 440 locr0[V0] = i; 441 locr0[A3] = 1; 442 #ifdef KTRACE 443 if (KTRPOINT(p, KTR_SYSCALL)) 444 ktrsyscall(p->p_tracep, code, 445 callp->sy_narg, args.i); 446 #endif 447 goto done; 448 } 449 } 450 } else { 451 if (code >= numsys) 452 callp = &systab[0]; /* indir (illegal) */ 453 else 454 callp = &systab[code]; 455 i = callp->sy_narg; 456 args.i[0] = locr0[A0]; 457 args.i[1] = locr0[A1]; 458 args.i[2] = locr0[A2]; 459 args.i[3] = locr0[A3]; 460 if (i > 4) { 461 i = copyin((caddr_t)(locr0[SP] + 462 4 * sizeof(int)), 463 (caddr_t)&args.i[4], 464 (u_int)(i - 4) * sizeof(int)); 465 if (i) { 466 locr0[V0] = i; 467 locr0[A3] = 1; 468 #ifdef KTRACE 469 if (KTRPOINT(p, KTR_SYSCALL)) 470 ktrsyscall(p->p_tracep, code, 471 callp->sy_narg, args.i); 472 #endif 473 goto done; 474 } 475 } 476 } 477 #ifdef KTRACE 478 if (KTRPOINT(p, KTR_SYSCALL)) 479 ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 480 #endif 481 /* 482 if (!strcmp(p->p_comm, "ftp")) 483 printf("syscall: pid=%d, code=%d, pc=0x%x\n", p->p_pid, code, pc); 484 */ 485 rval[0] = 0; 486 rval[1] = locr0[V1]; 487 #ifdef DEBUG 488 if (trp == trapdebug) 489 trapdebug[TRAPSIZE - 1].code = code; 490 else 491 trp[-1].code = code; 492 #endif 493 #ifdef COMPAT_NEWSOS 494 /* 151 = setenvp, 152 = sysnews, 162 = getdomainname KU:XXX */ 495 if (code == 151 || code == 152 || code == 162) 496 i = 0; 497 else 498 #endif 499 i = (*callp->sy_call)(p, &args, rval); 500 if(i==EINVAL) 501 printf("EINVAL: pid=%d, code=%d\n", p->p_pid, code); 502 /* 503 * Reinitialize proc pointer `p' as it may be different 504 * if this is a child returning from fork syscall. 505 */ 506 p = curproc; 507 locr0 = p->p_md.md_regs; 508 #ifdef DEBUG 509 { int s; 510 s = splhigh(); 511 trp->status = statusReg; 512 trp->cause = causeReg; 513 trp->vadr = locr0[SP]; 514 trp->pc = locr0[PC]; 515 trp->ra = locr0[RA]; 516 trp->code = -code; 517 if (++trp == &trapdebug[TRAPSIZE]) 518 trp = trapdebug; 519 splx(s); 520 } 521 #endif 522 if (i == ERESTART) 523 locr0[PC] = pc; 524 else if (i != EJUSTRETURN) { 525 if (i) { 526 locr0[V0] = i; 527 locr0[A3] = 1; 528 } else { 529 locr0[V0] = rval[0]; 530 locr0[V1] = rval[1]; 531 locr0[A3] = 0; 532 } 533 } 534 /* else if (i == EJUSTRETURN) */ 535 /* nothing to do */ 536 done: 537 #ifdef KTRACE 538 if (KTRPOINT(p, KTR_SYSRET)) 539 ktrsysret(p->p_tracep, code, i, rval[0]); 540 #endif 541 542 goto out; 543 } 544 545 case T_BREAK+T_USER: 546 { 547 register unsigned va, instr; 548 549 /* compute address of break instruction */ 550 va = pc; 551 if ((int)causeReg < 0) 552 va += 4; 553 554 /* read break instruction */ 555 instr = fuiword(va); 556 #ifdef KADB 557 if (instr == MACH_BREAK_BRKPT || instr == MACH_BREAK_SSTEP) 558 goto err; 559 #endif 560 if (p->p_md.md_ss_addr != va || instr != MACH_BREAK_SSTEP) { 561 i = SIGTRAP; 562 break; 563 } 564 565 /* restore original instruction and clear BP */ 566 i = suiword((caddr_t)va, p->p_md.md_ss_instr); 567 if (i < 0) { 568 vm_offset_t sa, ea; 569 int rv; 570 571 sa = trunc_page((vm_offset_t)va); 572 ea = round_page((vm_offset_t)va+sizeof(int)-1); 573 rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, 574 VM_PROT_DEFAULT, FALSE); 575 if (rv == KERN_SUCCESS) { 576 i = suiword((caddr_t)va, p->p_md.md_ss_instr); 577 (void) vm_map_protect(&p->p_vmspace->vm_map, 578 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, 579 FALSE); 580 } 581 } 582 if (i < 0) { 583 i = SIGTRAP; 584 break; 585 } 586 p->p_md.md_ss_addr = 0; 587 goto out; 588 } 589 590 case T_RES_INST+T_USER: 591 i = SIGILL; 592 break; 593 594 case T_COP_UNUSABLE+T_USER: 595 if ((causeReg & MACH_CR_COP_ERR) != 0x10000000) { 596 i = SIGILL; /* only FPU instructions allowed */ 597 break; 598 } 599 MachSwitchFPState(machFPCurProcPtr, p->p_md.md_regs); 600 machFPCurProcPtr = p; 601 p->p_md.md_regs[PS] |= MACH_SR_COP_1_BIT; 602 p->p_md.md_flags |= MDP_FPUSED; 603 goto out; 604 605 case T_OVFLOW+T_USER: 606 i = SIGFPE; 607 break; 608 609 case T_ADDR_ERR_LD: /* misaligned access */ 610 case T_ADDR_ERR_ST: /* misaligned access */ 611 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */ 612 if (i = ((struct pcb *)UADDR)->pcb_onfault) { 613 ((struct pcb *)UADDR)->pcb_onfault = 0; 614 return (onfault_table[i]); 615 } 616 /* FALLTHROUGH */ 617 618 default: 619 err: 620 #ifdef KADB 621 { 622 extern struct pcb kdbpcb; 623 624 if (USERMODE(statusReg)) 625 kdbpcb = p->p_addr->u_pcb; 626 else { 627 kdbpcb.pcb_regs[ZERO] = 0; 628 kdbpcb.pcb_regs[AST] = ((int *)&args)[2]; 629 kdbpcb.pcb_regs[V0] = ((int *)&args)[3]; 630 kdbpcb.pcb_regs[V1] = ((int *)&args)[4]; 631 kdbpcb.pcb_regs[A0] = ((int *)&args)[5]; 632 kdbpcb.pcb_regs[A1] = ((int *)&args)[6]; 633 kdbpcb.pcb_regs[A2] = ((int *)&args)[7]; 634 kdbpcb.pcb_regs[A3] = ((int *)&args)[8]; 635 kdbpcb.pcb_regs[T0] = ((int *)&args)[9]; 636 kdbpcb.pcb_regs[T1] = ((int *)&args)[10]; 637 kdbpcb.pcb_regs[T2] = ((int *)&args)[11]; 638 kdbpcb.pcb_regs[T3] = ((int *)&args)[12]; 639 kdbpcb.pcb_regs[T4] = ((int *)&args)[13]; 640 kdbpcb.pcb_regs[T5] = ((int *)&args)[14]; 641 kdbpcb.pcb_regs[T6] = ((int *)&args)[15]; 642 kdbpcb.pcb_regs[T7] = ((int *)&args)[16]; 643 kdbpcb.pcb_regs[T8] = ((int *)&args)[17]; 644 kdbpcb.pcb_regs[T9] = ((int *)&args)[18]; 645 kdbpcb.pcb_regs[RA] = ((int *)&args)[19]; 646 kdbpcb.pcb_regs[MULLO] = ((int *)&args)[21]; 647 kdbpcb.pcb_regs[MULHI] = ((int *)&args)[22]; 648 kdbpcb.pcb_regs[PC] = pc; 649 kdbpcb.pcb_regs[SR] = statusReg; 650 bzero((caddr_t)&kdbpcb.pcb_regs[F0], 33 * sizeof(int)); 651 } 652 if (kdb(causeReg, vadr, p, !USERMODE(statusReg))) 653 return (kdbpcb.pcb_regs[PC]); 654 } 655 #endif 656 printf("trap: pid %d %s sig %d adr %x pc %x ra %x\n", p->p_pid, 657 p->p_comm, i, vadr, pc, p->p_md.md_regs[RA]); /* XXX */ 658 trapDump("unkown exception"); 659 panic("trap"); 660 } 661 printf("trap: pid %d %s sig %d adr %x pc %x ra %x\n", p->p_pid, 662 p->p_comm, i, vadr, pc, p->p_md.md_regs[RA]); /* XXX */ 663 trapsignal(p, i, ucode); 664 out: 665 /* 666 * Note: we should only get here if returning to user mode. 667 */ 668 astpending = 0; 669 while (i = CURSIG(p)) 670 psig(i); 671 p->p_pri = p->p_usrpri; 672 if (want_resched) { 673 int s; 674 675 /* 676 * Since we are curproc, clock will normally just change 677 * our priority without moving us from one queue to another 678 * (since the running process is not on a queue.) 679 * If that happened after we setrq ourselves but before we 680 * swtch()'ed, we might not be on the queue indicated by 681 * our priority. 682 */ 683 s = splclock(); 684 setrq(p); 685 p->p_stats->p_ru.ru_nivcsw++; 686 swtch(); 687 splx(s); 688 while (i = CURSIG(p)) 689 psig(i); 690 } 691 if (p->p_stats->p_prof.pr_scale) { 692 int ticks; 693 struct timeval *tv = &p->p_stime; 694 695 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 696 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 697 if (ticks) 698 addupc(pc, &p->p_stats->p_prof, ticks); 699 } 700 curpri = p->p_pri; 701 return (pc); 702 } 703 704 #ifdef DS5000 705 struct intr_tab intr_tab[8]; 706 #endif 707 708 #if defined(DS3100) || defined(DS5100) 709 int temp; /* XXX ULTRIX compiler bug with -O */ 710 #endif 711 712 /* 713 * Handle an interrupt. 714 * Called from MachKernIntr() or MachUserIntr() 715 * Note: curproc might be NULL. 716 */ 717 interrupt(statusReg, causeReg, pc) 718 unsigned statusReg; /* status register at time of the exception */ 719 unsigned causeReg; /* cause register at time of exception */ 720 unsigned pc; /* program counter where to continue */ 721 { 722 register unsigned mask; 723 clockframe cf; 724 725 #ifdef DEBUG 726 trp->status = statusReg; 727 trp->cause = causeReg; 728 trp->vadr = 0; 729 trp->pc = pc; 730 trp->ra = 0; 731 trp->code = 0; 732 if (++trp == &trapdebug[TRAPSIZE]) 733 trp = trapdebug; 734 #endif 735 736 mask = causeReg & statusReg; /* pending interrupts & enable mask */ 737 #ifdef news3400 738 #ifndef NOPRIORITY 739 if (mask & MACH_INT_MASK_5) { /* level 5 interrupt */ 740 splx((MACH_SPL_MASK_8 & ~causeReg) | MACH_SR_INT_ENA_CUR); 741 printf("level 5 interrupt: PC %x CR %x SR %x\n", 742 pc, causeReg, statusReg); 743 causeReg &= ~MACH_INT_MASK_5; 744 } 745 if (mask & MACH_INT_MASK_4) { /* level 4 interrupt */ 746 /* 747 * asynchronous bus error 748 */ 749 splx((MACH_SPL_MASK_7 & ~causeReg) | MACH_SR_INT_ENA_CUR); 750 printf("level 4 interrupt: PC %x CR %x SR %x\n", 751 pc, causeReg, statusReg); 752 *(char *)INTCLR0 = INTCLR0_BERR; 753 causeReg &= ~MACH_INT_MASK_4; 754 } 755 if (mask & MACH_INT_MASK_3) { /* level 3 interrupt */ 756 /* 757 * fp error 758 */ 759 splx((MACH_SPL_MASK_6 & ~causeReg) | MACH_SR_INT_ENA_CUR); 760 if (!USERMODE(statusReg)) { 761 #ifdef DEBUG 762 trapDump("fpintr"); 763 #else 764 printf("FPU interrupt: PC %x CR %x SR %x\n", 765 pc, causeReg, statusReg); 766 #endif 767 } else 768 MachFPInterrupt(statusReg, causeReg, pc); 769 causeReg &= ~MACH_INT_MASK_3; 770 } 771 if (mask & MACH_INT_MASK_2) { /* level 2 interrupt */ 772 register int stat; 773 774 splx((MACH_SPL_MASK_5 & ~causeReg) | MACH_SR_INT_ENA_CUR); 775 stat = *(volatile u_char *)INTST0; 776 if (stat & INTST0_TIMINT) { /* timer */ 777 static int led_count = 0; 778 779 *(volatile u_char *)INTCLR0 = INTCLR0_TIMINT; 780 cf.pc = pc; 781 cf.ps = statusReg; 782 hardclock(cf); 783 if (++led_count > hz) { 784 led_count = 0; 785 *(volatile u_char *)DEBUG_PORT ^= DP_LED1; 786 } 787 } 788 #if NBM > 0 789 if (stat & INTST0_KBDINT) /* keyboard */ 790 kbm_rint(SCC_KEYBOARD); 791 #endif 792 #if NMS > 0 793 if (stat & INTST0_MSINT) /* mouse */ 794 kbm_rint(SCC_MOUSE); 795 #endif 796 causeReg &= ~MACH_INT_MASK_2; 797 } 798 if (mask & MACH_INT_MASK_1) { /* level 1 interrupt */ 799 splx((MACH_SPL_MASK_4 & ~causeReg) | MACH_SR_INT_ENA_CUR); 800 level1_intr(); 801 causeReg &= ~MACH_INT_MASK_1; 802 } 803 if (mask & MACH_INT_MASK_0) { /* level 0 interrupt */ 804 splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR); 805 level0_intr(); 806 causeReg &= ~MACH_INT_MASK_0; 807 } 808 splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR); 809 #else /* NOPRIORITY */ 810 /* handle clock interrupts ASAP */ 811 if (mask & MACH_INT_MASK_2) { /* level 2 interrupt */ 812 register int stat; 813 814 stat = *(volatile u_char *)INTST0; 815 if (stat & INTST0_TIMINT) { /* timer */ 816 static int led_count = 0; 817 818 *(volatile u_char *)INTCLR0 = INTCLR0_TIMINT; 819 cf.pc = pc; 820 cf.ps = statusReg; 821 hardclock(cf); 822 if (++led_count > hz) { 823 led_count = 0; 824 *(volatile u_char *)DEBUG_PORT ^= DP_LED1; 825 } 826 } 827 #if NBM > 0 828 if (stat & INTST0_KBDINT) /* keyboard */ 829 kbm_rint(SCC_KEYBOARD); 830 #endif 831 #if NMS > 0 832 if (stat & INTST0_MSINT) /* mouse */ 833 kbm_rint(SCC_MOUSE); 834 #endif 835 causeReg &= ~MACH_INT_MASK_2; /* reenable clock interrupts */ 836 } 837 /* 838 * Enable hardware interrupts which were enabled but not pending. 839 * We only respond to software interrupts when returning to spl0. 840 */ 841 splx((statusReg & ~causeReg & MACH_HARD_INT_MASK)|MACH_SR_INT_ENA_CUR); 842 843 if (mask & MACH_INT_MASK_5) { /* level 5 interrupt */ 844 printf("level 5 interrupt: PC %x CR %x SR %x\n", 845 pc, causeReg, statusReg); 846 ; 847 } 848 if (mask & MACH_INT_MASK_4) { /* level 4 interrupt */ 849 /* 850 * asynchronous bus error 851 */ 852 printf("level 4 interrupt: PC %x CR %x SR %x\n", 853 pc, causeReg, statusReg); 854 *(char *)INTCLR0 = INTCLR0_BERR; 855 } 856 if (mask & MACH_INT_MASK_3) { /* level 3 interrupt */ 857 /* 858 * fp error 859 */ 860 if (!USERMODE(statusReg)) { 861 #ifdef DEBUG 862 trapDump("fpintr"); 863 #else 864 printf("FPU interrupt: PC %x CR %x SR %x\n", 865 pc, causeReg, statusReg); 866 #endif 867 } else 868 MachFPInterrupt(statusReg, causeReg, pc); 869 } 870 if (mask & MACH_INT_MASK_1) /* level 1 interrupt */ 871 level1_intr(); 872 if (mask & MACH_INT_MASK_0) /* level 0 interrupt */ 873 level0_intr(); 874 #endif /* NOPRIORITY */ 875 #endif /* news3400 */ 876 #ifdef DS3100 877 /* handle clock interrupts ASAP */ 878 if (mask & MACH_INT_MASK_3) { 879 register volatile struct chiptime *c = 880 (volatile struct chiptime *)MACH_CLOCK_ADDR; 881 882 temp = c->regc; /* clear interrupt bits */ 883 cf.pc = pc; 884 cf.ps = statusReg; 885 hardclock(cf); 886 causeReg &= ~MACH_INT_MASK_3; /* reenable clock interrupts */ 887 } 888 /* 889 * Enable hardware interrupts which were enabled but not pending. 890 * We only respond to software interrupts when returning to spl0. 891 */ 892 splx((statusReg & ~causeReg & MACH_HARD_INT_MASK) | 893 MACH_SR_INT_ENA_CUR); 894 if (mask & MACH_INT_MASK_0) 895 siiintr(0); 896 if (mask & MACH_INT_MASK_1) 897 leintr(0); 898 if (mask & MACH_INT_MASK_2) 899 dcintr(0); 900 if (mask & MACH_INT_MASK_4) 901 MemErrorInterrupt(); 902 #endif /* DS3100 */ 903 #ifdef DS5000 904 /* handle clock interrupts ASAP */ 905 if (mask & MACH_INT_MASK_1) { 906 register volatile struct chiptime *c = 907 (volatile struct chiptime *)MACH_CLOCK_ADDR; 908 register unsigned csr; 909 static int warned = 0; 910 911 csr = *(unsigned *)MACH_SYS_CSR_ADDR; 912 if ((csr & MACH_CSR_PSWARN) && !warned) { 913 warned = 1; 914 printf("WARNING: power supply is overheating!\n"); 915 } else if (warned && !(csr & MACH_CSR_PSWARN)) { 916 warned = 0; 917 printf("WARNING: power supply is OK again\n"); 918 } 919 920 temp = c->regc; /* clear interrupt bits */ 921 cf.pc = pc; 922 cf.ps = statusReg; 923 hardclock(cf); 924 causeReg &= ~MACH_INT_MASK_1; /* reenable clock interrupts */ 925 } 926 if (mask & MACH_INT_MASK_0) { 927 register unsigned csr; 928 register unsigned i, m; 929 930 csr = *(unsigned *)MACH_SYS_CSR_ADDR; 931 m = csr & (csr >> MACH_CSR_IOINTEN_SHIFT) & MACH_CSR_IOINT_MASK; 932 #if 0 933 *(unsigned *)MACH_SYS_CSR_ADDR = 934 (csr & ~(MACH_CSR_MBZ | 0xFF)) | 935 (m << MACH_CSR_IOINTEN_SHIFT); 936 #endif 937 /* 938 * Enable hardware interrupts which were enabled but not 939 * pending. We only respond to software interrupts when 940 * returning to spl0. 941 */ 942 splx((statusReg & ~causeReg & MACH_HARD_INT_MASK) | 943 MACH_SR_INT_ENA_CUR); 944 for (i = 0; m; i++, m >>= 1) { 945 if (!(m & 1)) 946 continue; 947 if (intr_tab[i].func) 948 (*intr_tab[i].func)(intr_tab[i].unit); 949 else 950 printf("spurious interrupt %d\n", i); 951 } 952 #if 0 953 *(unsigned *)MACH_SYS_CSR_ADDR = 954 csr & ~(MACH_CSR_MBZ | 0xFF); 955 #endif 956 } else { 957 /* 958 * Enable hardware interrupts which were enabled but not 959 * pending. We only respond to software interrupts when 960 * returning to spl0. 961 */ 962 splx((statusReg & ~causeReg & MACH_HARD_INT_MASK) | 963 MACH_SR_INT_ENA_CUR); 964 } 965 if (mask & MACH_INT_MASK_3) 966 MemErrorInterrupt(); 967 #endif /* DS5000 */ 968 #if defined(DS3100) || defined(DS5000) 969 if (mask & MACH_INT_MASK_5) { 970 if (!USERMODE(statusReg)) { 971 #ifdef DEBUG 972 trapDump("fpintr"); 973 #else 974 printf("FPU interrupt: PC %x CR %x SR %x\n", 975 pc, causeReg, statusReg); 976 #endif 977 } else 978 MachFPInterrupt(statusReg, causeReg, pc); 979 } 980 #endif /* DS3100 || DS5000 */ 981 if (mask & MACH_SOFT_INT_MASK_0) { 982 clockframe cf; 983 984 clearsoftclock(); 985 cf.pc = pc; 986 cf.ps = statusReg; 987 softclock(cf); 988 } 989 /* process network interrupt if we trapped or will very soon */ 990 if ((mask & MACH_SOFT_INT_MASK_1) || 991 netisr && (statusReg & MACH_SOFT_INT_MASK_1)) { 992 clearsoftnet(); 993 #ifdef INET 994 if (netisr & (1 << NETISR_ARP)) { 995 netisr &= ~(1 << NETISR_ARP); 996 arpintr(); 997 } 998 if (netisr & (1 << NETISR_IP)) { 999 netisr &= ~(1 << NETISR_IP); 1000 ipintr(); 1001 } 1002 #endif 1003 #ifdef NS 1004 if (netisr & (1 << NETISR_NS)) { 1005 netisr &= ~(1 << NETISR_NS); 1006 nsintr(); 1007 } 1008 #endif 1009 #ifdef ISO 1010 if (netisr & (1 << NETISR_ISO)) { 1011 netisr &= ~(1 << NETISR_ISO); 1012 clnlintr(); 1013 } 1014 #endif 1015 } 1016 } 1017 1018 /* 1019 * This is called from MachUserIntr() if astpending is set. 1020 * This is very similar to the tail of trap(). 1021 */ 1022 softintr(statusReg, pc) 1023 unsigned statusReg; /* status register at time of the exception */ 1024 unsigned pc; /* program counter where to continue */ 1025 { 1026 register struct proc *p = curproc; 1027 register int i; 1028 1029 cnt.v_soft++; 1030 astpending = 0; 1031 while (i = CURSIG(p)) 1032 psig(i); 1033 p->p_pri = p->p_usrpri; 1034 if (want_resched) { 1035 int s; 1036 1037 /* 1038 * Since we are curproc, clock will normally just change 1039 * our priority without moving us from one queue to another 1040 * (since the running process is not on a queue.) 1041 * If that happened after we setrq ourselves but before we 1042 * swtch()'ed, we might not be on the queue indicated by 1043 * our priority. 1044 */ 1045 s = splclock(); 1046 setrq(p); 1047 p->p_stats->p_ru.ru_nivcsw++; 1048 swtch(); 1049 splx(s); 1050 while (i = CURSIG(p)) 1051 psig(i); 1052 } 1053 curpri = p->p_pri; 1054 } 1055 1056 #ifdef DEBUG 1057 trapDump(msg) 1058 char *msg; 1059 { 1060 register int i; 1061 int s; 1062 1063 s = splhigh(); 1064 printf("trapDump(%s)\n", msg); 1065 for (i = 0; i < TRAPSIZE; i++) { 1066 if (trp == trapdebug) 1067 trp = &trapdebug[TRAPSIZE - 1]; 1068 else 1069 trp--; 1070 if (trp->cause == 0) 1071 break; 1072 printf("%s: ADR %x PC %x CR %x SR %x\n", 1073 trap_type[(trp->cause & MACH_CR_EXC_CODE) >> 1074 MACH_CR_EXC_CODE_SHIFT], 1075 trp->vadr, trp->pc, trp->cause, trp->status); 1076 printf(" RA %x code %d\n", trp-> ra, trp->code); 1077 } 1078 bzero(trapdebug, sizeof(trapdebug)); 1079 trp = trapdebug; 1080 splx(s); 1081 } 1082 #endif 1083 1084 #ifdef X_KLUGE 1085 /* 1086 * This is a kludge to allow X windows to work. 1087 */ 1088 caddr_t 1089 vmUserMap(size, pa) 1090 int size; 1091 unsigned pa; 1092 { 1093 register caddr_t v; 1094 unsigned off, entry; 1095 1096 if (nUserMapPtes == 0) 1097 UserMapPid = curproc->p_pid; 1098 else if (UserMapPid != curproc->p_pid) 1099 return ((caddr_t)0); 1100 off = pa & PGOFSET; 1101 size = btoc(off + size); 1102 if (nUserMapPtes + size > NPTES) 1103 return ((caddr_t)0); 1104 v = (caddr_t)(USER_MAP_ADDR + pmax_ptob(nUserMapPtes) + off); 1105 entry = (pa & 0x9ffff000) | PG_V | PG_M; 1106 if (pa >= MACH_UNCACHED_MEMORY_ADDR) 1107 entry |= PG_N; 1108 while (size > 0) { 1109 UserMapPtes[nUserMapPtes].pt_entry = entry; 1110 entry += NBPG; 1111 nUserMapPtes++; 1112 size--; 1113 } 1114 return (v); 1115 } 1116 1117 vmUserUnmap() 1118 { 1119 int id; 1120 1121 nUserMapPtes = 0; 1122 if (UserMapPid == curproc->p_pid) { 1123 id = curproc->p_vmspace->vm_pmap.pm_tlbpid; 1124 if (id >= 0) 1125 MachTLBFlushPID(id); 1126 } 1127 UserMapPid = 0; 1128 } 1129 #endif 1130 1131 /* 1132 *---------------------------------------------------------------------- 1133 * 1134 * MemErrorInterrupt -- 1135 * 1136 * Handler an interrupt for the control register. 1137 * 1138 * Results: 1139 * None. 1140 * 1141 * Side effects: 1142 * None. 1143 * 1144 *---------------------------------------------------------------------- 1145 */ 1146 static void 1147 MemErrorInterrupt() 1148 { 1149 #ifdef DS3100 1150 volatile u_short *sysCSRPtr = (u_short *)MACH_SYS_CSR_ADDR; 1151 u_short csr; 1152 1153 csr = *sysCSRPtr; 1154 1155 if (csr & MACH_CSR_MEM_ERR) { 1156 printf("Memory error at 0x%x\n", 1157 *(unsigned *)MACH_WRITE_ERROR_ADDR); 1158 panic("Mem error interrupt"); 1159 } 1160 *sysCSRPtr = (csr & ~MACH_CSR_MBZ) | 0xff; 1161 #endif /* DS3100 */ 1162 #ifdef DS5000 1163 printf("erradr %x\n", *(unsigned *)MACH_ERROR_ADDR); 1164 *(unsigned *)MACH_ERROR_ADDR = 0; 1165 MachEmptyWriteBuffer(); 1166 #endif /* DS5000 */ 1167 } 1168 1169 /* 1170 * Return the resulting PC as if the branch was executed. 1171 */ 1172 unsigned 1173 MachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch) 1174 unsigned *regsPtr; 1175 unsigned instPC; 1176 unsigned fpcCSR; 1177 int allowNonBranch; 1178 { 1179 InstFmt inst; 1180 unsigned retAddr; 1181 int condition; 1182 extern unsigned GetBranchDest(); 1183 1184 #if 0 1185 printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC, 1186 *(unsigned *)instPC, fpcCSR); 1187 #endif 1188 1189 inst = *(InstFmt *)instPC; 1190 switch ((int)inst.JType.op) { 1191 case OP_SPECIAL: 1192 switch ((int)inst.RType.func) { 1193 case OP_JR: 1194 case OP_JALR: 1195 retAddr = regsPtr[inst.RType.rs]; 1196 break; 1197 1198 default: 1199 if (!allowNonBranch) 1200 panic("MachEmulateBranch: Non-branch"); 1201 retAddr = instPC + 4; 1202 break; 1203 } 1204 break; 1205 1206 case OP_BCOND: 1207 switch ((int)inst.IType.rt) { 1208 case OP_BLTZ: 1209 case OP_BLTZAL: 1210 if ((int)(regsPtr[inst.RType.rs]) < 0) 1211 retAddr = GetBranchDest((InstFmt *)instPC); 1212 else 1213 retAddr = instPC + 8; 1214 break; 1215 1216 case OP_BGEZAL: 1217 case OP_BGEZ: 1218 if ((int)(regsPtr[inst.RType.rs]) >= 0) 1219 retAddr = GetBranchDest((InstFmt *)instPC); 1220 else 1221 retAddr = instPC + 8; 1222 break; 1223 1224 default: 1225 panic("MachEmulateBranch: Bad branch cond"); 1226 } 1227 break; 1228 1229 case OP_J: 1230 case OP_JAL: 1231 retAddr = (inst.JType.target << 2) | 1232 ((unsigned)instPC & 0xF0000000); 1233 break; 1234 1235 case OP_BEQ: 1236 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt]) 1237 retAddr = GetBranchDest((InstFmt *)instPC); 1238 else 1239 retAddr = instPC + 8; 1240 break; 1241 1242 case OP_BNE: 1243 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt]) 1244 retAddr = GetBranchDest((InstFmt *)instPC); 1245 else 1246 retAddr = instPC + 8; 1247 break; 1248 1249 case OP_BLEZ: 1250 if ((int)(regsPtr[inst.RType.rs]) <= 0) 1251 retAddr = GetBranchDest((InstFmt *)instPC); 1252 else 1253 retAddr = instPC + 8; 1254 break; 1255 1256 case OP_BGTZ: 1257 if ((int)(regsPtr[inst.RType.rs]) > 0) 1258 retAddr = GetBranchDest((InstFmt *)instPC); 1259 else 1260 retAddr = instPC + 8; 1261 break; 1262 1263 case OP_COP1: 1264 switch (inst.RType.rs) { 1265 case OP_BCx: 1266 case OP_BCy: 1267 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE) 1268 condition = fpcCSR & MACH_FPC_COND_BIT; 1269 else 1270 condition = !(fpcCSR & MACH_FPC_COND_BIT); 1271 if (condition) 1272 retAddr = GetBranchDest((InstFmt *)instPC); 1273 else 1274 retAddr = instPC + 8; 1275 break; 1276 1277 default: 1278 if (!allowNonBranch) 1279 panic("MachEmulateBranch: Bad coproc branch instruction"); 1280 retAddr = instPC + 4; 1281 } 1282 break; 1283 1284 default: 1285 if (!allowNonBranch) 1286 panic("MachEmulateBranch: Non-branch instruction"); 1287 retAddr = instPC + 4; 1288 } 1289 #if 0 1290 printf("Target addr=%x\n", retAddr); 1291 #endif 1292 return (retAddr); 1293 } 1294 1295 unsigned 1296 GetBranchDest(InstPtr) 1297 InstFmt *InstPtr; 1298 { 1299 return ((unsigned)InstPtr + 4 + ((short)InstPtr->IType.imm << 2)); 1300 } 1301 1302 /* 1303 * This routine is called by procxmt() to single step one instruction. 1304 * We do this by storing a break instruction after the current instruction, 1305 * resuming execution, and then restoring the old instruction. 1306 */ 1307 cpu_singlestep(p) 1308 register struct proc *p; 1309 { 1310 register unsigned va; 1311 register int *locr0 = p->p_md.md_regs; 1312 int i; 1313 1314 /* compute next address after current location */ 1315 va = MachEmulateBranch(locr0, locr0[PC], 0, 1); 1316 if (p->p_md.md_ss_addr || p->p_md.md_ss_addr == va || 1317 !useracc((caddr_t)va, 4, B_READ)) { 1318 printf("SS %s (%d): breakpoint already set at %x (va %x)\n", 1319 p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */ 1320 return (EFAULT); 1321 } 1322 p->p_md.md_ss_addr = va; 1323 p->p_md.md_ss_instr = fuiword(va); 1324 i = suiword((caddr_t)va, MACH_BREAK_SSTEP); 1325 if (i < 0) { 1326 vm_offset_t sa, ea; 1327 int rv; 1328 1329 sa = trunc_page((vm_offset_t)va); 1330 ea = round_page((vm_offset_t)va+sizeof(int)-1); 1331 rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, 1332 VM_PROT_DEFAULT, FALSE); 1333 if (rv == KERN_SUCCESS) { 1334 i = suiword((caddr_t)va, MACH_BREAK_SSTEP); 1335 (void) vm_map_protect(&p->p_vmspace->vm_map, 1336 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE); 1337 } 1338 } 1339 if (i < 0) 1340 return (EFAULT); 1341 printf("SS %s (%d): breakpoint set at %x: %x (pc %x)\n", 1342 p->p_comm, p->p_pid, p->p_md.md_ss_addr, 1343 p->p_md.md_ss_instr, locr0[PC]); /* XXX */ 1344 return (0); 1345 } 1346 1347 #ifdef news3400 1348 /* 1349 * news3400 - INT0 service routine. 1350 * 1351 * INTST0 bit 4: dma 1352 * 3: slot #1 1353 * 2: slot #3 1354 * 1: external #1 1355 * 0: external #3 1356 */ 1357 1358 #define LEVEL0_MASK \ 1359 (INTST1_DMA|INTST1_SLOT1|INTST1_SLOT3|INTST1_EXT1|INTST1_EXT3) 1360 1361 level0_intr() 1362 { 1363 register int stat; 1364 1365 stat = *(volatile u_char *)INTST1 & LEVEL0_MASK; 1366 *(u_char *)INTCLR1 = stat; 1367 1368 if (stat & INTST1_DMA) 1369 dma_intr(); 1370 if (stat & INTST1_SLOT1) 1371 exec_hb_intr2(); 1372 #if NEN > 0 1373 if (stat & INTST1_SLOT3) { 1374 int s, t; 1375 1376 s = splimp(); 1377 t = lance_intr(); 1378 (void) splx(s); 1379 if (t == 0) 1380 exec_hb_intr4(); 1381 } 1382 #endif 1383 #if NLE > 0 1384 if (stat & INTST1_SLOT3) { 1385 int s; 1386 1387 s = splimp(); 1388 leintr(0); 1389 (void) splx(s); 1390 } 1391 #endif 1392 if (stat & INTST1_EXT1) 1393 print_int_stat("EXT #1"); 1394 if (stat & INTST1_EXT3) 1395 print_int_stat("EXT #3"); 1396 } 1397 1398 /* 1399 * news3400 - INT1 service routine. 1400 * 1401 * INTST0 bit 1: centro fault 1402 * 0: centro busy 1403 * INTST1 bit 7: beep 1404 * 6: scc 1405 * 5: lance 1406 */ 1407 1408 #define LEVEL1_MASK2 (INTST0_CFLT|INTST0_CBSY) 1409 #define LEVEL1_MASK1 (INTST1_BEEP|INTST1_SCC|INTST1_LANCE) 1410 1411 level1_intr(pc) 1412 unsigned pc; 1413 { 1414 register int stat; 1415 register u_int saved_inten1 = *(u_char *)INTEN1; 1416 1417 *(u_char *)INTEN1 = 0; /* disable intr: beep, lance, scc */ 1418 1419 stat = *(volatile u_char *)INTST1 & LEVEL1_MASK1; 1420 *(u_char *)INTCLR1 = stat; 1421 1422 stat &= saved_inten1; 1423 1424 if (stat & INTST1_BEEP) { 1425 *(volatile u_char *)INTCLR1 = INTCLR1_BEEP; 1426 print_int_stat("BEEP"); 1427 } 1428 if (stat & INTST1_SCC) { 1429 scc_intr(); 1430 if (saved_inten1 & *(u_char *)INTST1 & INTST1_SCC) 1431 scc_intr(); 1432 } 1433 #if NEN > 0 1434 if (stat & INTST1_LANCE) 1435 lance_intr(); 1436 #endif 1437 #if NLE > 0 1438 if (stat & INTST1_LANCE) 1439 leintr(0); 1440 #endif 1441 1442 *(u_char *)INTEN1 = saved_inten1; 1443 1444 #if NLP > 0 1445 /* 1446 * The PARK2 cannot find centro interrupt correctly. 1447 * We must check it by reading the cause register of cpu 1448 * while other interrupts are disabled. 1449 */ 1450 { 1451 register int causereg; 1452 int s = splhigh(); 1453 1454 causereg = get_causereg(); 1455 (void) splx(s); 1456 1457 if ((causereg & CAUSE_IP4) == 0) 1458 return; 1459 } 1460 #endif 1461 1462 stat = (int)(*(u_char *)INTST0) & LEVEL1_MASK2; 1463 *(u_char *)INTCLR0 = stat; 1464 1465 if (stat & INTST0_CBSY) /* centro busy */ 1466 #if NLP > 0 1467 lpxint(0); 1468 #else 1469 printf("stray intr: CBSY\n"); 1470 #endif 1471 } 1472 1473 /* 1474 * DMA interrupt service routine. 1475 */ 1476 dma_intr() 1477 { 1478 register volatile u_char *gsp = (u_char *)DMAC_GSTAT; 1479 register u_int gstat = *gsp; 1480 register int mrqb, i; 1481 1482 /* 1483 * when DMA intrrupt occurs there remain some untransferred data. 1484 * wait data transfer completion. 1485 */ 1486 mrqb = (gstat & (CH0_INT|CH1_INT|CH2_INT|CH3_INT)) << 1; 1487 if (gstat & mrqb) { 1488 /* 1489 * SHOULD USE DELAY() 1490 */ 1491 for (i = 0; i < 50; i++) 1492 ; 1493 if (*gsp & mrqb) 1494 printf("dma_intr: MRQ\n"); 1495 } 1496 1497 /* SCSI Dispatch */ 1498 if (gstat & CH_INT(CH_SCSI)) 1499 scintr(); 1500 1501 #include "fd.h" 1502 #if NFD > 0 1503 /* FDC Interrupt Dispatch */ 1504 if (gstat & CH_INT(CH_FDC)) 1505 fdc_intr(0); 1506 #endif /* NFD > 0 */ 1507 1508 #include "sb.h" 1509 #if NSB > 0 1510 /* Audio Interface Dispatch */ 1511 sbintr(0); 1512 #endif /* NSB > 0 */ 1513 1514 /* Video I/F Dispatch */ 1515 if (gstat & CH_INT(CH_VIDEO)) 1516 ; 1517 } 1518 1519 /* 1520 * SCC vector interrupt service routine. 1521 */ 1522 scc_intr() 1523 { 1524 int vec; 1525 extern int scc_xint(), scc_sint(), scc_rint(), scc_cint(); 1526 static int (*func[])() = { 1527 scc_xint, 1528 scc_sint, 1529 scc_rint, 1530 scc_cint 1531 }; 1532 1533 vec = *(volatile u_char *)SCCVECT; 1534 (*func[(vec & SCC_INT_MASK) >> 1])(vec); 1535 } 1536 1537 print_int_stat(msg) 1538 char *msg; 1539 { 1540 int s0 = *(volatile u_char *)INTST0; 1541 int s1 = *(volatile u_char *)INTST1; 1542 1543 if (msg) 1544 printf("%s: ", msg); 1545 else 1546 printf("intr: "); 1547 printf("INTST0=0x%x, INTST1=0x%x.\n", s0, s1); 1548 } 1549 #endif /* news3400 */ 1550