trap.c 18 KB

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