X86: Implement broadcast IPIs.

This commit is contained in:
Gabe Black 2009-04-19 04:14:01 -07:00
parent 829e424353
commit f82c123242
2 changed files with 38 additions and 9 deletions

View file

@ -338,10 +338,12 @@ X86ISA::Interrupts::recvResponse(PacketPtr pkt)
{ {
assert(!pkt->isError()); assert(!pkt->isError());
assert(pkt->cmd == MemCmd::MessageResp); assert(pkt->cmd == MemCmd::MessageResp);
InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW]; if (--pendingIPIs == 0) {
// Record that the ICR is now idle. InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
low.deliveryStatus = 0; // Record that the ICR is now idle.
regs[APIC_INTERRUPT_COMMAND_LOW] = low; low.deliveryStatus = 0;
regs[APIC_INTERRUPT_COMMAND_LOW] = low;
}
delete pkt->req; delete pkt->req;
delete pkt; delete pkt;
DPRINTF(LocalApic, "ICR is now idle.\n"); 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; regs[APIC_INTERRUPT_COMMAND_LOW] = low;
switch (low.destShorthand) { switch (low.destShorthand) {
case 0: case 0:
pendingIPIs++;
intPort->sendMessage(message, timing); intPort->sendMessage(message, timing);
newVal = regs[APIC_INTERRUPT_COMMAND_LOW]; newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
break; break;
case 1: case 1:
panic("Self IPIs aren't implemented.\n"); newVal = val;
requestInterrupt(message.vector,
message.deliveryMode, message.trigger);
break; break;
case 2: case 2:
panic("Broadcast including self IPIs aren't implemented.\n"); requestInterrupt(message.vector,
break; message.deliveryMode, message.trigger);
// Fall through
case 3: 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; break;
} }
} }
@ -563,7 +588,8 @@ X86ISA::Interrupts::Interrupts(Params * p) :
pendingExtInt(false), extIntVector(0), pendingExtInt(false), extIntVector(0),
pendingInit(false), initVector(0), pendingInit(false), initVector(0),
pendingStartup(false), startupVector(0), pendingStartup(false), startupVector(0),
startedUp(false), pendingUnmaskableInt(false) startedUp(false), pendingUnmaskableInt(false),
pendingIPIs(0)
{ {
pioSize = PageBytes; pioSize = PageBytes;
memset(regs, 0, sizeof(regs)); memset(regs, 0, sizeof(regs));

View file

@ -136,6 +136,9 @@ class Interrupts : public BasicPioDevice, IntDev
// This is a quick check whether any of the above (except ExtInt) are set. // This is a quick check whether any of the above (except ExtInt) are set.
bool pendingUnmaskableInt; bool pendingUnmaskableInt;
// A count of how many IPIs are in flight.
int pendingIPIs;
/* /*
* IRR and ISR maintenance. * IRR and ISR maintenance.
*/ */