trap.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /*
  2. * omap3530 traps, exceptions, interrupts, system calls.
  3. */
  4. #include "u.h"
  5. #include "../port/lib.h"
  6. #include "mem.h"
  7. #include "dat.h"
  8. #include "fns.h"
  9. #include "../port/error.h"
  10. #include "ureg.h"
  11. #include "arm.h"
  12. enum {
  13. Nirqs = 96,
  14. Nvec = 8, /* # of vectors at start of lexception.s */
  15. Bi2long = BI2BY * sizeof(long),
  16. };
  17. extern int notify(Ureg*);
  18. extern int ldrexvalid;
  19. /* omap35x intc (aka mpu_intc) */
  20. typedef struct Intrregs Intrregs;
  21. struct Intrregs {
  22. /*
  23. * the manual inserts "INTCPS_" before each register name;
  24. * we'll just assume the prefix.
  25. */
  26. uchar _pad0[4*4];
  27. ulong sysconfig;
  28. ulong sysstatus; /* ro */
  29. uchar _pad1[0x40 - 0x18];
  30. ulong sir_irq; /* ro */
  31. ulong sir_fiq; /* ro */
  32. ulong control;
  33. ulong protection;
  34. ulong idle;
  35. uchar _pad2[0x60 - 0x54];
  36. ulong irq_priority;
  37. ulong fiq_priority;
  38. ulong threshold;
  39. uchar _pad3[0x80 - 0x6c];
  40. struct Bits { /* bitmaps */
  41. ulong itr; /* ro: pending intrs (no mask) */
  42. ulong mir; /* interrupt mask: 1 means masked */
  43. ulong mir_clear; /* wo: 1 sets the bit */
  44. ulong mir_set; /* wo: 1 clears the bit */
  45. ulong isr_set; /* software interrupts */
  46. ulong isr_clear; /* wo */
  47. ulong pending_irq; /* ro */
  48. ulong pending_fiq; /* ro */
  49. } bits[3]; /* 3*32 = 96 (Nirqs) */
  50. ulong ilr[Nirqs];
  51. };
  52. enum {
  53. /* sysconfig bits */
  54. Softreset = 1<<1,
  55. /* sysstatus bits */
  56. Resetdone = 1<<0,
  57. /* sir_irq/fiq bits */
  58. Activeirq = MASK(7),
  59. /* control bits */
  60. Newirqagr = 1<<0,
  61. /* protection bits */
  62. Protection = 1<<0,
  63. /* irq/fiq_priority bits */
  64. Irqpriority = MASK(6),
  65. /* threshold bits */
  66. Prioritythreshold = MASK(8),
  67. /* ilr bits */
  68. Priority = MASK(8) - MASK(2),
  69. };
  70. typedef struct Vctl Vctl;
  71. typedef struct Vctl {
  72. Vctl* next; /* handlers on this vector */
  73. char *name; /* of driver, xallocated */
  74. void (*f)(Ureg*, void*); /* handler to call */
  75. void* a; /* argument to call it with */
  76. } Vctl;
  77. static Lock vctllock;
  78. static Vctl* vctl[Nirqs];
  79. /*
  80. * Layout at virtual address 0.
  81. */
  82. typedef struct Vpage0 {
  83. void (*vectors[Nvec])(void);
  84. u32int vtable[Nvec];
  85. } Vpage0;
  86. static Vpage0 *vpage0;
  87. uvlong ninterrupt;
  88. uvlong ninterruptticks;
  89. int irqtooearly = 1;
  90. static volatile int probing, trapped;
  91. static int
  92. irqinuse(uint irq)
  93. {
  94. Intrregs *ip = (Intrregs *)PHYSINTC;
  95. /*
  96. * mir registers are odd: a 0 bit means intr unmasked (i.e.,
  97. * we've unmasked it because it's in use).
  98. */
  99. return (ip->bits[irq / Bi2long].mir & (1 << (irq % Bi2long))) == 0;
  100. }
  101. static void
  102. intcmask(uint irq)
  103. {
  104. Intrregs *ip = (Intrregs *)PHYSINTC;
  105. ip->bits[irq / Bi2long].mir_set = 1 << (irq % Bi2long);
  106. coherence();
  107. }
  108. static void
  109. intcunmask(uint irq)
  110. {
  111. Intrregs *ip = (Intrregs *)PHYSINTC;
  112. ip->bits[irq / Bi2long].mir_clear = 1 << (irq % Bi2long);
  113. coherence();
  114. }
  115. static void
  116. intcmaskall(void)
  117. {
  118. int i;
  119. Intrregs *ip = (Intrregs *)PHYSINTC;
  120. for (i = 0; i < 3; i++)
  121. ip->bits[i].mir_set = ~0;
  122. coherence();
  123. }
  124. static void
  125. intcunmaskall(void)
  126. {
  127. int i;
  128. Intrregs *ip = (Intrregs *)PHYSINTC;
  129. for (i = 0; i < 3; i++)
  130. ip->bits[i].mir_clear = ~0;
  131. coherence();
  132. }
  133. static void
  134. intcinvertall(void)
  135. {
  136. int i, s;
  137. ulong bits;
  138. Intrregs *ip = (Intrregs *)PHYSINTC;
  139. s = splhi();
  140. for (i = 0; i < 3; i++) {
  141. bits = ip->bits[i].mir;
  142. ip->bits[i].mir_set = ~0; /* mask all */
  143. coherence();
  144. /* clearing enables only those intrs. that were disabled */
  145. ip->bits[i].mir_clear = bits;
  146. }
  147. coherence();
  148. splx(s);
  149. }
  150. static void
  151. intrsave(ulong buf[3])
  152. {
  153. int i;
  154. Intrregs *ip = (Intrregs *)PHYSINTC;
  155. for (i = 0; i < nelem(buf); i++)
  156. buf[i] = ip->bits[i].mir;
  157. coherence();
  158. }
  159. static void
  160. intrrestore(ulong buf[3])
  161. {
  162. int i, s;
  163. Intrregs *ip = (Intrregs *)PHYSINTC;
  164. s = splhi();
  165. for (i = 0; i < nelem(buf); i++) {
  166. ip->bits[i].mir_clear = ~0; /* unmask all */
  167. coherence();
  168. ip->bits[i].mir_set = buf[i]; /* mask previously disabled */
  169. }
  170. coherence();
  171. splx(s);
  172. }
  173. /*
  174. * set up for exceptions
  175. */
  176. void
  177. trapinit(void)
  178. {
  179. int i;
  180. Intrregs *ip = (Intrregs *)PHYSINTC;
  181. /* set up the exception vectors */
  182. vpage0 = (Vpage0*)HVECTORS;
  183. memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
  184. memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
  185. cacheuwbinv();
  186. l2cacheuwbinv();
  187. /* set up the stacks for the interrupt modes */
  188. setr13(PsrMfiq, m->sfiq);
  189. setr13(PsrMirq, m->sirq);
  190. setr13(PsrMabt, m->sabt);
  191. setr13(PsrMund, m->sund);
  192. #ifdef HIGH_SECURITY
  193. setr13(PsrMmon, m->smon);
  194. #endif
  195. setr13(PsrMsys, m->ssys);
  196. intcmaskall();
  197. ip->control = 0;
  198. ip->threshold = Prioritythreshold; /* disable threshold */
  199. for (i = 0; i < Nirqs; i++)
  200. ip->ilr[i] = 0<<2 | 0; /* all intrs pri 0 & to irq, not fiq */
  201. irqtooearly = 0;
  202. coherence();
  203. }
  204. void
  205. intrsoff(void)
  206. {
  207. Intrregs *ip = (Intrregs *)PHYSINTC;
  208. intcmaskall();
  209. ip->control = Newirqagr; /* dismiss interrupt */
  210. coherence();
  211. }
  212. /*
  213. * enable an irq interrupt
  214. */
  215. int
  216. irqenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
  217. {
  218. Vctl *v;
  219. if(irq >= nelem(vctl) || irq < 0)
  220. panic("irqenable irq %d", irq);
  221. if (irqtooearly) {
  222. iprint("irqenable for %d %s called too early\n", irq, name);
  223. return -1;
  224. }
  225. if(irqinuse(irq))
  226. print("irqenable: %s: irq %d already in use, chaining\n",
  227. name, irq);
  228. v = malloc(sizeof(Vctl));
  229. if (v == nil)
  230. panic("irqenable: malloc Vctl");
  231. v->f = f;
  232. v->a = a;
  233. v->name = malloc(strlen(name)+1);
  234. if (v->name == nil)
  235. panic("irqenable: malloc name");
  236. strcpy(v->name, name);
  237. lock(&vctllock);
  238. v->next = vctl[irq];
  239. vctl[irq] = v;
  240. intcunmask(irq);
  241. unlock(&vctllock);
  242. return 0;
  243. }
  244. /*
  245. * disable an irq interrupt
  246. */
  247. int
  248. irqdisable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
  249. {
  250. Vctl **vp, *v;
  251. if(irq >= nelem(vctl) || irq < 0)
  252. panic("irqdisable irq %d", irq);
  253. lock(&vctllock);
  254. for(vp = &vctl[irq]; v = *vp; vp = &v->next)
  255. if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
  256. print("irqdisable: remove %s\n", name);
  257. *vp = v->next;
  258. free(v);
  259. break;
  260. }
  261. if(v == nil)
  262. print("irqdisable: irq %d, name %s not enabled\n", irq, name);
  263. if(vctl[irq] == nil){
  264. print("irqdisable: clear icmr bit %d\n", irq);
  265. intcmask(irq);
  266. }
  267. unlock(&vctllock);
  268. return 0;
  269. }
  270. /*
  271. * called by trap to handle access faults
  272. */
  273. static void
  274. faultarm(Ureg *ureg, uintptr va, int user, int read)
  275. {
  276. int n, insyscall;
  277. char buf[ERRMAX];
  278. if(up == nil) {
  279. dumpregs(ureg);
  280. panic("fault: nil up in faultarm, accessing %#p", va);
  281. }
  282. insyscall = up->insyscall;
  283. up->insyscall = 1;
  284. n = fault(va, read);
  285. if(n < 0){
  286. if(!user){
  287. dumpregs(ureg);
  288. panic("fault: kernel accessing %#p", va);
  289. }
  290. /* don't dump registers; programs suicide all the time */
  291. snprint(buf, sizeof buf, "sys: trap: fault %s va=%#p",
  292. read? "read": "write", va);
  293. postnote(up, 1, buf, NDebug);
  294. }
  295. up->insyscall = insyscall;
  296. }
  297. /*
  298. * called by trap to handle interrupts.
  299. * returns true iff a clock interrupt, thus maybe reschedule.
  300. */
  301. static int
  302. irq(Ureg* ureg)
  303. {
  304. int clockintr;
  305. uint irqno, handled, t, ticks = perfticks();
  306. Intrregs *ip = (Intrregs *)PHYSINTC;
  307. Vctl *v;
  308. static int nesting, lastirq = -1;
  309. handled = 0;
  310. irqno = ip->sir_irq & Activeirq;
  311. if (irqno >= 37 && irqno <= 47) /* this is a clock intr? */
  312. m->inclockintr++; /* yes, count nesting */
  313. lastirq = irqno;
  314. if (irqno >= nelem(vctl)) {
  315. iprint("trap: irq %d >= # vectors (%d)\n", irqno, nelem(vctl));
  316. ip->control = Newirqagr; /* dismiss interrupt */
  317. return 0;
  318. }
  319. ++nesting;
  320. for(v = vctl[irqno]; v != nil; v = v->next)
  321. if (v->f) {
  322. if (islo())
  323. panic("trap: pl0 before trap handler for %s",
  324. v->name);
  325. v->f(ureg, v->a);
  326. if (islo())
  327. panic("trap: %s lowered pl", v->name);
  328. // splhi(); /* in case v->f lowered pl */
  329. handled++;
  330. }
  331. if(!handled) {
  332. iprint("unexpected interrupt: irq %d", irqno);
  333. switch (irqno) {
  334. case 56:
  335. case 57:
  336. iprint(" (I⁲C)");
  337. break;
  338. case 83:
  339. case 86:
  340. case 94:
  341. iprint(" (MMC)");
  342. break;
  343. }
  344. if(irqno < nelem(vctl)) {
  345. intcmask(irqno);
  346. iprint(", now masked");
  347. }
  348. iprint("\n");
  349. }
  350. t = perfticks();
  351. ninterrupt++;
  352. if(t < ticks)
  353. ninterruptticks += ticks-t;
  354. else
  355. ninterruptticks += t-ticks;
  356. ip->control = Newirqagr; /* dismiss interrupt */
  357. coherence();
  358. --nesting;
  359. clockintr = m->inclockintr == 1;
  360. if (irqno >= 37 && irqno <= 47)
  361. m->inclockintr--;
  362. return clockintr;
  363. }
  364. /*
  365. * returns 1 if the instruction writes memory, 0 otherwise
  366. */
  367. int
  368. writetomem(ulong inst)
  369. {
  370. /* swap always write memory */
  371. if((inst & 0x0FC00000) == 0x01000000)
  372. return 1;
  373. /* loads and stores are distinguished by bit 20 */
  374. if(inst & (1<<20))
  375. return 0;
  376. return 1;
  377. }
  378. void prgpmcerrs(void);
  379. /*
  380. * here on all exceptions other than syscall (SWI)
  381. */
  382. void
  383. trap(Ureg *ureg)
  384. {
  385. int clockintr, user, x, rv, rem;
  386. ulong inst, fsr;
  387. uintptr va;
  388. char buf[ERRMAX];
  389. splhi(); /* paranoia */
  390. if(up != nil)
  391. rem = ((char*)ureg)-up->kstack;
  392. else
  393. rem = ((char*)ureg)-((char*)m+sizeof(Mach));
  394. if(rem < 1024) {
  395. iprint("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux\n",
  396. rem, up, ureg, ureg->pc);
  397. delay(1000);
  398. dumpstack();
  399. panic("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux",
  400. rem, up, ureg, ureg->pc);
  401. }
  402. user = (ureg->psr & PsrMask) == PsrMusr;
  403. if(user){
  404. up->dbgreg = ureg;
  405. cycles(&up->kentry);
  406. }
  407. /*
  408. * All interrupts/exceptions should be resumed at ureg->pc-4,
  409. * except for Data Abort which resumes at ureg->pc-8.
  410. */
  411. if(ureg->type == (PsrMabt+1))
  412. ureg->pc -= 8;
  413. else
  414. ureg->pc -= 4;
  415. clockintr = 0; /* if set, may call sched() before return */
  416. switch(ureg->type){
  417. default:
  418. panic("unknown trap; type %#lux, psr mode %#lux", ureg->type,
  419. ureg->psr & PsrMask);
  420. break;
  421. case PsrMirq:
  422. ldrexvalid = 0;
  423. clockintr = irq(ureg);
  424. m->intr++;
  425. break;
  426. case PsrMabt: /* prefetch fault */
  427. ldrexvalid = 0;
  428. x = ifsrget();
  429. fsr = (x>>7) & 0x8 | x & 0x7;
  430. switch(fsr){
  431. case 0x02: /* instruction debug event (BKPT) */
  432. if(user){
  433. snprint(buf, sizeof buf, "sys: breakpoint");
  434. postnote(up, 1, buf, NDebug);
  435. }else{
  436. iprint("kernel bkpt: pc %#lux inst %#ux\n",
  437. ureg->pc, *(u32int*)ureg->pc);
  438. panic("kernel bkpt");
  439. }
  440. break;
  441. default:
  442. faultarm(ureg, ureg->pc, user, 1);
  443. break;
  444. }
  445. break;
  446. case PsrMabt+1: /* data fault */
  447. ldrexvalid = 0;
  448. va = farget();
  449. inst = *(ulong*)(ureg->pc);
  450. /* bits 12 and 10 have to be concatenated with status */
  451. x = fsrget();
  452. fsr = (x>>7) & 0x20 | (x>>6) & 0x10 | x & 0xf;
  453. if (probing && !user) {
  454. if (trapped++ > 0)
  455. panic("trap: recursive probe %#lux", va);
  456. ureg->pc += 4; /* continue at next instruction */
  457. break;
  458. }
  459. switch(fsr){
  460. default:
  461. case 0xa: /* ? was under external abort */
  462. panic("unknown data fault, 6b fsr %#lux", fsr);
  463. break;
  464. case 0x0:
  465. panic("vector exception at %#lux", ureg->pc);
  466. break;
  467. case 0x1: /* alignment fault */
  468. case 0x3: /* access flag fault (section) */
  469. if(user){
  470. snprint(buf, sizeof buf,
  471. "sys: alignment: pc %#lux va %#p\n",
  472. ureg->pc, va);
  473. postnote(up, 1, buf, NDebug);
  474. } else
  475. panic("kernel alignment: pc %#lux va %#p", ureg->pc, va);
  476. break;
  477. case 0x2:
  478. panic("terminal exception at %#lux", ureg->pc);
  479. break;
  480. case 0x4: /* icache maint fault */
  481. case 0x6: /* access flag fault (page) */
  482. case 0x8: /* precise external abort, non-xlat'n */
  483. case 0x28:
  484. case 0xc: /* l1 translation, precise ext. abort */
  485. case 0x2c:
  486. case 0xe: /* l2 translation, precise ext. abort */
  487. case 0x2e:
  488. case 0x16: /* imprecise ext. abort, non-xlt'n */
  489. case 0x36:
  490. panic("external abort %#lux pc %#lux addr %#p",
  491. fsr, ureg->pc, va);
  492. break;
  493. case 0x1c: /* l1 translation, precise parity err */
  494. case 0x1e: /* l2 translation, precise parity err */
  495. case 0x18: /* imprecise parity or ecc err */
  496. panic("translation parity error %#lux pc %#lux addr %#p",
  497. fsr, ureg->pc, va);
  498. break;
  499. case 0x5: /* translation fault, no section entry */
  500. case 0x7: /* translation fault, no page entry */
  501. faultarm(ureg, va, user, !writetomem(inst));
  502. break;
  503. case 0x9:
  504. case 0xb:
  505. /* domain fault, accessing something we shouldn't */
  506. if(user){
  507. snprint(buf, sizeof buf,
  508. "sys: access violation: pc %#lux va %#p\n",
  509. ureg->pc, va);
  510. postnote(up, 1, buf, NDebug);
  511. } else
  512. panic("kernel access violation: pc %#lux va %#p",
  513. ureg->pc, va);
  514. break;
  515. case 0xd:
  516. case 0xf:
  517. /* permission error, copy on write or real permission error */
  518. faultarm(ureg, va, user, !writetomem(inst));
  519. break;
  520. }
  521. break;
  522. case PsrMund: /* undefined instruction */
  523. if(user){
  524. if(seg(up, ureg->pc, 0) != nil &&
  525. *(u32int*)ureg->pc == 0xD1200070){
  526. snprint(buf, sizeof buf, "sys: breakpoint");
  527. postnote(up, 1, buf, NDebug);
  528. }else{
  529. /* look for floating point instructions to interpret */
  530. x = spllo();
  531. rv = fpiarm(ureg);
  532. splx(x);
  533. if(rv == 0){
  534. ldrexvalid = 0;
  535. snprint(buf, sizeof buf,
  536. "undefined instruction: pc %#lux\n",
  537. ureg->pc);
  538. postnote(up, 1, buf, NDebug);
  539. }
  540. }
  541. }else{
  542. if (ureg->pc & 3) {
  543. iprint("rounding fault pc %#lux down to word\n",
  544. ureg->pc);
  545. ureg->pc &= ~3;
  546. }
  547. iprint("undefined instruction: pc %#lux inst %#ux\n",
  548. ureg->pc, ((u32int*)ureg->pc)[-2]);
  549. panic("undefined instruction");
  550. }
  551. break;
  552. }
  553. splhi();
  554. /* delaysched set because we held a lock or because our quantum ended */
  555. if(up && up->delaysched && clockintr){
  556. ldrexvalid = 0;
  557. sched(); /* can cause more traps */
  558. splhi();
  559. }
  560. if(user){
  561. if(up->procctl || up->nnote)
  562. notify(ureg);
  563. kexit(ureg);
  564. }
  565. }
  566. /*
  567. * Fill in enough of Ureg to get a stack trace, and call a function.
  568. * Used by debugging interface rdb.
  569. */
  570. void
  571. callwithureg(void (*fn)(Ureg*))
  572. {
  573. Ureg ureg;
  574. ureg.pc = getcallerpc(&fn);
  575. ureg.sp = PTR2UINT(&fn);
  576. fn(&ureg);
  577. }
  578. static void
  579. dumpstackwithureg(Ureg *ureg)
  580. {
  581. int x;
  582. uintptr l, v, i, estack;
  583. char *s;
  584. dumpregs(ureg);
  585. if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
  586. iprint("dumpstack disabled\n");
  587. return;
  588. }
  589. iprint("dumpstack\n");
  590. x = 0;
  591. x += iprint("ktrace /kernel/path %#.8lux %#.8lux %#.8lux # pc, sp, link\n",
  592. ureg->pc, ureg->sp, ureg->r14);
  593. delay(20);
  594. i = 0;
  595. if(up
  596. && (uintptr)&l >= (uintptr)up->kstack
  597. && (uintptr)&l <= (uintptr)up->kstack+KSTACK)
  598. estack = (uintptr)up->kstack+KSTACK;
  599. else if((uintptr)&l >= (uintptr)m->stack
  600. && (uintptr)&l <= (uintptr)m+MACHSIZE)
  601. estack = (uintptr)m+MACHSIZE;
  602. else
  603. return;
  604. x += iprint("estackx %p\n", estack);
  605. for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
  606. v = *(uintptr*)l;
  607. if((KTZERO < v && v < (uintptr)etext) || estack-l < 32){
  608. x += iprint("%.8p ", v);
  609. delay(20);
  610. i++;
  611. }
  612. if(i == 8){
  613. i = 0;
  614. x += iprint("\n");
  615. delay(20);
  616. }
  617. }
  618. if(i)
  619. iprint("\n");
  620. }
  621. void
  622. dumpstack(void)
  623. {
  624. callwithureg(dumpstackwithureg);
  625. }
  626. /*
  627. * dump system control coprocessor registers
  628. */
  629. static void
  630. dumpscr(void)
  631. {
  632. iprint("0:\t%#8.8ux id\n", cpidget());
  633. iprint("\t%8.8#ux ct\n", cpctget());
  634. iprint("1:\t%#8.8ux control\n", controlget());
  635. iprint("2:\t%#8.8ux ttb\n", ttbget());
  636. iprint("3:\t%#8.8ux dac\n", dacget());
  637. iprint("4:\t(reserved)\n");
  638. iprint("5:\t%#8.8ux fsr\n", fsrget());
  639. iprint("6:\t%#8.8ux far\n", farget());
  640. iprint("7:\twrite-only cache\n");
  641. iprint("8:\twrite-only tlb\n");
  642. iprint("13:\t%#8.8ux pid\n", pidget());
  643. delay(10);
  644. }
  645. /*
  646. * dump general registers
  647. */
  648. static void
  649. dumpgpr(Ureg* ureg)
  650. {
  651. if(up != nil)
  652. iprint("cpu%d: registers for %s %lud\n",
  653. m->machno, up->text, up->pid);
  654. else
  655. iprint("cpu%d: registers for kernel\n", m->machno);
  656. delay(20);
  657. iprint("%#8.8lux\tr0\n", ureg->r0);
  658. iprint("%#8.8lux\tr1\n", ureg->r1);
  659. iprint("%#8.8lux\tr2\n", ureg->r2);
  660. delay(20);
  661. iprint("%#8.8lux\tr3\n", ureg->r3);
  662. iprint("%#8.8lux\tr4\n", ureg->r4);
  663. iprint("%#8.8lux\tr5\n", ureg->r5);
  664. delay(20);
  665. iprint("%#8.8lux\tr6\n", ureg->r6);
  666. iprint("%#8.8lux\tr7\n", ureg->r7);
  667. iprint("%#8.8lux\tr8\n", ureg->r8);
  668. delay(20);
  669. iprint("%#8.8lux\tr9 (up)\n", ureg->r9);
  670. iprint("%#8.8lux\tr10 (m)\n", ureg->r10);
  671. iprint("%#8.8lux\tr11 (loader temporary)\n", ureg->r11);
  672. iprint("%#8.8lux\tr12 (SB)\n", ureg->r12);
  673. delay(20);
  674. iprint("%#8.8lux\tr13 (sp)\n", ureg->r13);
  675. iprint("%#8.8lux\tr14 (link)\n", ureg->r14);
  676. iprint("%#8.8lux\tr15 (pc)\n", ureg->pc);
  677. delay(20);
  678. iprint("%10.10lud\ttype\n", ureg->type);
  679. iprint("%#8.8lux\tpsr\n", ureg->psr);
  680. delay(20);
  681. }
  682. void
  683. dumpregs(Ureg* ureg)
  684. {
  685. dumpgpr(ureg);
  686. dumpscr();
  687. }
  688. vlong
  689. probeaddr(uintptr addr)
  690. {
  691. vlong v;
  692. static Lock fltlck;
  693. ilock(&fltlck);
  694. trapped = 0;
  695. probing = 1;
  696. coherence();
  697. v = *(ulong *)addr; /* this may cause a fault */
  698. USED(probing);
  699. coherence();
  700. probing = 0;
  701. coherence();
  702. if (trapped)
  703. v = -1;
  704. iunlock(&fltlck);
  705. return v;
  706. }