summaryrefslogtreecommitdiff
path: root/src/arch/x86
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-04-19 04:14:01 -0700
committerGabe Black <gblack@eecs.umich.edu>2009-04-19 04:14:01 -0700
commitf82c1232427b744609fe8bfaa398a69ceaf3a068 (patch)
treeb0fcf83256310d177fc193ae70d74e33cf34cdc0 /src/arch/x86
parent829e424353b4a51acd3c0211ef7108e3883d971a (diff)
downloadgem5-f82c1232427b744609fe8bfaa398a69ceaf3a068.tar.xz
X86: Implement broadcast IPIs.
Diffstat (limited to 'src/arch/x86')
-rw-r--r--src/arch/x86/interrupts.cc44
-rw-r--r--src/arch/x86/interrupts.hh3
2 files changed, 38 insertions, 9 deletions
diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc
index e51fef623..60ea6215b 100644
--- a/src/arch/x86/interrupts.cc
+++ b/src/arch/x86/interrupts.cc
@@ -338,10 +338,12 @@ X86ISA::Interrupts::recvResponse(PacketPtr pkt)
{
assert(!pkt->isError());
assert(pkt->cmd == MemCmd::MessageResp);
- InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
- // Record that the ICR is now idle.
- low.deliveryStatus = 0;
- regs[APIC_INTERRUPT_COMMAND_LOW] = low;
+ if (--pendingIPIs == 0) {
+ InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
+ // Record that the ICR is now idle.
+ low.deliveryStatus = 0;
+ regs[APIC_INTERRUPT_COMMAND_LOW] = low;
+ }
delete pkt->req;
delete pkt;
DPRINTF(LocalApic, "ICR is now idle.\n");
@@ -496,17 +498,40 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
regs[APIC_INTERRUPT_COMMAND_LOW] = low;
switch (low.destShorthand) {
case 0:
+ pendingIPIs++;
intPort->sendMessage(message, timing);
newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
break;
case 1:
- panic("Self IPIs aren't implemented.\n");
+ newVal = val;
+ requestInterrupt(message.vector,
+ message.deliveryMode, message.trigger);
break;
case 2:
- panic("Broadcast including self IPIs aren't implemented.\n");
- break;
+ requestInterrupt(message.vector,
+ message.deliveryMode, message.trigger);
+ // Fall through
case 3:
- panic("Broadcast excluding self IPIs aren't implemented.\n");
+ {
+ 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) {
+ PacketPtr pkt = buildIntRequest(thisId, message);
+ if (timing)
+ intPort->sendMessageTiming(pkt, latency);
+ else
+ intPort->sendMessageAtomic(pkt);
+ }
+ }
+ }
+ newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
break;
}
}
@@ -563,7 +588,8 @@ X86ISA::Interrupts::Interrupts(Params * p) :
pendingExtInt(false), extIntVector(0),
pendingInit(false), initVector(0),
pendingStartup(false), startupVector(0),
- startedUp(false), pendingUnmaskableInt(false)
+ startedUp(false), pendingUnmaskableInt(false),
+ pendingIPIs(0)
{
pioSize = PageBytes;
memset(regs, 0, sizeof(regs));
diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh
index 6ae77d7e3..1f3a414ce 100644
--- a/src/arch/x86/interrupts.hh
+++ b/src/arch/x86/interrupts.hh
@@ -136,6 +136,9 @@ class Interrupts : public BasicPioDevice, IntDev
// This is a quick check whether any of the above (except ExtInt) are set.
bool pendingUnmaskableInt;
+ // A count of how many IPIs are in flight.
+ int pendingIPIs;
+
/*
* IRR and ISR maintenance.
*/