trap.c 19 KB

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