bool timing = sys->getMemoryMode() == Enums::timing;
// Be careful no updates of the delivery status bit get lost.
regs[APIC_INTERRUPT_COMMAND_LOW] = low;
+ ApicList apics;
+ int numContexts = sys->numContexts();
switch (low.destShorthand) {
case 0:
- pendingIPIs++;
- intPort->sendMessage(message, timing);
- newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
+ if (message.deliveryMode == DeliveryMode::LowestPriority) {
+ panic("Lowest priority delivery mode "
+ "IPIs aren't implemented.\n");
+ }
+ if (message.destMode == 1) {
+ int dest = message.destination;
+ hack_once("Assuming logical destinations are 1 << id.\n");
+ for (int i = 0; i < numContexts; i++) {
+ if (dest & 0x1)
+ apics.push_back(i);
+ dest = dest >> 1;
+ }
+ } else {
+ if (message.destination == 0xFF) {
+ for (int i = 0; i < numContexts; i++) {
+ if (i == initialApicId) {
+ requestInterrupt(message.vector,
+ message.deliveryMode, message.trigger);
+ } else {
+ apics.push_back(i);
+ }
+ }
+ } else {
+ if (message.destination == initialApicId) {
+ requestInterrupt(message.vector,
+ message.deliveryMode, message.trigger);
+ } else {
+ apics.push_back(message.destination);
+ }
+ }
+ }
break;
case 1:
newVal = val;
// Fall through
case 3:
{
- int numContexts = sys->numContexts();
- pendingIPIs += (numContexts - 1);
for (int i = 0; i < numContexts; i++) {
- int thisId = sys->getThreadContext(i)->contextId();
- if (thisId != initialApicId) {
- PacketPtr pkt = buildIntRequest(thisId, message);
- if (timing)
- intPort->sendMessageTiming(pkt, latency);
- else
- intPort->sendMessageAtomic(pkt);
+ if (i != initialApicId) {
+ apics.push_back(i);
}
}
}
- newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
break;
}
+ pendingIPIs += apics.size();
+ intPort->sendMessage(apics, message, timing);
+ newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
}
break;
case APIC_LVT_TIMER:
* Authors: Gabe Black
*/
+#include "arch/x86/interrupts.hh"
#include "arch/x86/intmessage.hh"
#include "dev/x86/i82094aa.hh"
#include "dev/x86/i8259.hh"
message.destMode = entry.destMode;
message.level = entry.polarity;
message.trigger = entry.trigger;
- intPort->sendMessage(message, sys->getMemoryMode() == Enums::timing);
+ ApicList apics;
+ int numContexts = sys->numContexts();
+ if (message.destMode == 0) {
+ if (message.deliveryMode == DeliveryMode::LowestPriority) {
+ panic("Lowest priority delivery mode from the "
+ "IO APIC aren't supported in physical "
+ "destination mode.\n");
+ }
+ if (message.destination == 0xFF) {
+ for (int i = 0; i < numContexts; i++) {
+ apics.push_back(i);
+ }
+ } else {
+ apics.push_back(message.destination);
+ }
+ } else {
+ for (int i = 0; i < numContexts; i++) {
+ std::map<int, Interrupts *>::iterator localApicIt =
+ localApics.find(i);
+ assert(localApicIt != localApics.end());
+ Interrupts *localApic = localApicIt->second;
+ if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) &
+ message.destination) {
+ apics.push_back(localApicIt->first);
+ }
+ }
+ if (message.deliveryMode == DeliveryMode::LowestPriority) {
+ panic("Lowest priority delivery mode is not implemented.\n");
+ }
+ }
+ intPort->sendMessage(apics, message,
+ sys->getMemoryMode() == Enums::timing);
}
}
#include "dev/x86/intdev.hh"
void
-X86ISA::IntDev::IntPort::sendMessage(TriggerIntMessage message, bool timing)
+X86ISA::IntDev::IntPort::sendMessage(ApicList apics,
+ TriggerIntMessage message, bool timing)
{
- if (DeliveryMode::isReserved(message.deliveryMode)) {
- fatal("Tried to use reserved delivery mode %d\n",
- message.deliveryMode);
- } else if (DTRACE(IntDev)) {
- DPRINTF(IntDev, "Delivery mode is: %s.\n",
- DeliveryMode::names[message.deliveryMode]);
- DPRINTF(IntDev, "Vector is %#x.\n", message.vector);
- }
- if (message.destMode == 0) {
- DPRINTF(IntDev,
- "Sending interrupt to APIC ID %d.\n", message.destination);
- PacketPtr pkt = buildIntRequest(message.destination, message);
- if (timing) {
+ ApicList::iterator apicIt;
+ for (apicIt = apics.begin(); apicIt != apics.end(); apicIt++) {
+ PacketPtr pkt = buildIntRequest(*apicIt, message);
+ if (timing)
sendMessageTiming(pkt, latency);
- } else {
+ else
sendMessageAtomic(pkt);
- }
- } else {
- DPRINTF(IntDev, "Sending interrupts to APIC IDs:"
- "%s%s%s%s%s%s%s%s\n",
- bits((int)message.destination, 0) ? " 0": "",
- bits((int)message.destination, 1) ? " 1": "",
- bits((int)message.destination, 2) ? " 2": "",
- bits((int)message.destination, 3) ? " 3": "",
- bits((int)message.destination, 4) ? " 4": "",
- bits((int)message.destination, 5) ? " 5": "",
- bits((int)message.destination, 6) ? " 6": "",
- bits((int)message.destination, 7) ? " 7": ""
- );
- uint8_t dests = message.destination;
- uint8_t id = 0;
- while(dests) {
- if (dests & 0x1) {
- PacketPtr pkt = buildIntRequest(id, message);
- if (timing)
- sendMessageTiming(pkt, latency);
- else
- sendMessageAtomic(pkt);
- }
- dests >>= 1;
- id++;
- }
}
}
#include "params/X86IntSinkPin.hh"
#include "params/X86IntLine.hh"
+#include <list>
+
namespace X86ISA {
+typedef std::list<int> ApicList;
+
class IntDev
{
protected:
// This is x86 focused, so if this class becomes generic, this would
// need to be moved into a subclass.
- void sendMessage(TriggerIntMessage message, bool timing);
+ void sendMessage(ApicList apics,
+ TriggerIntMessage message, bool timing);
void recvStatusChange(Status status)
{