From c8b29f6d038090a5b5b6272406afbadcf31e9809 Mon Sep 17 00:00:00 2001 From: kaashoek Date: Fri, 4 Aug 2006 18:12:31 +0000 Subject: [PATCH] better interrupt plan---this one appears to work ioapic --- Makefile | 1 + bio.c | 2 +- defs.h | 6 ++++ ide.c | 8 +++-- ioapic.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ ioapic.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ lapic.c | 6 ++++ main.c | 1 + mp.c | 31 ++++++++++++++----- picirq.c | 1 - syscall.c | 1 + 11 files changed, 217 insertions(+), 12 deletions(-) create mode 100644 ioapic.c create mode 100644 ioapic.h diff --git a/Makefile b/Makefile index d405284..c0153ad 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ OBJS = \ ide.o\ kalloc.o\ lapic.o\ + ioapic.o\ main.o\ mp.o\ picirq.o\ diff --git a/bio.c b/bio.c index c1a4bd6..602c915 100644 --- a/bio.c +++ b/bio.c @@ -43,7 +43,7 @@ bread(uint dev, uint sector) acquire(&ide_lock); c = ide_start_read(dev & 0xff, sector, b->data, 1); - // sleep (c, &ide_lock); + sleep (c, &ide_lock); ide_finish_read(c); release(&ide_lock); diff --git a/defs.h b/defs.h index c6c333b..1c28cc0 100644 --- a/defs.h +++ b/defs.h @@ -57,8 +57,14 @@ void lapic_timerinit(void); void lapic_timerintr(void); void lapic_enableintr(void); void lapic_disableintr(void); +void lapic_eoi(void); int cpu(void); +// ioapic +extern uchar ioapic_id; +void ioapic_init(void); +void ioapic_enable (int irq, int cpu); + // spinlock.c struct spinlock; void acquire(struct spinlock*); diff --git a/ide.c b/ide.c index 27a76fb..e2235a1 100644 --- a/ide.c +++ b/ide.c @@ -45,9 +45,12 @@ ide_wait_ready(int check_error) void ide_init(void) { - cprintf("ide_init: enable IRQ 14\n"); - irq_setmask_8259A(irq_mask_8259A & ~(1<<14)); + if (ncpu < 2) { + panic ("ide_init: disk interrupt is going to the second cpu\n"); + } + ioapic_enable (14, 1); // 14 is IRQ # for IDE ide_wait_ready(0); + cprintf ("ide_init:done\n"); } void @@ -57,6 +60,7 @@ ide_intr(void) cprintf("%d: ide_intr\n", cpu()); wakeup(&request[tail]); release(&ide_lock); + lapic_eoi(); } int diff --git a/ioapic.c b/ioapic.c new file mode 100644 index 0000000..776f895 --- /dev/null +++ b/ioapic.c @@ -0,0 +1,82 @@ +#include "types.h" +#include "mp.h" +#include "defs.h" +#include "x86.h" +#include "traps.h" +#include "ioapic.h" + +struct ioapic { + uint ioregsel; uint p01; uint p02; uint p03; + uint iowin; uint p11; uint p12; uint p13; +}; + + +#define IOAPIC_REDTBL_LO(i) (IOAPIC_REDTBL + (i) * 2) +#define IOAPIC_REDTBL_HI(i) (IOAPIC_REDTBL_LO(i) + 1) + +static uint +ioapic_read(struct ioapic *io, int reg) +{ + io->ioregsel = reg; + return (io->iowin); +} + +static void +ioapic_write(struct ioapic *io, int reg, uint val) +{ + io->ioregsel = reg; + io->iowin = val; +} + +void +ioapic_init(void) +{ + struct ioapic *io; + uint l, h; + int nintr; + uchar id; + int i; + + io = (struct ioapic *) IO_APIC_BASE; + l = ioapic_read(io, IOAPIC_VER); + nintr = ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1; + id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT; + if (id != ioapic_id) + panic ("ioapic_init: id isn't equal to ioapic_id\n"); + cprintf ("ioapic VER: 0x%x id %d nintr %d\n", l, id, nintr); + for (i = 0; i < nintr; i++) { + // active-hi and edge-triggered for ISA interrupts + // Assume that pin 0 on the first I/O APIC is an ExtINT pin. + // Assume that pins 1-15 are ISA interrupts and that all + l = ioapic_read(io, IOAPIC_REDTBL_LO(i)); + l = l & ~IOART_INTMASK; // allow INTs + l |= IOART_INTMSET; + l = l & ~IOART_INTPOL; // active hi + l = l & ~IOART_TRGRMOD; // edgee triggered + l = l & ~IOART_DELMOD; // fixed + l = l & ~IOART_DESTMOD; // physical mode + l = l | (IRQ_OFFSET + i); // vector + ioapic_write(io, IOAPIC_REDTBL_LO(i), l); + h = ioapic_read(io, IOAPIC_REDTBL_HI(i)); + h &= ~IOART_DEST; + ioapic_write(io, IOAPIC_REDTBL_HI(i), h); + // cprintf("intr %d: lo 0x%x hi 0x%x\n", i, l, h); + } +} + +void +ioapic_enable (int irq, int cpu) +{ + uint l, h; + struct ioapic *io; + + io = (struct ioapic *) IO_APIC_BASE; + l = ioapic_read(io, IOAPIC_REDTBL_LO(irq)); + l = l & ~IOART_INTMASK; // allow INTs + ioapic_write(io, IOAPIC_REDTBL_LO(irq), l); + h = ioapic_read(io, IOAPIC_REDTBL_HI(irq)); + h &= ~IOART_DEST; + h |= (cpu << APIC_ID_SHIFT); // for fun, disk interrupts to cpu 1 + ioapic_write(io, IOAPIC_REDTBL_HI(irq), h); + cprintf("intr %d: lo 0x%x hi 0x%x\n", irq, l, h); +} diff --git a/ioapic.h b/ioapic.h new file mode 100644 index 0000000..cd2fd5c --- /dev/null +++ b/ioapic.h @@ -0,0 +1,90 @@ +#define IO_APIC_BASE 0xFEC00000 /* default physical locations of an IO APIC */ +#define IOAPIC_WINDOW 0x10 /* window register offset */ + +/* constants relating to APIC ID registers */ +#define APIC_ID_MASK 0xff000000 +#define APIC_ID_SHIFT 24 +#define APIC_ID_CLUSTER 0xf0 +#define APIC_ID_CLUSTER_ID 0x0f +#define APIC_MAX_CLUSTER 0xe +#define APIC_MAX_INTRACLUSTER_ID 3 +#define APIC_ID_CLUSTER_SHIFT 4 + +/* fields in VER */ +#define APIC_VER_VERSION 0x000000ff +#define APIC_VER_MAXLVT 0x00ff0000 +#define MAXLVTSHIFT 16 + +/* Indexes into IO APIC */ +#define IOAPIC_ID 0x00 +#define IOAPIC_VER 0x01 +#define IOAPIC_ARB 0x02 +#define IOAPIC_REDTBL 0x10 +#define IOAPIC_REDTBL0 IOAPIC_REDTBL +#define IOAPIC_REDTBL1 (IOAPIC_REDTBL+0x02) +#define IOAPIC_REDTBL2 (IOAPIC_REDTBL+0x04) +#define IOAPIC_REDTBL3 (IOAPIC_REDTBL+0x06) +#define IOAPIC_REDTBL4 (IOAPIC_REDTBL+0x08) +#define IOAPIC_REDTBL5 (IOAPIC_REDTBL+0x0a) +#define IOAPIC_REDTBL6 (IOAPIC_REDTBL+0x0c) +#define IOAPIC_REDTBL7 (IOAPIC_REDTBL+0x0e) +#define IOAPIC_REDTBL8 (IOAPIC_REDTBL+0x10) +#define IOAPIC_REDTBL9 (IOAPIC_REDTBL+0x12) +#define IOAPIC_REDTBL10 (IOAPIC_REDTBL+0x14) +#define IOAPIC_REDTBL11 (IOAPIC_REDTBL+0x16) +#define IOAPIC_REDTBL12 (IOAPIC_REDTBL+0x18) +#define IOAPIC_REDTBL13 (IOAPIC_REDTBL+0x1a) +#define IOAPIC_REDTBL14 (IOAPIC_REDTBL+0x1c) +#define IOAPIC_REDTBL15 (IOAPIC_REDTBL+0x1e) +#define IOAPIC_REDTBL16 (IOAPIC_REDTBL+0x20) +#define IOAPIC_REDTBL17 (IOAPIC_REDTBL+0x22) +#define IOAPIC_REDTBL18 (IOAPIC_REDTBL+0x24) +#define IOAPIC_REDTBL19 (IOAPIC_REDTBL+0x26) +#define IOAPIC_REDTBL20 (IOAPIC_REDTBL+0x28) +#define IOAPIC_REDTBL21 (IOAPIC_REDTBL+0x2a) +#define IOAPIC_REDTBL22 (IOAPIC_REDTBL+0x2c) +#define IOAPIC_REDTBL23 (IOAPIC_REDTBL+0x2e) + +/* + * fields in the IO APIC's redirection table entries + */ +#define IOART_DEST APIC_ID_MASK /* broadcast addr: all APICs */ + +#define IOART_RESV 0x00fe0000 /* reserved */ + +#define IOART_INTMASK 0x00010000 /* R/W: INTerrupt mask */ +#define IOART_INTMCLR 0x00000000 /* clear, allow INTs */ +#define IOART_INTMSET 0x00010000 /* set, inhibit INTs */ + +#define IOART_TRGRMOD 0x00008000 /* R/W: trigger mode */ +#define IOART_TRGREDG 0x00000000 /* edge */ +#define IOART_TRGRLVL 0x00008000 /* level */ + +#define IOART_REM_IRR 0x00004000 /* RO: remote IRR */ + +#define IOART_INTPOL 0x00002000 /* R/W: INT input pin polarity */ +#define IOART_INTAHI 0x00000000 /* active high */ +#define IOART_INTALO 0x00002000 /* active low */ + +#define IOART_DELIVS 0x00001000 /* RO: delivery status */ + +#define IOART_DESTMOD 0x00000800 /* R/W: destination mode */ +#define IOART_DESTPHY 0x00000000 /* physical */ +#define IOART_DESTLOG 0x00000800 /* logical */ + +#define IOART_DELMOD 0x00000700 /* R/W: delivery mode */ +#define IOART_DELFIXED 0x00000000 /* fixed */ +#define IOART_DELLOPRI 0x00000100 /* lowest priority */ +#define IOART_DELSMI 0x00000200 /* System Management INT */ +#define IOART_DELRSV1 0x00000300 /* reserved */ +#define IOART_DELNMI 0x00000400 /* NMI signal */ +#define IOART_DELINIT 0x00000500 /* INIT signal */ +#define IOART_DELRSV2 0x00000600 /* reserved */ +#define IOART_DELEXINT 0x00000700 /* External INTerrupt */ + +#define IOART_INTVEC 0x000000ff /* R/W: INTerrupt vector field */ + +/* fields in VER */ +#define IOART_VER_VERSION 0x000000ff +#define IOART_VER_MAXREDIR 0x00ff0000 +#define MAXREDIRSHIFT 16 diff --git a/lapic.c b/lapic.c index 3aeda2f..f299b86 100644 --- a/lapic.c +++ b/lapic.c @@ -173,6 +173,12 @@ lapic_disableintr(void) lapic_write(LAPIC_TPR, 0xFF); } +void +lapic_eoi(void) +{ + lapic_write (LAPIC_EOI, 0); +} + int cpu(void) { diff --git a/main.c b/main.c index 3db7eab..021fb51 100644 --- a/main.c +++ b/main.c @@ -45,6 +45,7 @@ main0(void) cprintf("\nxV6\n\n"); pic_init(); // initialize PIC + ioapic_init(); kinit(); // physical memory allocator tvinit(); // trap vectors idtinit(); // CPU's idt diff --git a/mp.c b/mp.c index 4cb5db8..ece46a4 100644 --- a/mp.c +++ b/mp.c @@ -29,12 +29,12 @@ static char* buses[] = { 0, }; -#define APBOOTCODE 0x7000 // XXX hack - -static struct mp* mp; // The MP floating point structure struct cpu cpus[NCPU]; int ncpu; +uchar ioapic_id; + static struct cpu *bcpu; +static struct mp* mp; // The MP floating point structure static struct mp* mp_scan(uchar *addr, int len) @@ -112,7 +112,6 @@ mp_detect(void) if(sum || (pcmp->version != 1 && pcmp->version != 4)) return 3; - cprintf("Mp spec rev #: %x imcrp 0x%x\n", mp->specrev, mp->imcrp); return 0; } @@ -124,12 +123,15 @@ mp_init(void) struct mpctb *mpctb; struct mppe *proc; struct mpbe *bus; + struct mpioapic *ioapic; + struct mpie *intr; int i; + uchar byte; ncpu = 0; if ((r = mp_detect()) != 0) return; - cprintf ("This computer is a multiprocessor!\n"); + cprintf("Mp spec rev #: %x imcrp 0x%x\n", mp->specrev, mp->imcrp); /* * Run through the table saving information needed for starting @@ -164,11 +166,14 @@ mp_init(void) p += sizeof(struct mpbe); continue; case MPIOAPIC: - cprintf("an I/O APIC\n"); + ioapic = (struct mpioapic *) p; + cprintf("an I/O APIC: id %d %x\n", ioapic->apicno, ioapic->flags); + ioapic_id = ioapic->apicno; p += sizeof(struct mpioapic); continue; case MPIOINTR: - cprintf("an I/O intr\n"); + intr = (struct mpie *) p; + // cprintf("an I/O intr: type %d flags 0x%x bus %d souce bus irq %d dest ioapic id %d dest ioapic intin %d\n", intr->intr, intr->flags, intr->busno, intr->irq, intr->apicno, intr->intin); p += sizeof(struct mpie); continue; default: @@ -180,10 +185,18 @@ mp_init(void) break; } } - + + if (mp->imcrp) { // it appears that bochs doesn't support IMCR, and code won't run + outb(0x22, 0x70); /* select IMCR */ + byte = inb(0x23); /* current contents */ + byte |= 0x01; /* mask external INTR */ + outb(0x23, byte); /* disconnect 8259s/NMI */ + } + cprintf("ncpu: %d boot %d\n", ncpu, bcpu-cpus); } + int mp_bcpu(void) { @@ -192,6 +205,8 @@ mp_bcpu(void) extern void mpmain(void); +#define APBOOTCODE 0x7000 // XXX hack + void mp_startthem(void) { diff --git a/picirq.c b/picirq.c index 9818090..e774e6d 100644 --- a/picirq.c +++ b/picirq.c @@ -67,7 +67,6 @@ pic_init(void) if (irq_mask_8259A != 0xFFFF) irq_setmask_8259A(irq_mask_8259A); - } void diff --git a/syscall.c b/syscall.c index 43be534..77a16cd 100644 --- a/syscall.c +++ b/syscall.c @@ -415,6 +415,7 @@ sys_block(void) struct inode *ip; for (i = 0; i < 2; i++) { + cprintf ("issue read\n"); b = bread(1, i); cprintf("disk 1 sector %d: ", i);