trap.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  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 "io.h"
  8. #include "../port/error.h"
  9. void noted(Ureg*, Ureg**, ulong);
  10. void rfnote(Ureg**);
  11. void kernfault(Ureg*, int);
  12. void illegal(Ureg *);
  13. void fen(Ureg *);
  14. char *regname[]={
  15. "type", "a0", "a1",
  16. "a2", "R0", "R1",
  17. "R2", "R3", "R4",
  18. "R5", "R6", "R7",
  19. "R8", "R9", "R10",
  20. "R11", "R12", "R13",
  21. "R14", "R15", "R19",
  22. "R20", "R21", "R22",
  23. "R23", "R24", "R25",
  24. "R26", "R27", "R28",
  25. "R30", "status", "PC",
  26. "R29", "R16", "R17",
  27. "R18",
  28. };
  29. static Lock vctllock;
  30. static Vctl *vctl[256];
  31. void
  32. intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
  33. {
  34. int vno;
  35. Vctl *v;
  36. if(f == nil){
  37. print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",
  38. irq, tbdf, name);
  39. return;
  40. }
  41. v = xalloc(sizeof(Vctl));
  42. v->isintr = 1;
  43. v->irq = irq;
  44. v->tbdf = tbdf;
  45. v->f = f;
  46. v->a = a;
  47. strncpy(v->name, name, KNAMELEN-1);
  48. v->name[KNAMELEN-1] = 0;
  49. ilock(&vctllock);
  50. vno = arch->intrenable(v);
  51. if(vno == -1){
  52. iunlock(&vctllock);
  53. print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
  54. irq, tbdf, v->name);
  55. xfree(v);
  56. return;
  57. }
  58. if(vctl[vno]){
  59. if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
  60. panic("intrenable: handler: %s %s %luX %luX %luX %luX\n",
  61. vctl[vno]->name, v->name,
  62. vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
  63. v->next = vctl[vno];
  64. }
  65. vctl[vno] = v;
  66. iunlock(&vctllock);
  67. }
  68. int
  69. intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
  70. {
  71. Vctl **pv, *v;
  72. int vno;
  73. /*
  74. * For now, none of this will work with the APIC code,
  75. * there is no mapping between irq and vector as the IRQ
  76. * is pretty meaningless.
  77. */
  78. if(arch->intrvecno == nil)
  79. return -1;
  80. vno = arch->intrvecno(irq);
  81. ilock(&vctllock);
  82. for(pv = &vctl[vno]; *pv != nil; pv = &((*pv)->next)){
  83. if((*pv)->irq != irq)
  84. continue;
  85. if((*pv)->tbdf != tbdf)
  86. continue;
  87. if((*pv)->f != f)
  88. continue;
  89. if((*pv)->a != a)
  90. continue;
  91. if(strcmp((*pv)->name, name) != 0)
  92. continue;
  93. break;
  94. }
  95. assert(*pv != nil);
  96. v = *pv;
  97. *pv = (*pv)->next; /* Link out the entry */
  98. if (vctl[vno] == nil && arch->intrdisable != nil)
  99. arch->intrdisable(irq);
  100. iunlock(&vctllock);
  101. xfree(v);
  102. return 0;
  103. }
  104. int
  105. irqallocread(char *buf, long n, vlong offset)
  106. {
  107. int vno;
  108. Vctl *v;
  109. long oldn;
  110. char str[11+1+KNAMELEN+1], *p;
  111. int m;
  112. if(n < 0 || offset < 0)
  113. error(Ebadarg);
  114. oldn = n;
  115. for(vno=0; vno<nelem(vctl); vno++){
  116. for(v=vctl[vno]; v; v=v->next){
  117. m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name);
  118. if(m <= offset) /* if do not want this, skip entry */
  119. offset -= m;
  120. else{
  121. /* skip offset bytes */
  122. m -= offset;
  123. p = str+offset;
  124. offset = 0;
  125. /* write at most max(n,m) bytes */
  126. if(m > n)
  127. m = n;
  128. memmove(buf, p, m);
  129. n -= m;
  130. buf += m;
  131. if(n == 0)
  132. return oldn;
  133. }
  134. }
  135. }
  136. return oldn - n;
  137. }
  138. typedef struct Mcheck Mcheck;
  139. struct Mcheck
  140. {
  141. ulong len;
  142. ulong inprogress;
  143. ulong procoff;
  144. ulong sysoff;
  145. ulong code;
  146. };
  147. static char *
  148. smcheck(ulong code)
  149. {
  150. switch (code) {
  151. case 0x80: return "tag parity error";
  152. case 0x82: return "tag control parity error";
  153. case 0x84: return "generic hard error";
  154. case 0x86: return "correctable ECC error";
  155. case 0x88: return "uncorrectable ECC error";
  156. case 0x8a: return "OS-specific PAL bugcheck";
  157. case 0x90: return "callsys in kernel mode";
  158. case 0x96: return "i-cache read retryable error";
  159. case 0x98: return "processor detected hard error";
  160. case 0x203: return "system detected uncorrectable ECC error";
  161. case 0x205: return "parity error detected by CIA";
  162. case 0x207: return "non-existent memory error";
  163. case 0x209: return "PCI SERR detected";
  164. case 0x20b: return "PCI data parity error detected";
  165. case 0x20d: return "PCI address parity error detected";
  166. case 0x20f: return "PCI master abort error";
  167. case 0x211: return "PCI target abort error";
  168. case 0x213: return "scatter/gather PTE invalid error";
  169. case 0x215: return "flash ROM write error";
  170. case 0x217: return "IOA timeout detected";
  171. case 0x219: return "IOCHK#, EISA add-in board parity or other catastrophic error";
  172. case 0x21b: return "EISA fail-safe timer timeout";
  173. case 0x21d: return "EISA bus time-out";
  174. case 0x21f: return "EISA software generated NMI";
  175. case 0x221: return "unexpected ev5 IRQ[3] interrupt";
  176. default: return "unknown mcheck";
  177. }
  178. }
  179. void
  180. mcheck(Ureg *ur, void *x)
  181. {
  182. Mcheck *m;
  183. uvlong *data;
  184. int i, col;
  185. m = x;
  186. data = x;
  187. iprint("panic: Machine Check @%lux: %s (%lux) len %lud\n",
  188. m, smcheck(m->code), m->code, m->len);
  189. iprint("proc offset %lux sys offset %lux\n", m->procoff, m->sysoff);
  190. for (i = 0, col = 0; i < m->len/8; i++) {
  191. iprint("%.3x: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : " ");
  192. if (col++ == 2)
  193. col = 0;
  194. }
  195. if(col != 2)
  196. print("\n");
  197. print("\n");
  198. dumpregs(ur);
  199. prflush();
  200. firmware();
  201. }
  202. void
  203. intr(Ureg *ur)
  204. {
  205. int i, vno;
  206. Vctl *ctl, *v;
  207. Mach *mach;
  208. vno = (ulong)ur->a1>>4;
  209. vno -= 0x80;
  210. if(vno < nelem(vctl) && (ctl = vctl[vno])){
  211. if(ctl->isintr){
  212. m->intr++;
  213. if(vno >= VectorPIC && vno <= MaxVectorPIC)
  214. m->lastintr = vno-VectorPIC;
  215. }
  216. if(ctl->isr)
  217. ctl->isr(vno);
  218. for(v = ctl; v != nil; v = v->next) {
  219. if(v->f)
  220. v->f(ur, v->a);
  221. }
  222. if(ctl->eoi)
  223. ctl->eoi(vno);
  224. if(ctl->isintr)
  225. preempted();
  226. }
  227. else if(vno >= VectorPIC && vno <= MaxVectorPIC){
  228. /*
  229. * An unknown interrupt.
  230. * Check for a default IRQ7. This can happen when
  231. * the IRQ input goes away before the acknowledge.
  232. * In this case, a 'default IRQ7' is generated, but
  233. * the corresponding bit in the ISR isn't set.
  234. * In fact, just ignore all such interrupts.
  235. */
  236. iprint("cpu%d: spurious interrupt %d, last %d",
  237. m->machno, vno-VectorPIC, m->lastintr);
  238. for(i = 0; i < 32; i++){
  239. if(!(active.machs & (1<<i)))
  240. continue;
  241. mach = MACHP(i);
  242. if(m->machno == mach->machno)
  243. continue;
  244. iprint(": cpu%d: last %d", mach->machno, mach->lastintr);
  245. }
  246. iprint("\n");
  247. m->spuriousintr++;
  248. return;
  249. }
  250. else{
  251. dumpregs(ur);
  252. print("unknown intr: %d\n", vno); /* */
  253. }
  254. }
  255. void
  256. trap(Ureg *ur)
  257. {
  258. char buf[ERRMAX];
  259. int user, x;
  260. user = ur->status&UMODE;
  261. if(user){
  262. up = m->proc;
  263. up->dbgreg = ur;
  264. }
  265. switch ((int)ur->type) {
  266. case 1: /* arith */
  267. fptrap(ur);
  268. break;
  269. case 2: /* bad instr or FEN */
  270. illegal(ur);
  271. break;
  272. case 3: /* intr */
  273. m->intr++;
  274. switch ((int)ur->a0) {
  275. case 0: /* interprocessor */
  276. panic("interprocessor intr");
  277. break;
  278. case 1: /* clock */
  279. clock(ur);
  280. break;
  281. case 2: /* machine check */
  282. mcheck(ur, (void*)(KZERO|(ulong)ur->a2));
  283. break;
  284. case 3: /* device */
  285. intr(ur);
  286. break;
  287. case 4: /* perf counter */
  288. panic("perf count");
  289. break;
  290. default:
  291. panic("bad intr");
  292. break;
  293. }
  294. break;
  295. case 4: /* memory fault */
  296. if(up == 0)
  297. kernfault(ur, (ulong)ur->a1);
  298. x = up->insyscall;
  299. up->insyscall = 1;
  300. spllo();
  301. faultalpha(ur);
  302. up->insyscall = x;
  303. break;
  304. case 6: /* alignment fault */
  305. ur->pc -= 4;
  306. sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0);
  307. fataltrap(ur, buf);
  308. break;
  309. default: /* cannot happen */
  310. panic("bad trap type %d", (int)ur->type);
  311. break;
  312. }
  313. if(user && (up->procctl || up->nnote)){
  314. splhi();
  315. notify(ur);
  316. }
  317. }
  318. void
  319. trapinit(void)
  320. {
  321. splhi();
  322. wrent(0, intr0);
  323. wrent(1, arith);
  324. wrent(2, fault0);
  325. wrent(3, illegal0);
  326. wrent(4, unaligned);
  327. wrent(5, syscall0);
  328. }
  329. void
  330. fataltrap(Ureg *ur, char *reason)
  331. {
  332. char buf[ERRMAX];
  333. if(ur->status&UMODE) {
  334. spllo();
  335. sprint(buf, "sys: %s", reason);
  336. postnote(up, 1, buf, NDebug);
  337. return;
  338. }
  339. print("kernel %s pc=%lux\n", reason, (ulong)ur->pc);
  340. dumpregs(ur);
  341. dumpstack();
  342. if(m->machno == 0)
  343. spllo();
  344. exit(1);
  345. }
  346. void
  347. kernfault(Ureg *ur, int code)
  348. {
  349. Label l;
  350. char *s;
  351. splhi();
  352. if (code == 0)
  353. s = "read";
  354. else if (code == 1)
  355. s = "write";
  356. else
  357. s = "ifetch";
  358. print("panic: kfault %s VA=0x%lux\n", s, (ulong)ur->a0);
  359. print("u=0x%lux status=0x%lux pc=0x%lux sp=0x%lux\n",
  360. up, (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp);
  361. dumpregs(ur);
  362. l.sp = ur->sp;
  363. l.pc = ur->pc;
  364. dumpstack();
  365. exit(1);
  366. }
  367. void
  368. dumpregs(Ureg *ur)
  369. {
  370. int i, col;
  371. uvlong *l;
  372. if(up)
  373. print("registers for %s %ld\n", up->text, up->pid);
  374. else
  375. print("registers for kernel\n");
  376. l = &ur->type;
  377. col = 0;
  378. for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) {
  379. print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : " ");
  380. if (col++ == 2)
  381. col = 0;
  382. }
  383. print("\n");
  384. }
  385. /*
  386. * Fill in enough of Ureg to get a stack trace, and call a function.
  387. * Used by debugging interface rdb.
  388. */
  389. static void
  390. getpcsp(ulong *pc, ulong *sp)
  391. {
  392. *pc = getcallerpc(&pc);
  393. *sp = (ulong)&pc-8;
  394. }
  395. void
  396. callwithureg(void (*fn)(Ureg*))
  397. {
  398. Ureg ureg;
  399. getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
  400. ureg.r26 = getcallerpc(&fn);
  401. fn(&ureg);
  402. }
  403. void
  404. _dumpstack(Ureg *ureg)
  405. {
  406. ulong l, sl, el, v, i, instr, op;
  407. extern ulong etext;
  408. l=(ulong)&l;
  409. if(l&4)
  410. l += 4;
  411. if(up == 0){
  412. el = (ulong)m+BY2PG;
  413. sl = el-KSTACK;
  414. }
  415. else{
  416. sl = (ulong)up->kstack;
  417. el = sl + KSTACK;
  418. }
  419. if(l > el || l < sl){
  420. el = (ulong)m+BY2PG;
  421. sl = el-KSTACK;
  422. }
  423. if(l > el || l < sl)
  424. return;
  425. print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", (ulong)ureg->pc, (ulong)ureg->sp, (ulong)ureg->r26);
  426. i = 0;
  427. for(; l<el; l+=8){
  428. v = *(ulong*)l - 4;
  429. if(KTZERO < v && v < (ulong)&etext && (v&3) == 0){
  430. /*
  431. * Check for JSR/BSR
  432. */
  433. instr = *(ulong*)v;
  434. op = (instr>>26);
  435. if(op == 26 || op == 52){
  436. print("%lux=%lux ", l, v);
  437. i++;
  438. }
  439. }
  440. if(i == 4){
  441. i = 0;
  442. print("\n");
  443. }
  444. }
  445. if(i)
  446. print("\n");
  447. }
  448. void
  449. dumpstack(void)
  450. {
  451. callwithureg(_dumpstack);
  452. }
  453. int
  454. notify(Ureg *ur)
  455. {
  456. int l;
  457. ulong sp;
  458. Note *n;
  459. if(up->procctl)
  460. procctl(up);
  461. if(up->nnote == 0)
  462. return 0;
  463. spllo();
  464. qlock(&up->debug);
  465. up->notepending = 0;
  466. if(up->fpstate == FPactive){
  467. savefpregs(&up->fpsave);
  468. up->fpstate = FPinactive;
  469. }
  470. up->fpstate |= FPillegal;
  471. n = &up->note[0];
  472. if(strncmp(n->msg, "sys:", 4) == 0) {
  473. l = strlen(n->msg);
  474. if(l > ERRMAX-15) /* " pc=0x12345678\0" */
  475. l = ERRMAX-15;
  476. sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc);
  477. }
  478. if(n->flag != NUser && (up->notified || up->notify==0)) {
  479. if(n->flag == NDebug)
  480. pprint("suicide: %s\n", n->msg);
  481. qunlock(&up->debug);
  482. pexit(n->msg, n->flag!=NDebug);
  483. }
  484. if(up->notified) {
  485. qunlock(&up->debug);
  486. splhi();
  487. return 0;
  488. }
  489. if(!up->notify) {
  490. qunlock(&up->debug);
  491. pexit(n->msg, n->flag!=NDebug);
  492. }
  493. sp = ur->usp & ~(BY2V-1);
  494. sp -= sizeof(Ureg);
  495. if(!okaddr((ulong)up->notify, BY2WD, 0)
  496. || !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) {
  497. pprint("suicide: bad address or sp in notify\n");
  498. print("suicide: bad address or sp in notify\n");
  499. qunlock(&up->debug);
  500. pexit("Suicide", 0);
  501. }
  502. memmove((Ureg*)sp, ur, sizeof(Ureg));
  503. *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
  504. up->ureg = (void*)sp;
  505. sp -= 2*BY2WD+ERRMAX;
  506. memmove((char*)sp, up->note[0].msg, ERRMAX);
  507. sp -= 4*BY2WD;
  508. *(ulong*)(sp+3*BY2WD) = sp+4*BY2WD; /* arg 2 is string */
  509. ur->r0 = (ulong)up->ureg; /* arg 1 (R0) is ureg* */
  510. *(ulong*)(sp+2*BY2WD) = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
  511. *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
  512. ur->usp = sp;
  513. ur->pc = (ulong)up->notify;
  514. up->notified = 1;
  515. up->nnote--;
  516. memmove(&up->lastnote, &up->note[0], sizeof(Note));
  517. memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
  518. qunlock(&up->debug);
  519. splhi();
  520. return 1;
  521. }
  522. /*
  523. * Check that status is OK to return from note.
  524. */
  525. int
  526. validstatus(ulong kstatus, ulong ustatus)
  527. {
  528. if((kstatus & 7) != (ustatus & 7))
  529. return 0;
  530. if((ustatus&UMODE) != UMODE)
  531. return 0;
  532. return 1;
  533. }
  534. /*
  535. * Return user to state before notify()
  536. */
  537. void
  538. noted(Ureg *kur, Ureg **urp, ulong arg0)
  539. {
  540. Ureg *nur;
  541. ulong oureg, sp;
  542. qlock(&up->debug);
  543. if(arg0!=NRSTR && !up->notified) {
  544. qunlock(&up->debug);
  545. pprint("call to noted() when not notified\n");
  546. print("call to noted() when not notified\n");
  547. pexit("Suicide", 0);
  548. }
  549. up->notified = 0;
  550. up->fpstate &= ~FPillegal;
  551. nur = up->ureg;
  552. oureg = (ulong)nur;
  553. if((oureg & (BY2V-1))
  554. || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
  555. pprint("bad ureg in noted or call to noted() when not notified\n");
  556. print("bad ureg in noted or call to noted() when not notified\n");
  557. qunlock(&up->debug);
  558. pexit("Suicide", 0);
  559. }
  560. if(!validstatus(kur->status, nur->status)) {
  561. qunlock(&up->debug);
  562. pprint("bad noted ureg status %lux\n", (ulong)nur->status);
  563. print("bad noted ureg status %lux\n", (ulong)nur->status);
  564. pexit("Suicide", 0);
  565. }
  566. memmove(*urp, up->ureg, sizeof(Ureg));
  567. switch(arg0) {
  568. case NCONT:
  569. case NRSTR:
  570. if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
  571. pprint("suicide: trap in noted\n");
  572. print("suicide: trap in noted\n");
  573. qunlock(&up->debug);
  574. pexit("Suicide", 0);
  575. }
  576. up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
  577. qunlock(&up->debug);
  578. splhi();
  579. rfnote(urp);
  580. break;
  581. case NSAVE:
  582. if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
  583. pprint("suicide: trap in noted\n");
  584. print("suicide: trap in noted\n");
  585. qunlock(&up->debug);
  586. pexit("Suicide", 0);
  587. }
  588. qunlock(&up->debug);
  589. sp = oureg-4*BY2WD-ERRMAX;
  590. splhi();
  591. (*urp)->sp = sp;
  592. ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
  593. ((ulong*)sp)[0] = 0; /* arg 0 is pc */
  594. (*urp)->r0 = oureg; /* arg 1 is ureg* */
  595. rfnote(urp);
  596. break;
  597. default:
  598. pprint("unknown noted arg 0x%lux\n", arg0);
  599. print("unknown noted arg 0x%lux\n", arg0);
  600. up->lastnote.flag = NDebug;
  601. /* fall through */
  602. case NDFLT:
  603. if(up->lastnote.flag == NDebug)
  604. pprint("suicide: %s\n", up->lastnote.msg);
  605. qunlock(&up->debug);
  606. pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
  607. }
  608. }
  609. #include "../port/systab.h"
  610. long
  611. syscall(Ureg *aur)
  612. {
  613. int i;
  614. char *e;
  615. long ret;
  616. ulong sp;
  617. Ureg *ur;
  618. ulong scallnr;
  619. m->syscall++;
  620. up = m->proc;
  621. up->insyscall = 1;
  622. ur = aur;
  623. up->pc = ur->pc;
  624. up->dbgreg = aur;
  625. ur->type = 5; /* for debugging */
  626. scallnr = ur->r0;
  627. up->scallnr = ur->r0;
  628. if(scallnr == RFORK && up->fpstate == FPactive){
  629. savefpregs(&up->fpsave);
  630. up->fpstate = FPinactive;
  631. //print("SR=%lux+", up->fpsave.fpstatus);
  632. }
  633. spllo();
  634. sp = ur->sp;
  635. up->nerrlab = 0;
  636. ret = -1;
  637. if(!waserror()) {
  638. if(scallnr >= nsyscall || systab[scallnr] == nil){
  639. pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc);
  640. postnote(up, 1, "sys: bad sys call", NDebug);
  641. error(Ebadarg);
  642. }
  643. if(sp & (BY2WD-1)){ /* XXX too weak? */
  644. pprint("odd sp in sys call pc %lux sp %lux\n",
  645. (ulong)ur->pc, (ulong)ur->sp);
  646. postnote(up, 1, "sys: odd stack", NDebug);
  647. error(Ebadarg);
  648. }
  649. if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)))
  650. validaddr(sp, sizeof(Sargs), 0);
  651. up->s = *((Sargs*)(sp+2*BY2WD));
  652. up->psstate = sysctab[scallnr];
  653. ret = systab[scallnr](up->s.args);
  654. poperror();
  655. }else{
  656. /* failure: save the error buffer for errstr */
  657. e = up->syserrstr;
  658. up->syserrstr = up->errstr;
  659. up->errstr = e;
  660. }
  661. if(up->nerrlab){
  662. print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
  663. for(i = 0; i < NERR; i++)
  664. print("sp=%lux pc=%lux\n",
  665. up->errlab[i].sp, up->errlab[i].pc);
  666. panic("error stack");
  667. }
  668. up->nerrlab = 0;
  669. up->psstate = 0;
  670. up->insyscall = 0;
  671. if(scallnr == NOTED) /* ugly hack */
  672. noted(ur, &aur, *(ulong*)(sp+2*BY2WD)); /* doesn't return */
  673. if(scallnr!=RFORK && (up->procctl || up->nnote)){
  674. ur->r0 = ret; /* load up for noted() */
  675. if(notify(ur))
  676. return ur->r0;
  677. }
  678. return ret;
  679. }
  680. void
  681. forkchild(Proc *p, Ureg *ur)
  682. {
  683. Ureg *cur;
  684. p->sched.sp = (ulong)p->kstack+KSTACK-(4*BY2WD+sizeof(Ureg));
  685. p->sched.pc = (ulong)forkret;
  686. cur = (Ureg*)(p->sched.sp+4*BY2WD);
  687. memmove(cur, ur, sizeof(Ureg));
  688. /* Things from bottom of syscall we never got to execute */
  689. p->psstate = 0;
  690. p->insyscall = 0;
  691. }
  692. static
  693. void
  694. linkproc(void)
  695. {
  696. spllo();
  697. up->kpfun(up->kparg);
  698. pexit("kproc exiting", 0);
  699. }
  700. void
  701. kprocchild(Proc *p, void (*func)(void*), void *arg)
  702. {
  703. p->sched.pc = (ulong)linkproc;
  704. p->sched.sp = (ulong)p->kstack+KSTACK;
  705. p->kpfun = func;
  706. p->kparg = arg;
  707. }
  708. long
  709. execregs(ulong entry, ulong ssize, ulong nargs)
  710. {
  711. Ureg *ur;
  712. ulong *sp;
  713. sp = (ulong*)(USTKTOP - ssize);
  714. *--sp = nargs;
  715. ur = (Ureg*)up->dbgreg;
  716. ur->usp = (ulong)sp;
  717. ur->pc = entry;
  718. return USTKTOP-BY2WD; /* address of user-level clock */
  719. }
  720. ulong
  721. userpc(void)
  722. {
  723. Ureg *ur;
  724. ur = (Ureg*)up->dbgreg;
  725. return ur->pc;
  726. }
  727. /* This routine must save the values of registers the user is not permitted to write
  728. * from devproc and then restore the saved values before returning
  729. */
  730. void
  731. setregisters(Ureg *xp, char *pureg, char *uva, int n)
  732. {
  733. ulong status;
  734. status = xp->status;
  735. memmove(pureg, uva, n);
  736. xp->status = status;
  737. }
  738. /* Give enough context in the ureg to produce a kernel stack for
  739. * a sleeping process
  740. */
  741. void
  742. setkernur(Ureg *xp, Proc *p)
  743. {
  744. xp->pc = p->sched.pc;
  745. xp->sp = p->sched.sp;
  746. xp->r26 = (ulong)sched;
  747. }
  748. ulong
  749. dbgpc(Proc *p)
  750. {
  751. Ureg *ur;
  752. ur = p->dbgreg;
  753. if(ur == 0)
  754. return 0;
  755. return ur->pc;
  756. }
  757. void
  758. illegal(Ureg *ur)
  759. {
  760. switch ((int)ur->a0) {
  761. case 0: /* breakpoint */
  762. ur->pc -= 4;
  763. fataltrap(ur, "breakpoint");
  764. break;
  765. case 1: /* bugchk */
  766. fataltrap(ur, "trap: bugchk");
  767. break;
  768. case 2: /* gentrap */
  769. fataltrap(ur, "trap: gentrap");
  770. break;
  771. case 3: /* FEN */
  772. fen(ur);
  773. break;
  774. case 4: /* opDEC */
  775. fataltrap(ur, "trap: illegal instruction");
  776. break;
  777. default:
  778. panic("illegal illegal %d", (int)ur->a0);
  779. break;
  780. }
  781. }
  782. void
  783. fen(Ureg *ur)
  784. {
  785. if(up){
  786. switch(up->fpstate){
  787. case FPinit:
  788. restfpregs(&initfp);
  789. up->fpstate = FPactive;
  790. //print("EI=%lux+", initfp.fpstatus);
  791. return;
  792. case FPinactive:
  793. restfpregs(&up->fpsave);
  794. up->fpstate = FPactive;
  795. //print("EIA=%lux+", up->fpsave.fpstatus);
  796. return;
  797. }
  798. }
  799. fataltrap(ur, "trap: floating enable"); /* should never happen */
  800. }