diff options
| -rw-r--r-- | sys/src/9/pc/archacpi.c | 5 | ||||
| -rw-r--r-- | sys/src/9/pc/archgeneric.c | 59 | ||||
| -rw-r--r-- | sys/src/9/pc/archmp.c | 5 | ||||
| -rw-r--r-- | sys/src/9/pc/dat.h | 7 | ||||
| -rw-r--r-- | sys/src/9/pc/devarch.c | 89 | ||||
| -rw-r--r-- | sys/src/9/pc/fns.h | 8 | ||||
| -rw-r--r-- | sys/src/9/pc/i8259.c | 80 | ||||
| -rw-r--r-- | sys/src/9/pc/io.h | 14 | ||||
| -rw-r--r-- | sys/src/9/pc/irq.c | 307 | ||||
| -rw-r--r-- | sys/src/9/pc/mp.c | 171 | ||||
| -rw-r--r-- | sys/src/9/pc/mp.h | 3 | ||||
| -rw-r--r-- | sys/src/9/pc/pc | 1 | ||||
| -rw-r--r-- | sys/src/9/pc/trap.c | 2 | ||||
| -rw-r--r-- | sys/src/9/pc64/dat.h | 7 | ||||
| -rw-r--r-- | sys/src/9/pc64/fns.h | 8 | ||||
| -rw-r--r-- | sys/src/9/pc64/pc64 | 1 | ||||
| -rw-r--r-- | sys/src/9/pc64/trap.c | 2 | ||||
| -rw-r--r-- | sys/src/9/xen/archxen.c | 24 | ||||
| -rw-r--r-- | sys/src/9/xen/fns.h | 7 | ||||
| -rw-r--r-- | sys/src/9/xen/mkfile | 1 | ||||
| -rw-r--r-- | sys/src/9/xen/trap.c | 298 | ||||
| -rw-r--r-- | sys/src/9/xen/xensystem.c | 41 | ||||
| -rw-r--r-- | sys/src/9/xen/xentimer.c | 2 |
23 files changed, 483 insertions, 659 deletions
diff --git a/sys/src/9/pc/archacpi.c b/sys/src/9/pc/archacpi.c index e19c70166..560dc93a9 100644 --- a/sys/src/9/pc/archacpi.c +++ b/sys/src/9/pc/archacpi.c @@ -256,6 +256,7 @@ Foundbus: ai->intr = pi; ai->apic = a; ai->next = bus->aintr; + ai->bus = bus; bus->aintr = ai; } @@ -733,13 +734,15 @@ acpireset(void) } static int identify(void); +extern int i8259irqno(int, int); PCArch archacpi = { .id= "ACPI", .ident= identify, .reset= acpireset, .intrinit= acpiinit, -.intrenable= mpintrenable, +.intrassign= mpintrassign, +.intrirqno= i8259irqno, .intron= lapicintron, .introff= lapicintroff, .fastclock= i8253read, diff --git a/sys/src/9/pc/archgeneric.c b/sys/src/9/pc/archgeneric.c new file mode 100644 index 000000000..e51bf7ad7 --- /dev/null +++ b/sys/src/9/pc/archgeneric.c @@ -0,0 +1,59 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "../port/error.h" + +extern int i8259assign(Vctl*); +extern int i8259irqno(int, int); +extern void i8259init(void); +extern int i8259isr(int); +extern void i8259on(void); +extern void i8259off(void); +extern int i8259vecno(int); + +void +archreset(void) +{ + i8042reset(); + + /* + * Often the BIOS hangs during restart if a conventional 8042 + * warm-boot sequence is tried. The following is Intel specific and + * seems to perform a cold-boot, but at least it comes back. + * And sometimes there is no keyboard... + * + * The reset register (0xcf9) is usually in one of the bridge + * chips. The actual location and sequence could be extracted from + * ACPI but why bother, this is the end of the line anyway. + */ + print("Takes a licking and keeps on ticking...\n"); + *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */ + outb(0xcf9, 0x02); + outb(0xcf9, 0x06); + + print("can't reset\n"); + for(;;) + idle(); +} + +PCArch archgeneric = { +.id= "generic", +.ident= 0, +.reset= archreset, + +.intrinit= i8259init, +.intrassign= i8259assign, +.intrirqno= i8259irqno, +.intrvecno= i8259vecno, +.intrspurious= i8259isr, +.intron= i8259on, +.introff= i8259off, + +.clockenable= i8253enable, +.fastclock= i8253read, +.timerset= i8253timerset, +}; diff --git a/sys/src/9/pc/archmp.c b/sys/src/9/pc/archmp.c index 5d613dd0d..67a522a36 100644 --- a/sys/src/9/pc/archmp.c +++ b/sys/src/9/pc/archmp.c @@ -194,6 +194,7 @@ mkiointr(PCMPintr* p) } aintr->apic = mpioapic[p->apicno]; aintr->next = bus->aintr; + aintr->bus = bus; bus->aintr = aintr; return aintr; @@ -366,13 +367,15 @@ mpreset(void) } static int identify(void); +extern int i8259irqno(int, int); PCArch archmp = { .id= "_MP_", .ident= identify, .reset= mpreset, .intrinit= pcmpinit, -.intrenable= mpintrenable, +.intrassign= mpintrassign, +.intrirqno= i8259irqno, .intron= lapicintron, .introff= lapicintroff, .fastclock= i8253read, diff --git a/sys/src/9/pc/dat.h b/sys/src/9/pc/dat.h index 278f70893..644fab2a8 100644 --- a/sys/src/9/pc/dat.h +++ b/sys/src/9/pc/dat.h @@ -280,13 +280,12 @@ struct PCArch char* id; int (*ident)(void); /* this should be in the model */ void (*reset)(void); /* this should be in the model */ - int (*serialpower)(int); /* 1 == on, 0 == off */ - int (*modempower)(int); /* 1 == on, 0 == off */ void (*intrinit)(void); - int (*intrenable)(Vctl*); + int (*intrassign)(Vctl*); + int (*intrirqno)(int, int); + int (*intrspurious)(int); int (*intrvecno)(int); - int (*intrdisable)(int); void (*introff)(void); void (*intron)(void); diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index cc14b394b..6617d3e7b 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -324,31 +324,6 @@ nop(void) { } -void -archreset(void) -{ - i8042reset(); - - /* - * Often the BIOS hangs during restart if a conventional 8042 - * warm-boot sequence is tried. The following is Intel specific and - * seems to perform a cold-boot, but at least it comes back. - * And sometimes there is no keyboard... - * - * The reset register (0xcf9) is usually in one of the bridge - * chips. The actual location and sequence could be extracted from - * ACPI but why bother, this is the end of the line anyway. - */ - print("Takes a licking and keeps on ticking...\n"); - *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */ - outb(0xcf9, 0x02); - outb(0xcf9, 0x06); - - print("can't reset\n"); - for(;;) - idle(); -} - /* * 386 has no compare-and-swap instruction. * Run it with interrupts turned off instead. @@ -380,25 +355,6 @@ int (*cmpswap)(long*, long, long) = cmpswap386; PCArch* arch; extern PCArch* knownarch[]; -PCArch archgeneric = { -.id= "generic", -.ident= 0, -.reset= archreset, -.serialpower= unimplemented, -.modempower= unimplemented, - -.intrinit= i8259init, -.intrenable= i8259enable, -.intrvecno= i8259vecno, -.intrdisable= i8259disable, -.intron= i8259on, -.introff= i8259off, - -.clockenable= i8253enable, -.fastclock= i8253read, -.timerset= i8253timerset, -}; - typedef struct X86type X86type; struct X86type { int family; @@ -912,26 +868,22 @@ archinit(void) { PCArch **p; - arch = &archgeneric; + arch = knownarch[0]; for(p = knownarch; *p != nil; p++){ if((*p)->ident != nil && (*p)->ident() == 0){ arch = *p; break; } } - if(arch != &archgeneric){ + if(arch != knownarch[0]){ if(arch->id == nil) - arch->id = archgeneric.id; + arch->id = knownarch[0]->id; if(arch->reset == nil) - arch->reset = archgeneric.reset; - if(arch->serialpower == nil) - arch->serialpower = archgeneric.serialpower; - if(arch->modempower == nil) - arch->modempower = archgeneric.modempower; + arch->reset = knownarch[0]->reset; if(arch->intrinit == nil) - arch->intrinit = archgeneric.intrinit; - if(arch->intrenable == nil) - arch->intrenable = archgeneric.intrenable; + arch->intrinit = knownarch[0]->intrinit; + if(arch->intrassign == nil) + arch->intrassign = knownarch[0]->intrassign; } /* @@ -1100,6 +1052,33 @@ dumpmcregs(void) } } +static void +nmihandler(Ureg *ureg, void*) +{ + iprint("cpu%d: nmi PC %#p, status %ux\n", + m->machno, ureg->pc, inb(0x61)); + while(m->machno != 0) + ; +} + +void +nmienable(void) +{ + int x; + + trapenable(VectorNMI, nmihandler, nil, "nmi"); + + /* + * 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 setupwatchpts(Proc *pr, Watchpt *wp, int nwp) { diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index 669f02ee9..a16c0cf74 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -65,13 +65,6 @@ void i8253init(void); void i8253reset(void); uvlong i8253read(uvlong*); void i8253timerset(uvlong); -int i8259disable(int); -int i8259enable(Vctl*); -void i8259init(void); -int i8259isr(int); -void i8259on(void); -void i8259off(void); -int i8259vecno(int); void idle(void); void idlehands(void); int inb(int); @@ -111,6 +104,7 @@ char* mtrr(uvlong, uvlong, char *); void mtrrclock(void); int mtrrprint(char *, long); void mtrrsync(void); +void nmienable(void); uchar nvramread(int); void nvramwrite(int, uchar); void outb(int, int); diff --git a/sys/src/9/pc/i8259.c b/sys/src/9/pc/i8259.c index cfe1a5a42..0eed0954f 100644 --- a/sys/src/9/pc/i8259.c +++ b/sys/src/9/pc/i8259.c @@ -127,8 +127,38 @@ i8259isr(int vno) return isr & (1<<irq); } +static int +irqenable(Vctl *v, int shared) +{ + if(shared) + return 0; + ilock(&i8259lock); + i8259mask &= ~(1<<v->irq); + if(v->irq < 8) + outb(Int0aux, i8259mask & 0xFF); + else + outb(Int1aux, (i8259mask>>8) & 0xFF); + iunlock(&i8259lock); + return 0; +} + +static int +irqdisable(Vctl *v, int shared) +{ + if(shared) + return 0; + ilock(&i8259lock); + i8259mask |= 1<<v->irq; + if(v->irq < 8) + outb(Int0aux, i8259mask & 0xFF); + else + outb(Int1aux, (i8259mask>>8) & 0xFF); + iunlock(&i8259lock); + return 0; +} + int -i8259enable(Vctl* v) +i8259assign(Vctl *v) { int irq, irqbit; @@ -150,52 +180,40 @@ i8259enable(Vctl* v) iunlock(&i8259lock); return -1; } - i8259mask &= ~irqbit; - if(irq < 8) - outb(Int0aux, i8259mask & 0xFF); - else - outb(Int1aux, (i8259mask>>8) & 0xFF); + iunlock(&i8259lock); if(i8259elcr & irqbit) v->eoi = i8259isr; else v->isr = i8259isr; - iunlock(&i8259lock); - return VectorPIC+irq; -} + v->enable = irqenable; + v->disable = irqdisable; -int -i8259vecno(int irq) -{ return VectorPIC+irq; } int -i8259disable(int irq) +i8259irqno(int irq, int tbdf) { - int irqbit; + if(tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0)) + return -1; /* - * Given an IRQ, disable the corresponding interrupt - * in the 8259. + * 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 < 0 || irq > MaxIrqPIC){ - print("i8259disable: irq %d out of range\n", irq); - return -1; - } - irqbit = 1<<irq; + if(irq == 2) + irq = 9; - ilock(&i8259lock); - if(!(i8259mask & irqbit)){ - i8259mask |= irqbit; - if(irq < 8) - outb(Int0aux, i8259mask & 0xFF); - else - outb(Int1aux, (i8259mask>>8) & 0xFF); - } - iunlock(&i8259lock); - return 0; + return irq; +} + +int +i8259vecno(int irq) +{ + return VectorPIC+irq; } void diff --git a/sys/src/9/pc/io.h b/sys/src/9/pc/io.h index d0113af69..cbb03086f 100644 --- a/sys/src/9/pc/io.h +++ b/sys/src/9/pc/io.h @@ -46,19 +46,23 @@ enum { }; typedef struct Vctl { - Vctl* next; /* handlers on this vector */ + Vctl *next; /* handlers on this vector */ void (*f)(Ureg*, void*); /* handler to call */ - void* a; /* argument to call it with */ - - int isintr; /* interrupt or fault/trap */ + void *a; /* argument to call it with */ int (*isr)(int); /* get isr bit for this irq */ int (*eoi)(int); /* eoi */ - void (*disable)(Vctl*); + int (*enable)(Vctl*, int); + int (*disable)(Vctl*, int); + void *aux; + int irq; int tbdf; + int vno; + int cpu; + int local; char name[KNAMELEN]; /* of driver */ } Vctl; diff --git a/sys/src/9/pc/irq.c b/sys/src/9/pc/irq.c index 3ad717849..7bfee87a4 100644 --- a/sys/src/9/pc/irq.c +++ b/sys/src/9/pc/irq.c @@ -9,7 +9,7 @@ #include "../port/error.h" static Lock vctllock; -static Vctl *vctl[256]; +static Vctl *vclock, *vctl[256]; enum { @@ -46,86 +46,55 @@ 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; + ctl = vctl[vno]; + if(ctl != nil){ + if(vno < VectorPIC){ + (*ctl->f)(ureg, ctl->a); + return 1; } - 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(); - } + + m->perf.intrts = perfticks(); + m->intr++; + m->lastintr = ctl->irq; + if(ctl->isr != nil) + (*ctl->isr)(vno); + for(v = ctl; v != nil; v = v->next) + (*v->f)(ureg, v->a); + if(ctl->eoi != nil) + (*ctl->eoi)(vno); + intrtime(m, vno); + + if(up != nil){ + if(ctl == vclock){ + /* delaysched set because we held a lock or because our quantum ended */ + if(up->delaysched) + sched(); + } else { + preempted(); } } return 1; } - if(vno < VectorPIC) + if(vno < VectorPIC || vno == VectorSYSCALL) 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); + m->spuriousintr++; + if(arch->intrspurious != nil && (*arch->intrspurious)(vno) == 0) + return 1; /* false alarm */ - if(0)print("cpu%d: spurious interrupt %d, last %d\n", + iprint("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"); + /* call all non-local interrupt routines, just in case */ + for(i = VectorPIC; i < nelem(vctl); i++){ + ctl = vctl[i]; + if(ctl == nil || ctl == vclock || ctl->local) + continue; + for(v = ctl; v != nil; v = v->next) + (*v->f)(ureg, v->a); } - m->spuriousintr++; + return -1; } @@ -134,28 +103,59 @@ trapenable(int vno, void (*f)(Ureg*, void*), void* a, char *name) { Vctl *v; - if(vno < 0 || vno >= VectorPIC) - panic("trapenable: vno %d", vno); + if(f == nil){ + print("trapenable: nil handler for %d, for %s\n", + vno, name); + return; + } + + if(vno < 0 || vno >= VectorPIC){ + print("trapenable: vno %d out of range", vno); + return; + } + if((v = xalloc(sizeof(Vctl))) == nil) panic("trapenable: out of memory"); - v->tbdf = BUSUNKNOWN; + v->f = f; v->a = a; + + v->tbdf = BUSUNKNOWN; + v->irq = -1; + v->vno = vno; + v->cpu = -1; + strncpy(v->name, name, KNAMELEN-1); v->name[KNAMELEN-1] = 0; ilock(&vctllock); - if(vctl[vno]) - v->next = vctl[vno]->next; + if(vctl[vno] != nil){ + print("trapenable: vno %d assigned twice: %s %s\n", + vno, vctl[vno]->name, v->name); + iunlock(&vctllock); + xfree(v); + return; + } vctl[vno] = v; iunlock(&vctllock); } +static Vctl* +delayfree(Vctl *v) +{ + static Vctl *q[4]; + static uint x; + Vctl *r; + + r = q[x], q[x] = v; + x = (x+1) % nelem(q); + return r; +} + void intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) { - int vno; - Vctl *v; + Vctl **pv, *v; if(f == nil){ print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n", @@ -163,45 +163,63 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *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(arch->intrirqno != nil) + irq = (*arch->intrirqno)(irq, tbdf); 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; + + v->tbdf = tbdf; + v->irq = irq; + v->vno = -1; + v->cpu = -1; + 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", + v->vno = (*arch->intrassign)(v); + if(v->vno < VectorPIC || v->vno >= nelem(vctl)){ + print("intrenable: couldn't assign irq %d, tbdf 0x%uX for %s\n", irq, tbdf, v->name); - xfree(v); +Unlockandfree: + iunlock(&vctllock); + if(v != nil) + 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]; + pv = &vctl[v->vno]; + if(*pv != nil){ + if((*pv)->isr != v->isr || (*pv)->eoi != v->eoi){ + print("intrenable: incompatible handler: %s %s %#p %#p %#p %#p\n", + (*pv)->name, v->name, + (*pv)->isr, v->isr, + (*pv)->eoi, v->eoi); + goto Unlockandfree; + } + if(*pv == vclock) + pv = &vclock->next; + v->next = *pv; + } + if(strcmp(name, "clock") == 0) + vclock = v; + *pv = v; + if(v->enable != nil){ + coherence(); + if((*v->enable)(v, pv != &vctl[v->vno] || v->next != nil) < 0){ + print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n", + irq, tbdf, v->name); + *pv = v->next; + if(v == vclock) + vclock = nil; + if(conf.nmach > 1) + v = delayfree(v); + goto Unlockandfree; + } } - vctl[vno] = v; iunlock(&vctllock); } @@ -211,40 +229,47 @@ 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. - */ + if(arch->intrirqno != nil) + irq = (*arch->intrirqno)(irq, tbdf); + + if(irq != -1 && arch->intrvecno != nil) { + vno = (*arch->intrvecno)(irq); + if(vno < VectorPIC || vno >= nelem(vctl)){ + irq = -1; + vno = VectorPIC; + } + } else { 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) + if((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); + if(v->disable != nil){ + if((*v->disable)(v, pv != &vctl[vno] || v->next != nil) < 0){ + print("intrdisable: couldn't disable irq %d, tbdf 0x%uX for %s\n", + irq, tbdf, name); + } + coherence(); + } *pv = v->next; - xfree(v); - - if(irq != -1 && vctl[vno] == nil && arch->intrdisable != nil) - arch->intrdisable(irq); - break; + if(v == vclock) + vclock = nil; + if(conf.nmach > 1) + v = delayfree(v); + iunlock(&vctllock); + if(v != nil) + xfree(v); + return; } - } while(irq == -1 && ++vno <= MaxVectorAPIC); + } while(irq == -1 && ++vno < nelem(vctl)); iunlock(&vctllock); } @@ -258,8 +283,8 @@ irqallocread(Chan*, void *a, long n, vlong offset) if(n < 0 || offset < 0) error(Ebadarg); - for(vno=0; vno<nelem(vctl); vno++){ - for(v=vctl[vno]; v; v=v->next){ + for(vno = 0; vno < nelem(vctl); vno++){ + for(v = vctl[vno]; v != nil; v = v->next){ m = snprint(buf, sizeof(buf), "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name); offset -= m; if(offset >= 0) @@ -274,40 +299,8 @@ irqallocread(Chan*, void *a, long n, vlong offset) 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/mp.c b/sys/src/9/pc/mp.c index 591fc6735..abb3e010e 100644 --- a/sys/src/9/pc/mp.c +++ b/sys/src/9/pc/mp.c @@ -10,6 +10,8 @@ #include "mp.h" #include "apbootstrap.i" +extern void i8259init(void); + /* filled in by pcmpinit or acpiinit */ Bus* mpbus; Bus* mpbuslast; @@ -291,23 +293,51 @@ allocvector(void) } static int -mpintrenablex(Vctl* v, int tbdf) +ioapicirqenable(Vctl *v, int shared) +{ + Aintr *aintr = v->aux; + int lo, hi; + + if(shared) + return 0; + hi = v->cpu<<24; + lo = mpintrinit(aintr->bus, aintr->intr, v->vno, v->irq); + lo |= ApicPHYSICAL; /* no-op */ + ioapicrdtw(aintr->apic, aintr->intr->intin, hi, lo); + return 0; +} + +static int +ioapicirqdisable(Vctl *v, int shared) +{ + Aintr *aintr = v->aux; + int lo, hi; + + if(shared) + return 0; + hi = 0; + lo = ApicIMASK; + ioapicrdtw(aintr->apic, aintr->intr->intin, hi, lo); + return 0; +} + +static int +mpintrassignx(Vctl* v, int tbdf) { Bus *bus; + Pcidev *pci; Aintr *aintr; - Apic *apic; - Pcidev *pcidev; - int bno, dno, pin, hi, irq, lo, n, type, vno; + int bno, dno, pin, irq, type, lo, hi, n; type = BUSTYPE(tbdf); bno = BUSBNO(tbdf); dno = BUSDNO(tbdf); pin = 0; - pcidev = nil; + pci = nil; if(type == BusPCI){ - if(pcidev = pcimatchtbdf(tbdf)) - pin = pcicfgr8(pcidev, PciINTP); + if((pci = pcimatchtbdf(tbdf)) != nil) + pin = pcicfgr8(pci, PciINTP); } else if(type == BusISA) bno = mpisabus; @@ -325,14 +355,14 @@ Findbus: * by the MP or ACPI tables then walk up the bus translating interrupt * pin to parent bus. */ - if(pcidev && pcidev->parent && pin > 0){ + if(pci != nil && pci->parent != nil && pin > 0){ pin = ((dno+(pin-1))%4)+1; - pcidev = pcidev->parent; - bno = BUSBNO(pcidev->tbdf); - dno = BUSDNO(pcidev->tbdf); + pci = pci->parent; + bno = BUSBNO(pci->tbdf); + dno = BUSDNO(pci->tbdf); goto Findbus; } - print("mpintrenable: can't find bus type %d, number %d\n", type, bno); + print("mpintrassign: can't find bus type %d, number %d\n", type, bno); return -1; } @@ -346,65 +376,56 @@ Findbus: irq = (dno<<2)|(pin-1); else irq = -1; - } - else + } else irq = v->irq; /* * Find a matching interrupt entry from the list of interrupts * attached to this bus. */ - for(aintr = bus->aintr; aintr; aintr = aintr->next){ + for(aintr = bus->aintr; aintr != nil; aintr = aintr->next){ if(aintr->intr->irq != irq) continue; - if(0){ - PCMPintr* p = aintr->intr; - print("mpintrenablex: bus %d intin %d irq %d\n", - p->busno, p->intin, p->irq); - } + /* * Check if already enabled. Multifunction devices may share * INT[A-D]# so, if already enabled, check the polarity matches * and the trigger is level. - * - * Should check the devices differ only in the function number, - * but that can wait for the planned enable/disable rewrite. - * The RDT read here is safe for now as currently interrupts - * are never disabled once enabled. */ - apic = aintr->apic; - ioapicrdtr(apic, aintr->intr->intin, 0, &lo); - if(!(lo & ApicIMASK)){ - vno = lo & 0xFF; - if(0) print("%s vector %d (!imask)\n", v->name, vno); - n = mpintrinit(bus, aintr->intr, vno, v->irq); - n |= ApicPHYSICAL; /* no-op */ + ioapicrdtr(aintr->apic, aintr->intr->intin, &hi, &lo); + if(lo & ApicIMASK){ + v->vno = allocvector(); + v->cpu = mpintrcpu(); + lo = mpintrinit(aintr->bus, aintr->intr, v->vno, v->irq); + lo |= ApicPHYSICAL; /* no-op */ + if(lo & ApicIMASK){ + print("mpintrassign: disabled irq %d, tbdf %uX, lo %8.8uX, hi %8.8uX\n", + v->irq, v->tbdf, lo, hi); + break; + } + } else { + v->vno = lo & 0xFF; + v->cpu = hi >> 24; lo &= ~(ApicRemoteIRR|ApicDELIVS); - if(n != lo){ - print("mpintrenable: multiple botch irq %d, tbdf %uX, lo %8.8uX, n %8.8uX\n", - v->irq, tbdf, lo, n); - return -1; + n = mpintrinit(aintr->bus, aintr->intr, v->vno, v->irq); + n |= ApicPHYSICAL; /* no-op */ + if(lo != n){ + print("mpintrassign: multiple botch irq %d, tbdf %uX, lo %8.8uX, n %8.8uX\n", + v->irq, v->tbdf, lo, n); + break; } - v->isr = lapicisr; - v->eoi = lapiceoi; - return vno; - } - - vno = allocvector(); - hi = mpintrcpu()<<24; - lo = mpintrinit(bus, aintr->intr, vno, v->irq); - lo |= ApicPHYSICAL; /* no-op */ - if(lo & ApicIMASK){ - print("mpintrenable: disabled irq %d, tbdf %uX, lo %8.8uX, hi %8.8uX\n", - v->irq, tbdf, lo, hi); - return -1; } - if((apic->flags & PcmpEN) && apic->type == PcmpIOAPIC) - ioapicrdtw(apic, aintr->intr->intin, hi, lo); v->isr = lapicisr; v->eoi = lapiceoi; - return vno; + + if((aintr->apic->flags & PcmpEN) && aintr->apic->type == PcmpIOAPIC){ + v->aux = aintr; + v->enable = ioapicirqenable; + v->disable = ioapicirqdisable; + } + + return v->vno; } return -1; @@ -469,23 +490,29 @@ htmsienable(Pcidev *pdev) return -1; } -static void -msiintrdisable(Vctl *v) +static int +msiirqenable(Vctl *v, int) { - Pcidev *pci; + Pcidev *pci = v->aux; + return pcimsienable(pci, 0xFEE00000ULL | (v->cpu << 12), v->vno | (1<<14)); +} - if((pci = pcimatchtbdf(v->tbdf)) != nil) - pcimsidisable(pci); +static int +msiirqdisable(Vctl *v, int) +{ + Pcidev *pci = v->aux; + return pcimsidisable(pci); } static int msiintrenable(Vctl *v) { - int tbdf, vno, cpu; Pcidev *pci; + int tbdf; if(getconf("*nomsi") != nil) return -1; + tbdf = v->tbdf; if(tbdf == BUSUNKNOWN || BUSTYPE(tbdf) != BusPCI) return -1; @@ -498,18 +525,21 @@ msiintrenable(Vctl *v) return -1; if(pcimsidisable(pci) < 0) return -1; - vno = allocvector(); - cpu = mpintrcpu(); - if(pcimsienable(pci, 0xFEE00000ULL | (cpu << 12), vno | (1<<14)) < 0) - return -1; - v->disable = msiintrdisable; + + v->vno = allocvector(); + v->cpu = mpintrcpu(); v->isr = lapicisr; v->eoi = lapiceoi; - return vno; + + v->aux = pci; + v->enable = msiirqenable; + v->disable = msiirqdisable; + + return v->vno; } int -mpintrenable(Vctl* v) +mpintrassign(Vctl* v) { int irq, tbdf, vno; @@ -524,17 +554,18 @@ mpintrenable(Vctl* v) * breakpoint and page-fault). */ tbdf = v->tbdf; - if(tbdf != BUSUNKNOWN && (vno = mpintrenablex(v, tbdf)) != -1) + if(tbdf != BUSUNKNOWN && (vno = mpintrassignx(v, tbdf)) != -1) return vno; irq = v->irq; if(irq >= IrqLINT0 && irq <= MaxIrqLAPIC){ + v->local = 1; if(irq != IrqSPURIOUS) v->isr = lapiceoi; return VectorPIC+irq; } if(irq < 0 || irq > MaxIrqPIC){ - print("mpintrenable: irq %d out of range\n", irq); + print("mpintrassign: irq %d out of range\n", irq); return -1; } @@ -550,16 +581,16 @@ mpintrenable(Vctl* v) * be compatible with ISA. */ if(mpeisabus != -1){ - vno = mpintrenablex(v, MKBUS(BusEISA, 0, 0, 0)); + vno = mpintrassignx(v, MKBUS(BusEISA, 0, 0, 0)); if(vno != -1) return vno; } if(mpisabus != -1){ - vno = mpintrenablex(v, MKBUS(BusISA, 0, 0, 0)); + vno = mpintrassignx(v, MKBUS(BusISA, 0, 0, 0)); if(vno != -1) return vno; } - print("mpintrenable: out of choices eisa %d isa %d tbdf %uX irq %d\n", + print("mpintrassign: out of choices eisa %d isa %d tbdf %uX irq %d\n", mpeisabus, mpisabus, v->tbdf, v->irq); return -1; } diff --git a/sys/src/9/pc/mp.h b/sys/src/9/pc/mp.h index 4090f343e..802766cf6 100644 --- a/sys/src/9/pc/mp.h +++ b/sys/src/9/pc/mp.h @@ -168,6 +168,7 @@ typedef struct Bus { typedef struct Aintr { PCMPintr* intr; Apic* apic; + Bus* bus; Aintr* next; }; @@ -249,7 +250,7 @@ extern void lapictimerset(uvlong); extern int mpintrinit(Bus*, PCMPintr*, int, int); extern void mpinit(void); -extern int mpintrenable(Vctl*); +extern int mpintrassign(Vctl*); extern void mpshutdown(void); extern void mpstartap(Apic*); diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index 3f7816d6e..1b45434b1 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -96,6 +96,7 @@ link misc pci pcipc + archgeneric devkbd i8259 i8253 archacpi mp apic squidboy ec archmp mp apic squidboy mtrr diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c index 2d5d7cce9..c7dec7c13 100644 --- a/sys/src/9/pc/trap.c +++ b/sys/src/9/pc/trap.c @@ -66,6 +66,8 @@ trapinit(void) { irqinit(); + nmienable(); + /* * Special traps. * Syscall() is called directly without going through trap(). diff --git a/sys/src/9/pc64/dat.h b/sys/src/9/pc64/dat.h index 6cb1cc9ed..84efe9a2c 100644 --- a/sys/src/9/pc64/dat.h +++ b/sys/src/9/pc64/dat.h @@ -254,13 +254,12 @@ struct PCArch char* id; int (*ident)(void); /* this should be in the model */ void (*reset)(void); /* this should be in the model */ - int (*serialpower)(int); /* 1 == on, 0 == off */ - int (*modempower)(int); /* 1 == on, 0 == off */ void (*intrinit)(void); - int (*intrenable)(Vctl*); + int (*intrassign)(Vctl*); + int (*intrirqno)(int, int); int (*intrvecno)(int); - int (*intrdisable)(int); + int (*intrspurious)(int); void (*introff)(void); void (*intron)(void); diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h index b3408badb..5afd1c0b1 100644 --- a/sys/src/9/pc64/fns.h +++ b/sys/src/9/pc64/fns.h @@ -63,13 +63,6 @@ void i8253init(void); void i8253reset(void); uvlong i8253read(uvlong*); void i8253timerset(uvlong); -int i8259disable(int); -int i8259enable(Vctl*); -void i8259init(void); -int i8259isr(int); -void i8259on(void); -void i8259off(void); -int i8259vecno(int); void idle(void); void idlehands(void); int inb(int); @@ -109,6 +102,7 @@ char* mtrr(uvlong, uvlong, char *); void mtrrclock(void); int mtrrprint(char *, long); void mtrrsync(void); +void nmienable(void); void noteret(void); uchar nvramread(int); void nvramwrite(int, uchar); diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index c5ef1fbbe..b4891a04b 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -93,6 +93,7 @@ link misc pci pcipc + archgeneric devkbd i8259 i8253 archacpi mp apic squidboy ec archmp mp apic squidboy mtrr diff --git a/sys/src/9/pc64/trap.c b/sys/src/9/pc64/trap.c index c79bc4ec5..252462096 100644 --- a/sys/src/9/pc64/trap.c +++ b/sys/src/9/pc64/trap.c @@ -67,6 +67,8 @@ trapinit(void) { irqinit(); + nmienable(); + /* * Special traps. * Syscall() is called directly without going through trap(). diff --git a/sys/src/9/xen/archxen.c b/sys/src/9/xen/archxen.c index 50bf70f19..c4f1b5607 100644 --- a/sys/src/9/xen/archxen.c +++ b/sys/src/9/xen/archxen.c @@ -52,9 +52,7 @@ shutdown(void) HYPERVISOR_shutdown(1); } -int xenintrenable(Vctl *v); -int xenintrvecno(int irq); -int xenintrdisable(int irq); +int xenintrassign(Vctl *v); void xentimerenable(void); uvlong xentimerread(uvlong*); void xentimerset(uvlong); @@ -64,16 +62,14 @@ PCArch archxen = { .ident= identify, .reset= shutdown, .intrinit= intrinit, -.intrenable= xenintrenable, -.intrvecno= xenintrvecno, -.intrdisable= xenintrdisable, +.intrassign= xenintrassign, .clockenable= xentimerenable, .fastclock= xentimerread, .timerset= xentimerset, }; /* - * Placeholders to satisfy external references in generic devarch.c + * Placeholders to satisfy external references in devarch.c */ ulong getcr4(void) { return 0; } void putcr4(ulong) {} @@ -83,19 +79,7 @@ ulong inl(int) { return 0; } void outb(int, int) {} void outs(int, ushort) {} void outl(int, ulong) {} -void i8042reset(void) {} -void i8253enable(void) {} -void i8253init(void) {} -void i8253link(void) {} -uvlong i8253read(uvlong*) { return 0; } -void i8253timerset(uvlong) {} -int i8259disable(int) { return 0; } -int i8259enable(Vctl*) { return 0; } -void i8259init(void) {} -int i8259isr(int) { return 0; } -void i8259on(void) {} -void i8259off(void) {} -int i8259vecno(int) { return 0; } + int mtrrprint(char*, long) { return 0; } char* mtrr(uvlong, uvlong, char *) { return nil; } void mtrrsync(void) {} diff --git a/sys/src/9/xen/fns.h b/sys/src/9/xen/fns.h index 7289bd570..9dd3d239e 100644 --- a/sys/src/9/xen/fns.h +++ b/sys/src/9/xen/fns.h @@ -39,13 +39,6 @@ void i8253init(void); void i8253link(void); uvlong i8253read(uvlong*); void i8253timerset(uvlong); -int i8259disable(int); -int i8259enable(Vctl*); -void i8259init(void); -int i8259isr(int); -void i8259on(void); -void i8259off(void); -int i8259vecno(int); void idle(void); void idlehands(void); int inb(int); diff --git a/sys/src/9/xen/mkfile b/sys/src/9/xen/mkfile index 3a3ecc87b..e97857c01 100644 --- a/sys/src/9/xen/mkfile +++ b/sys/src/9/xen/mkfile @@ -71,6 +71,7 @@ OBJ=\ mmu.$O\ random.$O\ rdb.$O\ + irq.$O\ trap.$O\ $CONF.root.$O\ $CONF.rootc.$O\ diff --git a/sys/src/9/xen/trap.c b/sys/src/9/xen/trap.c index 8d77b8c43..0ed66fbd4 100644 --- a/sys/src/9/xen/trap.c +++ b/sys/src/9/xen/trap.c @@ -28,6 +28,9 @@ enum { void noted(Ureg*, ulong); +extern void irqinit(void); +extern int irqhandled(Ureg*, int); + static void debugbpt(Ureg*, void*); static void fault386(Ureg*, void*); static void safe_fault386(Ureg*, void*); @@ -35,148 +38,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; - -/**/ - SETUPLOG(dprint("intrenable: irq %d, f %p, a %p, tbdf 0x%x, name %s\n", - irq, f, a, tbdf, name);) -/**/ - if(f == nil){ - print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n", - irq, tbdf, name); - return; - } - - v = xalloc(sizeof(Vctl)); - 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\n", - vctl[vno]->name, v->name, - vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi); - v->next = vctl[vno]; - } - vctl[vno] = v; - SETUPLOG(dprint("INTRENABLE: vctl[%d] is %p\n", vno, vctl[vno]);) - iunlock(&vctllock); -} - -void -intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name) -{ - Vctl **pv, *v; - int vno; - - vno = arch->intrvecno(irq); - ilock(&vctllock); - for(pv = &vctl[vno]; (v = *pv) != nil; pv = &v->next){ - if(v->isintr && v->irq == irq - && v->tbdf == tbdf && v->f == f && v->a == a - && strcmp(v->name, name) == 0){ - *pv = v->next; - xfree(v); - - if(vctl[vno] == nil && arch->intrdisable != nil) - arch->intrdisable(irq); - break; - } - } - 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; vno<nelem(vctl); vno++){ - for(v=vctl[vno]; v; v=v->next){ - 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\n", vno); - v = xalloc(sizeof(Vctl)); - v->tbdf = BUSUNKNOWN; - v->f = f; - v->a = a; - strncpy(v->name, name, KNAMELEN); - v->name[KNAMELEN-1] = 0; - - lock(&vctllock); - if(vctl[vno]) - v->next = vctl[vno]->next; - vctl[vno] = v; - unlock(&vctllock); -} - -static void -nmienable(void) -{ - /* leave this here in case plan 9 ever makes it to dom0 */ -#ifdef NOWAY - /* - * Hack: should be locked with NVRAM access. - */ - outb(0x70, 0x80); /* NMI latch clear */ - outb(0x70, 0); - - x = inb(0x61) & 0x07; /* Enable NMI */ - outb(0x61, 0x08|x); - outb(0x61, x); -#endif -} - /* we started out doing the 'giant bulk init' for all traps. * we're going to do them one-by-one since error analysis is * so much easier that way. @@ -212,6 +73,8 @@ trapinit(void) vaddr += 6; } + irqinit(); + /* * Special traps. * Syscall() is called directly without going through trap(). @@ -220,9 +83,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] = { @@ -260,27 +120,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; - - 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; + char buf[ERRMAX]; - 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 */ @@ -304,120 +155,27 @@ kexit(Ureg*) * rather than directly vectoring the handler. However, this avoids a * lot of code duplication and possible bugs. The only exception is * VectorSYSCALL. - * Trap is called with interrupts (and events) disabled via interrupt-gates. + * Trap is called with interrupts disabled via interrupt-gates. */ void trap(Ureg* ureg) { - int clockintr, i, vno, user; - char buf[ERRMAX]; - Vctl *ctl, *v; - Mach *mach; + int vno, user; - TRAPLOG(dprint("trap ureg %lux %lux\n", (ulong*)ureg, ureg->trap);) - m->perf.intrts = perfticks(); - user = (ureg->cs & 0xFFFF) == UESEL; + user = userureg(ureg); if(user){ up->dbgreg = ureg; cycles(&up->kentry); } - clockintr = 0; - vno = ureg->trap; - if(vno < 0 || vno >= 256) - panic("bad interrupt number %d\n", vno); - TRAPLOG(dprint("trap: vno is 0x%x, vctl[%d] is %p\n", vno, vno, vctl[vno]);) - if(ctl = vctl[vno]){ - INTRLOG(dprint("ctl is %p, isintr is %d\n", ctl, ctl->isintr);) - if(ctl->isintr){ - m->intr++; - if(vno >= VectorPIC && vno != VectorSYSCALL) - m->lastintr = ctl->irq; - } - - INTRLOG(dprint("ctl %p, isr %p\n", ctl, ctl->isr);) - if(ctl->isr) - ctl->isr(vno); - for(v = ctl; v != nil; v = v->next){ - INTRLOG(dprint("ctl %p, f is %p\n", v, v->f);) - if(v->f) - v->f(ureg, v->a); - } - INTRLOG(dprint("ctl %p, eoi %p\n", ctl, ctl->eoi);) - if(ctl->eoi) - ctl->eoi(vno); - - if(ctl->isintr){ - intrtime(m, vno); - - //if(ctl->irq == IrqCLOCK || ctl->irq == IrqTIMER) - if (ctl->tbdf != BUSUNKNOWN && ctl->irq == VIRQ_TIMER) - 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); + if(!irqhandled(ureg, vno) && (!user || !usertrap(vno))){ + if(!user){ + /* early fault before trapinit() */ + if(vno == VectorPF) + fault386(ureg, 0); } - iprint("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){ - nmienable(); - if(m->machno != 0){ - print("cpu%d: PC %8.8luX\n", - m->machno, ureg->pc); - for(;;); - } - } dumpregs(ureg); if(!user){ ureg->sp = (ulong)&ureg->sp; @@ -425,18 +183,10 @@ trap(Ureg* ureg) } if(vno < nelem(excname)) panic("%s", excname[vno]); - panic("unknown trap/intr: %d\n", vno); + panic("unknown trap/intr: %d", vno); } splhi(); - /* delaysched set because we held a lock or because our quantum ended */ - if(up && up->delaysched && clockintr){ - INTRLOG(dprint("calling sched in trap? \n");) - sched(); - INTRLOG(dprint("Back from calling sched in trap?\n");) - splhi(); - } - if(user){ if(up->procctl || up->nnote) notify(ureg); diff --git a/sys/src/9/xen/xensystem.c b/sys/src/9/xen/xensystem.c index bff81afb3..82196d9ad 100644 --- a/sys/src/9/xen/xensystem.c +++ b/sys/src/9/xen/xensystem.c @@ -389,6 +389,26 @@ xenupcall(Ureg *ureg) } +static int +xenirqenable(Vctl *v, int shared) +{ + if(!shared){ + uint port = v->vno-100; + HYPERVISOR_shared_info->evtchn_mask[port/32] &= ~(1<<(port%32)); + } + return 0; +} + +static int +xenirqdisable(Vctl *v, int shared) +{ + if(!shared){ + uint port = v->vno-100; + HYPERVISOR_shared_info->evtchn_mask[port/32] |= (1<<(port%32)); + } + return 0; +} + /* * tbdf field is abused to distinguish virqs from channels: * @@ -396,37 +416,30 @@ xenupcall(Ureg *ureg) * tbdf=0 -> irq is a channel number */ int -xenintrenable(Vctl *v) +xenintrassign(Vctl *v) { evtchn_op_t op; uint port; - /* XXX locking? */ if (v->tbdf != BUSUNKNOWN) { op.cmd = EVTCHNOP_bind_virq; op.u.bind_virq.virq = v->irq; op.u.bind_virq.vcpu = m->machno; - if(HYPERVISOR_event_channel_op(&op) != 0) - panic("xenintrenable: bind %d failed", v->irq); + if(HYPERVISOR_event_channel_op(&op) != 0){ + print("xenintrenable: bind %d failed", v->irq); + return -1; + } port = op.u.bind_virq.port; } else port = v->irq; if (port > 155) return -1; - HYPERVISOR_shared_info->evtchn_mask[port/32] &= ~(1<<(port%32)); - if(0)print("xenintrenable %s: irq %d port %d mask[%d] = %#lux\n", v->name, v->irq, port, port/32, HYPERVISOR_shared_info->evtchn_mask[port/32]); + v->enable = xenirqenable; + v->disable = xenirqdisable; return 100+port; } int -xenintrdisable(int irq) -{ - USED(irq); - panic("xenintrdisable notyet\n"); - return 0; -} - -int xenintrvecno(int irq) { return irq; diff --git a/sys/src/9/xen/xentimer.c b/sys/src/9/xen/xentimer.c index 2a57cc5b9..4e6a2715e 100644 --- a/sys/src/9/xen/xentimer.c +++ b/sys/src/9/xen/xentimer.c @@ -68,7 +68,7 @@ xentimerclock(Ureg* ureg, void*) void xentimerenable(void) { - intrenable(VIRQ_TIMER, xentimerclock, nil, 0, "Xen Timer"); + intrenable(VIRQ_TIMER, xentimerclock, nil, 0, "clock"); } uvlong |
