trap.c 17 KB

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