X86: Start implementing the interrupt command register in the local APIC.
authorGabe Black <gblack@eecs.umich.edu>
Sun, 19 Apr 2009 09:43:22 +0000 (02:43 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sun, 19 Apr 2009 09:43:22 +0000 (02:43 -0700)
src/arch/x86/apicregs.hh
src/arch/x86/interrupts.cc
src/arch/x86/intmessage.hh

index 464c3af2dc790821847414305044d57e617f3fe2..dfea2650fe388613b4ca97433fcfcea7af2936b5 100644 (file)
@@ -31,6 +31,8 @@
 #ifndef __ARCH_X86_APICREGS_HH__
 #define __ARCH_X86_APICREGS_HH__
 
+#include "base/bitunion.hh"
+
 namespace X86ISA
 {
     enum ApicRegIndex
@@ -86,6 +88,20 @@ namespace X86ISA
     {
         return (ApicRegIndex)(APIC_INTERRUPT_REQUEST_BASE + index);
     }
+
+    BitUnion32(InterruptCommandRegLow)
+        Bitfield<7, 0> vector;
+        Bitfield<10, 8> deliveryMode;
+        Bitfield<11> destMode;
+        Bitfield<12> deliveryStatus;
+        Bitfield<14> level;
+        Bitfield<15> trigger;
+        Bitfield<19, 18> destShorthand;
+    EndBitUnion(InterruptCommandRegLow)
+
+    BitUnion32(InterruptCommandRegHigh)
+        Bitfield<31, 24> destination;
+    EndBitUnion(InterruptCommandRegHigh)
 }
 
 #endif
index 0603069a7053da1c054f243e4232585d05838cb4..7043840d21efd1225afcfb3382eb1102bea81d81 100644 (file)
@@ -60,6 +60,7 @@
 #include "arch/x86/intmessage.hh"
 #include "cpu/base.hh"
 #include "mem/packet_access.hh"
+#include "sim/system.hh"
 
 int
 divideFromConf(uint32_t conf)
@@ -366,14 +367,6 @@ X86ISA::Interrupts::readReg(ApicRegIndex reg)
       case APIC_ERROR_STATUS:
         regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
         break;
-      case APIC_INTERRUPT_COMMAND_LOW:
-        panic("Local APIC Interrupt Command low"
-                " register unimplemented.\n");
-        break;
-      case APIC_INTERRUPT_COMMAND_HIGH:
-        panic("Local APIC Interrupt Command high"
-                " register unimplemented.\n");
-        break;
       case APIC_CURRENT_COUNT:
         {
             if (apicTimerEvent.scheduled()) {
@@ -459,12 +452,40 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
         }
         break;
       case APIC_INTERRUPT_COMMAND_LOW:
-        panic("Local APIC Interrupt Command low"
-                " register unimplemented.\n");
-        break;
-      case APIC_INTERRUPT_COMMAND_HIGH:
-        panic("Local APIC Interrupt Command high"
-                " register unimplemented.\n");
+        {
+            InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
+            // Check if we're already sending an IPI.
+            if (low.deliveryStatus) {
+                newVal = low;
+                break;
+            }
+            low = val;
+            InterruptCommandRegHigh high = regs[APIC_INTERRUPT_COMMAND_HIGH];
+            // Record that an IPI is being sent.
+            low.deliveryStatus = 1;
+            TriggerIntMessage message;
+            message.destination = high.destination;
+            message.vector = low.vector;
+            message.deliveryMode = low.deliveryMode;
+            message.destMode = low.destMode;
+            message.level = low.level;
+            message.trigger = low.trigger;
+            bool timing = sys->getMemoryMode() == Enums::timing;
+            switch (low.destShorthand) {
+              case 0:
+                intPort->sendMessage(message, timing);
+                break;
+              case 1:
+                panic("Self IPIs aren't implemented.\n");
+                break;
+              case 2:
+                panic("Broadcast including self IPIs aren't implemented.\n");
+                break;
+              case 3:
+                panic("Broadcast excluding self IPIs aren't implemented.\n");
+                break;
+            }
+        }
         break;
       case APIC_LVT_TIMER:
       case APIC_LVT_THERMAL_SENSOR:
index f5f8519e2d4088a4274eed84eee6224c8aee3d7b..ec3a76c66b5f31e6de482bc99b618b9bed3d982a 100644 (file)
@@ -34,6 +34,7 @@
 #include "arch/x86/x86_traits.hh"
 #include "base/bitunion.hh"
 #include "mem/packet.hh"
+#include "mem/packet_access.hh"
 #include "mem/request.hh"
 #include "sim/host.hh"