From c5e2cf841d2502479a8f00c20ab70ab9ae325d69 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 26 Apr 2009 02:06:21 -0700 Subject: [PATCH] X86: Record the initial APIC ID which identifies an APIC in M5. 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 | 36 ++++++++++++++++-------------------- src/arch/x86/interrupts.hh | 2 ++ src/dev/x86/i82094aa.cc | 2 +- src/dev/x86/i82094aa.hh | 6 ++++-- 4 files changed, 23 insertions(+), 23 deletions(-) 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);