X86: Record the initial APIC ID which identifies an APIC in M5.
authorGabe Black <gblack@eecs.umich.edu>
Sun, 26 Apr 2009 09:06:21 +0000 (02:06 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sun, 26 Apr 2009 09:06:21 +0000 (02:06 -0700)
The ID as exposed to software can be changed. Tracking those changes in M5
would be cumbersome, especially since there's no guarantee the IDs will remain
unique.

src/arch/x86/interrupts.cc
src/arch/x86/interrupts.hh
src/dev/x86/i82094aa.cc
src/dev/x86/i82094aa.hh

index 60ea6215be00dba6929d751b24e9dbf6f1843aad..dc4193f363169e786b69201905bafe90d4e418ac 100644 (file)
@@ -295,17 +295,21 @@ X86ISA::Interrupts::requestInterrupt(uint8_t vector,
 void
 X86ISA::Interrupts::setCPU(BaseCPU * newCPU)
 {
+    assert(newCPU);
+    if (cpu != NULL && cpu->cpuId() != newCPU->cpuId()) {
+        panic("Local APICs can't be moved between CPUs"
+                " with different IDs.\n");
+    }
     cpu = newCPU;
-    assert(cpu);
-    regs[APIC_ID] = (cpu->cpuId() << 24);
+    initialApicId = cpu->cpuId();
+    regs[APIC_ID] = (initialApicId << 24);
 }
 
 
 Tick
 X86ISA::Interrupts::recvMessage(PacketPtr pkt)
 {
-    uint8_t id = (regs[APIC_ID] >> 24);
-    Addr offset = pkt->getAddr() - x86InterruptAddress(id, 0);
+    Addr offset = pkt->getAddr() - x86InterruptAddress(initialApicId, 0);
     assert(pkt->cmd == MemCmd::MessageReq);
     switch(offset)
     {
@@ -315,9 +319,6 @@ X86ISA::Interrupts::recvMessage(PacketPtr pkt)
             DPRINTF(LocalApic,
                     "Got Trigger Interrupt message with vector %#x.\n",
                     message.vector);
-            // Make sure we're really supposed to get this.
-            assert((message.destMode == 0 && message.destination == id) ||
-                   (bits((int)message.destination, id)));
 
             requestInterrupt(message.vector,
                     message.deliveryMode, message.trigger);
@@ -354,10 +355,10 @@ X86ISA::Interrupts::recvResponse(PacketPtr pkt)
 void
 X86ISA::Interrupts::addressRanges(AddrRangeList &range_list)
 {
-    uint8_t id = (regs[APIC_ID] >> 24);
     range_list.clear();
-    Range<Addr> range = RangeEx(x86LocalAPICAddress(id, 0),
-                                x86LocalAPICAddress(id, 0) + PageBytes);
+    Range<Addr> range = RangeEx(x86LocalAPICAddress(initialApicId, 0),
+                                x86LocalAPICAddress(initialApicId, 0) + 
+                                PageBytes);
     range_list.push_back(range);
     pioAddr = range.start;
 }
@@ -366,10 +367,10 @@ X86ISA::Interrupts::addressRanges(AddrRangeList &range_list)
 void
 X86ISA::Interrupts::getIntAddrRange(AddrRangeList &range_list)
 {
-    uint8_t id = (regs[APIC_ID] >> 24);
     range_list.clear();
-    range_list.push_back(RangeEx(x86InterruptAddress(id, 0),
-                x86InterruptAddress(id, 0) + PhysAddrAPICRangeSize));
+    range_list.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
+                x86InterruptAddress(initialApicId, 0) +
+                PhysAddrAPICRangeSize));
 }
 
 
@@ -515,14 +516,9 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
                 {
                     int numContexts = sys->numContexts();
                     pendingIPIs += (numContexts - 1);
-                    // We have no way to get at the thread context we're part
-                    // of, so we'll just have to go with the CPU for now.
-                    hack_once("Broadcast IPIs can't handle more than "
-                            "one context per CPU.\n");
-                    int myId = cpu->getContext(0)->contextId();
                     for (int i = 0; i < numContexts; i++) {
                         int thisId = sys->getThreadContext(i)->contextId();
-                        if (thisId != myId) {
+                        if (thisId != initialApicId) {
                             PacketPtr pkt = buildIntRequest(thisId, message);
                             if (timing)
                                 intPort->sendMessageTiming(pkt, latency);
@@ -589,7 +585,7 @@ X86ISA::Interrupts::Interrupts(Params * p) :
     pendingInit(false), initVector(0),
     pendingStartup(false), startupVector(0),
     startedUp(false), pendingUnmaskableInt(false),
-    pendingIPIs(0)
+    pendingIPIs(0), cpu(NULL)
 {
     pioSize = PageBytes;
     memset(regs, 0, sizeof(regs));
index 72a852adaa434d7ebf8adb41b6239783b9624a75..33fafd9415a147dffc4c1ae811669e2219d63b78 100644 (file)
@@ -191,6 +191,8 @@ class Interrupts : public BasicPioDevice, IntDev
 
     BaseCPU *cpu;
 
+    int initialApicId;
+
   public:
     /*
      * Params stuff.
index 21332c3ae6f5335465449937c35e4ebb034ca8ae..e55f1ec87fb329010caf530f0ce0e4be324ecd2e 100644 (file)
@@ -40,7 +40,7 @@ X86ISA::I82094AA::I82094AA(Params *p) : PioDevice(p), IntDev(this),
     extIntPic(p->external_int_pic)
 {
     // This assumes there's only one I/O APIC in the system
-    id = p->apic_id;
+    initialApicId = id = p->apic_id;
     assert(id <= 0xf);
     arbId = id;
     regSel = 0;
index 598e218f858672c6137ee6f65c774d3819af767a..7501259c12bacfe44a418b87e4b0ce1d0a9b59e9 100644 (file)
@@ -68,6 +68,7 @@ class I82094AA : public PioDevice, public IntDev
     I8259 * extIntPic;
 
     uint8_t regSel;
+    uint8_t initialApicId;
     uint8_t id;
     uint8_t arbId;
 
@@ -103,8 +104,9 @@ class I82094AA : public PioDevice, public IntDev
     void getIntAddrRange(AddrRangeList &range_list)
     {
         range_list.clear();
-        range_list.push_back(RangeEx(x86InterruptAddress(id, 0),
-                    x86InterruptAddress(id, 0) + PhysAddrAPICRangeSize));
+        range_list.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
+                    x86InterruptAddress(initialApicId, 0) +
+                    PhysAddrAPICRangeSize));
     }
 
     void writeReg(uint8_t offset, uint32_t value);