x86: Turn the local APIC into a PioDevice instead of a BasicPioDevice.
authorGabe Black <gabeblack@google.com>
Tue, 10 Sep 2019 00:44:54 +0000 (17:44 -0700)
committerGabe Black <gabeblack@google.com>
Sat, 21 Sep 2019 05:05:18 +0000 (05:05 +0000)
This will let us accept several address ranges through our pio port
instead of just one, and that will in turn let us accept interrupt
requests and pio requests through the same port.

Change-Id: I70b78c8cd0edca7fe58b3d4cd241e41d9e0f2c20
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20819
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/arch/x86/X86LocalApic.py
src/arch/x86/interrupts.cc
src/arch/x86/interrupts.hh

index c1b835ccbab52a796a0e4ccc2bfa04dbdf60a363..456409a62b92cfe9ccf7b163c965d4635f97f953 100644 (file)
@@ -42,10 +42,10 @@ from m5.defines import buildEnv
 from m5.params import *
 from m5.proxy import *
 
-from m5.objects.Device import BasicPioDevice
+from m5.objects.Device import PioDevice
 from m5.objects.ClockDomain import DerivedClockDomain
 
-class X86LocalApic(BasicPioDevice):
+class X86LocalApic(PioDevice):
     type = 'X86LocalApic'
     cxx_class = 'X86ISA::Interrupts'
     cxx_header = 'arch/x86/interrupts.hh'
@@ -54,10 +54,7 @@ class X86LocalApic(BasicPioDevice):
     int_latency = Param.Latency('1ns', \
             "Latency for an interrupt to propagate through this device.")
 
-    # pio_addr isn't used by the local APIC model since it's address is
-    # calculated dynamically using the initial ID of the CPU it's attached to,
-    # but it needs to be set to something to make the BasicPioDevice happy.
-    pio_addr = 0x2000000000000000
+    pio_latency = Param.Latency('100ns', 'Programmed IO latency')
 
     # The clock rate for the local APIC timer is supposed to be the "bus clock"
     # which we assume is 1/16th the rate of the CPU clock. I don't think this
index 8ba1819482c3d6ddcebe502d648d7008fa5a09b7..b7d02353758d60a34f90270b2124ad0d171f9670 100644 (file)
@@ -191,7 +191,7 @@ 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);
@@ -208,7 +208,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);
@@ -295,7 +295,7 @@ X86ISA::Interrupts::init()
     // int port that it inherited from IntDevice.  Note IntDevice is
     // not a SimObject itself.
     //
-    BasicPioDevice::init();
+    PioDevice::init();
     IntDevice::init();
 
     // the slave port has a range so inform the connected master
@@ -347,6 +347,16 @@ X86ISA::Interrupts::recvResponse(PacketPtr pkt)
 }
 
 
+AddrRangeList
+X86ISA::Interrupts::getAddrRanges() const
+{
+    assert(cpu);
+    AddrRangeList ranges;
+    ranges.push_back(RangeSize(pioAddr, PageBytes));
+    return ranges;
+}
+
+
 AddrRangeList
 X86ISA::Interrupts::getIntAddrRange() const
 {
@@ -587,7 +597,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
 
 
 X86ISA::Interrupts::Interrupts(Params * p)
-    : BasicPioDevice(p, PageBytes), IntDevice(this, p->int_latency),
+    : PioDevice(p), IntDevice(this, p->int_latency),
       apicTimerEvent([this]{ processApicTimerEvent(); }, name()),
       pendingSmi(false), smiVector(0),
       pendingNmi(false), nmiVector(0),
@@ -596,7 +606,8 @@ 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),
+      pioDelay(p->pio_latency)
 {
     memset(regs, 0, sizeof(regs));
     //Set the local apic DFR to the flat model.
index dfdff2b3f6ab3f5944e583923481067a5ed52631..bd674cc7e84c1c77f90c81fcac3298644171e02e 100644 (file)
@@ -72,7 +72,7 @@ namespace X86ISA {
 
 ApicRegIndex decodeAddr(Addr paddr);
 
-class Interrupts : public BasicPioDevice, IntDevice
+class Interrupts : public PioDevice, IntDevice
 {
   protected:
     // Storage for the APIC registers
@@ -174,6 +174,9 @@ class Interrupts : public BasicPioDevice, IntDevice
     // Port for receiving interrupts
     IntSlavePort intSlavePort;
 
+    Tick pioDelay;
+    Addr pioAddr = MaxAddr;
+
   public:
 
     int getInitialApicId() { return initialApicId; }
@@ -213,6 +216,7 @@ class Interrupts : public BasicPioDevice, IntDevice
         return entry.periodic;
     }
 
+    AddrRangeList getAddrRanges() const override;
     AddrRangeList getIntAddrRange() const override;
 
     Port &getPort(const std::string &if_name,
@@ -223,7 +227,7 @@ class Interrupts : public BasicPioDevice, IntDevice
         } else if (if_name == "int_slave") {
             return intSlavePort;
         }
-        return BasicPioDevice::getPort(if_name, idx);
+        return PioDevice::getPort(if_name, idx);
     }
 
     /*