x86: De-x86ify the IntMasterPort.

The devices which host an IntMasterPort are very specific to x86 at the
moment, but the ports don't have to be. This change moves
responsibilities around so that the x86 specific aspects are handled
in the device, and the ports themselves are ISA agnostic.

Change-Id: I50141b66895be7d8f6303605505002ef424af7fd
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20827
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc
index d4ee9f6..1b21835 100644
--- a/src/arch/x86/interrupts.cc
+++ b/src/arch/x86/interrupts.cc
@@ -51,6 +51,7 @@
 
 #include "arch/x86/interrupts.hh"
 
+#include <list>
 #include <memory>
 
 #include "arch/x86/intmessage.hh"
@@ -484,7 +485,7 @@
             message.destMode = low.destMode;
             message.level = low.level;
             message.trigger = low.trigger;
-            ApicList apics;
+            std::list<int> apics;
             int numContexts = sys->numContexts();
             switch (low.destShorthand) {
               case 0:
@@ -545,7 +546,10 @@
                 pendingIPIs += apics.size();
             }
             regs[APIC_INTERRUPT_COMMAND_LOW] = low;
-            intMasterPort.sendMessage(apics, message, sys->isTimingMode());
+            for (auto id: apics) {
+                PacketPtr pkt = buildIntTriggerPacket(id, message);
+                intMasterPort.sendMessage(pkt, sys->isTimingMode());
+            }
             newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
         }
         break;
diff --git a/src/arch/x86/intmessage.hh b/src/arch/x86/intmessage.hh
index d2a5dfa..bf1e5c4 100644
--- a/src/arch/x86/intmessage.hh
+++ b/src/arch/x86/intmessage.hh
@@ -34,6 +34,7 @@
 #include "arch/x86/x86_traits.hh"
 #include "base/bitunion.hh"
 #include "base/types.hh"
+#include "dev/x86/intdev.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
 #include "mem/request.hh"
@@ -76,16 +77,11 @@
 
     static const Addr TriggerIntOffset = 0;
 
-    template<class T>
-    PacketPtr
-    buildIntPacket(Addr addr, T payload)
+    static inline PacketPtr
+    buildIntTriggerPacket(int id, TriggerIntMessage message)
     {
-        RequestPtr req = std::make_shared<Request>(
-            addr, sizeof(T), Request::UNCACHEABLE, Request::intMasterId);
-        PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
-        pkt->allocate();
-        pkt->setRaw<T>(payload);
-        return pkt;
+        Addr addr = x86InterruptAddress(id, TriggerIntOffset);
+        return buildIntPacket(addr, message);
     }
 }
 
diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc
index 5daebe7..17ac65f 100644
--- a/src/dev/x86/i82094aa.cc
+++ b/src/dev/x86/i82094aa.cc
@@ -30,6 +30,8 @@
 
 #include "dev/x86/i82094aa.hh"
 
+#include <list>
+
 #include "arch/x86/interrupts.hh"
 #include "arch/x86/intmessage.hh"
 #include "cpu/base.hh"
@@ -205,7 +207,7 @@
         message.destMode = entry.destMode;
         message.level = entry.polarity;
         message.trigger = entry.trigger;
-        ApicList apics;
+        std::list<int> apics;
         int numContexts = sys->numContexts();
         if (message.destMode == 0) {
             if (message.deliveryMode == DeliveryMode::LowestPriority) {
@@ -237,7 +239,7 @@
                 // through the set of APICs selected above.
                 uint64_t modOffset = lowestPriorityOffset % apics.size();
                 lowestPriorityOffset++;
-                ApicList::iterator apicIt = apics.begin();
+                auto apicIt = apics.begin();
                 while (modOffset--) {
                     apicIt++;
                     assert(apicIt != apics.end());
@@ -247,7 +249,10 @@
                 apics.push_back(selected);
             }
         }
-        intMasterPort.sendMessage(apics, message, sys->isTimingMode());
+        for (auto id: apics) {
+            PacketPtr pkt = buildIntTriggerPacket(id, message);
+            intMasterPort.sendMessage(pkt, sys->isTimingMode());
+        }
     }
 }
 
diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh
index 0529280..48d32d7 100644
--- a/src/dev/x86/intdev.hh
+++ b/src/dev/x86/intdev.hh
@@ -44,10 +44,8 @@
 #define __DEV_X86_INTDEV_HH__
 
 #include <cassert>
-#include <list>
 #include <string>
 
-#include "arch/x86/intmessage.hh"
 #include "mem/tport.hh"
 #include "sim/sim_object.hh"
 
@@ -83,7 +81,17 @@
     }
 };
 
-typedef std::list<int> ApicList;
+template<class T>
+PacketPtr
+buildIntPacket(Addr addr, T payload)
+{
+    RequestPtr req = std::make_shared<Request>(
+        addr, sizeof(T), Request::UNCACHEABLE, Request::intMasterId);
+    PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
+    pkt->allocate();
+    pkt->setRaw<T>(payload);
+    return pkt;
+}
 
 template <class Device>
 class IntMasterPort : public QueuedMasterPort
@@ -109,24 +117,18 @@
         return device->recvResponse(pkt);
     }
 
-    // This is x86 focused, so if this class becomes generic, this would
-    // need to be moved into a subclass.
     void
-    sendMessage(X86ISA::ApicList apics, TriggerIntMessage message, bool timing)
+    sendMessage(PacketPtr pkt, bool timing)
     {
-        for (auto id: apics) {
-            Addr addr = x86InterruptAddress(id, TriggerIntOffset);
-            PacketPtr pkt = buildIntPacket(addr, message);
-            if (timing) {
-                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);
-            }
+        if (timing) {
+            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);
         }
     }
 };