trap.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  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 && up)
  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 clockintr, user, x;
  260. user = ur->status&UMODE;
  261. if(user){
  262. up = m->proc;
  263. up->dbgreg = ur;
  264. }
  265. clockintr = 0;
  266. switch ((int)ur->type) {
  267. case 1: /* arith */
  268. fptrap(ur);
  269. break;
  270. case 2: /* bad instr or FEN */
  271. illegal(ur);
  272. break;
  273. case 3: /* intr */
  274. m->intr++;
  275. switch ((int)ur->a0) {
  276. case 0: /* interprocessor */
  277. panic("interprocessor intr");
  278. break;
  279. case 1: /* clock */
  280. clockintr = 1;
  281. clock(ur);
  282. break;
  283. case 2: /* machine check */
  284. mcheck(ur, (void*)(KZERO|(ulong)ur->a2));
  285. break;
  286. case 3: /* device */
  287. intr(ur);
  288. break;
  289. case 4: /* perf counter */
  290. panic("perf count");
  291. break;
  292. default:
  293. panic("bad intr");
  294. break;
  295. }
  296. break;
  297. case 4: /* memory fault */
  298. if(up == 0)
  299. kernfault(ur, (ulong)ur->a1);
  300. x = up->insyscall;
  301. up->insyscall = 1;
  302. spllo();
  303. faultalpha(ur);
  304. up->insyscall = x;
  305. break;
  306. case 6: /* alignment fault */
  307. ur->pc -= 4;
  308. sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0);
  309. fataltrap(ur, buf);
  310. break;
  311. default: /* cannot happen */
  312. panic("bad trap type %d", (int)ur->type);
  313. break;
  314. }
  315. splhi();
  316. /* delaysched set because we held a lock or because our quantum ended */
  317. if(up && up->delaysched && clockintr){
  318. sched();
  319. splhi();
  320. }
  321. if(user){
  322. if(up->procctl || up->nnote)
  323. notify(ur);
  324. kexit(ur);
  325. }
  326. }
  327. void
  328. trapinit(void)
  329. {
  330. splhi();
  331. wrent(0, intr0);
  332. wrent(1, arith);
  333. wrent(2, fault0);
  334. wrent(3, illegal0);
  335. wrent(4, unaligned);
  336. wrent(5, syscall0);
  337. }
  338. void
  339. fataltrap(Ureg *ur, char *reason)
  340. {
  341. char buf[ERRMAX];
  342. if(ur->status&UMODE) {
  343. spllo();
  344. sprint(buf, "sys: %s", reason);
  345. postnote(up, 1, buf, NDebug);
  346. return;
  347. }
  348. print("kernel %s pc=%lux\n", reason, (ulong)ur->pc);
  349. dumpregs(ur);
  350. dumpstack();
  351. if(m->machno == 0)
  352. spllo();
  353. exit(1);
  354. }
  355. void
  356. kernfault(Ureg *ur, int code)
  357. {
  358. Label l;
  359. char *s;
  360. splhi();
  361. if (code == 0)
  362. s = "read";
  363. else if (code == 1)
  364. s = "write";
  365. else
  366. s = "ifetch";
  367. print("panic: kfault %s VA=0x%lux\n", s, (ulong)ur->a0);
  368. print("u=0x%lux status=0x%lux pc=0x%lux sp=0x%lux\n",
  369. up, (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp);
  370. dumpregs(ur);
  371. l.sp = ur->sp;
  372. l.pc = ur->pc;
  373. dumpstack();
  374. exit(1);
  375. }
  376. void
  377. dumpregs(Ureg *ur)
  378. {
  379. int i, col;
  380. uvlong *l;
  381. if(up)
  382. print("registers for %s %ld\n", up->text, up->pid);
  383. else
  384. print("registers for kernel\n");
  385. l = &ur->type;
  386. col = 0;
  387. for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) {
  388. print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : " ");
  389. if (col++ == 2)
  390. col = 0;
  391. }
  392. print("\n");
  393. }
  394. /*
  395. * Fill in enough of Ureg to get a stack trace, and call a function.
  396. * Used by debugging interface rdb.
  397. */
  398. static void
  399. getpcsp(ulong *pc, ulong *sp)
  400. {
  401. *pc = getcallerpc(&pc);
  402. *sp = (ulong)&pc-8;
  403. }
  404. void
  405. callwithureg(void (*fn)(Ureg*))
  406. {
  407. Ureg ureg;
  408. getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
  409. ureg.r26 = getcallerpc(&fn);
  410. fn(&ureg);
  411. }
  412. void
  413. _dumpstack(Ureg *ureg)
  414. {
  415. ulong l, sl, el, v, i, instr, op;
  416. extern ulong etext;
  417. l=(ulong)&l;
  418. if(l&4)
  419. l += 4;
  420. if(up == 0){
  421. el = (ulong)m+BY2PG;
  422. sl = el-KSTACK;
  423. }
  424. else{
  425. sl = (ulong)up->kstack;
  426. el = sl + KSTACK;
  427. }
  428. if(l > el || l < sl){
  429. el = (ulong)m+BY2PG;
  430. sl = el-KSTACK;
  431. }
  432. if(l > el || l < sl)
  433. return;
  434. print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", (ulong)ureg->pc, (ulong)ureg->sp, (ulong)ureg->r26);
  435. i = 0;
  436. for(; l<el; l+=8){
  437. v = *(ulong*)l - 4;
  438. if(KTZERO < v && v < (ulong)&etext && (v&3) == 0){
  439. /*
  440. * Check for JSR/BSR
  441. */
  442. instr = *(ulong*)v;
  443. op = (instr>>26);
  444. if(op == 26 || op == 52){
  445. print("%lux=%lux ", l, v);
  446. i++;
  447. }
  448. }
  449. if(i == 4){
  450. i = 0;
  451. print("\n");
  452. }
  453. }
  454. if(i)
  455. print("\n");
  456. }
  457. void
  458. dumpstack(void)
  459. {
  460. callwithureg(_dumpstack);
  461. }
  462. int
  463. notify(Ureg *ur)
  464. {
  465. int l;
  466. ulong sp;
  467. Note *n;
  468. if(up->procctl)
  469. procctl(up);
  470. if(up->nnote == 0)
  471. return 0;
  472. spllo();
  473. qlock(&up->debug);
  474. up->notepending = 0;
  475. if(up->fpstate == FPactive){
  476. savefpregs(&up->fpsave);
  477. up->fpstate = FPinactive;
  478. }
  479. up->fpstate |= FPillegal;
  480. n = &up->note[0];
  481. if(strncmp(n->msg, "sys:", 4) == 0) {
  482. l = strlen(n->msg);
  483. if(l > ERRMAX-15) /* " pc=0x12345678\0" */
  484. l = ERRMAX-15;
  485. sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc);
  486. }
  487. if(n->flag != NUser && (up->notified || up->notify==0)) {
  488. if(n->flag == NDebug)
  489. pprint("suicide: %s\n", n->msg);
  490. qunlock(&up->debug);
  491. pexit(n->msg, n->flag!=NDebug);
  492. }
  493. if(up->notified) {
  494. qunlock(&up->debug);
  495. splhi();
  496. return 0;
  497. }
  498. if(!up->notify) {
  499. qunlock(&up->debug);
  500. pexit(n->msg, n->flag!=NDebug);
  501. }
  502. sp = ur->usp & ~(BY2V-1);
  503. sp -= sizeof(Ureg);
  504. if(!okaddr((ulong)up->notify, BY2WD, 0)
  505. || !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) {
  506. pprint("suicide: bad address or sp in notify\n");
  507. print("suicide: bad address or sp in notify\n");
  508. qunlock(&up->debug);
  509. pexit("Suicide", 0);
  510. }
  511. memmove((Ureg*)sp, ur, sizeof(Ureg));
  512. *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
  513. up->ureg = (void*)sp;
  514. sp -= 2*BY2WD+ERRMAX;
  515. memmove((char*)sp, up->note[0].msg, ERRMAX);
  516. sp -= 4*BY2WD;
  517. *(ulong*)(sp+3*BY2WD) = sp+4*BY2WD; /* arg 2 is string */
  518. ur->r0 = (ulong)up->ureg; /* arg 1 (R0) is ureg* */
  519. *(ulong*)(sp+2*BY2WD) = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
  520. *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
  521. ur->usp = sp;
  522. ur->pc = (ulong)up->notify;
  523. up->notified = 1;
  524. up->nnote--;
  525. memmove(&up->lastnote, &up->note[0], sizeof(Note));
  526. memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
  527. qunlock(&up->debug);
  528. splhi();
  529. return 1;
  530. }
  531. /*
  532. * Check that status is OK to return from note.
  533. */
  534. int
  535. validstatus(ulong kstatus, ulong ustatus)
  536. {
  537. if((kstatus & 7) != (ustatus & 7))
  538. return 0;
  539. if((ustatus&UMODE) != UMODE)
  540. return 0;
  541. return 1;
  542. }
  543. /*
  544. * Return user to state before notify()
  545. */
  546. void
  547. noted(Ureg *kur, Ureg **urp, ulong arg0)
  548. {
  549. Ureg *nur;
  550. ulong oureg, sp;
  551. qlock(&up->debug);
  552. if(arg0!=NRSTR && !up->notified) {
  553. qunlock(&up->debug);
  554. pprint("call to noted() when not notified\n");
  555. print("call to noted() when not notified\n");
  556. pexit("Suicide", 0);
  557. }
  558. up->notified = 0;
  559. up->fpstate &= ~FPillegal;
  560. nur = up->ureg;
  561. oureg = (ulong)nur;
  562. if((oureg & (BY2V-1))
  563. || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
  564. pprint("bad ureg in noted or call to noted() when not notified\n");
  565. print("bad ureg in noted or call to noted() when not notified\n");
  566. qunlock(&up->debug);
  567. pexit("Suicide", 0);
  568. }
  569. if(!validstatus(kur->status, nur->status)) {
  570. qunlock(&up->debug);
  571. pprint("bad noted ureg status %lux\n", (ulong)nur->status);
  572. print("bad noted ureg status %lux\n", (ulong)nur->status);
  573. pexit("Suicide", 0);
  574. }
  575. memmove(*urp, up->ureg, sizeof(Ureg));
  576. switch(arg0) {
  577. case NCONT:
  578. case NRSTR:
  579. if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
  580. pprint("suicide: trap in noted\n");
  581. print("suicide: trap in noted\n");
  582. qunlock(&up->debug);
  583. pexit("Suicide", 0);
  584. }
  585. up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
  586. qunlock(&up->debug);
  587. splhi();
  588. rfnote(urp);
  589. break;
  590. case NSAVE:
  591. if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
  592. pprint("suicide: trap in noted\n");
  593. print("suicide: trap in noted\n");
  594. qunlock(&up->debug);
  595. pexit("Suicide", 0);
  596. }
  597. qunlock(&up->debug);
  598. sp = oureg-4*BY2WD-ERRMAX;
  599. splhi();
  600. (*urp)->sp = sp;
  601. ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
  602. ((ulong*)sp)[0] = 0; /* arg 0 is pc */
  603. (*urp)->r0 = oureg; /* arg 1 is ureg* */
  604. rfnote(urp);
  605. break;
  606. default:
  607. pprint("unknown noted arg 0x%lux\n", arg0);
  608. print("unknown noted arg 0x%lux\n", arg0);
  609. up->lastnote.flag = NDebug;
  610. /* fall through */
  611. case NDFLT:
  612. if(up->lastnote.flag == NDebug)
  613. pprint("suicide: %s\n", up->lastnote.msg);
  614. qunlock(&up->debug);
  615. pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
  616. }
  617. }
  618. #include "../port/systab.h"
  619. long
  620. syscall(Ureg *aur)
  621. {
  622. int i;
  623. char *e;
  624. long ret;
  625. ulong sp;
  626. Ureg *ur;
  627. ulong scallnr;
  628. m->syscall++;
  629. up = m->proc;
  630. up->insyscall = 1;
  631. ur = aur;
  632. up->pc = ur->pc;
  633. up->dbgreg = aur;
  634. ur->type = 5; /* for debugging */
  635. scallnr = ur->r0;
  636. up->scallnr = ur->r0;
  637. if(scallnr == RFORK && up->fpstate == FPactive){
  638. savefpregs(&up->fpsave);
  639. up->fpstate = FPinactive;
  640. //print("SR=%lux+", up->fpsave.fpstatus);
  641. }
  642. spllo();
  643. sp = ur->sp;
  644. up->nerrlab = 0;
  645. ret = -1;
  646. if(!waserror()) {
  647. if(scallnr >= nsyscall || systab[scallnr] == nil){
  648. pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc);
  649. postnote(up, 1, "sys: bad sys call", NDebug);
  650. error(Ebadarg);
  651. }
  652. if(sp & (BY2WD-1)){ /* XXX too weak? */
  653. pprint("odd sp in sys call pc %lux sp %lux\n",
  654. (ulong)ur->pc, (ulong)ur->sp);
  655. postnote(up, 1, "sys: odd stack", NDebug);
  656. error(Ebadarg);
  657. }
  658. if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)))
  659. validaddr(sp, sizeof(Sargs), 0);
  660. up->s = *((Sargs*)(sp+2*BY2WD));
  661. up->psstate = sysctab[scallnr];
  662. ret = systab[scallnr](up->s.args);
  663. poperror();
  664. }else{
  665. /* failure: save the error buffer for errstr */
  666. e = up->syserrstr;
  667. up->syserrstr = up->errstr;
  668. up->errstr = e;
  669. }
  670. if(up->nerrlab){
  671. print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
  672. for(i = 0; i < NERR; i++)
  673. print("sp=%lux pc=%lux\n",
  674. up->errlab[i].sp, up->errlab[i].pc);
  675. panic("error stack");
  676. }
  677. up->nerrlab = 0;
  678. up->psstate = 0;
  679. up->insyscall = 0;
  680. if(scallnr == NOTED) /* ugly hack */
  681. noted(ur, &aur, *(ulong*)(sp+2*BY2WD)); /* doesn't return */
  682. if(scallnr!=RFORK && (up->procctl || up->nnote)){
  683. ur->r0 = ret; /* load up for noted() */
  684. if(notify(ur))
  685. return ur->r0;
  686. }
  687. return ret;
  688. }
  689. void
  690. forkchild(Proc *p, Ureg *ur)
  691. {
  692. Ureg *cur;
  693. p->sched.sp = (ulong)p->kstack+KSTACK-(4*BY2WD+sizeof(Ureg));
  694. p->sched.pc = (ulong)forkret;
  695. cur = (Ureg*)(p->sched.sp+4*BY2WD);
  696. memmove(cur, ur, sizeof(Ureg));
  697. /* Things from bottom of syscall we never got to execute */
  698. p->psstate = 0;
  699. p->insyscall = 0;
  700. }
  701. static
  702. void
  703. linkproc(void)
  704. {
  705. spllo();
  706. up->kpfun(up->kparg);
  707. pexit("kproc exiting", 0);
  708. }
  709. void
  710. kprocchild(Proc *p, void (*func)(void*), void *arg)
  711. {
  712. p->sched.pc = (ulong)linkproc;
  713. p->sched.sp = (ulong)p->kstack+KSTACK;
  714. p->kpfun = func;
  715. p->kparg = arg;
  716. }
  717. long
  718. execregs(ulong entry, ulong ssize, ulong nargs)
  719. {
  720. Ureg *ur;
  721. ulong *sp;
  722. sp = (ulong*)(USTKTOP - ssize);
  723. *--sp = nargs;
  724. ur = (Ureg*)up->dbgreg;
  725. ur->usp = (ulong)sp;
  726. ur->pc = entry;
  727. return USTKTOP-BY2WD; /* address of user-level clock */
  728. }
  729. ulong
  730. userpc(void)
  731. {
  732. Ureg *ur;
  733. ur = (Ureg*)up->dbgreg;
  734. return ur->pc;
  735. }
  736. /* This routine must save the values of registers the user is not permitted to write
  737. * from devproc and then restore the saved values before returning
  738. */
  739. void
  740. setregisters(Ureg *xp, char *pureg, char *uva, int n)
  741. {
  742. ulong status;
  743. status = xp->status;
  744. memmove(pureg, uva, n);
  745. xp->status = status;
  746. }
  747. /* Give enough context in the ureg to produce a kernel stack for
  748. * a sleeping process
  749. */
  750. void
  751. setkernur(Ureg *xp, Proc *p)
  752. {
  753. xp->pc = p->sched.pc;
  754. xp->sp = p->sched.sp;
  755. xp->r26 = (ulong)sched;
  756. }
  757. ulong
  758. dbgpc(Proc *p)
  759. {
  760. Ureg *ur;
  761. ur = p->dbgreg;
  762. if(ur == 0)
  763. return 0;
  764. return ur->pc;
  765. }
  766. void
  767. illegal(Ureg *ur)
  768. {
  769. switch ((int)ur->a0) {
  770. case 0: /* breakpoint */
  771. ur->pc -= 4;
  772. fataltrap(ur, "breakpoint");
  773. break;
  774. case 1: /* bugchk */
  775. fataltrap(ur, "trap: bugchk");
  776. break;
  777. case 2: /* gentrap */
  778. fataltrap(ur, "trap: gentrap");
  779. break;
  780. case 3: /* FEN */
  781. fen(ur);
  782. break;
  783. case 4: /* opDEC */
  784. fataltrap(ur, "trap: illegal instruction");
  785. break;
  786. default:
  787. panic("illegal illegal %d", (int)ur->a0);
  788. break;
  789. }
  790. }
  791. void
  792. fen(Ureg *ur)
  793. {
  794. if(up){
  795. switch(up->fpstate){
  796. case FPinit:
  797. restfpregs(&initfp);
  798. up->fpstate = FPactive;
  799. //print("EI=%lux+", initfp.fpstatus);
  800. return;
  801. case FPinactive:
  802. restfpregs(&up->fpsave);
  803. up->fpstate = FPactive;
  804. //print("EIA=%lux+", up->fpsave.fpstatus);
  805. return;
  806. }
  807. }
  808. fataltrap(ur, "trap: floating enable"); /* should never happen */
  809. }