better interrupt plan---this one appears to work

ioapic
This commit is contained in:
kaashoek 2006-08-04 18:12:31 +00:00
parent 32630628a9
commit c8b29f6d03
11 changed files with 217 additions and 12 deletions

View file

@ -4,6 +4,7 @@ OBJS = \
ide.o\
kalloc.o\
lapic.o\
ioapic.o\
main.o\
mp.o\
picirq.o\

2
bio.c
View file

@ -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);

6
defs.h
View file

@ -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*);

8
ide.c
View file

@ -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

82
ioapic.c Normal file
View file

@ -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);
}

90
ioapic.h Normal file
View file

@ -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

View file

@ -173,6 +173,12 @@ lapic_disableintr(void)
lapic_write(LAPIC_TPR, 0xFF);
}
void
lapic_eoi(void)
{
lapic_write (LAPIC_EOI, 0);
}
int
cpu(void)
{

1
main.c
View file

@ -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
mp.c
View file

@ -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:
@ -181,9 +186,17 @@ mp_init(void)
}
}
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)
{

View file

@ -67,7 +67,6 @@ pic_init(void)
if (irq_mask_8259A != 0xFFFF)
irq_setmask_8259A(irq_mask_8259A);
}
void

View file

@ -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);