x86: Use a std::function to handle MSI completion.

This removes the recvResponse callback from the IntMasterPort, and
makes it easier to handle the default case where we just need to clean
up the Packet.

Change-Id: I8bcbfee0aaf68b12310d773f925c399fc87ea65d
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20828
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Brandon Potter <Brandon.Potter@amd.com>
This commit is contained in:
Gabe Black
2019-09-11 16:11:11 -07:00
parent d856e5ce71
commit 245422102c
4 changed files with 21 additions and 20 deletions

View File

@@ -331,11 +331,9 @@ X86ISA::Interrupts::recvMessage(PacketPtr pkt)
}
bool
X86ISA::Interrupts::recvResponse(PacketPtr pkt)
void
X86ISA::Interrupts::completeIPI(PacketPtr pkt)
{
assert(!pkt->isError());
assert(pkt->cmd == MemCmd::WriteResp);
if (--pendingIPIs == 0) {
InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
// Record that the ICR is now idle.
@@ -343,7 +341,7 @@ X86ISA::Interrupts::recvResponse(PacketPtr pkt)
regs[APIC_INTERRUPT_COMMAND_LOW] = low;
}
DPRINTF(LocalApic, "ICR is now idle.\n");
return true;
delete pkt;
}
@@ -548,7 +546,8 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
regs[APIC_INTERRUPT_COMMAND_LOW] = low;
for (auto id: apics) {
PacketPtr pkt = buildIntTriggerPacket(id, message);
intMasterPort.sendMessage(pkt, sys->isTimingMode());
intMasterPort.sendMessage(pkt, sys->isTimingMode(),
[this](PacketPtr pkt) { completeIPI(pkt); });
}
newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
}

View File

@@ -206,7 +206,7 @@ class Interrupts : public PioDevice
Tick read(PacketPtr pkt) override;
Tick write(PacketPtr pkt) override;
Tick recvMessage(PacketPtr pkt);
bool recvResponse(PacketPtr pkt);
void completeIPI(PacketPtr pkt);
bool
triggerTimerInterrupt()

View File

@@ -89,14 +89,6 @@ X86ISA::I82094AA::getPort(const std::string &if_name, PortID idx)
return BasicPioDevice::getPort(if_name, idx);
}
bool
X86ISA::I82094AA::recvResponse(PacketPtr pkt)
{
// Packet instantiated calling sendMessage() in signalInterrupt()
delete pkt;
return true;
}
Tick
X86ISA::I82094AA::read(PacketPtr pkt)
{

View File

@@ -44,6 +44,7 @@
#define __DEV_X86_INTDEV_HH__
#include <cassert>
#include <functional>
#include <string>
#include "mem/tport.hh"
@@ -96,12 +97,18 @@ buildIntPacket(Addr addr, T payload)
template <class Device>
class IntMasterPort : public QueuedMasterPort
{
private:
ReqPacketQueue reqQueue;
SnoopRespPacketQueue snoopRespQueue;
Device* device;
Tick latency;
typedef std::function<void(PacketPtr)> OnCompletionFunc;
OnCompletionFunc onCompletion = nullptr;
// If nothing extra needs to happen, just clean up the packet.
static void defaultOnCompletion(PacketPtr pkt) { delete pkt; }
public:
IntMasterPort(const std::string& _name, SimObject* _parent,
Device* dev, Tick _latency) :
@@ -114,21 +121,24 @@ class IntMasterPort : public QueuedMasterPort
bool
recvTimingResp(PacketPtr pkt) override
{
return device->recvResponse(pkt);
assert(pkt->isResponse());
onCompletion(pkt);
onCompletion = nullptr;
return true;
}
void
sendMessage(PacketPtr pkt, bool timing)
sendMessage(PacketPtr pkt, bool timing,
OnCompletionFunc func=defaultOnCompletion)
{
if (timing) {
onCompletion = func;
schedTimingReq(pkt, curTick() + latency);
// The target handles cleaning up the packet in timing mode.
} else {
// ignore the latency involved in the atomic transaction
sendAtomic(pkt);
assert(pkt->isResponse());
// also ignore the latency in handling the response
device->recvResponse(pkt);
func(pkt);
}
}
};