1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "ureg.h" 7 #include "../port/error.h" 8 #include "tos.h" 9 #include <trace.h> 10 11 static Lock vctllock; 12 Vctl *vctl[256]; 13 14 int intrstack[5]; 15 uvlong intrtime[5]; 16 vlong lastoffset; 17 int inintr; 18 int nintr[10]; 19 int nintro; 20 int dblintr[64]; 21 ulong thisto[32]; 22 ulong thistoo; 23 vlong vnot[64]; 24 ulong vnon[64]; 25 26 void 27 intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name) 28 { 29 int vno; 30 Vctl *v; 31 32 if(f == nil){ 33 print("intrenable: nil handler for %d for %s\n", 34 irq, name); 35 return; 36 } 37 38 v = xalloc(sizeof(Vctl)); 39 v->isintr = 1; 40 v->irq = irq; 41 v->f = f; 42 v->a = a; 43 strncpy(v->name, name, KNAMELEN-1); 44 v->name[KNAMELEN-1] = 0; 45 46 ilock(&vctllock); 47 vno = vectorenable(v); 48 if(vno == -1){ 49 iunlock(&vctllock); 50 print("intrenable: couldn't enable irq %d for %s\n", 51 irq, v->name); 52 xfree(v); 53 return; 54 } 55 v->next = vctl[vno]; 56 vctl[vno] = v; 57 iunlock(&vctllock); 58 } 59 60 void 61 intrdisable(int irq, void (*f)(Ureg *, void *), void *a, char *name) 62 { 63 Vctl **pv, *v; 64 65 ilock(&vctllock); 66 pv = &vctl[irq]; 67 while (*pv && 68 ((*pv)->irq != irq || (*pv)->f != f || (*pv)->a != a || 69 strcmp((*pv)->name, name))) 70 pv = &((*pv)->next); 71 72 if(*pv == nil){ 73 print("intrdisable: irq %d not found\n", irq); 74 iunlock(&vctllock); 75 return; 76 } 77 78 v = *pv; 79 *pv = (*pv)->next; /* Link out the entry */ 80 81 if(vctl[irq] == nil) 82 vectordisable(v); 83 iunlock(&vctllock); 84 xfree(v); 85 } 86 87 void syscall(Ureg*); 88 void noted(Ureg*, ulong); 89 static void _dumpstack(Ureg*); 90 91 char *excname[] = 92 { 93 "reserved 0", 94 "system reset", 95 "machine check", 96 "data access", 97 "instruction access", 98 "external interrupt", 99 "alignment", 100 "program exception", 101 "floating-point unavailable", 102 "decrementer", 103 "reserved A", 104 "reserved B", 105 "system call", 106 "trace trap", 107 "floating point assist", 108 "reserved F", 109 "reserved 10", 110 "data load translation miss", 111 "data store translation miss", 112 "instruction address breakpoint", 113 "system management interrupt", 114 }; 115 116 char *fpcause[] = 117 { 118 "inexact operation", 119 "division by zero", 120 "underflow", 121 "overflow", 122 "invalid operation", 123 }; 124 char *fpexcname(Ureg*, ulong, char*); 125 #define FPEXPMASK 0xfff80300 /* Floating exception bits in fpscr */ 126 127 128 char *regname[]={ 129 "CAUSE", "SRR1", 130 "PC", "GOK", 131 "LR", "CR", 132 "XER", "CTR", 133 "R0", "R1", 134 "R2", "R3", 135 "R4", "R5", 136 "R6", "R7", 137 "R8", "R9", 138 "R10", "R11", 139 "R12", "R13", 140 "R14", "R15", 141 "R16", "R17", 142 "R18", "R19", 143 "R20", "R21", 144 "R22", "R23", 145 "R24", "R25", 146 "R26", "R27", 147 "R28", "R29", 148 "R30", "R31", 149 "DCMP", "ICMP", 150 "DMISS", "IMISS", 151 "HASH1", "HASH2", 152 "DAR", "DSISR", 153 }; 154 155 void 156 kexit(Ureg*) 157 { 158 uvlong t; 159 Tos *tos; 160 161 /* precise time accounting, kernel exit */ 162 tos = (Tos*)(USTKTOP-sizeof(Tos)); 163 cycles(&t); 164 tos->kcycles += t - up->kentry; 165 tos->pcycles = up->pcycles; 166 tos->pid = up->pid; 167 } 168 169 void 170 trap(Ureg *ureg) 171 { 172 int ecode, user; 173 char buf[ERRMAX], *s; 174 extern FPsave initfp; 175 176 ecode = (ureg->cause >> 8) & 0xff; 177 user = (ureg->srr1 & MSR_PR) != 0; 178 if(user){ 179 cycles(&up->kentry); 180 up->dbgreg = ureg; 181 } 182 if(ureg->status & MSR_RI == 0) 183 print("double fault?: ecode = %d\n", ecode); 184 185 switch(ecode) { 186 case CEI: 187 m->intr++; 188 intr(ureg); 189 break; 190 case CDEC: 191 clockintr(ureg); 192 break; 193 case CDSI: 194 m->pfault++; 195 if (up == nil){ 196 dumpregs(ureg); 197 panic("kernel fault"); 198 } 199 up->mmureg = ureg; 200 faultpower(ureg, ureg->dar, (ureg->dsisr & BIT(6)) == 0); 201 break; 202 case CISI: 203 m->pfault++; 204 if (up == nil){ 205 dumpregs(ureg); 206 panic("kernel fault"); 207 } 208 up->mmureg = ureg; 209 faultpower(ureg, ureg->pc, 1); 210 break; 211 case CIMISS: /* instruction miss */ 212 if (up == nil){ 213 dumpregs(ureg); 214 panic("kernel fault"); 215 } 216 up->mmureg = ureg; 217 faultpower(ureg, ureg->imiss, 1); 218 break; 219 case CLMISS: /* data load miss */ 220 if (up == nil){ 221 dumpregs(ureg); 222 panic("kernel fault"); 223 } 224 up->mmureg = ureg; 225 faultpower(ureg, ureg->dmiss, 1); 226 break; 227 case CSMISS: /* data store miss */ 228 if (up == nil){ 229 dumpregs(ureg); 230 panic("kernel fault"); 231 } 232 up->mmureg = ureg; 233 faultpower(ureg, ureg->dmiss, 0); 234 break; 235 236 case CSYSCALL: 237 if(!user) 238 panic("syscall in kernel: srr1 0x%4.4luX\n", ureg->srr1); 239 syscall(ureg); 240 if (up->delaysched){ 241 sched(); 242 splhi(); 243 } 244 kexit(ureg); 245 return; /* syscall() calls notify itself, don't do it again */ 246 247 case CFPU: 248 if(!user || up == nil) { 249 dumpregs(ureg); 250 panic("floating point in kernel"); 251 } 252 switch(up->fpstate){ 253 case FPinit: 254 fprestore(&initfp); 255 up->fpstate = FPactive; 256 break; 257 case FPinactive: 258 fprestore(&up->fpsave); 259 up->fpstate = FPactive; 260 break; 261 case FPactive: 262 print("up->fpstate %d\n", up->fpstate); 263 delay(100); 264 dumpregs(ureg); 265 delay(200); 266 panic("fpstate"); 267 break; 268 default: 269 if(user){ 270 spllo(); 271 sprint(buf, "sys: floating point in note handler:"); 272 postnote(up, 1, buf, NDebug); 273 break; 274 } 275 panic("kernel fpstate illegal"); 276 } 277 ureg->srr1 |= MSR_FP; 278 break; 279 case CPROG: 280 if(ureg->status & (1<<19)) 281 s = "floating point exception"; 282 else if(ureg->status & (1<<18)) 283 s = "illegal instruction"; 284 else if(ureg->status & (1<<17)) 285 s = "privileged instruction"; 286 else 287 s = "undefined program exception"; 288 if(user){ 289 spllo(); 290 sprint(buf, "sys: trap: %s", s); 291 postnote(up, 1, buf, NDebug); 292 break; 293 } 294 dumpregs(ureg); 295 panic(s); 296 break; 297 default: 298 if(ecode < nelem(excname) && user){ 299 spllo(); 300 sprint(buf, "sys: trap: %s", excname[ecode]); 301 postnote(up, 1, buf, NDebug); 302 break; 303 } 304 dumpregs(ureg); 305 if(ecode < nelem(excname)) 306 panic("%s", excname[ecode]); 307 panic("unknown trap/intr: %d\n", ecode); 308 } 309 310 /* restoreureg must execute at high IPL */ 311 splhi(); 312 313 /* delaysched set because we held a lock or because our quantum ended */ 314 if(up && up->delaysched && ecode == CDEC){ 315 sched(); 316 splhi(); 317 } 318 319 if(user) { 320 if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){ 321 postnote(up, 1, buf, NDebug); 322 } 323 notify(ureg); 324 if(up->fpstate != FPactive) 325 ureg->srr1 &= ~MSR_FP; 326 kexit(ureg); 327 } 328 } 329 330 void 331 faultpower(Ureg *ureg, ulong addr, int read) 332 { 333 int user, insyscall, n; 334 char buf[ERRMAX]; 335 336 user = (ureg->srr1 & MSR_PR) != 0; 337 insyscall = up->insyscall; 338 up->insyscall = 1; 339 n = fault(addr, read); 340 if(n < 0){ 341 if(!user){ 342 dumpregs(ureg); 343 panic("fault: 0x%lux", addr); 344 } 345 sprint(buf, "sys: trap: fault %s addr=0x%lux", read? "read" : "write", addr); 346 postnote(up, 1, buf, NDebug); 347 } 348 up->insyscall = insyscall; 349 } 350 351 void 352 sethvec(int v, void (*r)(void)) 353 { 354 ulong *vp, pa, o; 355 356 vp = KADDR(v); 357 vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */ 358 vp[1] = 0x7c0802a6; /* MOVW LR, R0 */ 359 vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */ 360 pa = PADDR(r); 361 o = pa >> 25; 362 if(o != 0 && o != 0x7F){ 363 /* a branch too far */ 364 vp[3] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */ 365 vp[4] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */ 366 vp[5] = 0x7c0803a6; /* MOVW R0, LR */ 367 vp[6] = 0x4e800021; /* BL (LR) */ 368 }else 369 vp[3] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */ 370 } 371 372 void 373 setmvec(int v, void (*r)(void), void (*t)(void)) 374 { 375 ulong *vp, pa, o, n; 376 377 vp = KADDR(v); 378 n = 0; 379 vp[n++] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */ 380 vp[n++] = 0x7c0802a6; /* MOVW LR, R0 */ 381 vp[n++] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */ 382 pa = PADDR(r); 383 o = pa >> 25; 384 if(o != 0 && o != 0x7F){ 385 /* a branch too far */ 386 vp[n++] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */ 387 vp[n++] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */ 388 vp[n++] = 0x7c0803a6; /* MOVW R0, LR */ 389 vp[n++] = 0x4e800021; /* BL (LR) */ 390 }else 391 vp[n++] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */ 392 pa = PADDR(t); 393 o = pa >> 25; 394 if(o != 0 && o != 0x7F){ 395 /* a branch too far */ 396 vp[n++] = (15<<26)|(pa>>16); /* MOVW $r&~0xFFFF, R0 */ 397 vp[n++] = (24<<26)|(pa&0xFFFF); /* OR $r&0xFFFF, R0 */ 398 vp[n++] = 0x7c0803a6; /* MOVW R0, LR */ 399 vp[n] = 0x4e800021; /* BL (LR) */ 400 }else 401 vp[n] = (18<<26)|(pa&0x3FFFFFC)|3; /* bla */ 402 } 403 404 405 void 406 intr(Ureg *ureg) 407 { 408 int vno, pvno, i; 409 Vctl *ctl, *v; 410 void (*pt)(Proc*, int, vlong); 411 uvlong tt, x; 412 413 cycles(&tt); 414 pt = proctrace; 415 pvno = -1; 416 for(i = 0; i < 64; i++){ 417 vno = intvec(); 418 if(vno == 0) 419 break; 420 cycles(&x); 421 vnot[vno] -= x; 422 if(vno == pvno) 423 dblintr[vno]++; 424 pvno = vno; 425 if(pt && up && up->trace) 426 pt(up, (vno << 16) | SInts, 0); 427 428 if(vno > nelem(vctl) || (ctl = vctl[vno]) == 0) { 429 iprint("spurious intr %d\n", vno); 430 return; 431 } 432 433 for(v = ctl; v != nil; v = v->next) 434 if(v->f) 435 v->f(ureg, v->a); 436 437 intend(vno); /* reenable the interrupt */ 438 439 if(pt && up && up->trace) 440 pt(up, (vno << 16) | SInte, 0); 441 cycles(&x); 442 vnot[vno] += x; 443 vnon[vno]++; 444 } 445 if(i < nelem(nintr)) 446 nintr[i]++; 447 else 448 nintro++; 449 cycles(&x); 450 tt = x - tt; 451 i = tt / 3600; /* 100 microseconds units */ 452 if(i < nelem(thisto)) 453 thisto[i]++; 454 else 455 thistoo++; 456 457 if(up) 458 preempted(); 459 } 460 461 char* 462 fpexcname(Ureg *ur, ulong fpscr, char *buf) 463 { 464 int i; 465 char *s; 466 ulong fppc; 467 468 fppc = ur->pc; 469 s = 0; 470 fpscr >>= 3; /* trap enable bits */ 471 fpscr &= (fpscr>>22); /* anded with exceptions */ 472 for(i=0; i<5; i++) 473 if(fpscr & (1<<i)) 474 s = fpcause[i]; 475 if(s == 0) 476 return "no floating point exception"; 477 sprint(buf, "%s fppc=0x%lux", s, fppc); 478 return buf; 479 } 480 481 /* 482 * Fill in enough of Ureg to get a stack trace, and call a function. 483 * Used by debugging interface rdb. 484 */ 485 486 static void 487 getpcsp(ulong *pc, ulong *sp) 488 { 489 *pc = getcallerpc(&pc); 490 *sp = (ulong)&pc-4; 491 } 492 493 void 494 callwithureg(void (*fn)(Ureg*)) 495 { 496 Ureg ureg; 497 498 getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp); 499 ureg.lr = getcallerpc(&fn); 500 fn(&ureg); 501 } 502 503 static void 504 _dumpstack(Ureg *ureg) 505 { 506 ulong l, sl, el, v; 507 int i; 508 509 l = (ulong)&l; 510 if(up == 0){ 511 el = (ulong)m+BY2PG; 512 sl = el-KSTACK; 513 } 514 else{ 515 sl = (ulong)up->kstack; 516 el = sl + KSTACK; 517 } 518 if(l > el || l < sl){ 519 el = (ulong)m+BY2PG; 520 sl = el-KSTACK; 521 } 522 if(l > el || l < sl) 523 return; 524 print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->lr); 525 i = 0; 526 for(; l < el; l += 4){ 527 v = *(ulong*)l; 528 if(KTZERO < v && v < (ulong)etext){ 529 print("%.8lux=%.8lux ", l, v); 530 if(i++ == 4){ 531 print("\n"); 532 i = 0; 533 } 534 } 535 } 536 } 537 538 void 539 dumpstack(void) 540 { 541 callwithureg(_dumpstack); 542 } 543 544 void 545 dumpregs(Ureg *ur) 546 { 547 int i; 548 ulong *l; 549 550 if(up) { 551 print("registers for %s %ld\n", up->text, up->pid); 552 if(ur->srr1 & MSR_PR == 0) 553 if(ur->usp < (ulong)up->kstack || ur->usp > (ulong)up->kstack+KSTACK) 554 print("invalid stack ptr\n"); 555 } 556 else 557 print("registers for kernel\n"); 558 559 for(i=0; i<16; i+=2) 560 print("sr[%x]\t0x%.8lux\tsr[%x]\t0x%.8lux\n", i, getsr(i<<28), i+1, getsr((i+1)<<28)); 561 l = &ur->cause; 562 for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2) 563 print("%s\t0x%.8lux\t%s\t0x%.8lux\n", regname[i], l[0], regname[i+1], l[1]); 564 delay(500); 565 } 566 567 static void 568 linkproc(void) 569 { 570 spllo(); 571 (*up->kpfun)(up->kparg); 572 pexit("", 0); 573 } 574 575 void 576 kprocchild(Proc *p, void (*func)(void*), void *arg) 577 { 578 p->sched.pc = (ulong)linkproc; 579 p->sched.sp = (ulong)p->kstack+KSTACK; 580 581 p->kpfun = func; 582 p->kparg = arg; 583 } 584 585 /* 586 * called in sysfile.c 587 */ 588 void 589 evenaddr(ulong addr) 590 { 591 if(addr & 3){ 592 postnote(up, 1, "sys: odd address", NDebug); 593 error(Ebadarg); 594 } 595 } 596 597 long 598 execregs(ulong entry, ulong ssize, ulong nargs) 599 { 600 ulong *sp; 601 Ureg *ureg; 602 603 sp = (ulong*)(USTKTOP - ssize); 604 *--sp = nargs; 605 606 ureg = up->dbgreg; 607 ureg->usp = (ulong)sp; 608 ureg->pc = entry; 609 ureg->srr1 &= ~MSR_FP; /* disable floating point */ 610 up->fpstate = FPinit; 611 return USTKTOP-sizeof(Tos); /* address of kernel/user shared data */ 612 } 613 614 void 615 forkchild(Proc *p, Ureg *ur) 616 { 617 Ureg *cur; 618 619 p->sched.sp = (ulong)p->kstack+KSTACK-UREGSIZE; 620 p->sched.pc = (ulong)forkret; 621 622 cur = (Ureg*)(p->sched.sp+2*BY2WD); 623 memmove(cur, ur, sizeof(Ureg)); 624 cur->r3 = 0; 625 626 /* Things from bottom of syscall we never got to execute */ 627 p->psstate = 0; 628 p->insyscall = 0; 629 } 630 631 ulong 632 userpc(void) 633 { 634 Ureg *ureg; 635 636 ureg = (Ureg*)up->dbgreg; 637 return ureg->pc; 638 } 639 640 641 /* This routine must save the values of registers the user is not 642 * permitted to write from devproc and then restore the saved values 643 * before returning 644 */ 645 void 646 setregisters(Ureg *xp, char *pureg, char *uva, int n) 647 { 648 ulong status; 649 650 status = xp->status; 651 memmove(pureg, uva, n); 652 xp->status = status; 653 } 654 655 /* Give enough context in the ureg to produce a kernel stack for 656 * a sleeping process 657 */ 658 void 659 setkernur(Ureg* ureg, Proc* p) 660 { 661 ureg->pc = p->sched.pc; 662 ureg->sp = p->sched.sp+4; 663 } 664 665 ulong 666 dbgpc(Proc *p) 667 { 668 Ureg *ureg; 669 670 ureg = p->dbgreg; 671 if(ureg == 0) 672 return 0; 673 674 return ureg->pc; 675 } 676 677 /* 678 * system calls 679 */ 680 #include "../port/systab.h" 681 682 /* TODO: make this trap a separate asm entry point, like on other RISC architectures */ 683 void 684 syscall(Ureg* ureg) 685 { 686 int i; 687 char *e; 688 long ret; 689 ulong sp, scallnr; 690 691 m->syscall++; 692 up->insyscall = 1; 693 up->pc = ureg->pc; 694 up->dbgreg = ureg; 695 696 if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){ 697 print("fpstate check, entry syscall\n"); 698 delay(200); 699 dumpregs(ureg); 700 print("fpstate check, entry syscall\n"); 701 } 702 703 scallnr = ureg->r3; 704 up->scallnr = ureg->r3; 705 if(scallnr == RFORK && up->fpstate == FPactive){ 706 fpsave(&up->fpsave); 707 up->fpstate = FPinactive; 708 } 709 spllo(); 710 711 sp = ureg->usp; 712 up->nerrlab = 0; 713 ret = -1; 714 if(!waserror()){ 715 if(scallnr >= nsyscall || systab[scallnr] == nil){ 716 pprint("bad sys call number %ld pc %lux\n", scallnr, ureg->pc); 717 postnote(up, 1, "sys: bad sys call", NDebug); 718 error(Ebadarg); 719 } 720 721 if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD)) 722 validaddr(sp, sizeof(Sargs)+BY2WD, 0); 723 724 up->s = *((Sargs*)(sp+BY2WD)); 725 up->psstate = sysctab[scallnr]; 726 727 ret = systab[scallnr](up->s.args); 728 poperror(); 729 }else{ 730 /* failure: save the error buffer for errstr */ 731 e = up->syserrstr; 732 up->syserrstr = up->errstr; 733 up->errstr = e; 734 } 735 if(up->nerrlab){ 736 print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab); 737 print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr); 738 for(i = 0; i < NERR; i++) 739 print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc); 740 panic("error stack"); 741 } 742 743 up->insyscall = 0; 744 up->psstate = 0; 745 746 /* 747 * Put return value in frame. On the x86 the syscall is 748 * just another trap and the return value from syscall is 749 * ignored. On other machines the return value is put into 750 * the results register by caller of syscall. 751 */ 752 ureg->r3 = ret; 753 754 if(scallnr == NOTED) 755 noted(ureg, *(ulong*)(sp+BY2WD)); 756 757 /* restoreureg must execute at high IPL */ 758 splhi(); 759 if(scallnr!=RFORK) 760 notify(ureg); 761 762 if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){ 763 print("fpstate check, exit syscall nr %lud, pid %lud\n", scallnr, up->pid); 764 dumpregs(ureg); 765 } 766 if(up->fpstate != FPactive) 767 ureg->srr1 &= ~MSR_FP; 768 } 769 770 /* 771 * Call user, if necessary, with note. 772 * Pass user the Ureg struct and the note on his stack. 773 */ 774 int 775 notify(Ureg* ur) 776 { 777 int l; 778 ulong s, sp; 779 Note *n; 780 781 if(up->procctl) 782 procctl(up); 783 if(up->nnote == 0) 784 return 0; 785 786 s = spllo(); 787 qlock(&up->debug); 788 up->notepending = 0; 789 n = &up->note[0]; 790 if(strncmp(n->msg, "sys:", 4) == 0){ 791 l = strlen(n->msg); 792 if(l > ERRMAX-15) /* " pc=0x12345678\0" */ 793 l = ERRMAX-15; 794 sprint(n->msg+l, " pc=0x%.8lux", ur->pc); 795 } 796 797 if(n->flag!=NUser && (up->notified || up->notify==0)){ 798 if(n->flag == NDebug) 799 pprint("suicide: %s\n", n->msg); 800 qunlock(&up->debug); 801 pexit(n->msg, n->flag!=NDebug); 802 } 803 804 if(up->notified) { 805 qunlock(&up->debug); 806 splhi(); 807 return 0; 808 } 809 810 if(!up->notify) { 811 qunlock(&up->debug); 812 pexit(n->msg, n->flag!=NDebug); 813 } 814 815 if(up->fpstate == FPactive){ 816 fpsave(&up->fpsave); 817 up->fpstate = FPinactive; 818 } 819 up->fpstate |= FPillegal; 820 821 sp = ur->usp & ~(BY2V-1); 822 sp -= sizeof(Ureg); 823 824 if(!okaddr((ulong)up->notify, BY2WD, 0) || 825 !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)) { 826 pprint("suicide: bad address or sp in notify\n"); 827 qunlock(&up->debug); 828 pexit("Suicide", 0); 829 } 830 831 memmove((Ureg*)sp, ur, sizeof(Ureg)); 832 *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */ 833 up->ureg = (void*)sp; 834 sp -= BY2WD+ERRMAX; 835 memmove((char*)sp, up->note[0].msg, ERRMAX); 836 sp -= 3*BY2WD; 837 *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */ 838 ur->r1 = (long)up->ureg; /* arg 1 is ureg* */ 839 ((ulong*)sp)[1] = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */ 840 ((ulong*)sp)[0] = 0; /* arg 0 is pc */ 841 ur->usp = sp; 842 ur->pc = (ulong)up->notify; 843 up->notified = 1; 844 up->nnote--; 845 memmove(&up->lastnote, &up->note[0], sizeof(Note)); 846 memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note)); 847 848 qunlock(&up->debug); 849 splx(s); 850 return 1; 851 } 852 853 854 /* 855 * Return user to state before notify() 856 */ 857 void 858 noted(Ureg* ureg, ulong arg0) 859 { 860 Ureg *nureg; 861 ulong oureg, sp; 862 863 qlock(&up->debug); 864 if(arg0!=NRSTR && !up->notified) { 865 qunlock(&up->debug); 866 pprint("call to noted() when not notified\n"); 867 pexit("Suicide", 0); 868 } 869 up->notified = 0; 870 871 nureg = up->ureg; /* pointer to user returned Ureg struct */ 872 873 /* sanity clause */ 874 oureg = (ulong)nureg; 875 if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){ 876 pprint("bad ureg in noted or call to noted when not notified\n"); 877 qunlock(&up->debug); 878 pexit("Suicide", 0); 879 } 880 881 memmove(ureg, nureg, sizeof(Ureg)); 882 883 switch(arg0){ 884 case NCONT: 885 case NRSTR: 886 if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){ 887 pprint("suicide: trap in noted\n"); 888 qunlock(&up->debug); 889 pexit("Suicide", 0); 890 } 891 up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD)); 892 qunlock(&up->debug); 893 break; 894 895 case NSAVE: 896 if(!okaddr(nureg->pc, BY2WD, 0) 897 || !okaddr(nureg->usp, BY2WD, 0)){ 898 pprint("suicide: trap in noted\n"); 899 qunlock(&up->debug); 900 pexit("Suicide", 0); 901 } 902 qunlock(&up->debug); 903 sp = oureg-4*BY2WD-ERRMAX; 904 splhi(); 905 ureg->sp = sp; 906 ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */ 907 ((ulong*)sp)[0] = 0; /* arg 0 is pc */ 908 break; 909 910 default: 911 pprint("unknown noted arg 0x%lux\n", arg0); 912 up->lastnote.flag = NDebug; 913 /* fall through */ 914 915 case NDFLT: 916 if(up->lastnote.flag == NDebug) 917 pprint("suicide: %s\n", up->lastnote.msg); 918 qunlock(&up->debug); 919 pexit(up->lastnote.msg, up->lastnote.flag!=NDebug); 920 } 921 up->fpstate &= ~FPillegal; 922 if (up->fpstate == FPactive) 923 ureg->srr1 |= MSR_FP; 924 else 925 ureg->srr1 &= ~MSR_FP; 926 } 927