better interrupt plan---this one appears to work
ioapic
This commit is contained in:
parent
32630628a9
commit
c8b29f6d03
1
Makefile
1
Makefile
|
@ -4,6 +4,7 @@ OBJS = \
|
|||
ide.o\
|
||||
kalloc.o\
|
||||
lapic.o\
|
||||
ioapic.o\
|
||||
main.o\
|
||||
mp.o\
|
||||
picirq.o\
|
||||
|
|
2
bio.c
2
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);
|
||||
|
||||
|
|
6
defs.h
6
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*);
|
||||
|
|
8
ide.c
8
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
|
||||
|
|
82
ioapic.c
Normal file
82
ioapic.c
Normal 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
90
ioapic.h
Normal 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
|
6
lapic.c
6
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)
|
||||
{
|
||||
|
|
1
main.c
1
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
|
||||
|
|
29
mp.c
29
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:
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
1
picirq.c
1
picirq.c
|
@ -67,7 +67,6 @@ pic_init(void)
|
|||
|
||||
if (irq_mask_8259A != 0xFFFF)
|
||||
irq_setmask_8259A(irq_mask_8259A);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue