trap.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  1. /*
  2. * arm mpcore generic interrupt controller (gic) v1
  3. * traps, exceptions, interrupts, system calls.
  4. *
  5. * there are two pieces: the interrupt distributor and the cpu interface.
  6. *
  7. * memset or memmove on any of the distributor registers generates an
  8. * exception like this one:
  9. * panic: external abort 0x28 pc 0xc048bf68 addr 0x50041800
  10. *
  11. * we use l1 and l2 cache ops to force vectors to be visible everywhere.
  12. *
  13. * apparently irqs 0—15 (SGIs) are always enabled.
  14. */
  15. #include "u.h"
  16. #include "../port/lib.h"
  17. #include "mem.h"
  18. #include "dat.h"
  19. #include "fns.h"
  20. #include "../port/error.h"
  21. #include "ureg.h"
  22. #include "arm.h"
  23. #define ISSGI(irq) ((uint)(irq) < Nsgi)
  24. enum {
  25. Debug = 0,
  26. Nvec = 8, /* # of vectors at start of lexception.s */
  27. Bi2long = BI2BY * sizeof(long),
  28. Nirqs = 1024,
  29. Nsgi = 16, /* software-generated (inter-processor) intrs */
  30. Nppi = 32, /* sgis + other private peripheral intrs */
  31. };
  32. typedef struct Intrcpuregs Intrcpuregs;
  33. typedef struct Intrdistregs Intrdistregs;
  34. /*
  35. * almost this entire register set is buggered.
  36. * the distributor is supposed to be per-system, not per-cpu,
  37. * yet some registers are banked per-cpu, as marked.
  38. */
  39. struct Intrdistregs { /* distributor */
  40. ulong ctl;
  41. ulong ctlrtype;
  42. ulong distid;
  43. uchar _pad0[0x80 - 0xc];
  44. /* botch: *[0] are banked per-cpu from here */
  45. /* bit maps */
  46. ulong grp[32]; /* in group 1 (non-secure) */
  47. ulong setena[32]; /* forward to cpu interfaces */
  48. ulong clrena[32];
  49. ulong setpend[32];
  50. ulong clrpend[32];
  51. ulong setact[32]; /* active? */
  52. ulong clract[32];
  53. /* botch: *[0] are banked per-cpu until here */
  54. uchar pri[1020]; /* botch: pri[0] — pri[7] are banked per-cpu */
  55. ulong _rsrvd1;
  56. /* botch: targ[0] through targ[7] are banked per-cpu and RO */
  57. uchar targ[1020]; /* byte bit maps: cpu targets indexed by intr */
  58. ulong _rsrvd2;
  59. /* botch: cfg[1] is banked per-cpu */
  60. ulong cfg[64]; /* bit pairs: edge? 1-N? */
  61. ulong _pad1[64];
  62. ulong nsac[64]; /* bit pairs (v2 only) */
  63. /* software-generated intrs (a.k.a. sgi) */
  64. ulong swgen; /* intr targets */
  65. uchar _pad2[0xf10 - 0xf04];
  66. uchar clrsgipend[16]; /* bit map (v2 only) */
  67. uchar setsgipend[16]; /* bit map (v2 only) */
  68. };
  69. enum {
  70. /* ctl bits */
  71. Forw2cpuif = 1,
  72. /* ctlrtype bits */
  73. Cpunoshft = 5,
  74. Cpunomask = MASK(3),
  75. Intrlines = MASK(5),
  76. /* cfg bits */
  77. Level = 0<<1,
  78. Edge = 1<<1, /* edge-, not level-sensitive */
  79. Toall = 0<<0,
  80. To1 = 1<<0, /* vs. to all */
  81. /* swgen bits */
  82. Totargets = 0,
  83. Tonotme = 1<<24,
  84. Tome = 2<<24,
  85. };
  86. /* each cpu sees its own registers at the same base address (soc.intr) */
  87. struct Intrcpuregs {
  88. ulong ctl;
  89. ulong primask;
  90. ulong binpt; /* group pri vs subpri split */
  91. ulong ack;
  92. ulong end;
  93. ulong runpri;
  94. ulong hipripend;
  95. /* aliased regs (secure, for group 1) */
  96. ulong alibinpt;
  97. ulong aliack; /* (v2 only) */
  98. ulong aliend; /* (v2 only) */
  99. ulong alihipripend; /* (v2 only) */
  100. uchar _pad0[0xd0 - 0x2c];
  101. ulong actpri[4]; /* (v2 only) */
  102. ulong nsactpri[4]; /* (v2 only) */
  103. uchar _pad0[0xfc - 0xf0];
  104. ulong ifid; /* ro */
  105. uchar _pad0[0x1000 - 0x100];
  106. ulong deact; /* wo (v2 only) */
  107. };
  108. enum {
  109. /* ctl bits */
  110. Enable = 1,
  111. Eoinodeact = 1<<9, /* (v2 only) */
  112. /* (ali) ack/end/hipriend/deact bits */
  113. Intrmask = MASK(10),
  114. Cpuidshift = 10,
  115. Cpuidmask = MASK(3),
  116. /* ifid bits */
  117. Archversshift = 16,
  118. Archversmask = MASK(4),
  119. };
  120. typedef struct Vctl Vctl;
  121. typedef struct Vctl {
  122. Vctl* next; /* handlers on this vector */
  123. char *name; /* of driver, xallocated */
  124. void (*f)(Ureg*, void*); /* handler to call */
  125. void* a; /* argument to call it with */
  126. } Vctl;
  127. static Lock vctllock;
  128. static Vctl* vctl[Nirqs];
  129. /*
  130. * Layout at virtual address 0.
  131. */
  132. typedef struct Vpage0 {
  133. void (*vectors[Nvec])(void);
  134. u32int vtable[Nvec];
  135. } Vpage0;
  136. enum
  137. {
  138. Ntimevec = 20 /* number of time buckets for each intr */
  139. };
  140. ulong intrtimes[Nirqs][Ntimevec];
  141. uvlong ninterrupt;
  142. uvlong ninterruptticks;
  143. int irqtooearly = 1;
  144. static ulong shadena[32]; /* copy of enable bits, saved by intcmaskall */
  145. static Lock distlock, nintrlock;
  146. extern int notify(Ureg*);
  147. static void dumpstackwithureg(Ureg *ureg);
  148. void
  149. printrs(int base, ulong word)
  150. {
  151. int bit;
  152. for (bit = 0; word; bit++, word >>= 1)
  153. if (word & 1)
  154. iprint(" %d", base + bit);
  155. }
  156. void
  157. dumpintrs(char *what, ulong *bits)
  158. {
  159. int i, first, some;
  160. ulong word;
  161. Intrdistregs *idp = (Intrdistregs *)soc.intrdist;
  162. first = 1;
  163. some = 0;
  164. USED(idp);
  165. for (i = 0; i < nelem(idp->setpend); i++) {
  166. word = bits[i];
  167. if (word) {
  168. if (first) {
  169. first = 0;
  170. iprint("%s", what);
  171. }
  172. some = 1;
  173. printrs(i * Bi2long, word);
  174. }
  175. }
  176. if (!some)
  177. iprint("%s none", what);
  178. iprint("\n");
  179. }
  180. void
  181. dumpintrpend(void)
  182. {
  183. Intrdistregs *idp = (Intrdistregs *)soc.intrdist;
  184. iprint("\ncpu%d gic regs:\n", m->machno);
  185. dumpintrs("group 1", idp->grp);
  186. dumpintrs("enabled", idp->setena);
  187. dumpintrs("pending", idp->setpend);
  188. dumpintrs("active ", idp->setact);
  189. }
  190. /*
  191. * keep histogram of interrupt service times
  192. */
  193. void
  194. intrtime(Mach*, int vno)
  195. {
  196. ulong diff;
  197. ulong x;
  198. x = perfticks();
  199. diff = x - m->perf.intrts;
  200. m->perf.intrts = x;
  201. m->perf.inintr += diff;
  202. if(up == nil && m->perf.inidle > diff)
  203. m->perf.inidle -= diff;
  204. if (m->cpumhz == 0)
  205. return; /* don't divide by zero */
  206. diff /= m->cpumhz*100; /* quantum = 100µsec */
  207. if(diff >= Ntimevec)
  208. diff = Ntimevec-1;
  209. if ((uint)vno >= Nirqs)
  210. vno = Nirqs-1;
  211. intrtimes[vno][diff]++;
  212. }
  213. static ulong
  214. intack(Intrcpuregs *icp)
  215. {
  216. return icp->ack & Intrmask;
  217. }
  218. static void
  219. intdismiss(Intrcpuregs *icp, ulong ack)
  220. {
  221. icp->end = ack;
  222. coherence();
  223. }
  224. static int
  225. irqinuse(uint irq)
  226. {
  227. Intrdistregs *idp = (Intrdistregs *)soc.intrdist;
  228. return idp->setena[irq / Bi2long] & (1 << (irq % Bi2long));
  229. }
  230. void
  231. intcunmask(uint irq)
  232. {
  233. Intrdistregs *idp = (Intrdistregs *)soc.intrdist;
  234. ilock(&distlock);
  235. idp->setena[irq / Bi2long] = 1 << (irq % Bi2long);
  236. iunlock(&distlock);
  237. }
  238. void
  239. intcmask(uint irq)
  240. {
  241. Intrdistregs *idp = (Intrdistregs *)soc.intrdist;
  242. ilock(&distlock);
  243. idp->clrena[irq / Bi2long] = 1 << (irq % Bi2long);
  244. iunlock(&distlock);
  245. }
  246. static void
  247. intcmaskall(Intrdistregs *idp) /* mask all intrs for all cpus */
  248. {
  249. int i;
  250. for (i = 0; i < nelem(idp->setena); i++)
  251. shadena[i] = idp->setena[i];
  252. for (i = 0; i < nelem(idp->clrena); i++)
  253. idp->clrena[i] = ~0;
  254. coherence();
  255. }
  256. static void
  257. intcunmaskall(Intrdistregs *idp) /* unused */
  258. {
  259. int i;
  260. for (i = 0; i < nelem(idp->setena); i++)
  261. idp->setena[i] = shadena[i];
  262. coherence();
  263. }
  264. static ulong
  265. permintrs(Intrdistregs *idp, int base, int r)
  266. {
  267. ulong perms;
  268. idp->clrena[r] = ~0; /* disable all */
  269. coherence();
  270. perms = idp->clrena[r];
  271. if (perms) {
  272. iprint("perm intrs:");
  273. printrs(base, perms);
  274. iprint("\n");
  275. }
  276. return perms;
  277. }
  278. static void
  279. intrcfg(Intrdistregs *idp)
  280. {
  281. int i, cpumask;
  282. ulong pat;
  283. /* set up all interrupts as level-sensitive, to one cpu (0) */
  284. pat = 0;
  285. for (i = 0; i < Bi2long; i += 2)
  286. pat |= (Level | To1) << i;
  287. if (m->machno == 0) { /* system-wide & cpu0 cfg */
  288. for (i = 0; i < nelem(idp->grp); i++)
  289. idp->grp[i] = 0; /* secure */
  290. for (i = 0; i < nelem(idp->pri); i++)
  291. idp->pri[i] = 0; /* highest priority */
  292. /* set up all interrupts as level-sensitive, to one cpu (0) */
  293. for (i = 0; i < nelem(idp->cfg); i++)
  294. idp->cfg[i] = pat;
  295. /* first Nppi are read-only for SGIs and PPIs */
  296. cpumask = 1<<0; /* just cpu 0 */
  297. navailcpus = getncpus();
  298. for (i = Nppi; i < sizeof idp->targ; i++)
  299. idp->targ[i] = cpumask;
  300. coherence();
  301. intcmaskall(idp);
  302. for (i = 0; i < nelem(idp->clrena); i++) {
  303. // permintrs(idp, i * Bi2long, i);
  304. idp->clrpend[i] = idp->clract[i] = idp->clrena[i] = ~0;
  305. }
  306. } else { /* per-cpu config */
  307. idp->grp[0] = 0; /* secure */
  308. for (i = 0; i < 8; i++)
  309. idp->pri[i] = 0; /* highest priority */
  310. /* idp->targ[0 through Nppi-1] are supposed to be read-only */
  311. for (i = 0; i < Nppi; i++)
  312. idp->targ[i] = 1<<m->machno;
  313. idp->cfg[1] = pat;
  314. coherence();
  315. // permintrs(idp, i * Bi2long, i);
  316. idp->clrpend[0] = idp->clract[0] = idp->clrena[0] = ~0;
  317. /* on cpu1, irq Extpmuirq (118) is always pending here */
  318. }
  319. coherence();
  320. }
  321. void
  322. intrto(int cpu, int irq)
  323. {
  324. Intrdistregs *idp = (Intrdistregs *)soc.intrdist;
  325. /* first Nppi are read-only for SGIs and the like */
  326. ilock(&distlock);
  327. idp->targ[irq] = 1 << cpu;
  328. iunlock(&distlock);
  329. }
  330. void
  331. intrsto(int cpu) /* unused */
  332. {
  333. int i;
  334. Intrdistregs *idp = (Intrdistregs *)soc.intrdist;
  335. /* first Nppi are read-only for SGIs and the like */
  336. for (i = Nppi; i < sizeof idp->targ; i++)
  337. intrto(cpu, i);
  338. USED(idp);
  339. }
  340. void
  341. intrcpu(int cpu)
  342. {
  343. Intrdistregs *idp = (Intrdistregs *)soc.intrdist;
  344. ilock(&distlock);
  345. idp->swgen = Totargets | 1 << (cpu + 16) | m->machno;
  346. iunlock(&distlock);
  347. }
  348. /*
  349. * set up for exceptions
  350. */
  351. void
  352. trapinit(void)
  353. {
  354. int s;
  355. Intrdistregs *idp = (Intrdistregs *)soc.intrdist;
  356. Intrcpuregs *icp = (Intrcpuregs *)soc.intr;
  357. Vpage0 *vpage0;
  358. enum { Vecsize = sizeof vpage0->vectors + sizeof vpage0->vtable, };
  359. /*
  360. * set up the exception vectors, high and low.
  361. *
  362. * we can't use cache ops on HVECTORS address, since they
  363. * work on virtual addresses, and only those that have a
  364. * physical address == PADDR(virtual).
  365. */
  366. if (m->machno == 0) {
  367. vpage0 = (Vpage0*)HVECTORS;
  368. memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
  369. memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
  370. vpage0 = (Vpage0*)KADDR(0);
  371. memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
  372. memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
  373. allcache->wbse(vpage0, Vecsize);
  374. cacheiinv();
  375. }
  376. /*
  377. * set up the stack pointers for the exception modes for this cpu.
  378. * they point to small `save areas' in Mach, not actual stacks.
  379. */
  380. s = splhi(); /* make these modes ignore intrs too */
  381. setr13(PsrMfiq, m->sfiq);
  382. setr13(PsrMirq, m->sirq);
  383. setr13(PsrMmon, m->smon);
  384. setr13(PsrMabt, m->sabt);
  385. setr13(PsrMund, m->sund);
  386. setr13(PsrMsys, m->ssys);
  387. splx(s);
  388. assert((idp->distid & MASK(12)) == 0x43b); /* made by arm */
  389. assert((icp->ifid & MASK(12)) == 0x43b); /* made by arm */
  390. ilock(&distlock);
  391. idp->ctl = 0;
  392. icp->ctl = 0;
  393. coherence();
  394. intrcfg(idp); /* some per-cpu cfg here */
  395. icp->ctl = Enable;
  396. icp->primask = (uchar)~0; /* let all priorities through */
  397. coherence();
  398. idp->ctl = Forw2cpuif;
  399. iunlock(&distlock);
  400. }
  401. void
  402. intrsoff(void)
  403. {
  404. ilock(&distlock);
  405. intcmaskall((Intrdistregs *)soc.intrdist);
  406. iunlock(&distlock);
  407. }
  408. void
  409. intrcpushutdown(void)
  410. {
  411. Intrcpuregs *icp = (Intrcpuregs *)soc.intr;
  412. icp->ctl = 0;
  413. icp->primask = 0; /* let no priorities through */
  414. coherence();
  415. }
  416. /* called from cpu0 after other cpus are shutdown */
  417. void
  418. intrshutdown(void)
  419. {
  420. Intrdistregs *idp = (Intrdistregs *)soc.intrdist;
  421. intrsoff();
  422. idp->ctl = 0;
  423. intrcpushutdown();
  424. }
  425. /*
  426. * enable an irq interrupt
  427. * note that the same private interrupt may be enabled on multiple cpus
  428. */
  429. int
  430. irqenable(uint irq, void (*f)(Ureg*, void*), void* a, char *name)
  431. {
  432. Vctl *v;
  433. if(irq >= nelem(vctl))
  434. panic("irqenable irq %d", irq);
  435. if (irqtooearly) {
  436. iprint("irqenable for %d %s called too early\n", irq, name);
  437. return -1;
  438. }
  439. /*
  440. * if in use, could be a private interrupt on a secondary cpu,
  441. * so don't add anything to the vector chain. irqs should
  442. * otherwise be one-to-one with devices.
  443. */
  444. if(!ISSGI(irq) && irqinuse(irq)) {
  445. lock(&vctllock);
  446. if (vctl[irq] == nil) {
  447. dumpintrpend();
  448. panic("non-sgi irq %d in use yet no Vctl allocated", irq);
  449. }
  450. unlock(&vctllock);
  451. }
  452. /* could be 1st use of this irq or could be an sgi (always in use) */
  453. else if (vctl[irq] == nil) {
  454. v = malloc(sizeof(Vctl));
  455. if (v == nil)
  456. panic("irqenable: malloc Vctl");
  457. v->f = f;
  458. v->a = a;
  459. v->name = malloc(strlen(name)+1);
  460. if (v->name == nil)
  461. panic("irqenable: malloc name");
  462. strcpy(v->name, name);
  463. lock(&vctllock);
  464. if (vctl[irq] != nil) {
  465. /* allocation race: someone else did it first */
  466. free(v->name);
  467. free(v);
  468. } else {
  469. v->next = vctl[irq];
  470. vctl[irq] = v;
  471. }
  472. unlock(&vctllock);
  473. }
  474. intcunmask(irq);
  475. return 0;
  476. }
  477. /*
  478. * disable an irq interrupt
  479. */
  480. int
  481. irqdisable(uint irq, void (*f)(Ureg*, void*), void* a, char *name)
  482. {
  483. Vctl **vp, *v;
  484. if(irq >= nelem(vctl))
  485. panic("irqdisable irq %d", irq);
  486. lock(&vctllock);
  487. for(vp = &vctl[irq]; v = *vp; vp = &v->next)
  488. if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
  489. print("irqdisable: remove %s\n", name);
  490. *vp = v->next;
  491. free(v->name);
  492. free(v);
  493. break;
  494. }
  495. if(v == nil)
  496. print("irqdisable: irq %d, name %s not enabled\n", irq, name);
  497. if(vctl[irq] == nil){
  498. print("irqdisable: clear icmr bit %d\n", irq);
  499. intcmask(irq);
  500. }
  501. unlock(&vctllock);
  502. return 0;
  503. }
  504. /*
  505. * called by trap to handle access faults
  506. */
  507. static void
  508. faultarm(Ureg *ureg, uintptr va, int user, int read)
  509. {
  510. int n, insyscall;
  511. if(up == nil) {
  512. dumpstackwithureg(ureg);
  513. panic("faultarm: cpu%d: nil up, %sing %#p at %#p",
  514. m->machno, (read? "read": "writ"), va, ureg->pc);
  515. }
  516. insyscall = up->insyscall;
  517. up->insyscall = 1;
  518. n = fault(va, read); /* goes spllo */
  519. splhi();
  520. if(n < 0){
  521. char buf[ERRMAX];
  522. if(!user){
  523. dumpstackwithureg(ureg);
  524. panic("fault: cpu%d: kernel %sing %#p at %#p",
  525. m->machno, read? "read": "writ", va, ureg->pc);
  526. }
  527. /* don't dump registers; programs suicide all the time */
  528. snprint(buf, sizeof buf, "sys: trap: fault %s va=%#p",
  529. read? "read": "write", va);
  530. postnote(up, 1, buf, NDebug);
  531. }
  532. up->insyscall = insyscall;
  533. }
  534. /*
  535. * called by trap to handle interrupts.
  536. * returns true iff a clock interrupt, thus maybe reschedule.
  537. */
  538. static int
  539. irq(Ureg* ureg)
  540. {
  541. int clockintr, ack;
  542. uint irqno, handled, t, ticks;
  543. Intrcpuregs *icp = (Intrcpuregs *)soc.intr;
  544. Vctl *v;
  545. ticks = perfticks();
  546. handled = 0;
  547. ack = intack(icp);
  548. irqno = ack & Intrmask;
  549. if (irqno >= nelem(vctl)) {
  550. iprint("trap: irq %d >= # vectors (%d)\n", irqno, nelem(vctl));
  551. intdismiss(icp, ack);
  552. return 0;
  553. }
  554. if (irqno == Loctmrirq) /* this is a clock intr? */
  555. m->inclockintr++; /* yes, count nesting */
  556. if(m->machno && m->inclockintr > 1) {
  557. iprint("cpu%d: nested clock intrs\n", m->machno);
  558. m->inclockintr--;
  559. intdismiss(icp, ack);
  560. return 0;
  561. }
  562. for(v = vctl[irqno]; v != nil; v = v->next)
  563. if (v->f) {
  564. if (islo())
  565. panic("trap: pl0 before trap handler for %s",
  566. v->name);
  567. v->f(ureg, v->a);
  568. if (islo())
  569. panic("trap: %s lowered pl", v->name);
  570. // splhi(); /* in case v->f lowered pl */
  571. handled++;
  572. }
  573. if(!handled)
  574. if (irqno >= 1022)
  575. iprint("cpu%d: ignoring spurious interrupt\n", m->machno);
  576. else {
  577. intcmask(irqno);
  578. iprint("cpu%d: unexpected interrupt %d, now masked\n",
  579. m->machno, irqno);
  580. }
  581. t = perfticks();
  582. if (0) { /* left over from another port? */
  583. ilock(&nintrlock);
  584. ninterrupt++;
  585. if(t < ticks)
  586. ninterruptticks += ticks-t;
  587. else
  588. ninterruptticks += t-ticks;
  589. iunlock(&nintrlock);
  590. }
  591. USED(t, ticks);
  592. clockintr = m->inclockintr == 1;
  593. if (irqno == Loctmrirq)
  594. m->inclockintr--;
  595. intdismiss(icp, ack);
  596. intrtime(m, irqno);
  597. return clockintr;
  598. }
  599. /*
  600. * returns 1 if the instruction writes memory, 0 otherwise
  601. */
  602. int
  603. writetomem(ulong inst)
  604. {
  605. /* swap always write memory */
  606. if((inst & 0x0FC00000) == 0x01000000)
  607. return 1;
  608. /* loads and stores are distinguished by bit 20 */
  609. if(inst & (1<<20))
  610. return 0;
  611. return 1;
  612. }
  613. static void
  614. datafault(Ureg *ureg, int user)
  615. {
  616. int x;
  617. ulong inst, fsr;
  618. uintptr va;
  619. va = farget();
  620. if (m->probing && !user) {
  621. if (m->trapped++ > 0) {
  622. dumpstackwithureg(ureg);
  623. panic("trap: recursive probe %#lux", va);
  624. }
  625. ureg->pc += 4; /* continue after faulting instr'n */
  626. return;
  627. }
  628. inst = *(ulong*)(ureg->pc);
  629. /* bits 12 and 10 have to be concatenated with status */
  630. x = fsrget();
  631. fsr = (x>>7) & 0x20 | (x>>6) & 0x10 | x & 0xf;
  632. switch(fsr){
  633. default:
  634. case 0xa: /* ? was under external abort */
  635. panic("unknown data fault, 6b fsr %#lux", fsr);
  636. break;
  637. case 0x0:
  638. panic("vector exception at %#lux", ureg->pc);
  639. break;
  640. case 0x1: /* alignment fault */
  641. case 0x3: /* access flag fault (section) */
  642. if(user){
  643. char buf[ERRMAX];
  644. snprint(buf, sizeof buf,
  645. "sys: alignment: pc %#lux va %#p\n",
  646. ureg->pc, va);
  647. postnote(up, 1, buf, NDebug);
  648. } else {
  649. dumpstackwithureg(ureg);
  650. panic("kernel alignment: pc %#lux va %#p", ureg->pc, va);
  651. }
  652. break;
  653. case 0x2:
  654. panic("terminal exception at %#lux", ureg->pc);
  655. break;
  656. case 0x4: /* icache maint fault */
  657. case 0x6: /* access flag fault (page) */
  658. case 0x8: /* precise external abort, non-xlat'n */
  659. case 0x28:
  660. case 0x16: /* imprecise ext. abort, non-xlt'n */
  661. case 0x36:
  662. panic("external non-translation abort %#lux pc %#lux addr %#p",
  663. fsr, ureg->pc, va);
  664. break;
  665. case 0xc: /* l1 translation, precise ext. abort */
  666. case 0x2c:
  667. case 0xe: /* l2 translation, precise ext. abort */
  668. case 0x2e:
  669. panic("external translation abort %#lux pc %#lux addr %#p",
  670. fsr, ureg->pc, va);
  671. break;
  672. case 0x1c: /* l1 translation, precise parity err */
  673. case 0x1e: /* l2 translation, precise parity err */
  674. case 0x18: /* imprecise parity or ecc err */
  675. panic("translation parity error %#lux pc %#lux addr %#p",
  676. fsr, ureg->pc, va);
  677. break;
  678. case 0x5: /* translation fault, no section entry */
  679. case 0x7: /* translation fault, no page entry */
  680. faultarm(ureg, va, user, !writetomem(inst));
  681. break;
  682. case 0x9:
  683. case 0xb:
  684. /* domain fault, accessing something we shouldn't */
  685. if(user){
  686. char buf[ERRMAX];
  687. snprint(buf, sizeof buf,
  688. "sys: access violation: pc %#lux va %#p\n",
  689. ureg->pc, va);
  690. postnote(up, 1, buf, NDebug);
  691. } else
  692. panic("kernel access violation: pc %#lux va %#p",
  693. ureg->pc, va);
  694. break;
  695. case 0xd:
  696. case 0xf:
  697. /* permission error, copy on write or real permission error */
  698. faultarm(ureg, va, user, !writetomem(inst));
  699. break;
  700. }
  701. }
  702. /*
  703. * here on all exceptions other than syscall (SWI) and reset
  704. */
  705. void
  706. trap(Ureg *ureg)
  707. {
  708. int clockintr, user, rem;
  709. uintptr va, ifar, ifsr;
  710. splhi(); /* paranoia */
  711. if(up != nil)
  712. rem = ((char*)ureg)-up->kstack;
  713. else
  714. rem = ((char*)ureg)-((char*)m+sizeof(Mach));
  715. if(rem < 1024) {
  716. iprint("trap: %d stack bytes left, up %#p ureg %#p m %#p cpu%d at pc %#lux\n",
  717. rem, up, ureg, m, m->machno, ureg->pc);
  718. dumpstackwithureg(ureg);
  719. panic("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux",
  720. rem, up, ureg, ureg->pc);
  721. }
  722. m->perf.intrts = perfticks();
  723. user = (ureg->psr & PsrMask) == PsrMusr;
  724. if(user){
  725. up->dbgreg = ureg;
  726. cycles(&up->kentry);
  727. }
  728. /*
  729. * All interrupts/exceptions should be resumed at ureg->pc-4,
  730. * except for Data Abort which resumes at ureg->pc-8.
  731. */
  732. if(ureg->type == (PsrMabt+1))
  733. ureg->pc -= 8;
  734. else
  735. ureg->pc -= 4;
  736. clockintr = 0; /* if set, may call sched() before return */
  737. switch(ureg->type){
  738. default:
  739. panic("unknown trap; type %#lux, psr mode %#lux", ureg->type,
  740. ureg->psr & PsrMask);
  741. break;
  742. case PsrMirq:
  743. m->intr++;
  744. clockintr = irq(ureg);
  745. if(0 && up && !clockintr)
  746. preempted(); /* this causes spurious suicides */
  747. break;
  748. case PsrMabt: /* prefetch (instruction) fault */
  749. va = ureg->pc;
  750. ifsr = cprdsc(0, CpFSR, 0, CpIFSR);
  751. ifsr = (ifsr>>7) & 0x8 | ifsr & 0x7;
  752. switch(ifsr){
  753. case 0x02: /* instruction debug event (BKPT) */
  754. if(user)
  755. postnote(up, 1, "sys: breakpoint", NDebug);
  756. else{
  757. iprint("kernel bkpt: pc %#lux inst %#ux\n",
  758. va, *(u32int*)va);
  759. panic("kernel bkpt");
  760. }
  761. break;
  762. default:
  763. ifar = cprdsc(0, CpFAR, 0, CpIFAR);
  764. if (va != ifar)
  765. iprint("trap: cpu%d: i-fault va %#p != ifar %#p\n",
  766. m->machno, va, ifar);
  767. faultarm(ureg, va, user, 1);
  768. break;
  769. }
  770. break;
  771. case PsrMabt+1: /* data fault */
  772. datafault(ureg, user);
  773. break;
  774. case PsrMund: /* undefined instruction */
  775. if(!user) {
  776. if (ureg->pc & 3) {
  777. iprint("rounding fault pc %#lux down to word\n",
  778. ureg->pc);
  779. ureg->pc &= ~3;
  780. }
  781. if (Debug)
  782. iprint("mathemu: cpu%d fpon %d instr %#8.8lux at %#p\n",
  783. m->machno, m->fpon, *(ulong *)ureg->pc,
  784. ureg->pc);
  785. dumpstackwithureg(ureg);
  786. panic("cpu%d: undefined instruction: pc %#lux inst %#ux",
  787. m->machno, ureg->pc, ((u32int*)ureg->pc)[0]);
  788. } else if(seg(up, ureg->pc, 0) != nil &&
  789. *(u32int*)ureg->pc == 0xD1200070)
  790. postnote(up, 1, "sys: breakpoint", NDebug);
  791. else if(fpuemu(ureg) == 0){ /* didn't find any FP instrs? */
  792. char buf[ERRMAX];
  793. snprint(buf, sizeof buf,
  794. "undefined instruction: pc %#lux instr %#8.8lux\n",
  795. ureg->pc, *(ulong *)ureg->pc);
  796. postnote(up, 1, buf, NDebug);
  797. }
  798. break;
  799. }
  800. splhi();
  801. /* delaysched set because we held a lock or because our quantum ended */
  802. if(up && up->delaysched && clockintr){
  803. sched(); /* can cause more traps */
  804. splhi();
  805. }
  806. if(user){
  807. if(up->procctl || up->nnote)
  808. notify(ureg);
  809. kexit(ureg);
  810. }
  811. }
  812. /*
  813. * Fill in enough of Ureg to get a stack trace, and call a function.
  814. * Used by debugging interface rdb.
  815. */
  816. void
  817. callwithureg(void (*fn)(Ureg*))
  818. {
  819. Ureg ureg;
  820. memset(&ureg, 0, sizeof ureg);
  821. ureg.pc = getcallerpc(&fn);
  822. ureg.sp = PTR2UINT(&fn);
  823. fn(&ureg);
  824. }
  825. static void
  826. dumpstackwithureg(Ureg *ureg)
  827. {
  828. int x;
  829. uintptr l, v, i, estack;
  830. char *s;
  831. dumpregs(ureg);
  832. if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
  833. iprint("dumpstack disabled\n");
  834. return;
  835. }
  836. delay(1000);
  837. iprint("dumpstack\n");
  838. x = 0;
  839. x += iprint("ktrace /kernel/path %#.8lux %#.8lux %#.8lux # pc, sp, link\n",
  840. ureg->pc, ureg->sp, ureg->r14);
  841. delay(20);
  842. i = 0;
  843. if(up
  844. && (uintptr)&l >= (uintptr)up->kstack
  845. && (uintptr)&l <= (uintptr)up->kstack+KSTACK)
  846. estack = (uintptr)up->kstack+KSTACK;
  847. else if((uintptr)&l >= (uintptr)m->stack
  848. && (uintptr)&l <= (uintptr)m+MACHSIZE)
  849. estack = (uintptr)m+MACHSIZE;
  850. else
  851. return;
  852. x += iprint("estackx %p\n", estack);
  853. for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
  854. v = *(uintptr*)l;
  855. if((KTZERO < v && v < (uintptr)etext) || estack-l < 32){
  856. x += iprint("%.8p ", v);
  857. delay(20);
  858. i++;
  859. }
  860. if(i == 8){
  861. i = 0;
  862. x += iprint("\n");
  863. delay(20);
  864. }
  865. }
  866. if(i)
  867. iprint("\n");
  868. delay(3000);
  869. }
  870. void
  871. dumpstack(void)
  872. {
  873. callwithureg(dumpstackwithureg);
  874. }
  875. /*
  876. * dump system control coprocessor registers
  877. */
  878. static void
  879. dumpscr(void)
  880. {
  881. iprint("0:\t%#8.8ux id\n", cpidget());
  882. iprint("\t%8.8#ux ct\n", cpctget());
  883. iprint("1:\t%#8.8ux control\n", controlget());
  884. iprint("2:\t%#8.8ux ttb\n", ttbget());
  885. iprint("3:\t%#8.8ux dac\n", dacget());
  886. iprint("4:\t(reserved)\n");
  887. iprint("5:\t%#8.8ux fsr\n", fsrget());
  888. iprint("6:\t%#8.8ux far\n", farget());
  889. iprint("7:\twrite-only cache\n");
  890. iprint("8:\twrite-only tlb\n");
  891. iprint("13:\t%#8.8ux pid\n", pidget());
  892. delay(10);
  893. }
  894. /*
  895. * dump general registers
  896. */
  897. static void
  898. dumpgpr(Ureg* ureg)
  899. {
  900. if(up != nil)
  901. iprint("cpu%d: registers for %s %lud\n",
  902. m->machno, up->text, up->pid);
  903. else
  904. iprint("cpu%d: registers for kernel\n", m->machno);
  905. delay(20);
  906. iprint("%#8.8lux\tr0\n", ureg->r0);
  907. iprint("%#8.8lux\tr1\n", ureg->r1);
  908. iprint("%#8.8lux\tr2\n", ureg->r2);
  909. delay(20);
  910. iprint("%#8.8lux\tr3\n", ureg->r3);
  911. iprint("%#8.8lux\tr4\n", ureg->r4);
  912. iprint("%#8.8lux\tr5\n", ureg->r5);
  913. delay(20);
  914. iprint("%#8.8lux\tr6\n", ureg->r6);
  915. iprint("%#8.8lux\tr7\n", ureg->r7);
  916. iprint("%#8.8lux\tr8\n", ureg->r8);
  917. delay(20);
  918. iprint("%#8.8lux\tr9 (up)\n", ureg->r9);
  919. iprint("%#8.8lux\tr10 (m)\n", ureg->r10);
  920. iprint("%#8.8lux\tr11 (loader temporary)\n", ureg->r11);
  921. iprint("%#8.8lux\tr12 (SB)\n", ureg->r12);
  922. delay(20);
  923. iprint("%#8.8lux\tr13 (sp)\n", ureg->r13);
  924. iprint("%#8.8lux\tr14 (link)\n", ureg->r14);
  925. iprint("%#8.8lux\tr15 (pc)\n", ureg->pc);
  926. delay(20);
  927. iprint("%10.10lud\ttype\n", ureg->type);
  928. iprint("%#8.8lux\tpsr\n", ureg->psr);
  929. delay(500);
  930. }
  931. void
  932. dumpregs(Ureg* ureg)
  933. {
  934. dumpgpr(ureg);
  935. dumpscr();
  936. }
  937. vlong
  938. probeaddr(uintptr addr)
  939. {
  940. vlong v;
  941. ilock(&m->probelock);
  942. m->trapped = 0;
  943. m->probing = 1;
  944. coherence();
  945. v = *(ulong *)addr; /* this may cause a fault */
  946. coherence();
  947. m->probing = 0;
  948. if (m->trapped)
  949. v = -1;
  950. iunlock(&m->probelock);
  951. return v;
  952. }