mem-cache: Add multiple eviction stats
[gem5.git] / src / arch / x86 / interrupts.cc
index 10387c07afd2b8947abc7915f8ca941c01672a81..b447216d9d88dec974813e0116b925904ee550fb 100644 (file)
  * Authors: Gabe Black
  */
 
+#include "arch/x86/interrupts.hh"
+
+#include <list>
 #include <memory>
 
-#include "arch/x86/regs/apic.hh"
-#include "arch/x86/interrupts.hh"
 #include "arch/x86/intmessage.hh"
+#include "arch/x86/regs/apic.hh"
 #include "cpu/base.hh"
 #include "debug/LocalApic.hh"
 #include "dev/x86/i82094aa.hh"
 #include "dev/x86/pc.hh"
 #include "dev/x86/south_bridge.hh"
 #include "mem/packet_access.hh"
-#include "sim/system.hh"
 #include "sim/full_system.hh"
+#include "sim/system.hh"
 
 int
 divideFromConf(uint32_t conf)
@@ -190,11 +192,11 @@ Tick
 X86ISA::Interrupts::read(PacketPtr pkt)
 {
     Addr offset = pkt->getAddr() - pioAddr;
-    //Make sure we're at least only accessing one register.
+    // Make sure we're at least only accessing one register.
     if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
         panic("Accessed more than one register at a time in the APIC!\n");
     ApicRegIndex reg = decodeAddr(offset);
-    uint32_t val = htog(readReg(reg));
+    uint32_t val = htole(readReg(reg));
     DPRINTF(LocalApic,
             "Reading Local APIC register %d at offset %#x as %#x.\n",
             reg, offset, val);
@@ -207,7 +209,7 @@ Tick
 X86ISA::Interrupts::write(PacketPtr pkt)
 {
     Addr offset = pkt->getAddr() - pioAddr;
-    //Make sure we're at least only accessing one register.
+    // Make sure we're at least only accessing one register.
     if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
         panic("Accessed more than one register at a time in the APIC!\n");
     ApicRegIndex reg = decodeAddr(offset);
@@ -215,8 +217,8 @@ X86ISA::Interrupts::write(PacketPtr pkt)
     pkt->writeData(((uint8_t *)&val) + (offset & mask(3)));
     DPRINTF(LocalApic,
             "Writing Local APIC register %d at offset %#x as %#x.\n",
-            reg, offset, gtoh(val));
-    setReg(reg, gtoh(val));
+            reg, offset, letoh(val));
+    setReg(reg, letoh(val));
     pkt->makeAtomicResponse();
     return pioDelay;
 }
@@ -288,17 +290,13 @@ X86ISA::Interrupts::setCPU(BaseCPU * newCPU)
 void
 X86ISA::Interrupts::init()
 {
-    //
-    // The local apic must register its address ranges on both its pio
-    // port via the basicpiodevice(piodevice) init() function and its
-    // int port that it inherited from IntDevice.  Note IntDevice is
-    // not a SimObject itself.
-    //
-    BasicPioDevice::init();
-    IntDevice::init();
-
-    // the slave port has a range so inform the connected master
+    panic_if(!intMasterPort.isConnected(),
+            "Int port not connected to anything!");
+    panic_if(!pioPort.isConnected(),
+            "Pio port of %s not connected to anything!", name());
+
     intSlavePort.sendRangeChange();
+    pioPort.sendRangeChange();
 }
 
 
@@ -306,12 +304,12 @@ Tick
 X86ISA::Interrupts::recvMessage(PacketPtr pkt)
 {
     Addr offset = pkt->getAddr() - x86InterruptAddress(initialApicId, 0);
-    assert(pkt->cmd == MemCmd::MessageReq);
+    assert(pkt->cmd == MemCmd::WriteReq);
     switch(offset)
     {
       case 0:
         {
-            TriggerIntMessage message = pkt->get<TriggerIntMessage>();
+            TriggerIntMessage message = pkt->getRaw<TriggerIntMessage>();
             DPRINTF(LocalApic,
                     "Got Trigger Interrupt message with vector %#x.\n",
                     message.vector);
@@ -330,11 +328,9 @@ X86ISA::Interrupts::recvMessage(PacketPtr pkt)
 }
 
 
-Tick
-X86ISA::Interrupts::recvResponse(PacketPtr pkt)
+void
+X86ISA::Interrupts::completeIPI(PacketPtr pkt)
 {
-    assert(!pkt->isError());
-    assert(pkt->cmd == MemCmd::MessageResp);
     if (--pendingIPIs == 0) {
         InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
         // Record that the ICR is now idle.
@@ -342,7 +338,17 @@ X86ISA::Interrupts::recvResponse(PacketPtr pkt)
         regs[APIC_INTERRUPT_COMMAND_LOW] = low;
     }
     DPRINTF(LocalApic, "ICR is now idle.\n");
-    return 0;
+    delete pkt;
+}
+
+
+AddrRangeList
+X86ISA::Interrupts::getAddrRanges() const
+{
+    assert(cpu);
+    AddrRangeList ranges;
+    ranges.push_back(RangeSize(pioAddr, PageBytes));
+    return ranges;
 }
 
 
@@ -474,7 +480,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
             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:
@@ -535,7 +541,11 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
                 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(),
+                        [this](PacketPtr pkt) { completeIPI(pkt); });
+            }
             newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
         }
         break;
@@ -586,8 +596,8 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
 
 
 X86ISA::Interrupts::Interrupts(Params * p)
-    : BasicPioDevice(p, PageBytes), IntDevice(this, p->int_latency),
-      apicTimerEvent(this),
+    : BaseInterrupts(p), sys(p->system), clockDomain(*p->clk_domain),
+      apicTimerEvent([this]{ processApicTimerEvent(); }, name()),
       pendingSmi(false), smiVector(0),
       pendingNmi(false), nmiVector(0),
       pendingExtInt(false), extIntVector(0),
@@ -595,13 +605,17 @@ X86ISA::Interrupts::Interrupts(Params * p)
       pendingStartup(false), startupVector(0),
       startedUp(false), pendingUnmaskableInt(false),
       pendingIPIs(0), cpu(NULL),
-      intSlavePort(name() + ".int_slave", this, this)
+      intSlavePort(name() + ".int_slave", this, this),
+      intMasterPort(name() + ".int_master", this, this, p->int_latency),
+      pioPort(this), pioDelay(p->pio_latency)
 {
     memset(regs, 0, sizeof(regs));
     //Set the local apic DFR to the flat model.
     regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1);
     ISRV = 0;
     IRRV = 0;
+
+    regs[APIC_VERSION] = (5 << 16) | 0x14;
 }
 
 
@@ -766,3 +780,9 @@ X86LocalApicParams::create()
 {
     return new X86ISA::Interrupts(this);
 }
+
+void
+X86ISA::Interrupts::processApicTimerEvent() {
+    if (triggerTimerInterrupt())
+        setReg(APIC_INITIAL_COUNT, readReg(APIC_INITIAL_COUNT));
+}