trap.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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. /*
  149. * pass #2 8259 interrupts to #1
  150. */
  151. int0mask &= ~0x04;
  152. outb(Int0aux, int0mask);
  153. /*
  154. * Set Ocw3 to return the ISR when ctl read.
  155. */
  156. outb(Int0ctl, Ocw3|0x03);
  157. outb(Int1ctl, Ocw3|0x03);
  158. /*
  159. * Check for Edge/Level register.
  160. * This check may not work for all chipsets.
  161. */
  162. elcr1 = inb(Elcr1);
  163. outb(Elcr1, 0);
  164. if(inb(Elcr1) == 0){
  165. outb(Elcr1, 0x20);
  166. if(inb(Elcr1) == 0x20)
  167. elcr = (inb(Elcr2)<<8)|elcr1;
  168. }
  169. outb(Elcr1, elcr1);
  170. fpinit();
  171. }
  172. static int
  173. i8259isr(int v)
  174. {
  175. int isr;
  176. /*
  177. * tell the 8259 that we're done with the
  178. * highest level interrupt (interrupts are still
  179. * off at this point)
  180. */
  181. isr = 0;
  182. if(v >= Int0vec && v < Int0vec+16){
  183. isr = inb(Int0ctl);
  184. outb(Int0ctl, EOI);
  185. if(v >= Int0vec+8){
  186. isr |= inb(Int1ctl)<<8;
  187. outb(Int1ctl, EOI);
  188. }
  189. }
  190. return isr & (1<<(v-Int0vec));
  191. }
  192. char *excname[] = {
  193. [0] "divide error",
  194. [1] "debug exception",
  195. [2] " nonmaskable interrupt",
  196. [3] "breakpoint",
  197. [4] "overflow",
  198. [5] "bounds check",
  199. [6] "invalid opcode",
  200. [7] "coprocessor not available",
  201. [8] "double fault",
  202. [9] "9 (reserved)",
  203. [10] "invalid TSS",
  204. [11] "segment not present",
  205. [12] "stack exception",
  206. [13] "general protection violation",
  207. [14] "page fault",
  208. [15] "15 (reserved)",
  209. [16] "coprocessor error",
  210. [17] "alignment check",
  211. [18] "machine check",
  212. };
  213. Ureg lasttrap, *lastur;
  214. static int nspuriousintr;
  215. static int lastintr;
  216. /*
  217. * All traps
  218. */
  219. void
  220. trap(Ureg *ur)
  221. {
  222. int v;
  223. Handler *h;
  224. v = ur->trap;
  225. if(h = halloc.ivec[v]){
  226. if((v >= Int0vec && v < Int0vec+16) && !(elcr & (1<<(v-Int0vec)))){
  227. i8259isr(v);
  228. lastintr = v-Int0vec;
  229. }
  230. MACHP(0)->intrp = 0;
  231. /* there may be multiple handlers on one interrupt level */
  232. do {
  233. if (h->r == 0)
  234. panic("trap: nil h->r");
  235. (*h->r)(ur, h->arg);
  236. h = h->next;
  237. } while(h);
  238. if((v >= Int0vec && v < Int0vec+16) && (elcr & (1<<(v-Int0vec)))){
  239. i8259isr(v);
  240. lastintr = v-Int0vec;
  241. }
  242. }
  243. else if(v >= Int0vec && v < Int0vec+16){
  244. /*
  245. * An unknown interrupt.
  246. * Check for a default IRQ7. This can happen when
  247. * the IRQ input goes away before the acknowledge.
  248. * In this case, a 'default IRQ7' is generated, but
  249. * the corresponding bit in the ISR isn't set.
  250. * In fact, just ignore all such interrupts.
  251. if(nspuriousintr < 2)
  252. */
  253. print("spurious interrupt %d, lastintr %d\n", v-Int0vec, lastintr);
  254. nspuriousintr++;
  255. return;
  256. }
  257. else{
  258. dumpregs(ur);
  259. if(v < (sizeof(excname)/sizeof(excname[0])))
  260. panic("%s", excname[v]);
  261. panic("unknown trap/intr: %d\n", v);
  262. }
  263. splhi();
  264. if(u && u->state == Running)
  265. sched();
  266. lasttrap = *ur;
  267. lastur = ur;
  268. }
  269. /*
  270. * dump registers
  271. */
  272. void
  273. dumpregs2(Ureg *ur)
  274. {
  275. print("FLAGS=%lux TRAP=%lux ECODE=%lux CS=%lux PC=%lux\n", ur->flags, ur->trap,
  276. ur->ecode, ur->cs&0xff, ur->pc);
  277. print(" AX %8.8lux BX %8.8lux CX %8.8lux DX %8.8lux\n",
  278. ur->ax, ur->bx, ur->cx, ur->dx);
  279. print(" SI %8.8lux DI %8.8lux BP %8.8lux\n",
  280. ur->si, ur->di, ur->bp);
  281. print(" DS %4.4lux ES %4.4lux FS %4.4lux GS %4.4lux\n",
  282. ur->ds&0xffff, ur->es&0xffff, ur->fs&0xffff, ur->gs&0xffff);
  283. print(" CR0 %8.8lux CR2 %8.8lux\n", getcr0(), getcr2());
  284. }
  285. void
  286. dumpregs(Ureg *ur)
  287. {
  288. dumpregs2(ur);
  289. print(" ur %lux\n", (ulong)ur);
  290. dumpregs2(&lasttrap);
  291. print(" lastur %lux\n", (ulong)lastur);
  292. }
  293. void
  294. dumpstack(User *p)
  295. {
  296. ulong i, l, v, hl;
  297. extern ulong etext;
  298. if(p == 0)
  299. return;
  300. hl = 0;
  301. print("stack trace of %d\n", p->pid);
  302. i = 0;
  303. for(l = (ulong)(p->stack+MAXSTACK)-4; l >= (ulong)(p->stack); l -= 4){
  304. v = *(ulong*)l;
  305. if(v)
  306. hl = l;
  307. if(KTZERO < v && v < (ulong)&etext){
  308. print("0x%8.8lux ", v);
  309. i++;
  310. }
  311. if(i == 8){
  312. i = 0;
  313. print("\n");
  314. }
  315. }
  316. if(hl)
  317. print("%ld stack used out of %d\n",
  318. (ulong)(p->stack+MAXSTACK)-hl, MAXSTACK);
  319. print("\n");
  320. }