diff options
| author | kaashoek <kaashoek> | 2006-08-04 18:12:31 +0000 | 
|---|---|---|
| committer | kaashoek <kaashoek> | 2006-08-04 18:12:31 +0000 | 
| commit | c8b29f6d038090a5b5b6272406afbadcf31e9809 (patch) | |
| tree | bc3c7a2592eb7e8cadfc903e518683eaa564b35f | |
| parent | 32630628a996e29018641af262272339ed6fef88 (diff) | |
| download | xv6-labs-c8b29f6d038090a5b5b6272406afbadcf31e9809.tar.gz xv6-labs-c8b29f6d038090a5b5b6272406afbadcf31e9809.tar.bz2 xv6-labs-c8b29f6d038090a5b5b6272406afbadcf31e9809.zip  | |
better interrupt plan---this one appears to work
ioapic
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | bio.c | 2 | ||||
| -rw-r--r-- | defs.h | 6 | ||||
| -rw-r--r-- | ide.c | 8 | ||||
| -rw-r--r-- | ioapic.c | 82 | ||||
| -rw-r--r-- | ioapic.h | 90 | ||||
| -rw-r--r-- | lapic.c | 6 | ||||
| -rw-r--r-- | main.c | 1 | ||||
| -rw-r--r-- | mp.c | 31 | ||||
| -rw-r--r-- | picirq.c | 1 | ||||
| -rw-r--r-- | syscall.c | 1 | 
11 files changed, 217 insertions, 12 deletions
@@ -4,6 +4,7 @@ OBJS = \  	ide.o\  	kalloc.o\  	lapic.o\ +	ioapic.o\  	main.o\  	mp.o\  	picirq.o\ @@ -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); @@ -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*); @@ -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 @@ -173,6 +173,12 @@ lapic_disableintr(void)    lapic_write(LAPIC_TPR, 0xFF);  } +void +lapic_eoi(void) +{ +  lapic_write (LAPIC_EOI, 0); +} +  int  cpu(void)  { @@ -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 @@ -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)  { @@ -67,7 +67,6 @@ pic_init(void)    if (irq_mask_8259A != 0xFFFF)      irq_setmask_8259A(irq_mask_8259A); -  }  void @@ -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);  | 
