trap.c 16 KB

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