#include "all.h"#include "mem.h"#include "ureg.h"#include "io.h" void intr0(void), intr1(void), intr2(void), intr3(void);void intr4(void), intr5(void), intr6(void), intr7(void);void intr8(void), intr9(void), intr10(void), intr11(void);void intr12(void), intr13(void), intr14(void), intr15(void);void intr16(void);void intr24(void), intr25(void), intr26(void), intr27(void);void intr28(void), intr29(void), intr30(void), intr31(void);void intr32(void), intr33(void), intr34(void), intr35(void);void intr36(void), intr37(void), intr38(void), intr39(void);void intr64(void);void intrbad(void); int int0mask = 0xff; /* interrupts enabled for first 8259 */int int1mask = 0xff; /* interrupts enabled for second 8259 */ int elcr; /* mask of level-triggered interrupts */ /* * trap/interrupt gates */Segdesc ilt[256];int badintr[16]; enum { Maxhandler= 128, /* max number of interrupt handlers */}; typedef struct Handler Handler;struct Handler{ void (*r)(Ureg*, void*); void *arg; Handler *next;}; struct{ Lock; Handler *ivec[256]; Handler h[Maxhandler]; int free;} halloc; voidsethvec(int v, void (*r)(void), int type, int pri){ ilt[v].d0 = ((ulong)r)&0xFFFF|(KESEL<<16); ilt[v].d1 = ((ulong)r)&0xFFFF0000|SEGP|SEGPL(pri)|type;} voidsetvec(int v, void (*r)(Ureg*, void*), void *arg){ Handler *h; lock(&halloc); if(halloc.free >= Maxhandler) panic("out of interrupt handlers"); h = &halloc.h[halloc.free++]; h->next = halloc.ivec[v]; h->r = r; h->arg = arg; halloc.ivec[v] = h; unlock(&halloc); /* * enable corresponding interrupt in 8259 */ if((v&~0x7) == Int0vec){ int0mask &= ~(1<<(v&7)); outb(Int0aux, int0mask); } else if((v&~0x7) == Int1vec){ int1mask &= ~(1<<(v&7)); outb(Int1aux, int1mask); }} /* * set up the interrupt/trap gates */voidtrapinit(void){ int elcr1, i; /* * set all interrupts to panics */ for(i = 0; i < 256; i++) sethvec(i, intrbad, SEGTG, 0); /* * 80386 processor (and coprocessor) traps */ sethvec(0, intr0, SEGTG, 0); sethvec(1, intr1, SEGTG, 0); sethvec(2, intr2, SEGTG, 0); sethvec(4, intr4, SEGTG, 0); sethvec(5, intr5, SEGTG, 0); sethvec(6, intr6, SEGTG, 0); sethvec(7, intr7, SEGTG, 0); sethvec(8, intr8, SEGTG, 0); sethvec(9, intr9, SEGTG, 0); sethvec(10, intr10, SEGTG, 0); sethvec(11, intr11, SEGTG, 0); sethvec(12, intr12, SEGTG, 0); sethvec(13, intr13, SEGTG, 0); sethvec(14, intr14, SEGIG, 0); /* page fault, interrupts off */ sethvec(15, intr15, SEGTG, 0); sethvec(16, intr16, SEGIG, 0); /* math coprocessor, interrupts off */ /* * device interrupts */ sethvec(24, intr24, SEGIG, 0); sethvec(25, intr25, SEGIG, 0); sethvec(26, intr26, SEGIG, 0); sethvec(27, intr27, SEGIG, 0); sethvec(28, intr28, SEGIG, 0); sethvec(29, intr29, SEGIG, 0); sethvec(30, intr30, SEGIG, 0); sethvec(31, intr31, SEGIG, 0); sethvec(32, intr32, SEGIG, 0); sethvec(33, intr33, SEGIG, 0); sethvec(34, intr34, SEGIG, 0); sethvec(35, intr35, SEGIG, 0); sethvec(36, intr36, SEGIG, 0); sethvec(37, intr37, SEGIG, 0); sethvec(38, intr38, SEGIG, 0); sethvec(39, intr39, SEGIG, 0); /* * tell the hardware where the table is (and how long) */ putidt(ilt, sizeof(ilt)); /* * Set up the first 8259 interrupt processor. * Make 8259 interrupts start at CPU vector Int0vec. * Set the 8259 as master with edge triggered * input with fully nested interrupts. */ outb(Int0ctl, 0x11); /* ICW1 - edge triggered, master, ICW4 will be sent */ outb(Int0aux, Int0vec); /* ICW2 - interrupt vector offset */ outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */ outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */ /* * Set up the second 8259 interrupt processor. * Make 8259 interrupts start at CPU vector Int0vec. * Set the 8259 as master with edge triggered * input with fully nested interrupts. */ outb(Int1ctl, 0x11); /* ICW1 - edge triggered, master, ICW4 will be sent */ outb(Int1aux, Int1vec); /* ICW2 - interrupt vector offset */ outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */ outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */ outb(Int1aux, 0xFF); /* * pass #2 8259 interrupts to #1 */ int0mask &= ~0x04; outb(Int0aux, int0mask); /* * Set Ocw3 to return the ISR when ctl read. */ inb(Int0ctl); outb(Int0ctl, Ocw3|0x03); inb(Int1ctl); outb(Int1ctl, Ocw3|0x03); /* * Check for Edge/Level register. * This check may not work for all chipsets. */ elcr1 = inb(Elcr1); outb(Elcr1, 0); if(inb(Elcr1) == 0){ outb(Elcr1, 0x20); if(inb(Elcr1) == 0x20) elcr = inb(Elcr2)<<8|elcr1; } outb(Elcr1, elcr1); fpinit();} static inti8259isr(int v){ int isr; /* * tell the 8259 that we're done with the * highest level interrupt (interrupts are still * off at this point) */ isr = 0; if(v >= Int0vec && v < Int0vec+16){ isr = inb(Int0ctl); outb(Int0ctl, EOI); if(v >= Int0vec+8){ isr |= inb(Int1ctl)<<8; outb(Int1ctl, EOI); } } return isr & (1<<(v-Int0vec));} char *excname[] = { [0] "divide error", [1] "debug exception", [2] " nonmaskable interrupt", [3] "breakpoint", [4] "overflow", [5] "bounds check", [6] "invalid opcode", [7] "coprocessor not available", [8] "double fault", [9] "9 (reserved)", [10] "invalid TSS", [11] "segment not present", [12] "stack exception", [13] "general protection violation", [14] "page fault", [15] "15 (reserved)", [16] "coprocessor error", [17] "alignment check", [18] "machine check",}; Ureg lasttrap, *lastur;static long nspuriousintr;static int lastintr;static uvlong nintr;static uvlong intrtab[256];static int schedticks; /* * All traps */voidtrap(Ureg *ur){ int v; Handler *h; nintr++; v = ur->trap; intrtab[v]++; if(h = halloc.ivec[v]){ if((v >= Int0vec && v < Int0vec+16) && !(elcr & (1<<(v-Int0vec)))){ i8259isr(v); lastintr = v-Int0vec; } MACHP(0)->intrp = 0; /* there may be multiple handlers on one interrupt level */ for(; h; h = h->next){ if (h->r == 0) panic("trap: nil h->r"); h->r(ur, h->arg); } if((v >= Int0vec && v < Int0vec+16) && (elcr & (1<<(v-Int0vec)))){ i8259isr(v); lastintr = v-Int0vec; } } else if(v >= Int0vec && v < Int0vec+16){ /* * An unknown interrupt. * Check for a default IRQ7. This can happen when * the IRQ input goes away before the acknowledge. * In this case, a 'default IRQ7' is generated, but * the corresponding bit in the ISR isn't set. * In fact, just ignore all such interrupts. */ if(nspuriousintr < 2) print("spurious interrupt %d, lastintr %d\n", v-Int0vec, lastintr); nspuriousintr++; return; } else{ dumpregs(ur); if(v < nelem(excname)) panic("%s", excname[v]); panic("unknown trap/intr: %d\n", v); } if(v != Clockvec){ lasttrap = *ur; lastur = ur; // if(u && u->state == Running && runqtail() != tail) // goto preempt; return; } /* * even at HZ = 1000, this doesn't help (try again later after fixing lock?) */ if(schedticks++ < MS2TK(1) || u == 0 || u->state != Running) return;//preempt: if(u->nlock && u->delaysched < MS2TK(500)){ u->delaysched++; return; } if(u->delaysched > MS2TK(3)){ print("%d: delay %ld nl %ld\n", u->pid, u->delaysched, u->nlock); printlocks(u); } schedticks = 0; u->delaysched = 0; splhi(); sched();} voidtrapstats(void){ int i, j; print("spurious %ld\n", nspuriousintr); print("total %ulld\n", nintr); j = 0; for(i = 0; i < 256; i++) if(intrtab[i] > 0){ print("%3d %.11ulld ", i, intrtab[i]); if((++j&3) == 0) print("\n"); } if(j&3) print("\n");} /* * dump registers */voiddumpregs2(Ureg *ur){ print("FLAGS=%lux TRAP=%lux ECODE=%lux CS=%lux PC=0x%lux\n", ur->flags, ur->trap, ur->ecode, ur->cs&0xff, ur->pc); print(" AX %8.8lux BX %8.8lux CX %8.8lux DX %8.8lux\n", ur->ax, ur->bx, ur->cx, ur->dx); print(" SI %8.8lux DI %8.8lux BP %8.8lux\n", ur->si, ur->di, ur->bp); print(" DS %4.4lux ES %4.4lux FS %4.4lux GS %4.4lux\n", ur->ds&0xffff, ur->es&0xffff, ur->fs&0xffff, ur->gs&0xffff); print(" CR0 %8.8lux CR2 %8.8lux\n", getcr0(), getcr2());} voiddumpregs(Ureg *ur){ dumpregs2(ur); print(" ur %lux\n", (ulong)ur); dumpregs2(&lasttrap); print(" lastur %lux\n", (ulong)lastur);} voiddumpstack(User *p){ ulong i, l, v, hl; extern ulong etext; if(p == 0) return; hl = 0; print("stack trace of %d\n", p->pid); i = 0; for(l = (ulong)(p->stack+MAXSTACK)-4; l >= (ulong)(p->stack); l -= 4){ v = *(ulong*)l; if(v) hl = l; if(KTZERO < v && v < (ulong)&etext){ print("0x%8.8lux ", v); i++; } if(i == 8){ i = 0; print("\n"); } } if(hl) print("%ld stack used out of %d\n", (ulong)(p->stack+MAXSTACK)-hl, MAXSTACK); print("\n");}
#include "all.h"
#include "mem.h"
#include "ureg.h"
#include "io.h"
void intr0(void), intr1(void), intr2(void), intr3(void);
void intr4(void), intr5(void), intr6(void), intr7(void);
void intr8(void), intr9(void), intr10(void), intr11(void);
void intr12(void), intr13(void), intr14(void), intr15(void);
void intr16(void);
void intr24(void), intr25(void), intr26(void), intr27(void);
void intr28(void), intr29(void), intr30(void), intr31(void);
void intr32(void), intr33(void), intr34(void), intr35(void);
void intr36(void), intr37(void), intr38(void), intr39(void);
void intr64(void);
void intrbad(void);
int int0mask = 0xff; /* interrupts enabled for first 8259 */
int int1mask = 0xff; /* interrupts enabled for second 8259 */
int elcr; /* mask of level-triggered interrupts */
/*
* trap/interrupt gates
*/
Segdesc ilt[256];
int badintr[16];
enum
{
Maxhandler= 128, /* max number of interrupt handlers */
};
typedef struct Handler Handler;
struct Handler
{
void (*r)(Ureg*, void*);
void *arg;
Handler *next;
};
struct
{
Lock;
Handler *ivec[256];
Handler h[Maxhandler];
int free;
} halloc;
void
sethvec(int v, void (*r)(void), int type, int pri)
{
ilt[v].d0 = ((ulong)r)&0xFFFF|(KESEL<<16);
ilt[v].d1 = ((ulong)r)&0xFFFF0000|SEGP|SEGPL(pri)|type;
}
void
setvec(int v, void (*r)(Ureg*, void*), void *arg)
{
Handler *h;
lock(&halloc);
if(halloc.free >= Maxhandler)
panic("out of interrupt handlers");
h = &halloc.h[halloc.free++];
h->next = halloc.ivec[v];
h->r = r;
h->arg = arg;
halloc.ivec[v] = h;
unlock(&halloc);
/*
* enable corresponding interrupt in 8259
*/
if((v&~0x7) == Int0vec){
int0mask &= ~(1<<(v&7));
outb(Int0aux, int0mask);
} else if((v&~0x7) == Int1vec){
int1mask &= ~(1<<(v&7));
outb(Int1aux, int1mask);
}
}
/*
* set up the interrupt/trap gates
*/
void
trapinit(void)
{
int elcr1, i;
/*
* set all interrupts to panics
*/
for(i = 0; i < 256; i++)
sethvec(i, intrbad, SEGTG, 0);
/*
* 80386 processor (and coprocessor) traps
*/
sethvec(0, intr0, SEGTG, 0);
sethvec(1, intr1, SEGTG, 0);
sethvec(2, intr2, SEGTG, 0);
sethvec(4, intr4, SEGTG, 0);
sethvec(5, intr5, SEGTG, 0);
sethvec(6, intr6, SEGTG, 0);
sethvec(7, intr7, SEGTG, 0);
sethvec(8, intr8, SEGTG, 0);
sethvec(9, intr9, SEGTG, 0);
sethvec(10, intr10, SEGTG, 0);
sethvec(11, intr11, SEGTG, 0);
sethvec(12, intr12, SEGTG, 0);
sethvec(13, intr13, SEGTG, 0);
sethvec(14, intr14, SEGIG, 0); /* page fault, interrupts off */
sethvec(15, intr15, SEGTG, 0);
sethvec(16, intr16, SEGIG, 0); /* math coprocessor, interrupts off */
/*
* device interrupts
*/
sethvec(24, intr24, SEGIG, 0);
sethvec(25, intr25, SEGIG, 0);
sethvec(26, intr26, SEGIG, 0);
sethvec(27, intr27, SEGIG, 0);
sethvec(28, intr28, SEGIG, 0);
sethvec(29, intr29, SEGIG, 0);
sethvec(30, intr30, SEGIG, 0);
sethvec(31, intr31, SEGIG, 0);
sethvec(32, intr32, SEGIG, 0);
sethvec(33, intr33, SEGIG, 0);
sethvec(34, intr34, SEGIG, 0);
sethvec(35, intr35, SEGIG, 0);
sethvec(36, intr36, SEGIG, 0);
sethvec(37, intr37, SEGIG, 0);
sethvec(38, intr38, SEGIG, 0);
sethvec(39, intr39, SEGIG, 0);
/*
* tell the hardware where the table is (and how long)
*/
putidt(ilt, sizeof(ilt));
/*
* Set up the first 8259 interrupt processor.
* Make 8259 interrupts start at CPU vector Int0vec.
* Set the 8259 as master with edge triggered
* input with fully nested interrupts.
*/
outb(Int0ctl, 0x11); /* ICW1 - edge triggered, master,
ICW4 will be sent */
outb(Int0aux, Int0vec); /* ICW2 - interrupt vector offset */
outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */
outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */
/*
* Set up the second 8259 interrupt processor.
* Make 8259 interrupts start at CPU vector Int0vec.
* Set the 8259 as master with edge triggered
* input with fully nested interrupts.
*/
outb(Int1ctl, 0x11); /* ICW1 - edge triggered, master,
ICW4 will be sent */
outb(Int1aux, Int1vec); /* ICW2 - interrupt vector offset */
outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */
outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */
outb(Int1aux, 0xFF);
/*
* pass #2 8259 interrupts to #1
*/
int0mask &= ~0x04;
outb(Int0aux, int0mask);
/*
* Set Ocw3 to return the ISR when ctl read.
*/
inb(Int0ctl);
outb(Int0ctl, Ocw3|0x03);
inb(Int1ctl);
outb(Int1ctl, Ocw3|0x03);
/*
* Check for Edge/Level register.
* This check may not work for all chipsets.
*/
elcr1 = inb(Elcr1);
outb(Elcr1, 0);
if(inb(Elcr1) == 0){
outb(Elcr1, 0x20);
if(inb(Elcr1) == 0x20)
elcr = inb(Elcr2)<<8|elcr1;
}
outb(Elcr1, elcr1);
fpinit();
}
static int
i8259isr(int v)
{
int isr;
/*
* tell the 8259 that we're done with the
* highest level interrupt (interrupts are still
* off at this point)
*/
isr = 0;
if(v >= Int0vec && v < Int0vec+16){
isr = inb(Int0ctl);
outb(Int0ctl, EOI);
if(v >= Int0vec+8){
isr |= inb(Int1ctl)<<8;
outb(Int1ctl, EOI);
}
}
return isr & (1<<(v-Int0vec));
}
char *excname[] = {
[0] "divide error",
[1] "debug exception",
[2] " nonmaskable interrupt",
[3] "breakpoint",
[4] "overflow",
[5] "bounds check",
[6] "invalid opcode",
[7] "coprocessor not available",
[8] "double fault",
[9] "9 (reserved)",
[10] "invalid TSS",
[11] "segment not present",
[12] "stack exception",
[13] "general protection violation",
[14] "page fault",
[15] "15 (reserved)",
[16] "coprocessor error",
[17] "alignment check",
[18] "machine check",
};
Ureg lasttrap, *lastur;
static long nspuriousintr;
static int lastintr;
static uvlong nintr;
static uvlong intrtab[256];
static int schedticks;
/*
* All traps
*/
void
trap(Ureg *ur)
{
int v;
Handler *h;
nintr++;
v = ur->trap;
intrtab[v]++;
if(h = halloc.ivec[v]){
if((v >= Int0vec && v < Int0vec+16) && !(elcr & (1<<(v-Int0vec)))){
i8259isr(v);
lastintr = v-Int0vec;
}
MACHP(0)->intrp = 0;
/* there may be multiple handlers on one interrupt level */
for(; h; h = h->next){
if (h->r == 0)
panic("trap: nil h->r");
h->r(ur, h->arg);
}
if((v >= Int0vec && v < Int0vec+16) && (elcr & (1<<(v-Int0vec)))){
i8259isr(v);
lastintr = v-Int0vec;
}
}
else if(v >= Int0vec && v < Int0vec+16){
/*
* An unknown interrupt.
* Check for a default IRQ7. This can happen when
* the IRQ input goes away before the acknowledge.
* In this case, a 'default IRQ7' is generated, but
* the corresponding bit in the ISR isn't set.
* In fact, just ignore all such interrupts.
*/
if(nspuriousintr < 2)
print("spurious interrupt %d, lastintr %d\n", v-Int0vec, lastintr);
nspuriousintr++;
return;
}
else{
dumpregs(ur);
if(v < nelem(excname))
panic("%s", excname[v]);
panic("unknown trap/intr: %d\n", v);
}
if(v != Clockvec){
lasttrap = *ur;
lastur = ur;
// if(u && u->state == Running && runqtail() != tail)
// goto preempt;
return;
}
/*
* even at HZ = 1000, this doesn't help (try again later after fixing lock?)
*/
if(schedticks++ < MS2TK(1) || u == 0 || u->state != Running)
return;
//preempt:
if(u->nlock && u->delaysched < MS2TK(500)){
u->delaysched++;
return;
}
if(u->delaysched > MS2TK(3)){
print("%d: delay %ld nl %ld\n", u->pid, u->delaysched, u->nlock);
printlocks(u);
}
schedticks = 0;
u->delaysched = 0;
splhi();
sched();
}
void
trapstats(void)
{
int i, j;
print("spurious %ld\n", nspuriousintr);
print("total %ulld\n", nintr);
j = 0;
for(i = 0; i < 256; i++)
if(intrtab[i] > 0){
print("%3d %.11ulld ", i, intrtab[i]);
if((++j&3) == 0)
print("\n");
}
if(j&3)
print("\n");
}
/*
* dump registers
*/
void
dumpregs2(Ureg *ur)
{
print("FLAGS=%lux TRAP=%lux ECODE=%lux CS=%lux PC=0x%lux\n", ur->flags, ur->trap, ur->ecode, ur->cs&0xff, ur->pc);
print(" AX %8.8lux BX %8.8lux CX %8.8lux DX %8.8lux\n", ur->ax, ur->bx, ur->cx, ur->dx);
print(" SI %8.8lux DI %8.8lux BP %8.8lux\n", ur->si, ur->di, ur->bp);
print(" DS %4.4lux ES %4.4lux FS %4.4lux GS %4.4lux\n", ur->ds&0xffff, ur->es&0xffff, ur->fs&0xffff, ur->gs&0xffff);
print(" CR0 %8.8lux CR2 %8.8lux\n", getcr0(), getcr2());
}
void
dumpregs(Ureg *ur)
{
dumpregs2(ur);
print(" ur %lux\n", (ulong)ur);
dumpregs2(&lasttrap);
print(" lastur %lux\n", (ulong)lastur);
}
void
dumpstack(User *p)
{
ulong i, l, v, hl;
extern ulong etext;
if(p == 0)
return;
hl = 0;
print("stack trace of %d\n", p->pid);
i = 0;
for(l = (ulong)(p->stack+MAXSTACK)-4; l >= (ulong)(p->stack); l -= 4){
v = *(ulong*)l;
if(v)
hl = l;
if(KTZERO < v && v < (ulong)&etext){
print("0x%8.8lux ", v);
i++;
}
if(i == 8){
i = 0;
print("\n");
}
}
if(hl)
print("%ld stack used out of %d\n",
(ulong)(p->stack+MAXSTACK)-hl, MAXSTACK);
print("\n");
}