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