]> hydra-www.ietfng.org Git - xv6-public/commitdiff
Proper masking, check against maxintr.
authorPeter H. Froehlich <peter.hans.froehlich@gmail.com>
Mon, 19 Oct 2015 00:00:28 +0000 (20:00 -0400)
committerPeter H. Froehlich <peter.hans.froehlich@gmail.com>
Mon, 19 Oct 2015 00:00:28 +0000 (20:00 -0400)
ioapic.c

index fc3fc5ee237cd34193a46da07fe55d87d997adcf..be9bf1916c70425c6d62cbb9faabd33200645344 100644 (file)
--- 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
 // 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
 }