X86: Implement broadcast IPIs.
This commit is contained in:
parent
829e424353
commit
f82c123242
|
@ -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));
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue