trap.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "ureg.h"
  8. #include "../port/error.h"
  9. #include "tos.h"
  10. Intrregs *intrregs;
  11. typedef struct Vctl {
  12. Vctl* next; /* handlers on this vector */
  13. char *name; /* of driver, xallocated */
  14. void (*f)(Ureg*, void*); /* handler to call */
  15. void* a; /* argument to call it with */
  16. } Vctl;
  17. static Lock vctllock;
  18. static Vctl *vctl[32];
  19. static Vctl *gpiovctl[27];
  20. static int gpioirqref[12];
  21. /*
  22. * Layout at virtual address 0.
  23. */
  24. typedef struct Vpage0 {
  25. void (*vectors[8])(void);
  26. ulong vtable[8];
  27. } Vpage0;
  28. Vpage0 *vpage0;
  29. static int irq(Ureg*);
  30. static void gpiointr(Ureg*, void*);
  31. /* recover state after power suspend
  32. * NB: to help debugging bad suspend code,
  33. * I changed some prints below to iprints,
  34. * to avoid deadlocks when a panic is being
  35. * issued during the suspend/resume handler.
  36. */
  37. void
  38. trapresume(void)
  39. {
  40. vpage0 = (Vpage0*)EVECTORS;
  41. memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
  42. memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
  43. wbflush();
  44. mappedIvecEnable();
  45. }
  46. /*
  47. * set up for exceptions
  48. */
  49. void
  50. trapinit(void)
  51. {
  52. /* set up the exception vectors */
  53. vpage0 = (Vpage0*)EVECTORS;
  54. memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
  55. memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
  56. wbflush();
  57. /* use exception vectors at 0xFFFF0000 */
  58. mappedIvecEnable();
  59. /* set up the stacks for the interrupt modes */
  60. setr13(PsrMfiq, m->sfiq);
  61. setr13(PsrMirq, m->sirq);
  62. setr13(PsrMabt, m->sabt);
  63. setr13(PsrMund, m->sund);
  64. /* map in interrupt registers */
  65. intrregs = mapspecial(INTRREGS, sizeof(*intrregs));
  66. /* make all interrupts IRQ (i.e. not FIQ) and disable all interrupts */
  67. intrregs->iclr = 0;
  68. intrregs->icmr = 0;
  69. /* turn off all gpio interrupts */
  70. gpioregs->rising = 0;
  71. gpioregs->falling = 0;
  72. gpioregs->edgestatus = gpioregs->edgestatus;
  73. /* allow all enabled interrupts to take processor out of sleep mode */
  74. intrregs->iccr = 0;
  75. }
  76. void
  77. trapdump(char *tag)
  78. {
  79. iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n",
  80. tag, intrregs->icip, intrregs->icmr, intrregs->iclr,
  81. intrregs->iccr, intrregs->icfp);
  82. }
  83. void
  84. warnregs(Ureg *ur, char *tag)
  85. {
  86. char buf[1024];
  87. char *e = buf+sizeof(buf);
  88. char *p;
  89. p = seprint(buf, e, "%s:\n", tag);
  90. p = seprint(p, e, "type 0x%.8lux psr 0x%.8lux pc 0x%.8lux\n",
  91. ur->type, ur->psr, ur->pc);
  92. p = seprint(p, e, "r0 0x%.8lux r1 0x%.8lux r2 0x%.8lux r3 0x%.8lux\n",
  93. ur->r0, ur->r1, ur->r2, ur->r3);
  94. p = seprint(p, e, "r4 0x%.8lux r5 0x%.8lux r6 0x%.8lux r7 0x%.8lux\n",
  95. ur->r4, ur->r5, ur->r6, ur->r7);
  96. p = seprint(p, e, "r8 0x%.8lux r9 0x%.8lux r10 0x%.8lux r11 0x%.8lux\n",
  97. ur->r8, ur->r9, ur->r10, ur->r11);
  98. seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n",
  99. ur->r12, ur->r13, ur->r14);
  100. iprint("%s", buf);
  101. }
  102. /*
  103. * enable an irq interrupt
  104. */
  105. static void
  106. irqenable(int irq, IntrHandler *f, void* a, char *name)
  107. {
  108. Vctl *v;
  109. if(irq >= nelem(vctl) || irq < 0)
  110. panic("intrenable");
  111. v = malloc(sizeof(Vctl));
  112. v->f = f;
  113. v->a = a;
  114. v->name = xalloc(strlen(name)+1);
  115. strcpy(v->name, name);
  116. lock(&vctllock);
  117. v->next = vctl[irq];
  118. vctl[irq] = v;
  119. intrregs->icmr |= 1<<irq;
  120. unlock(&vctllock);
  121. }
  122. /*
  123. * disable an irq interrupt
  124. */
  125. static void
  126. irqdisable(int irq, IntrHandler *f, void* a, char *name)
  127. {
  128. Vctl **vp, *v;
  129. if(irq >= nelem(vctl) || irq < 0)
  130. panic("intrdisable");
  131. lock(&vctllock);
  132. for(vp = &vctl[irq]; v = *vp; vp = &v->next)
  133. if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
  134. print("irqdisable: remove %s\n", name);
  135. *vp = v->next;
  136. free(v);
  137. break;
  138. }
  139. if (v == nil)
  140. print("irqdisable: irq %d, name %s not enabled\n", irq, name);
  141. if (vctl[irq] == nil){
  142. print("irqdisable: clear icmr bit %d\n", irq);
  143. intrregs->icmr &= ~(1<<irq);
  144. }
  145. unlock(&vctllock);
  146. }
  147. /*
  148. * enable an interrupt
  149. */
  150. void
  151. intrenable(int type, int which, IntrHandler *f, void* a, char *name)
  152. {
  153. int irq;
  154. Vctl *v;
  155. if(type == IRQ){
  156. irqenable(which, f, a, name);
  157. return;
  158. }
  159. /* from here down, it must be a GPIO edge interrupt */
  160. irq = which;
  161. if(which >= nelem(gpiovctl) || which < 0)
  162. panic("intrenable");
  163. if(which > 11)
  164. irq = 11;
  165. /* the pin had better be configured as input */
  166. if((1<<which) & gpioregs->direction)
  167. panic("intrenable of output pin %d", which);
  168. /* create a second level vctl for the gpio edge interrupt */
  169. v = malloc(sizeof(Vctl));
  170. v->f = f;
  171. v->a = a;
  172. v->name = xalloc(strlen(name)+1);
  173. strcpy(v->name, name);
  174. lock(&vctllock);
  175. v->next = gpiovctl[which];
  176. gpiovctl[which] = v;
  177. /* set edge register to enable interrupt */
  178. switch(type){
  179. case GPIOboth:
  180. gpioregs->rising |= 1<<which;
  181. gpioregs->falling |= 1<<which;
  182. break;
  183. case GPIOfalling:
  184. gpioregs->falling |= 1<<which;
  185. break;
  186. case GPIOrising:
  187. gpioregs->rising |= 1<<which;
  188. break;
  189. }
  190. unlock(&vctllock);
  191. /* point the irq to the gpio interrupt handler */
  192. if(gpioirqref[irq]++ == 0)
  193. irqenable(irq, gpiointr, nil, "gpio edge");
  194. }
  195. /*
  196. * disable an interrupt
  197. */
  198. void
  199. intrdisable(int type, int which, IntrHandler *f, void* a, char *name)
  200. {
  201. int irq;
  202. Vctl **vp, *v;
  203. if(type == IRQ){
  204. irqdisable(which, f, a, name);
  205. return;
  206. }
  207. /* from here down, it must be a GPIO edge interrupt */
  208. irq = which;
  209. if(which >= nelem(gpiovctl) || which < 0)
  210. panic("intrdisable");
  211. if(which > 11)
  212. irq = 11;
  213. lock(&vctllock);
  214. for(vp = &gpiovctl[which]; v = *vp; vp = &v->next)
  215. if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
  216. break;
  217. }
  218. if (gpiovctl[which] == nil){
  219. /* set edge register to enable interrupt */
  220. switch(type){
  221. case GPIOboth:
  222. print("intrdisable: gpio-rising+falling clear bit %d\n", which);
  223. gpioregs->rising &= ~(1<<which);
  224. gpioregs->falling &= ~(1<<which);
  225. break;
  226. case GPIOfalling:
  227. print("intrdisable: gpio-falling clear bit %d\n", which);
  228. gpioregs->falling &= ~(1<<which);
  229. break;
  230. case GPIOrising:
  231. print("intrdisable: gpio-rising clear bit %d\n", which);
  232. gpioregs->rising &= ~(1<<which);
  233. break;
  234. }
  235. }
  236. if (v) {
  237. print("intrdisable: removing %s\n", name);
  238. *vp = v->next;
  239. }else
  240. print("intrdisable: which %d, name %s not enabled\n", which, name);
  241. unlock(&vctllock);
  242. /* disable the gpio interrupt handler if necessary */
  243. if(--gpioirqref[irq] == 0){
  244. print("intrdisable: inrqdisable gpiointr\n");
  245. irqdisable(irq, gpiointr, nil, "gpio edge");
  246. }
  247. free(v);
  248. }
  249. /*
  250. * called by trap to handle access faults
  251. */
  252. static void
  253. faultarm(Ureg *ureg, ulong va, int user, int read)
  254. {
  255. int n, insyscall;
  256. char buf[ERRMAX];
  257. if (up == nil) {
  258. warnregs(ureg, "kernel fault");
  259. panic("fault: nil up in faultarm, accessing 0x%lux\n", va);
  260. }
  261. insyscall = up->insyscall;
  262. up->insyscall = 1;
  263. n = fault(va, read);
  264. if(n < 0){
  265. if(!user){
  266. warnregs(ureg, "kernel fault");
  267. panic("fault: kernel accessing 0x%lux\n", va);
  268. }
  269. // warnregs(ureg, "user fault");
  270. sprint(buf, "sys: trap: fault %s va=0x%lux", read ? "read" : "write", va);
  271. postnote(up, 1, buf, NDebug);
  272. }
  273. up->insyscall = insyscall;
  274. }
  275. /*
  276. * returns 1 if the instruction writes memory, 0 otherwise
  277. */
  278. int
  279. writetomem(ulong inst)
  280. {
  281. /* swap always write memory */
  282. if((inst & 0x0FC00000) == 0x01000000)
  283. return 1;
  284. /* loads and stores are distinguished by bit 20 */
  285. if(inst & (1<<20))
  286. return 0;
  287. return 1;
  288. }
  289. /*
  290. * here on all exceptions other than syscall (SWI)
  291. */
  292. void
  293. trap(Ureg *ureg)
  294. {
  295. ulong inst;
  296. int clockintr, user, x, rv;
  297. ulong va, fsr;
  298. char buf[ERRMAX];
  299. int rem;
  300. if(up != nil)
  301. rem = ((char*)ureg)-up->kstack;
  302. else
  303. rem = ((char*)ureg)-((char*)(MACHADDR+sizeof(Mach)));
  304. if(rem < 256) {
  305. dumpstack();
  306. panic("trap %d bytes remaining, up = 0x%lux, ureg = 0x%lux, at pc 0x%lux",
  307. rem, up, ureg, ureg->pc);
  308. }
  309. user = (ureg->psr & PsrMask) == PsrMusr;
  310. /*
  311. * All interrupts/exceptions should be resumed at ureg->pc-4,
  312. * except for Data Abort which resumes at ureg->pc-8.
  313. */
  314. if(ureg->type == (PsrMabt+1))
  315. ureg->pc -= 8;
  316. else
  317. ureg->pc -= 4;
  318. clockintr = 0;
  319. switch(ureg->type){
  320. default:
  321. panic("unknown trap");
  322. break;
  323. case PsrMirq:
  324. clockintr = irq(ureg);
  325. break;
  326. case PsrMabt: /* prefetch fault */
  327. faultarm(ureg, ureg->pc, user, 1);
  328. break;
  329. case PsrMabt+1: /* data fault */
  330. va = getfar();
  331. inst = *(ulong*)(ureg->pc);
  332. fsr = getfsr() & 0xf;
  333. switch(fsr){
  334. case 0x0:
  335. panic("vector exception at %lux\n", ureg->pc);
  336. break;
  337. case 0x1:
  338. case 0x3:
  339. if(user){
  340. snprint(buf, sizeof(buf), "sys: alignment: pc 0x%lux va 0x%lux\n",
  341. ureg->pc, va);
  342. postnote(up, 1, buf, NDebug);
  343. } else
  344. panic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va);
  345. break;
  346. case 0x2:
  347. panic("terminal exception at %lux\n", ureg->pc);
  348. break;
  349. case 0x4:
  350. case 0x6:
  351. case 0x8:
  352. case 0xa:
  353. case 0xc:
  354. case 0xe:
  355. panic("external abort 0x%lux pc 0x%lux addr 0x%lux\n", fsr, ureg->pc, va);
  356. break;
  357. case 0x5:
  358. case 0x7:
  359. /* translation fault, i.e., no pte entry */
  360. faultarm(ureg, va, user, !writetomem(inst));
  361. break;
  362. case 0x9:
  363. case 0xb:
  364. /* domain fault, accessing something we shouldn't */
  365. if(user){
  366. sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n",
  367. ureg->pc, va);
  368. postnote(up, 1, buf, NDebug);
  369. } else
  370. panic("kernel access violation: pc 0x%lux va 0x%lux\n",
  371. ureg->pc, va);
  372. break;
  373. case 0xd:
  374. case 0xf:
  375. /* permission error, copy on write or real permission error */
  376. faultarm(ureg, va, user, !writetomem(inst));
  377. break;
  378. }
  379. break;
  380. case PsrMund: /* undefined instruction */
  381. if (user) {
  382. /* look for floating point instructions to interpret */
  383. x = spllo();
  384. rv = fpiarm(ureg);
  385. splx(x);
  386. if (rv == 0) {
  387. sprint(buf, "undefined instruction: pc 0x%lux\n", ureg->pc);
  388. postnote(up, 1, buf, NDebug);
  389. }
  390. }else{
  391. iprint("undefined instruction: pc=0x%lux, inst=0x%lux, 0x%lux, 0x%lux, 0x%lux, 0x%lux\n", ureg->pc, ((ulong*)ureg->pc)[-2], ((ulong*)ureg->pc)[-1], ((ulong*)ureg->pc)[0], ((ulong*)ureg->pc)[1], ((ulong*)ureg->pc)[2]);
  392. panic("undefined instruction");
  393. }
  394. break;
  395. }
  396. splhi();
  397. /* delaysched set because we held a lock or because our quantum ended */
  398. if(up && up->delaysched && clockintr){
  399. sched();
  400. splhi();
  401. }
  402. if(user){
  403. if(up->procctl || up->nnote)
  404. notify(ureg);
  405. kexit(ureg);
  406. }
  407. }
  408. /*
  409. * here on irq's
  410. */
  411. static int
  412. irq(Ureg *ur)
  413. {
  414. ulong va;
  415. int clockintr, i;
  416. Vctl *v;
  417. va = intrregs->icip;
  418. if(va & (1<<IRQtimer0))
  419. clockintr = 1;
  420. else
  421. clockintr = 0;
  422. for(i = 0; i < 32; i++){
  423. if(((1<<i) & va) == 0)
  424. continue;
  425. for(v = vctl[i]; v != nil; v = v->next){
  426. v->f(ur, v->a);
  427. va &= ~(1<<i);
  428. }
  429. }
  430. if(va)
  431. print("unknown interrupt: %lux\n", va);
  432. return clockintr;
  433. }
  434. /*
  435. * here on gpio interrupts
  436. */
  437. static void
  438. gpiointr(Ureg *ur, void*)
  439. {
  440. ulong va;
  441. int i;
  442. Vctl *v;
  443. va = gpioregs->edgestatus;
  444. gpioregs->edgestatus = va;
  445. for(i = 0; i < 27; i++){
  446. if(((1<<i) & va) == 0)
  447. continue;
  448. for(v = gpiovctl[i]; v != nil; v = v->next){
  449. v->f(ur, v->a);
  450. va &= ~(1<<i);
  451. }
  452. }
  453. if(va)
  454. print("unknown gpio interrupt: %lux\n", va);
  455. }
  456. /*
  457. * system calls
  458. */
  459. #include "../port/systab.h"
  460. /*
  461. * Syscall is called directly from assembler without going through trap().
  462. */
  463. void
  464. syscall(Ureg* ureg)
  465. {
  466. char *e;
  467. ulong sp;
  468. long ret;
  469. int i, scallnr;
  470. if((ureg->psr & PsrMask) != PsrMusr) {
  471. panic("syscall: pc 0x%lux r14 0x%lux cs 0x%lux\n", ureg->pc, ureg->r14, ureg->psr);
  472. }
  473. m->syscall++;
  474. up->insyscall = 1;
  475. up->pc = ureg->pc;
  476. up->dbgreg = ureg;
  477. scallnr = ureg->r0;
  478. up->scallnr = scallnr;
  479. spllo();
  480. sp = ureg->sp;
  481. up->nerrlab = 0;
  482. ret = -1;
  483. if(!waserror()){
  484. if(scallnr >= nsyscall){
  485. pprint("bad sys call number %d pc %lux\n",
  486. scallnr, ureg->pc);
  487. postnote(up, 1, "sys: bad sys call", NDebug);
  488. error(Ebadarg);
  489. }
  490. if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
  491. validaddr(sp, sizeof(Sargs)+BY2WD, 0);
  492. up->s = *((Sargs*)(sp+BY2WD));
  493. up->psstate = sysctab[scallnr];
  494. ret = systab[scallnr](up->s.args);
  495. poperror();
  496. }else{
  497. /* failure: save the error buffer for errstr */
  498. e = up->syserrstr;
  499. up->syserrstr = up->errstr;
  500. up->errstr = e;
  501. }
  502. if(up->nerrlab){
  503. print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
  504. for(i = 0; i < NERR; i++)
  505. print("sp=%lux pc=%lux\n",
  506. up->errlab[i].sp, up->errlab[i].pc);
  507. panic("error stack");
  508. }
  509. up->insyscall = 0;
  510. up->psstate = 0;
  511. /*
  512. * Put return value in frame. On the x86 the syscall is
  513. * just another trap and the return value from syscall is
  514. * ignored. On other machines the return value is put into
  515. * the results register by caller of syscall.
  516. */
  517. ureg->r0 = ret;
  518. if(scallnr == NOTED)
  519. noted(ureg, *(ulong*)(sp+BY2WD));
  520. if(up->delaysched)
  521. sched();
  522. splhi();
  523. if(scallnr != RFORK && (up->procctl || up->nnote))
  524. notify(ureg);
  525. }
  526. /*
  527. * Return user to state before notify()
  528. */
  529. void
  530. noted(Ureg* ureg, ulong arg0)
  531. {
  532. Ureg *nureg;
  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. pexit("Suicide", 0);
  539. }
  540. up->notified = 0;
  541. nureg = up->ureg; /* pointer to user returned Ureg struct */
  542. /* sanity clause */
  543. oureg = (ulong)nureg;
  544. if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
  545. pprint("bad ureg in noted or call to noted when not notified\n");
  546. qunlock(&up->debug);
  547. pexit("Suicide", 0);
  548. }
  549. /* don't let user change system flags */
  550. nureg->psr = (ureg->psr & ~(PsrMask|PsrDfiq|PsrDirq)) |
  551. (nureg->psr & (PsrMask|PsrDfiq|PsrDirq));
  552. memmove(ureg, nureg, sizeof(Ureg));
  553. switch(arg0){
  554. case NCONT:
  555. case NRSTR:
  556. if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->sp, BY2WD, 0)){
  557. qunlock(&up->debug);
  558. pprint("suicide: trap in noted\n");
  559. pexit("Suicide", 0);
  560. }
  561. up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
  562. qunlock(&up->debug);
  563. break;
  564. case NSAVE:
  565. if(!okaddr(nureg->pc, BY2WD, 0)
  566. || !okaddr(nureg->sp, BY2WD, 0)){
  567. qunlock(&up->debug);
  568. pprint("suicide: trap in noted\n");
  569. pexit("Suicide", 0);
  570. }
  571. qunlock(&up->debug);
  572. sp = oureg-4*BY2WD-ERRMAX;
  573. splhi();
  574. ureg->sp = sp;
  575. ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
  576. ((ulong*)sp)[0] = 0; /* arg 0 is pc */
  577. break;
  578. default:
  579. pprint("unknown noted arg 0x%lux\n", arg0);
  580. up->lastnote.flag = NDebug;
  581. /* fall through */
  582. case NDFLT:
  583. if(up->lastnote.flag == NDebug){
  584. qunlock(&up->debug);
  585. pprint("suicide: %s\n", up->lastnote.msg);
  586. } else
  587. qunlock(&up->debug);
  588. pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
  589. }
  590. }
  591. /*
  592. * Call user, if necessary, with note.
  593. * Pass user the Ureg struct and the note on his stack.
  594. */
  595. int
  596. notify(Ureg* ureg)
  597. {
  598. int l;
  599. ulong s, sp;
  600. Note *n;
  601. if(up->procctl)
  602. procctl(up);
  603. if(up->nnote == 0)
  604. return 0;
  605. s = spllo();
  606. qlock(&up->debug);
  607. up->notepending = 0;
  608. n = &up->note[0];
  609. if(strncmp(n->msg, "sys:", 4) == 0){
  610. l = strlen(n->msg);
  611. if(l > ERRMAX-15) /* " pc=0x12345678\0" */
  612. l = ERRMAX-15;
  613. sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
  614. }
  615. if(n->flag!=NUser && (up->notified || up->notify==0)){
  616. if(n->flag == NDebug)
  617. pprint("suicide: %s\n", n->msg);
  618. qunlock(&up->debug);
  619. pexit(n->msg, n->flag!=NDebug);
  620. }
  621. if(up->notified) {
  622. qunlock(&up->debug);
  623. splhi();
  624. return 0;
  625. }
  626. if(!up->notify){
  627. qunlock(&up->debug);
  628. pexit(n->msg, n->flag!=NDebug);
  629. }
  630. sp = ureg->sp;
  631. sp -= sizeof(Ureg);
  632. if(!okaddr((ulong)up->notify, 1, 0)
  633. || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)){
  634. pprint("suicide: bad address in notify\n");
  635. qunlock(&up->debug);
  636. pexit("Suicide", 0);
  637. }
  638. up->ureg = (void*)sp;
  639. memmove((Ureg*)sp, ureg, sizeof(Ureg));
  640. *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
  641. up->ureg = (void*)sp;
  642. sp -= BY2WD+ERRMAX;
  643. memmove((char*)sp, up->note[0].msg, ERRMAX);
  644. sp -= 3*BY2WD;
  645. *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
  646. *(ulong*)(sp+1*BY2WD) = (ulong)up->ureg; /* arg 1 is ureg* */
  647. *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
  648. ureg->sp = sp;
  649. ureg->pc = (ulong)up->notify;
  650. up->notified = 1;
  651. up->nnote--;
  652. memmove(&up->lastnote, &up->note[0], sizeof(Note));
  653. memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
  654. qunlock(&up->debug);
  655. splx(s);
  656. return 1;
  657. }
  658. /* Give enough context in the ureg to produce a kernel stack for
  659. * a sleeping process
  660. */
  661. void
  662. setkernur(Ureg *ureg, Proc *p)
  663. {
  664. ureg->pc = p->sched.pc;
  665. ureg->sp = p->sched.sp+4;
  666. ureg->r14 = (ulong)sched;
  667. }
  668. /*
  669. * return the userpc the last exception happened at
  670. */
  671. ulong
  672. userpc(void)
  673. {
  674. Ureg *ureg;
  675. ureg = (Ureg*)up->dbgreg;
  676. return ureg->pc;
  677. }
  678. /* This routine must save the values of registers the user is not permitted
  679. * to write from devproc and then restore the saved values before returning.
  680. */
  681. void
  682. setregisters(Ureg* ureg, char* pureg, char* uva, int n)
  683. {
  684. USED(ureg, pureg, uva, n);
  685. }
  686. /*
  687. * this is the body for all kproc's
  688. */
  689. static void
  690. linkproc(void)
  691. {
  692. spllo();
  693. up->kpfun(up->kparg);
  694. pexit("kproc exiting", 0);
  695. }
  696. /*
  697. * setup stack and initial PC for a new kernel proc. This is architecture
  698. * dependent because of the starting stack location
  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. /*
  709. * Craft a return frame which will cause the child to pop out of
  710. * the scheduler in user mode with the return register zero. Set
  711. * pc to point to a l.s return function.
  712. */
  713. void
  714. forkchild(Proc *p, Ureg *ureg)
  715. {
  716. Ureg *cureg;
  717. //print("%lud setting up for forking child %lud\n", up->pid, p->pid);
  718. p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg);
  719. p->sched.pc = (ulong)forkret;
  720. cureg = (Ureg*)(p->sched.sp);
  721. memmove(cureg, ureg, sizeof(Ureg));
  722. /* syscall returns 0 for child */
  723. cureg->r0 = 0;
  724. /* Things from bottom of syscall which were never executed */
  725. p->psstate = 0;
  726. p->insyscall = 0;
  727. }
  728. /*
  729. * setup stack, initial PC, and any arch dependent regs for an execing user proc.
  730. */
  731. long
  732. execregs(ulong entry, ulong ssize, ulong nargs)
  733. {
  734. ulong *sp;
  735. Ureg *ureg;
  736. sp = (ulong*)(USTKTOP - ssize);
  737. *--sp = nargs;
  738. ureg = up->dbgreg;
  739. memset(ureg, 0, 15*sizeof(ulong));
  740. ureg->r13 = (ulong)sp;
  741. ureg->pc = entry;
  742. //print("%lud: EXECREGS pc 0x%lux sp 0x%lux\n", up->pid, ureg->pc, ureg->r13);
  743. return USTKTOP-sizeof(Tos); /* address of kernel/user shared data */
  744. }
  745. /*
  746. * Fill in enough of Ureg to get a stack trace, and call a function.
  747. * Used by debugging interface rdb.
  748. */
  749. void
  750. callwithureg(void (*fn)(Ureg*))
  751. {
  752. Ureg ureg;
  753. ureg.pc = getcallerpc(&fn);
  754. ureg.sp = (ulong)&fn;
  755. fn(&ureg);
  756. }
  757. static void
  758. _dumpstack(Ureg *ureg)
  759. {
  760. ulong l, v, i;
  761. ulong *p;
  762. extern ulong etext;
  763. if(up == 0){
  764. iprint("no current proc\n");
  765. return;
  766. }
  767. iprint("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14);
  768. i = 0;
  769. for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){
  770. v = *(ulong*)l;
  771. if(KTZERO < v && v < (ulong)&etext && (v&3)==0){
  772. v -= 4;
  773. p = (ulong*)v;
  774. if((*p & 0x0f000000) == 0x0b000000){
  775. iprint("%.8lux=%.8lux ", l, v);
  776. i++;
  777. }
  778. }
  779. if(i == 4){
  780. i = 0;
  781. iprint("\n");
  782. }
  783. }
  784. if(i)
  785. iprint("\n");
  786. }
  787. void
  788. dumpstack(void)
  789. {
  790. callwithureg(_dumpstack);
  791. }
  792. /*
  793. * pc output by ps
  794. */
  795. ulong
  796. dbgpc(Proc *p)
  797. {
  798. Ureg *ureg;
  799. ureg = p->dbgreg;
  800. if(ureg == 0)
  801. return 0;
  802. return ureg->pc;
  803. }
  804. /*
  805. * called in sysfile.c
  806. */
  807. void
  808. evenaddr(ulong addr)
  809. {
  810. if(addr & 3){
  811. postnote(up, 1, "sys: odd address", NDebug);
  812. error(Ebadarg);
  813. }
  814. }