diff --git a/sys/src/9/pc/irq.c b/sys/src/9/pc/irq.c new file mode 100644 index 000000000..3ad717849 --- /dev/null +++ b/sys/src/9/pc/irq.c @@ -0,0 +1,313 @@ +#include "u.h" +#include "tos.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "../port/error.h" + +static Lock vctllock; +static Vctl *vctl[256]; + +enum +{ + Ntimevec = 20 /* number of time buckets for each intr */ +}; +ulong intrtimes[256][Ntimevec]; + +/* + * keep histogram of interrupt service times + */ +static void +intrtime(Mach*, int vno) +{ + ulong diff; + ulong x; + + x = perfticks(); + diff = x - m->perf.intrts; + m->perf.intrts = x; + + m->perf.inintr += diff; + if(up == nil && m->perf.inidle > diff) + m->perf.inidle -= diff; + + diff /= m->cpumhz*100; /* quantum = 100µsec */ + if(diff >= Ntimevec) + diff = Ntimevec-1; + intrtimes[vno][diff]++; +} + +int +irqhandled(Ureg *ureg, int vno) +{ + Vctl *ctl, *v; + int i; + + if(ctl = vctl[vno]){ + if(ctl->isintr){ + m->perf.intrts = perfticks(); + m->intr++; + if(vno >= VectorPIC) + m->lastintr = ctl->irq; + } + if(ctl->isr) + ctl->isr(vno); + for(v = ctl; v != nil; v = v->next){ + if(v->f) + v->f(ureg, v->a); + } + if(ctl->eoi) + ctl->eoi(vno); + + if(ctl->isintr){ + intrtime(m, vno); + + if(up){ + if(ctl->irq == IrqCLOCK || ctl->irq == IrqTIMER){ + /* delaysched set because we held a lock or because our quantum ended */ + if(up->delaysched) + sched(); + } else { + preempted(); + } + } + } + return 1; + } + + if(vno < VectorPIC) + return 0; + + /* + * 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. + */ + + /* call all interrupt routines, just in case */ + for(i = VectorPIC; i <= MaxIrqLAPIC; i++){ + ctl = vctl[i]; + if(ctl == nil) + continue; + if(!ctl->isintr) + continue; + for(v = ctl; v != nil; v = v->next){ + if(v->f) + v->f(ureg, v->a); + } + /* should we do this? */ + if(ctl->eoi) + ctl->eoi(i); + } + + /* clear the interrupt */ + i8259isr(vno); + + if(0)print("cpu%d: spurious interrupt %d, last %d\n", + m->machno, vno, m->lastintr); + if(0)if(conf.nmach > 1){ + for(i = 0; i < MAXMACH; i++){ + Mach *mach; + + if(active.machs[i] == 0) + continue; + mach = MACHP(i); + if(m->machno == mach->machno) + continue; + print(" cpu%d: last %d", + mach->machno, mach->lastintr); + } + print("\n"); + } + m->spuriousintr++; + return -1; +} + +void +trapenable(int vno, void (*f)(Ureg*, void*), void* a, char *name) +{ + Vctl *v; + + if(vno < 0 || vno >= VectorPIC) + panic("trapenable: vno %d", vno); + if((v = xalloc(sizeof(Vctl))) == nil) + panic("trapenable: out of memory"); + v->tbdf = BUSUNKNOWN; + v->f = f; + v->a = a; + strncpy(v->name, name, KNAMELEN-1); + v->name[KNAMELEN-1] = 0; + + ilock(&vctllock); + if(vctl[vno]) + v->next = vctl[vno]->next; + vctl[vno] = v; + iunlock(&vctllock); +} + +void +intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) +{ + int vno; + Vctl *v; + + if(f == nil){ + print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n", + irq, tbdf, name); + return; + } + + if(tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0)) + irq = -1; + + + /* + * IRQ2 doesn't really exist, it's used to gang the interrupt + * controllers together. A device set to IRQ2 will appear on + * the second interrupt controller as IRQ9. + */ + if(irq == 2) + irq = 9; + + if((v = xalloc(sizeof(Vctl))) == nil) + panic("intrenable: out of memory"); + v->isintr = 1; + v->irq = irq; + v->tbdf = tbdf; + v->f = f; + v->a = a; + strncpy(v->name, name, KNAMELEN-1); + v->name[KNAMELEN-1] = 0; + + ilock(&vctllock); + vno = arch->intrenable(v); + if(vno == -1){ + iunlock(&vctllock); + print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n", + irq, tbdf, v->name); + xfree(v); + return; + } + if(vctl[vno]){ + if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi) + panic("intrenable: handler: %s %s %#p %#p %#p %#p", + vctl[vno]->name, v->name, + vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi); + v->next = vctl[vno]; + } + vctl[vno] = v; + iunlock(&vctllock); +} + +void +intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name) +{ + Vctl **pv, *v; + int vno; + + if(irq == 2) + irq = 9; + if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){ + /* + * on APIC machine, irq is pretty meaningless + * and disabling a the vector is not implemented. + * however, we still want to remove the matching + * Vctl entry to prevent calling Vctl.f() with a + * stale Vctl.a pointer. + */ + irq = -1; + vno = VectorPIC; + } else { + vno = arch->intrvecno(irq); + } + ilock(&vctllock); + do { + for(pv = &vctl[vno]; (v = *pv) != nil; pv = &v->next){ + if(v->isintr && (v->irq == irq || irq == -1) + && v->tbdf == tbdf && v->f == f && v->a == a + && strcmp(v->name, name) == 0) + break; + } + if(v != nil){ + if(v->disable != nil) + (*v->disable)(v); + *pv = v->next; + xfree(v); + + if(irq != -1 && vctl[vno] == nil && arch->intrdisable != nil) + arch->intrdisable(irq); + break; + } + } while(irq == -1 && ++vno <= MaxVectorAPIC); + iunlock(&vctllock); +} + +static long +irqallocread(Chan*, void *a, long n, vlong offset) +{ + char buf[2*(11+1)+KNAMELEN+1+1]; + int vno, m; + Vctl *v; + + if(n < 0 || offset < 0) + error(Ebadarg); + + for(vno=0; vnonext){ + m = snprint(buf, sizeof(buf), "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name); + offset -= m; + if(offset >= 0) + continue; + if(n > -offset) + n = -offset; + offset += m; + memmove(a, buf+offset, n); + return n; + } + } + return 0; +} + +static void +nmienable(void) +{ + int x; + + /* + * Hack: should be locked with NVRAM access. + */ + outb(0x70, 0x80); /* NMI latch clear */ + outb(0x70, 0); + + x = inb(0x61) & 0x07; /* Enable NMI */ + outb(0x61, 0x0C|x); + outb(0x61, x); +} + +static void +nmihandler(Ureg *ureg, void*) +{ + /* + * Don't re-enable, it confuses the crash dumps. + nmienable(); + */ + iprint("cpu%d: nmi PC %#p, status %ux\n", + m->machno, ureg->pc, inb(0x61)); + while(m->machno != 0) + ; +} + +void +irqinit(void) +{ + addarchfile("irqalloc", 0444, irqallocread, nil); + + trapenable(VectorNMI, nmihandler, nil, "nmi"); + nmienable(); +} diff --git a/sys/src/9/pc/mkfile b/sys/src/9/pc/mkfile index e75948924..c72705fda 100644 --- a/sys/src/9/pc/mkfile +++ b/sys/src/9/pc/mkfile @@ -54,6 +54,7 @@ OBJ=\ main.$O\ memory.$O\ mmu.$O\ + irq.$O\ trap.$O\ bootargs.$O\ $CONF.root.$O\ diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c index cca5a53c8..2d5d7cce9 100644 --- a/sys/src/9/pc/trap.c +++ b/sys/src/9/pc/trap.c @@ -9,6 +9,9 @@ #include "../port/error.h" #include +extern int irqhandled(Ureg*, int); +extern void irqinit(void); + void noted(Ureg*, ulong); static void debugexc(Ureg*, void*); @@ -18,173 +21,6 @@ static void doublefault(Ureg*, void*); static void unexpected(Ureg*, void*); static void _dumpstack(Ureg*); -static Lock vctllock; -static Vctl *vctl[256]; - -enum -{ - Ntimevec = 20 /* number of time buckets for each intr */ -}; -ulong intrtimes[256][Ntimevec]; - -void -intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) -{ - int vno; - Vctl *v; - - if(f == nil){ - print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n", - irq, tbdf, name); - return; - } - if(tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0)) - irq = -1; - - /* - * IRQ2 doesn't really exist, it's used to gang the interrupt - * controllers together. A device set to IRQ2 will appear on - * the second interrupt controller as IRQ9. - */ - if(irq == 2) - irq = 9; - - if((v = xalloc(sizeof(Vctl))) == nil) - panic("intrenable: out of memory"); - v->isintr = 1; - v->irq = irq; - v->tbdf = tbdf; - v->f = f; - v->a = a; - strncpy(v->name, name, KNAMELEN-1); - v->name[KNAMELEN-1] = 0; - - ilock(&vctllock); - vno = arch->intrenable(v); - if(vno == -1){ - iunlock(&vctllock); - print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n", - irq, tbdf, v->name); - xfree(v); - return; - } - if(vctl[vno]){ - if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi) - panic("intrenable: handler: %s %s %#p %#p %#p %#p", - vctl[vno]->name, v->name, - vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi); - v->next = vctl[vno]; - } - vctl[vno] = v; - iunlock(&vctllock); -} - -void -intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name) -{ - Vctl **pv, *v; - int vno; - - if(irq == 2) - irq = 9; - if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){ - /* - * on APIC machine, irq is pretty meaningless. - * however, we still want to remove the matching - * Vctl entry to prevent calling Vctl.f() with a - * stale Vctl.a pointer. - */ - irq = -1; - vno = VectorPIC; - } else { - vno = arch->intrvecno(irq); - } - ilock(&vctllock); - do { - for(pv = &vctl[vno]; (v = *pv) != nil; pv = &v->next){ - if(v->isintr && (v->irq == irq || irq == -1) - && v->tbdf == tbdf && v->f == f && v->a == a - && strcmp(v->name, name) == 0) - break; - } - if(v != nil){ - if(v->disable != nil) - (*v->disable)(v); - *pv = v->next; - xfree(v); - - if(irq != -1 && vctl[vno] == nil && arch->intrdisable != nil) - arch->intrdisable(irq); - break; - } - } while(irq == -1 && ++vno <= MaxVectorAPIC); - iunlock(&vctllock); -} - -static long -irqallocread(Chan*, void *a, long n, vlong offset) -{ - char buf[2*(11+1)+KNAMELEN+1+1]; - int vno, m; - Vctl *v; - - if(n < 0 || offset < 0) - error(Ebadarg); - - for(vno=0; vnonext){ - m = snprint(buf, sizeof(buf), "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name); - offset -= m; - if(offset >= 0) - continue; - if(n > -offset) - n = -offset; - offset += m; - memmove(a, buf+offset, n); - return n; - } - } - return 0; -} - -void -trapenable(int vno, void (*f)(Ureg*, void*), void* a, char *name) -{ - Vctl *v; - - if(vno < 0 || vno >= VectorPIC) - panic("trapenable: vno %d", vno); - if((v = xalloc(sizeof(Vctl))) == nil) - panic("trapenable: out of memory"); - v->tbdf = BUSUNKNOWN; - v->f = f; - v->a = a; - strncpy(v->name, name, KNAMELEN-1); - v->name[KNAMELEN-1] = 0; - - ilock(&vctllock); - if(vctl[vno]) - v->next = vctl[vno]->next; - vctl[vno] = v; - iunlock(&vctllock); -} - -static void -nmienable(void) -{ - int x; - - /* - * Hack: should be locked with NVRAM access. - */ - outb(0x70, 0x80); /* NMI latch clear */ - outb(0x70, 0); - - x = inb(0x61) & 0x07; /* Enable NMI */ - outb(0x61, 0x0C|x); - outb(0x61, x); -} - /* * Minimal trap setup. Just enough so that we can panic * on traps (bugs) during kernel initialization. @@ -228,6 +64,8 @@ trapinit0(void) void trapinit(void) { + irqinit(); + /* * Special traps. * Syscall() is called directly without going through trap(). @@ -237,9 +75,6 @@ trapinit(void) trapenable(VectorPF, fault386, 0, "fault386"); trapenable(Vector2F, doublefault, 0, "doublefault"); trapenable(Vector15, unexpected, 0, "unexpected"); - nmienable(); - - addarchfile("irqalloc", 0444, irqallocread, nil); } static char* excname[32] = { @@ -277,27 +112,18 @@ static char* excname[32] = { "31 (reserved)", }; -/* - * keep histogram of interrupt service times - */ -void -intrtime(Mach*, int vno) +static int +usertrap(int vno) { - ulong diff; - ulong x; + char buf[ERRMAX]; - x = perfticks(); - diff = x - m->perf.intrts; - m->perf.intrts = x; - - m->perf.inintr += diff; - if(up == nil && m->perf.inidle > diff) - m->perf.inidle -= diff; - - diff /= m->cpumhz*100; /* quantum = 100µsec */ - if(diff >= Ntimevec) - diff = Ntimevec-1; - intrtimes[vno][diff]++; + if(vno < nelem(excname)){ + spllo(); + sprint(buf, "sys: trap: %s", excname[vno]); + postnote(up, 1, buf, NDebug); + return 1; + } + return 0; } /* go to user space */ @@ -325,112 +151,16 @@ kexit(Ureg*) void trap(Ureg* ureg) { - int clockintr, i, vno, user; - char buf[ERRMAX]; - Vctl *ctl, *v; - Mach *mach; + int vno, user; - m->perf.intrts = perfticks(); user = userureg(ureg); if(user){ up->dbgreg = ureg; cycles(&up->kentry); } - clockintr = 0; - vno = ureg->trap; - if(ctl = vctl[vno]){ - if(ctl->isintr){ - m->intr++; - if(vno >= VectorPIC && vno != VectorSYSCALL) - m->lastintr = ctl->irq; - } - - if(ctl->isr) - ctl->isr(vno); - for(v = ctl; v != nil; v = v->next){ - if(v->f) - v->f(ureg, v->a); - } - if(ctl->eoi) - ctl->eoi(vno); - - if(ctl->isintr){ - intrtime(m, vno); - - if(ctl->irq == IrqCLOCK || ctl->irq == IrqTIMER) - clockintr = 1; - - if(up && !clockintr) - preempted(); - } - } - else if(vno < nelem(excname) && user){ - spllo(); - sprint(buf, "sys: trap: %s", excname[vno]); - postnote(up, 1, buf, NDebug); - } - else if(vno >= VectorPIC && vno != VectorSYSCALL){ - /* - * 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. - */ - - /* call all interrupt routines, just in case */ - for(i = VectorPIC; i <= MaxIrqLAPIC; i++){ - ctl = vctl[i]; - if(ctl == nil) - continue; - if(!ctl->isintr) - continue; - for(v = ctl; v != nil; v = v->next){ - if(v->f) - v->f(ureg, v->a); - } - /* should we do this? */ - if(ctl->eoi) - ctl->eoi(i); - } - - /* clear the interrupt */ - i8259isr(vno); - - if(0)print("cpu%d: spurious interrupt %d, last %d\n", - m->machno, vno, m->lastintr); - if(0)if(conf.nmach > 1){ - for(i = 0; i < MAXMACH; i++){ - if(active.machs[i] == 0) - continue; - mach = MACHP(i); - if(m->machno == mach->machno) - continue; - print(" cpu%d: last %d", - mach->machno, mach->lastintr); - } - print("\n"); - } - m->spuriousintr++; - if(user) - kexit(ureg); - return; - } - else{ - if(vno == VectorNMI){ - /* - * Don't re-enable, it confuses the crash dumps. - nmienable(); - */ - iprint("cpu%d: nmi PC %#8.8lux, status %ux\n", - m->machno, ureg->pc, inb(0x61)); - while(m->machno != 0) - ; - } - + if(!irqhandled(ureg, vno) && (!user || !usertrap(vno))){ if(!user){ void (*pc)(void); ulong *sp; @@ -494,12 +224,6 @@ trap(Ureg* ureg) } splhi(); - /* delaysched set because we held a lock or because our quantum ended */ - if(up && up->delaysched && clockintr){ - sched(); - splhi(); - } - if(user){ if(up->procctl || up->nnote) notify(ureg); diff --git a/sys/src/9/pc64/mkfile b/sys/src/9/pc64/mkfile index 8ac22f653..f34201e0d 100644 --- a/sys/src/9/pc64/mkfile +++ b/sys/src/9/pc64/mkfile @@ -52,6 +52,7 @@ OBJ=\ main.$O\ memory.$O\ mmu.$O\ + irq.$O\ trap.$O\ bootargs.$O\ $CONF.root.$O\ diff --git a/sys/src/9/pc64/trap.c b/sys/src/9/pc64/trap.c index 25b6510fa..c79bc4ec5 100644 --- a/sys/src/9/pc64/trap.c +++ b/sys/src/9/pc64/trap.c @@ -9,6 +9,9 @@ #include "../port/error.h" #include +extern int irqhandled(Ureg*, int); +extern void irqinit(void); + void noted(Ureg*, ulong); static void debugexc(Ureg*, void*); @@ -18,176 +21,6 @@ static void doublefault(Ureg*, void*); static void unexpected(Ureg*, void*); static void _dumpstack(Ureg*); -static Lock vctllock; -static Vctl *vctl[256]; - -enum -{ - Ntimevec = 20 /* number of time buckets for each intr */ -}; -ulong intrtimes[256][Ntimevec]; - -void -intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) -{ - int vno; - Vctl *v; - - if(f == nil){ - print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n", - irq, tbdf, name); - return; - } - - if(tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0)) - irq = -1; - - - /* - * IRQ2 doesn't really exist, it's used to gang the interrupt - * controllers together. A device set to IRQ2 will appear on - * the second interrupt controller as IRQ9. - */ - if(irq == 2) - irq = 9; - - if((v = xalloc(sizeof(Vctl))) == nil) - panic("intrenable: out of memory"); - v->isintr = 1; - v->irq = irq; - v->tbdf = tbdf; - v->f = f; - v->a = a; - strncpy(v->name, name, KNAMELEN-1); - v->name[KNAMELEN-1] = 0; - - ilock(&vctllock); - vno = arch->intrenable(v); - if(vno == -1){ - iunlock(&vctllock); - print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n", - irq, tbdf, v->name); - xfree(v); - return; - } - if(vctl[vno]){ - if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi) - panic("intrenable: handler: %s %s %#p %#p %#p %#p", - vctl[vno]->name, v->name, - vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi); - v->next = vctl[vno]; - } - vctl[vno] = v; - iunlock(&vctllock); -} - -void -intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name) -{ - Vctl **pv, *v; - int vno; - - if(irq == 2) - irq = 9; - if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){ - /* - * on APIC machine, irq is pretty meaningless - * and disabling a the vector is not implemented. - * however, we still want to remove the matching - * Vctl entry to prevent calling Vctl.f() with a - * stale Vctl.a pointer. - */ - irq = -1; - vno = VectorPIC; - } else { - vno = arch->intrvecno(irq); - } - ilock(&vctllock); - do { - for(pv = &vctl[vno]; (v = *pv) != nil; pv = &v->next){ - if(v->isintr && (v->irq == irq || irq == -1) - && v->tbdf == tbdf && v->f == f && v->a == a - && strcmp(v->name, name) == 0) - break; - } - if(v != nil){ - if(v->disable != nil) - (*v->disable)(v); - *pv = v->next; - xfree(v); - - if(irq != -1 && vctl[vno] == nil && arch->intrdisable != nil) - arch->intrdisable(irq); - break; - } - } while(irq == -1 && ++vno <= MaxVectorAPIC); - iunlock(&vctllock); -} - -static long -irqallocread(Chan*, void *a, long n, vlong offset) -{ - char buf[2*(11+1)+KNAMELEN+1+1]; - int vno, m; - Vctl *v; - - if(n < 0 || offset < 0) - error(Ebadarg); - - for(vno=0; vnonext){ - m = snprint(buf, sizeof(buf), "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name); - offset -= m; - if(offset >= 0) - continue; - if(n > -offset) - n = -offset; - offset += m; - memmove(a, buf+offset, n); - return n; - } - } - return 0; -} - -void -trapenable(int vno, void (*f)(Ureg*, void*), void* a, char *name) -{ - Vctl *v; - - if(vno < 0 || vno >= VectorPIC) - panic("trapenable: vno %d", vno); - if((v = xalloc(sizeof(Vctl))) == nil) - panic("trapenable: out of memory"); - v->tbdf = BUSUNKNOWN; - v->f = f; - v->a = a; - strncpy(v->name, name, KNAMELEN-1); - v->name[KNAMELEN-1] = 0; - - ilock(&vctllock); - if(vctl[vno]) - v->next = vctl[vno]->next; - vctl[vno] = v; - iunlock(&vctllock); -} - -static void -nmienable(void) -{ - int x; - - /* - * Hack: should be locked with NVRAM access. - */ - outb(0x70, 0x80); /* NMI latch clear */ - outb(0x70, 0); - - x = inb(0x61) & 0x07; /* Enable NMI */ - outb(0x61, 0x0C|x); - outb(0x61, x); -} - void trapinit0(void) { @@ -232,6 +65,8 @@ trapinit0(void) void trapinit(void) { + irqinit(); + /* * Special traps. * Syscall() is called directly without going through trap(). @@ -241,8 +76,6 @@ trapinit(void) trapenable(VectorPF, faultamd64, 0, "faultamd64"); trapenable(Vector2F, doublefault, 0, "doublefault"); trapenable(Vector15, unexpected, 0, "unexpected"); - nmienable(); - addarchfile("irqalloc", 0444, irqallocread, nil); } static char* excname[32] = { @@ -280,27 +113,18 @@ static char* excname[32] = { "31 (reserved)", }; -/* - * keep histogram of interrupt service times - */ -void -intrtime(Mach*, int vno) +static int +usertrap(int vno) { - ulong diff; - ulong x; + char buf[ERRMAX]; - x = perfticks(); - diff = x - m->perf.intrts; - m->perf.intrts = x; - - m->perf.inintr += diff; - if(up == nil && m->perf.inidle > diff) - m->perf.inidle -= diff; - - diff /= m->cpumhz*100; /* quantum = 100µsec */ - if(diff >= Ntimevec) - diff = Ntimevec-1; - intrtimes[vno][diff]++; + if(vno < nelem(excname)){ + spllo(); + sprint(buf, "sys: trap: %s", excname[vno]); + postnote(up, 1, buf, NDebug); + return 1; + } + return 0; } /* go to user space */ @@ -321,112 +145,16 @@ kexit(Ureg*) void trap(Ureg *ureg) { - int clockintr, i, vno, user; - char buf[ERRMAX]; - Vctl *ctl, *v; - Mach *mach; + int vno, user; - m->perf.intrts = perfticks(); user = userureg(ureg); if(user){ up->dbgreg = ureg; cycles(&up->kentry); } - clockintr = 0; - vno = ureg->type; - - if(ctl = vctl[vno]){ - if(ctl->isintr){ - m->intr++; - if(vno >= VectorPIC) - m->lastintr = ctl->irq; - } - if(ctl->isr) - ctl->isr(vno); - for(v = ctl; v != nil; v = v->next){ - if(v->f) - v->f(ureg, v->a); - } - if(ctl->eoi) - ctl->eoi(vno); - - if(ctl->isintr){ - intrtime(m, vno); - - if(ctl->irq == IrqCLOCK || ctl->irq == IrqTIMER) - clockintr = 1; - - if(up && !clockintr) - preempted(); - } - } - else if(vno < nelem(excname) && user){ - spllo(); - sprint(buf, "sys: trap: %s", excname[vno]); - postnote(up, 1, buf, NDebug); - } - else if(vno >= VectorPIC){ - /* - * 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. - */ - - /* call all interrupt routines, just in case */ - for(i = VectorPIC; i <= MaxIrqLAPIC; i++){ - ctl = vctl[i]; - if(ctl == nil) - continue; - if(!ctl->isintr) - continue; - for(v = ctl; v != nil; v = v->next){ - if(v->f) - v->f(ureg, v->a); - } - /* should we do this? */ - if(ctl->eoi) - ctl->eoi(i); - } - - /* clear the interrupt */ - i8259isr(vno); - - if(0)print("cpu%d: spurious interrupt %d, last %d\n", - m->machno, vno, m->lastintr); - if(0)if(conf.nmach > 1){ - for(i = 0; i < MAXMACH; i++){ - if(active.machs[i] == 0) - continue; - mach = MACHP(i); - if(m->machno == mach->machno) - continue; - print(" cpu%d: last %d", - mach->machno, mach->lastintr); - } - print("\n"); - } - m->spuriousintr++; - if(user) - kexit(ureg); - return; - } - else{ - if(vno == VectorNMI){ - /* - * Don't re-enable, it confuses the crash dumps. - nmienable(); - */ - iprint("cpu%d: nmi PC %#p, status %ux\n", - m->machno, ureg->pc, inb(0x61)); - while(m->machno != 0) - ; - } - + if(!irqhandled(ureg, vno) && (!user || !usertrap(vno))){ if(!user){ void (*pc)(void); @@ -464,12 +192,6 @@ trap(Ureg *ureg) } splhi(); - /* delaysched set because we held a lock or because our quantum ended */ - if(up && up->delaysched && clockintr){ - sched(); - splhi(); - } - if(user){ if(up->procctl || up->nnote) notify(ureg);