summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-04-26 02:06:21 -0700
committerGabe Black <gblack@eecs.umich.edu>2009-04-26 02:06:21 -0700
commitc5e2cf841d2502479a8f00c20ab70ab9ae325d69 (patch)
treecddec849e22944583155adb0400511c1773346e3
parent8d84f81e7041bd26320b0795800100f2aa298965 (diff)
downloadgem5-c5e2cf841d2502479a8f00c20ab70ab9ae325d69.tar.xz
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.
-rw-r--r--src/arch/x86/interrupts.cc36
-rw-r--r--src/arch/x86/interrupts.hh2
-rw-r--r--src/dev/x86/i82094aa.cc2
-rw-r--r--src/dev/x86/i82094aa.hh6
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<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));
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);