trap.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. #include "all.h"
  2. #include "mem.h"
  3. #include "ureg.h"
  4. #include "io.h"
  5. void intr0(void), intr1(void), intr2(void), intr3(void);
  6. void intr4(void), intr5(void), intr6(void), intr7(void);
  7. void intr8(void), intr9(void), intr10(void), intr11(void);
  8. void intr12(void), intr13(void), intr14(void), intr15(void);
  9. void intr16(void);
  10. void intr24(void), intr25(void), intr26(void), intr27(void);
  11. void intr28(void), intr29(void), intr30(void), intr31(void);
  12. void intr32(void), intr33(void), intr34(void), intr35(void);
  13. void intr36(void), intr37(void), intr38(void), intr39(void);
  14. void intr64(void);
  15. void intrbad(void);
  16. int int0mask = 0xff; /* interrupts enabled for first 8259 */
  17. int int1mask = 0xff; /* interrupts enabled for second 8259 */
  18. int elcr; /* mask of level-triggered interrupts */
  19. /*
  20. * trap/interrupt gates
  21. */
  22. Segdesc ilt[256];
  23. int badintr[16];
  24. enum
  25. {
  26. Maxhandler= 128, /* max number of interrupt handlers */
  27. };
  28. typedef struct Handler Handler;
  29. struct Handler
  30. {
  31. void (*r)(Ureg*, void*);
  32. void *arg;
  33. Handler *next;
  34. };
  35. struct
  36. {
  37. Lock;
  38. Handler *ivec[256];
  39. Handler h[Maxhandler];
  40. int free;
  41. } halloc;
  42. void
  43. sethvec(int v, void (*r)(void), int type, int pri)
  44. {
  45. ilt[v].d0 = ((ulong)r)&0xFFFF|(KESEL<<16);
  46. ilt[v].d1 = ((ulong)r)&0xFFFF0000|SEGP|SEGPL(pri)|type;
  47. }
  48. void
  49. setvec(int v, void (*r)(Ureg*, void*), void *arg)
  50. {
  51. Handler *h;
  52. lock(&halloc);
  53. if(halloc.free >= Maxhandler)
  54. panic("out of interrupt handlers");
  55. h = &halloc.h[halloc.free++];
  56. h->next = halloc.ivec[v];
  57. h->r = r;
  58. h->arg = arg;
  59. halloc.ivec[v] = h;
  60. unlock(&halloc);
  61. /*
  62. * enable corresponding interrupt in 8259
  63. */
  64. if((v&~0x7) == Int0vec){
  65. int0mask &= ~(1<<(v&7));
  66. outb(Int0aux, int0mask);
  67. } else if((v&~0x7) == Int1vec){
  68. int1mask &= ~(1<<(v&7));
  69. outb(Int1aux, int1mask);
  70. }
  71. }
  72. /*
  73. * set up the interrupt/trap gates
  74. */
  75. void
  76. trapinit(void)
  77. {
  78. int elcr1, i;
  79. /*
  80. * set all interrupts to panics
  81. */
  82. for(i = 0; i < 256; i++)
  83. sethvec(i, intrbad, SEGTG, 0);
  84. /*
  85. * 80386 processor (and coprocessor) traps
  86. */
  87. sethvec(0, intr0, SEGTG, 0);
  88. sethvec(1, intr1, SEGTG, 0);
  89. sethvec(2, intr2, SEGTG, 0);
  90. sethvec(4, intr4, SEGTG, 0);
  91. sethvec(5, intr5, SEGTG, 0);
  92. sethvec(6, intr6, SEGTG, 0);
  93. sethvec(7, intr7, SEGTG, 0);
  94. sethvec(8, intr8, SEGTG, 0);
  95. sethvec(9, intr9, SEGTG, 0);
  96. sethvec(10, intr10, SEGTG, 0);
  97. sethvec(11, intr11, SEGTG, 0);
  98. sethvec(12, intr12, SEGTG, 0);
  99. sethvec(13, intr13, SEGTG, 0);
  100. sethvec(14, intr14, SEGIG, 0); /* page fault, interrupts off */
  101. sethvec(15, intr15, SEGTG, 0);
  102. sethvec(16, intr16, SEGIG, 0); /* math coprocessor, interrupts off */
  103. /*
  104. * device interrupts
  105. */
  106. sethvec(24, intr24, SEGIG, 0);
  107. sethvec(25, intr25, SEGIG, 0);
  108. sethvec(26, intr26, SEGIG, 0);
  109. sethvec(27, intr27, SEGIG, 0);
  110. sethvec(28, intr28, SEGIG, 0);
  111. sethvec(29, intr29, SEGIG, 0);
  112. sethvec(30, intr30, SEGIG, 0);
  113. sethvec(31, intr31, SEGIG, 0);
  114. sethvec(32, intr32, SEGIG, 0);
  115. sethvec(33, intr33, SEGIG, 0);
  116. sethvec(34, intr34, SEGIG, 0);
  117. sethvec(35, intr35, SEGIG, 0);
  118. sethvec(36, intr36, SEGIG, 0);
  119. sethvec(37, intr37, SEGIG, 0);
  120. sethvec(38, intr38, SEGIG, 0);
  121. sethvec(39, intr39, SEGIG, 0);
  122. /*
  123. * tell the hardware where the table is (and how long)
  124. */
  125. putidt(ilt, sizeof(ilt));
  126. /*
  127. * Set up the first 8259 interrupt processor.
  128. * Make 8259 interrupts start at CPU vector Int0vec.
  129. * Set the 8259 as master with edge triggered
  130. * input with fully nested interrupts.
  131. */
  132. outb(Int0ctl, 0x11); /* ICW1 - edge triggered, master,
  133. ICW4 will be sent */
  134. outb(Int0aux, Int0vec); /* ICW2 - interrupt vector offset */
  135. outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */
  136. outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */
  137. /*
  138. * Set up the second 8259 interrupt processor.
  139. * Make 8259 interrupts start at CPU vector Int0vec.
  140. * Set the 8259 as master with edge triggered
  141. * input with fully nested interrupts.
  142. */
  143. outb(Int1ctl, 0x11); /* ICW1 - edge triggered, master,
  144. ICW4 will be sent */
  145. outb(Int1aux, Int1vec); /* ICW2 - interrupt vector offset */
  146. outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */
  147. outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */
  148. outb(Int1aux, 0xFF);
  149. /*
  150. * pass #2 8259 interrupts to #1
  151. */
  152. int0mask &= ~0x04;
  153. outb(Int0aux, int0mask);
  154. /*
  155. * Set Ocw3 to return the ISR when ctl read.
  156. */
  157. inb(Int0ctl);
  158. outb(Int0ctl, Ocw3|0x03);
  159. inb(Int1ctl);
  160. outb(Int1ctl, Ocw3|0x03);
  161. /*
  162. * Check for Edge/Level register.
  163. * This check may not work for all chipsets.
  164. */
  165. elcr1 = inb(Elcr1);
  166. outb(Elcr1, 0);
  167. if(inb(Elcr1) == 0){
  168. outb(Elcr1, 0x20);
  169. if(inb(Elcr1) == 0x20)
  170. elcr = (inb(Elcr2)<<8)|elcr1;
  171. }
  172. outb(Elcr1, elcr1);
  173. fpinit();
  174. }
  175. static int
  176. i8259isr(int v)
  177. {
  178. int isr;
  179. /*
  180. * tell the 8259 that we're done with the
  181. * highest level interrupt (interrupts are still
  182. * off at this point)
  183. */
  184. isr = 0;
  185. if(v >= Int0vec && v < Int0vec+16){
  186. isr = inb(Int0ctl);
  187. outb(Int0ctl, EOI);
  188. if(v >= Int0vec+8){
  189. isr |= inb(Int1ctl)<<8;
  190. outb(Int1ctl, EOI);
  191. }
  192. }
  193. return isr & (1<<(v-Int0vec));
  194. }
  195. char *excname[] = {
  196. [0] "divide error",
  197. [1] "debug exception",
  198. [2] " nonmaskable interrupt",
  199. [3] "breakpoint",
  200. [4] "overflow",
  201. [5] "bounds check",
  202. [6] "invalid opcode",
  203. [7] "coprocessor not available",
  204. [8] "double fault",
  205. [9] "9 (reserved)",
  206. [10] "invalid TSS",
  207. [11] "segment not present",
  208. [12] "stack exception",
  209. [13] "general protection violation",
  210. [14] "page fault",
  211. [15] "15 (reserved)",
  212. [16] "coprocessor error",
  213. [17] "alignment check",
  214. [18] "machine check",
  215. };
  216. Ureg lasttrap, *lastur;
  217. static int nspuriousintr;
  218. static int lastintr;
  219. /*
  220. * All traps
  221. */
  222. void
  223. trap(Ureg *ur)
  224. {
  225. int v;
  226. Handler *h;
  227. v = ur->trap;
  228. if(h = halloc.ivec[v]){
  229. if((v >= Int0vec && v < Int0vec+16) && !(elcr & (1<<(v-Int0vec)))){
  230. i8259isr(v);
  231. lastintr = v-Int0vec;
  232. }
  233. MACHP(0)->intrp = 0;
  234. /* there may be multiple handlers on one interrupt level */
  235. do {
  236. if (h->r == 0)
  237. panic("trap: nil h->r");
  238. (*h->r)(ur, h->arg);
  239. h = h->next;
  240. } while(h);
  241. if((v >= Int0vec && v < Int0vec+16) && (elcr & (1<<(v-Int0vec)))){
  242. i8259isr(v);
  243. lastintr = v-Int0vec;
  244. }
  245. }
  246. else if(v >= Int0vec && v < Int0vec+16){
  247. /*
  248. * An unknown interrupt.
  249. * Check for a default IRQ7. This can happen when
  250. * the IRQ input goes away before the acknowledge.
  251. * In this case, a 'default IRQ7' is generated, but
  252. * the corresponding bit in the ISR isn't set.
  253. * In fact, just ignore all such interrupts.
  254. */
  255. if(nspuriousintr < 2)
  256. print("spurious interrupt %d, lastintr %d\n", v-Int0vec, lastintr);
  257. nspuriousintr++;
  258. return;
  259. }
  260. else{
  261. dumpregs(ur);
  262. if(v < (sizeof(excname)/sizeof(excname[0])))
  263. panic("%s", excname[v]);
  264. panic("unknown trap/intr: %d\n", v);
  265. }
  266. splhi();
  267. if(u && u->state == Running)
  268. sched();
  269. lasttrap = *ur;
  270. lastur = ur;
  271. }
  272. /*
  273. * dump registers
  274. */
  275. void
  276. dumpregs2(Ureg *ur)
  277. {
  278. print("FLAGS=%lux TRAP=%lux ECODE=%lux CS=%lux PC=%lux\n", ur->flags, ur->trap,
  279. ur->ecode, ur->cs&0xff, ur->pc);
  280. print(" AX %8.8lux BX %8.8lux CX %8.8lux DX %8.8lux\n",
  281. ur->ax, ur->bx, ur->cx, ur->dx);
  282. print(" SI %8.8lux DI %8.8lux BP %8.8lux\n",
  283. ur->si, ur->di, ur->bp);
  284. print(" DS %4.4lux ES %4.4lux FS %4.4lux GS %4.4lux\n",
  285. ur->ds&0xffff, ur->es&0xffff, ur->fs&0xffff, ur->gs&0xffff);
  286. print(" CR0 %8.8lux CR2 %8.8lux\n", getcr0(), getcr2());
  287. }
  288. void
  289. dumpregs(Ureg *ur)
  290. {
  291. dumpregs2(ur);
  292. print(" ur %lux\n", (ulong)ur);
  293. dumpregs2(&lasttrap);
  294. print(" lastur %lux\n", (ulong)lastur);
  295. }
  296. void
  297. dumpstack(User *p)
  298. {
  299. ulong i, l, v, hl;
  300. extern ulong etext;
  301. if(p == 0)
  302. return;
  303. hl = 0;
  304. print("stack trace of %d\n", p->pid);
  305. i = 0;
  306. for(l = (ulong)(p->stack+MAXSTACK)-4; l >= (ulong)(p->stack); l -= 4){
  307. v = *(ulong*)l;
  308. if(v)
  309. hl = l;
  310. if(KTZERO < v && v < (ulong)&etext){
  311. print("0x%8.8lux ", v);
  312. i++;
  313. }
  314. if(i == 8){
  315. i = 0;
  316. print("\n");
  317. }
  318. }
  319. if(hl)
  320. print("%ld stack used out of %d\n",
  321. (ulong)(p->stack+MAXSTACK)-hl, MAXSTACK);
  322. print("\n");
  323. }