Gabe Black has submitted this change. (
https://gem5-review.googlesource.com/c/public/gem5/+/55695 )
Change subject: arch-x86,dev: Use INTA to get the vector for the IO APIC.
......................................................................
arch-x86,dev: Use INTA to get the vector for the IO APIC.
When receiving an ExtInt at the IO APIC, use an INTA and not a direct
pointer to find the vector to use.
Change-Id: I173f99645c3bbd20de9cbeb17e00b4f91ac66089
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55695
Reviewed-by: Gabe Black <gabe.bl...@gmail.com>
Maintainer: Gabe Black <gabe.bl...@gmail.com>
Tested-by: kokoro <noreply+kok...@google.com>
---
M src/arch/x86/intmessage.hh
M src/dev/x86/I82094AA.py
M src/dev/x86/SouthBridge.py
M src/dev/x86/i82094aa.cc
M src/dev/x86/i82094aa.hh
M src/dev/x86/pc.cc
6 files changed, 105 insertions(+), 65 deletions(-)
Approvals:
Gabe Black: Looks good to me, approved; Looks good to me, approved
kokoro: Regressions pass
diff --git a/src/arch/x86/intmessage.hh b/src/arch/x86/intmessage.hh
index e775e2a..f7692e2 100644
--- a/src/arch/x86/intmessage.hh
+++ b/src/arch/x86/intmessage.hh
@@ -88,6 +88,17 @@
return buildIntPacket(addr, message);
}
+ static inline PacketPtr
+ buildIntAcknowledgePacket()
+ {
+ RequestPtr req = std::make_shared<Request>(
+ PhysAddrIntA, 1, Request::UNCACHEABLE,
+ Request::intRequestorId);
+ PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
+ pkt->allocate();
+ return pkt;
+ }
+
} // namespace X86ISA
} // namespace gem5
diff --git a/src/dev/x86/I82094AA.py b/src/dev/x86/I82094AA.py
index 212bca3..591c8d1 100644
--- a/src/dev/x86/I82094AA.py
+++ b/src/dev/x86/I82094AA.py
@@ -38,6 +38,5 @@
int_requestor = RequestPort("Port for sending interrupt messages")
int_latency = Param.Latency('1ns', \
"Latency for an interrupt to propagate through this device.")
- external_int_pic = Param.I8259(NULL, "External PIC, if any")
inputs = VectorIntSinkPin('The pins that drive this IO APIC')
diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py
index 6570cac..35866a7 100644
--- a/src/dev/x86/SouthBridge.py
+++ b/src/dev/x86/SouthBridge.py
@@ -81,7 +81,6 @@
# Tell the devices about each other
self.pic1.slave = self.pic2
self.speaker.i8254 = self.pit
- self.io_apic.external_int_pic = self.pic1
# Connect to the bus
self.cmos.pio = bus.mem_side_ports
self.dma1.pio = bus.mem_side_ports
diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc
index f5e51b0..437b462 100644
--- a/src/dev/x86/i82094aa.cc
+++ b/src/dev/x86/i82094aa.cc
@@ -43,8 +43,7 @@
{
X86ISA::I82094AA::I82094AA(const Params &p)
- : BasicPioDevice(p, 20), extIntPic(p.external_int_pic),
- lowestPriorityOffset(0),
+ : BasicPioDevice(p, 20), lowestPriorityOffset(0),
intRequestPort(name() + ".int_request", this, this, p.int_latency)
{
// This assumes there's only one I/O APIC in the system and since the
apic
@@ -179,7 +178,7 @@
}
void
-X86ISA::I82094AA::signalInterrupt(int line)
+X86ISA::I82094AA::requestInterrupt(int line)
{
DPRINTF(I82094AA, "Received interrupt %d.\n", line);
assert(line < TableSize);
@@ -187,67 +186,83 @@
if (entry.mask) {
DPRINTF(I82094AA, "Entry was masked.\n");
return;
+ }
+
+ TriggerIntMessage message = 0;
+
+ message.destination = entry.dest;
+ message.deliveryMode = entry.deliveryMode;
+ message.destMode = entry.destMode;
+ message.level = entry.polarity;
+ message.trigger = entry.trigger;
+
+ if (entry.deliveryMode == delivery_mode::ExtInt) {
+ // We need to ask the I8259 for the vector.
+ PacketPtr pkt = buildIntAcknowledgePacket();
+ auto on_completion = [this, message](PacketPtr pkt) {
+ auto msg_copy = message;
+ msg_copy.vector = pkt->getLE<uint8_t>();
+ signalInterrupt(msg_copy);
+ delete pkt;
+ };
+ intRequestPort.sendMessage(pkt, sys->isTimingMode(),
+ on_completion);
} else {
- TriggerIntMessage message = 0;
- message.destination = entry.dest;
- if (entry.deliveryMode == delivery_mode::ExtInt) {
- assert(extIntPic);
- message.vector = extIntPic->getVector();
- } else {
- message.vector = entry.vector;
+ message.vector = entry.vector;
+ signalInterrupt(message);
+ }
+}
+
+void
+X86ISA::I82094AA::signalInterrupt(TriggerIntMessage message)
+{
+ std::list<int> apics;
+ int numContexts = sys->threads.size();
+ if (message.destMode == 0) {
+ if (message.deliveryMode == delivery_mode::LowestPriority) {
+ panic("Lowest priority delivery mode from the "
+ "IO APIC aren't supported in physical "
+ "destination mode.\n");
}
- message.deliveryMode = entry.deliveryMode;
- message.destMode = entry.destMode;
- message.level = entry.polarity;
- message.trigger = entry.trigger;
- std::list<int> apics;
- int numContexts = sys->threads.size();
- if (message.destMode == 0) {
- if (message.deliveryMode == delivery_mode::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 {
+ if (message.destination == 0xFF) {
for (int i = 0; i < numContexts; i++) {
- BaseInterrupts *base_int = sys->threads[i]->
- getCpuPtr()->getInterruptController(0);
- auto *localApic = dynamic_cast<Interrupts *>(base_int);
- if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) &
- message.destination) {
- apics.push_back(localApic->getInitialApicId());
- }
+ apics.push_back(i);
}
- if (message.deliveryMode == delivery_mode::LowestPriority &&
- apics.size()) {
- // The manual seems to suggest that the chipset just does
- // something reasonable for these instead of actually using
- // state from the local APIC. We'll just rotate an offset
- // through the set of APICs selected above.
- uint64_t modOffset = lowestPriorityOffset % apics.size();
- lowestPriorityOffset++;
- auto apicIt = apics.begin();
- while (modOffset--) {
- apicIt++;
- assert(apicIt != apics.end());
- }
- int selected = *apicIt;
- apics.clear();
- apics.push_back(selected);
+ } else {
+ apics.push_back(message.destination);
+ }
+ } else {
+ for (int i = 0; i < numContexts; i++) {
+ BaseInterrupts *base_int = sys->threads[i]->
+ getCpuPtr()->getInterruptController(0);
+ auto *localApic = dynamic_cast<Interrupts *>(base_int);
+ if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) &
+ message.destination) {
+ apics.push_back(localApic->getInitialApicId());
}
}
- for (auto id: apics) {
- PacketPtr pkt = buildIntTriggerPacket(id, message);
- intRequestPort.sendMessage(pkt, sys->isTimingMode());
+ if (message.deliveryMode == delivery_mode::LowestPriority &&
+ apics.size()) {
+ // The manual seems to suggest that the chipset just does
+ // something reasonable for these instead of actually using
+ // state from the local APIC. We'll just rotate an offset
+ // through the set of APICs selected above.
+ uint64_t modOffset = lowestPriorityOffset % apics.size();
+ lowestPriorityOffset++;
+ auto apicIt = apics.begin();
+ while (modOffset--) {
+ apicIt++;
+ assert(apicIt != apics.end());
+ }
+ int selected = *apicIt;
+ apics.clear();
+ apics.push_back(selected);
}
}
+ for (auto id: apics) {
+ PacketPtr pkt = buildIntTriggerPacket(id, message);
+ intRequestPort.sendMessage(pkt, sys->isTimingMode());
+ }
}
void
@@ -255,7 +270,7 @@
{
assert(number < TableSize);
if (!pinStates[number])
- signalInterrupt(number);
+ requestInterrupt(number);
pinStates[number] = true;
}
diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh
index 6427dbf..b50d122 100644
--- a/src/dev/x86/i82094aa.hh
+++ b/src/dev/x86/i82094aa.hh
@@ -31,6 +31,7 @@
#include <map>
+#include "arch/x86/intmessage.hh"
#include "base/bitunion.hh"
#include "dev/x86/intdev.hh"
#include "dev/intpin.hh"
@@ -43,7 +44,6 @@
namespace X86ISA
{
-class I8259;
class Interrupts;
class I82094AA : public BasicPioDevice
@@ -66,8 +66,6 @@
EndBitUnion(RedirTableEntry)
protected:
- I8259 * extIntPic;
-
uint8_t regSel;
uint8_t initialApicId;
uint8_t id;
@@ -87,6 +85,8 @@
IntRequestPort<I82094AA> intRequestPort;
+ void signalInterrupt(TriggerIntMessage message);
+
public:
using Params = I82094AAParams;
@@ -105,7 +105,7 @@
bool recvResponse(PacketPtr pkt);
- void signalInterrupt(int line);
+ void requestInterrupt(int line);
void raiseInterruptPin(int number);
void lowerInterruptPin(int number);
diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc
index 71881aa..e7f4636 100644
--- a/src/dev/x86/pc.cc
+++ b/src/dev/x86/pc.cc
@@ -107,7 +107,7 @@
void
Pc::postConsoleInt()
{
- southBridge->ioApic->signalInterrupt(4);
+ southBridge->ioApic->requestInterrupt(4);
southBridge->pic1->signalInterrupt(4);
}
@@ -121,7 +121,7 @@
void
Pc::postPciInt(int line)
{
- southBridge->ioApic->signalInterrupt(line);
+ southBridge->ioApic->requestInterrupt(line);
}
void
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/55695
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I173f99645c3bbd20de9cbeb17e00b4f91ac66089
Gerrit-Change-Number: 55695
Gerrit-PatchSet: 14
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-Reviewer: Andreas Sandberg <andreas.sandb...@arm.com>
Gerrit-Reviewer: Bradford Beckmann <bradford.beckm...@gmail.com>
Gerrit-Reviewer: Gabe Black <gabe.bl...@gmail.com>
Gerrit-Reviewer: Matt Sinclair <mattdsincl...@gmail.com>
Gerrit-Reviewer: kokoro <noreply+kok...@google.com>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s