From 7476f0c4ee0af97516421bccc720b56fcf129930 Mon Sep 17 00:00:00 2001 From: "Peter H. Froehlich" Date: Sun, 18 Oct 2015 20:00:28 -0400 Subject: [PATCH] Proper masking, check against maxintr. --- ioapic.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/ioapic.c b/ioapic.c index fc3fc5e..be9bf19 100644 --- a/ioapic.c +++ b/ioapic.c @@ -10,6 +10,7 @@ #define REG_ID 0x00 // Register index: ID #define REG_VER 0x01 // Register index: version +#define REG_ARB 0x02 // Register index: arbitration ID #define REG_TABLE 0x10 // Redirection table base // The redirection table starts at REG_TABLE and uses @@ -17,38 +18,39 @@ // The first (low) register in a pair contains configuration bits. // The second (high) register contains a bitmask telling which // CPUs can serve that interrupt. -#define INT_DISABLED 0x00010000 // Interrupt disabled -#define INT_LEVEL 0x00008000 // Level-triggered (vs edge-) -#define INT_ACTIVELOW 0x00002000 // Active low (vs high) -#define INT_LOGICAL 0x00000800 // Destination is CPU id (vs APIC ID) +#define INT_DISABLED (1 << 16) // Interrupt disabled +#define INT_LEVEL (1 << 15) // Level-triggered (vs edge-) +#define INT_ACTIVELOW (1 << 13) // Active low (vs high) +#define INT_LOGICAL (1 << 11) // Destination is CPU id (vs APIC ID) volatile struct ioapic *ioapic; // Initialized in mp.c +static int maxintr; // Maximum number of interrupts // IO APIC MMIO structure: write reg, then read or write data. struct ioapic { - uint reg; - uint pad[3]; - uint data; + uint reg; // offset 00 + uint pad[3]; // offsets 04 08 0C + uint data; // offset 10 }; static uint ioapicread(int reg) { - ioapic->reg = reg; + ioapic->reg = (reg & 0xFF); // bits 0..7, see datasheet return ioapic->data; } static void ioapicwrite(int reg, uint data) { - ioapic->reg = reg; + ioapic->reg = (reg & 0xFF); // bits 0..7, see datasheet ioapic->data = data; } void ioapicinit(void) { - int i, id, maxintr; + int i, id; if(!ismp) return; @@ -57,8 +59,8 @@ ioapicinit(void) ioapic = (volatile struct ioapic*)IOAPIC; cprintf("ioapicinit: falling back to default ioapic address\n"); } - maxintr = (ioapicread(REG_VER) >> 16) & 0xFF; - id = ioapicread(REG_ID) >> 24; + maxintr = (ioapicread(REG_VER) >> 16) & 0xFF; // bits 16..23, see datasheet + id = (ioapicread(REG_ID) >> 24) & 0x0F; // bits 24..27, see datasheet if(id != ioapicid) cprintf("ioapicinit: id isn't equal to ioapicid; not a MP\n"); @@ -76,9 +78,14 @@ ioapicenable(int irq, int cpunum) if(!ismp) return; + if(irq > maxintr) + cprintf("ioapicenable: no irq %d, maximum is %d\n", irq, maxintr); + + cpunum = cpunum & 0x0F; // used as APIC id below, 4 bits, see datasheet + // Mark interrupt edge-triggered, active high, // enabled, and routed to the given cpunum, // which happens to be that cpu's APIC ID. ioapicwrite(REG_TABLE+2*irq, T_IRQ0 + irq); - ioapicwrite(REG_TABLE+2*irq+1, cpunum << 24); + ioapicwrite(REG_TABLE+2*irq+1, cpunum << 24); // bits 56..59, see datasheet } -- 2.50.1