diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 60ea6215b..dc4193f36 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -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 range = RangeEx(x86LocalAPICAddress(id, 0), - x86LocalAPICAddress(id, 0) + PageBytes); + Range 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)); diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index 72a852ada..33fafd941 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -191,6 +191,8 @@ class Interrupts : public BasicPioDevice, IntDev BaseCPU *cpu; + int initialApicId; + public: /* * Params stuff. diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index 21332c3ae..e55f1ec87 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -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; diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index 598e218f8..7501259c1 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -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);