changeset 1e239f3a1927 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=1e239f3a1927
description:
        dev: Add support for MSI-X and Capability Lists for ARM and PCI devices

        This patch adds the registers and fields to the PCI device to support
        Capability lists and to support MSI-X in the GIC.

diffstat:

 src/dev/Pci.py           |   63 +++++++++
 src/dev/arm/Gic.py       |    2 +-
 src/dev/arm/gic_pl390.cc |   63 +++++++++-
 src/dev/arm/gic_pl390.hh |   18 ++
 src/dev/pcidev.cc        |  224 ++++++++++++++++++++++++++++++++-
 src/dev/pcidev.hh        |   32 ++++
 src/dev/pcireg.h         |  317 ++++++++++++++++++++++++++++++++++++++++++++++-
 7 files changed, 709 insertions(+), 10 deletions(-)

diffs (truncated from 934 to 300 lines):

diff -r 6f2b525b8f16 -r 1e239f3a1927 src/dev/Pci.py
--- a/src/dev/Pci.py    Thu Oct 31 13:41:13 2013 -0500
+++ b/src/dev/Pci.py    Thu Oct 31 13:41:13 2013 -0500
@@ -1,3 +1,15 @@
+# Copyright (c) 2013 ARM Limited
+#  All rights reserved
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder.  You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
 # Copyright (c) 2005-2007 The Regents of The University of Michigan
 # All rights reserved.
 #
@@ -91,9 +103,60 @@
     SubsystemID = Param.UInt16(0x00, "Subsystem ID")
     SubsystemVendorID = Param.UInt16(0x00, "Subsystem Vendor ID")
     ExpansionROM = Param.UInt32(0x00, "Expansion ROM Base Address")
+    CapabilityPtr = Param.UInt8(0x00, "Capability List Pointer offset")
     InterruptLine = Param.UInt8(0x00, "Interrupt Line")
     InterruptPin = Param.UInt8(0x00, "Interrupt Pin")
     MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
     MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
 
+    # Capabilities List structures for PCIe devices
+    # PMCAP - PCI Power Management Capability
+    PMCAPBaseOffset = \
+        Param.UInt8(0x00, "Base offset of PMCAP in PCI Config space")
+    PMCAPNextCapability = \
+        Param.UInt8(0x00, "Pointer to next capability block")
+    PMCAPCapId = \
+        Param.UInt8(0x00, "Specifies this is the Power Management capability")
+    PMCAPCapabilities = \
+        Param.UInt16(0x0000, "PCI Power Management Capabilities Register")
+    PMCAPCtrlStatus = \
+        Param.UInt16(0x0000, "PCI Power Management Control and Status")
 
+    # MSICAP - Message Signaled Interrupt Capability
+    MSICAPBaseOffset = \
+        Param.UInt8(0x00, "Base offset of MSICAP in PCI Config space")
+    MSICAPNextCapability = \
+        Param.UInt8(0x00, "Pointer to next capability block")
+    MSICAPCapId = Param.UInt8(0x00, "Specifies this is the MSI Capability")
+    MSICAPMsgCtrl = Param.UInt16(0x0000, "MSI Message Control")
+    MSICAPMsgAddr = Param.UInt32(0x00000000, "MSI Message Address")
+    MSICAPMsgUpperAddr = Param.UInt32(0x00000000, "MSI Message Upper Address")
+    MSICAPMsgData = Param.UInt16(0x0000, "MSI Message Data")
+    MSICAPMaskBits = Param.UInt32(0x00000000, "MSI Interrupt Mask Bits")
+    MSICAPPendingBits = Param.UInt32(0x00000000, "MSI Pending Bits")
+
+    # MSIXCAP - MSI-X Capability
+    MSIXCAPBaseOffset = \
+        Param.UInt8(0x00, "Base offset of MSIXCAP in PCI Config space")
+    MSIXCAPNextCapability = \
+        Param.UInt8(0x00, "Pointer to next capability block")
+    MSIXCAPCapId = Param.UInt8(0x00, "Specifices this the MSI-X Capability")
+    MSIXMsgCtrl = Param.UInt16(0x0000, "MSI-X Message Control")
+    MSIXTableOffset = \
+        Param.UInt32(0x00000000, "MSI-X Table Offset and Table BIR")
+    MSIXPbaOffset = Param.UInt32(0x00000000, "MSI-X PBA Offset and PBA BIR")
+
+    # PXCAP - PCI Express Capability
+    PXCAPBaseOffset = \
+        Param.UInt8(0x00, "Base offset of PXCAP in PCI Config space")
+    PXCAPNextCapability = Param.UInt8(0x00, "Pointer to next capability block")
+    PXCAPCapId = Param.UInt8(0x00, "Specifies this is the PCIe Capability")
+    PXCAPCapabilities = Param.UInt16(0x0000, "PCIe Capabilities")
+    PXCAPDevCapabilities = Param.UInt32(0x00000000, "PCIe Device Capabilities")
+    PXCAPDevCtrl = Param.UInt16(0x0000, "PCIe Device Control")
+    PXCAPDevStatus = Param.UInt16(0x0000, "PCIe Device Status")
+    PXCAPLinkCap = Param.UInt32(0x00000000, "PCIe Link Capabilities")
+    PXCAPLinkCtrl = Param.UInt16(0x0000, "PCIe Link Control")
+    PXCAPLinkStatus = Param.UInt16(0x0000, "PCIe Link Status")
+    PXCAPDevCap2 = Param.UInt32(0x00000000, "PCIe Device Capabilities 2")
+    PXCAPDevCtrl2 = Param.UInt32(0x00000000, "PCIe Device Control 2")
diff -r 6f2b525b8f16 -r 1e239f3a1927 src/dev/arm/Gic.py
--- a/src/dev/arm/Gic.py        Thu Oct 31 13:41:13 2013 -0500
+++ b/src/dev/arm/Gic.py        Thu Oct 31 13:41:13 2013 -0500
@@ -54,8 +54,8 @@
 
     dist_addr = Param.Addr(0x1f001000, "Address for distributor")
     cpu_addr = Param.Addr(0x1f000100, "Address for cpu")
+    msix_addr = Param.Addr(0x0, "Address for MSI-X register")
     dist_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to distributor")
     cpu_pio_delay = Param.Latency('10ns', "Delay for PIO r/w to cpu interface")
     int_latency = Param.Latency('10ns', "Delay for interrupt to get to CPU")
     it_lines = Param.UInt32(128, "Number of interrupt lines supported (max = 
1020)")
-
diff -r 6f2b525b8f16 -r 1e239f3a1927 src/dev/arm/gic_pl390.cc
--- a/src/dev/arm/gic_pl390.cc  Thu Oct 31 13:41:13 2013 -0500
+++ b/src/dev/arm/gic_pl390.cc  Thu Oct 31 13:41:13 2013 -0500
@@ -56,7 +56,8 @@
     : BaseGic(p), distAddr(p->dist_addr),
       cpuAddr(p->cpu_addr), distPioDelay(p->dist_pio_delay),
       cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency),
-      enabled(false), itLines(p->it_lines)
+      enabled(false), itLines(p->it_lines), msixRegAddr(p->msix_addr),
+      msixReg(0x0)
 {
     itLinesLog2 = ceilLog2(itLines);
 
@@ -117,6 +118,10 @@
         return readDistributor(pkt);
     else if (addr >= cpuAddr && addr < cpuAddr + CPU_SIZE)
         return readCpu(pkt);
+    else if (msixRegAddr != 0x0 &&
+             addr >= msixRegAddr &&
+             addr < msixRegAddr + MSIX_SIZE)
+        return readMsix(pkt);
     else
         panic("Read to unknown address %#x\n", pkt->getAddr());
 }
@@ -132,6 +137,10 @@
         return writeDistributor(pkt);
     else if (addr >= cpuAddr && addr < cpuAddr + CPU_SIZE)
         return writeCpu(pkt);
+    else if (msixRegAddr != 0x0 &&
+             addr >= msixRegAddr &&
+             addr < msixRegAddr + MSIX_SIZE)
+        return writeMsix(pkt);
     else
         panic("Write to unknown address %#x\n", pkt->getAddr());
 }
@@ -355,6 +364,26 @@
     return cpuPioDelay;
 }
 
+Tick
+Pl390::readMsix(PacketPtr pkt)
+{
+    Addr daddr = pkt->getAddr() - msixRegAddr;
+    pkt->allocate();
+
+    DPRINTF(GIC, "Gic MSIX read register %#x\n", daddr);
+
+    switch (daddr) {
+        case MSIX_SR:
+            pkt->set<uint32_t>(msixReg);
+            break;
+        default:
+            panic("Tried to read Gic MSIX register at offset %#x\n", daddr);
+            break;
+    }
+
+    pkt->makeAtomicResponse();
+    return distPioDelay;
+}
 
 Tick
 Pl390::writeDistributor(PacketPtr pkt)
@@ -535,6 +564,31 @@
     return cpuPioDelay;
 }
 
+Tick
+Pl390::writeMsix(PacketPtr pkt)
+{
+    Addr daddr = pkt->getAddr() - msixRegAddr;
+    pkt->allocate();
+
+    DPRINTF(GIC, "Gic MSI-X write register %#x data %d\n",
+                 daddr, pkt->get<uint32_t>());
+
+    switch (daddr) {
+        case MSIX_SR:
+            // This value is little endian, just like the ARM guest
+            msixReg = pkt->get<uint32_t>();
+            pendingInt[intNumToWord(letoh(msixReg))] |= 1UL << 
intNumToBit(letoh(msixReg));
+            updateIntState(-1);
+            break;
+        default:
+            panic("Tried to write Gic MSI-X register at offset %#x\n", daddr);
+            break;
+    }
+
+    pkt->makeAtomicResponse();
+    return distPioDelay;
+}
+
 void
 Pl390::softInt(int ctx_id, SWI swi)
 {
@@ -726,6 +780,9 @@
     AddrRangeList ranges;
     ranges.push_back(RangeSize(distAddr, DIST_SIZE));
     ranges.push_back(RangeSize(cpuAddr, CPU_SIZE));
+    if (msixRegAddr != 0) {
+        ranges.push_back(RangeSize(msixRegAddr, MSIX_SIZE));
+    }
     return ranges;
 }
 
@@ -742,6 +799,8 @@
     SERIALIZE_SCALAR(enabled);
     SERIALIZE_SCALAR(itLines);
     SERIALIZE_SCALAR(itLinesLog2);
+    SERIALIZE_SCALAR(msixRegAddr);
+    SERIALIZE_SCALAR(msixReg);
     SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX);
     SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX);
     SERIALIZE_ARRAY(activeInt, INT_BITS_MAX);
@@ -782,6 +841,8 @@
     UNSERIALIZE_SCALAR(enabled);
     UNSERIALIZE_SCALAR(itLines);
     UNSERIALIZE_SCALAR(itLinesLog2);
+    UNSERIALIZE_SCALAR(msixRegAddr);
+    UNSERIALIZE_SCALAR(msixReg);
     UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX);
     UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX);
     UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX);
diff -r 6f2b525b8f16 -r 1e239f3a1927 src/dev/arm/gic_pl390.hh
--- a/src/dev/arm/gic_pl390.hh  Thu Oct 31 13:41:13 2013 -0500
+++ b/src/dev/arm/gic_pl390.hh  Thu Oct 31 13:41:13 2013 -0500
@@ -113,6 +113,10 @@
     static const int INT_BITS_MAX = 32;
     static const int INT_LINES_MAX = 1020;
 
+    /** MSI-X register offset and size */
+    static const int MSIX_SR = 0x0; // MSI register devices will write to
+    static const int MSIX_SIZE = 0x4; // Size of MSI-X register space
+
     BitUnion32(SWI)
         Bitfield<3,0> sgi_id;
         Bitfield<23,16> cpu_list;
@@ -207,6 +211,10 @@
     /** IRQ Enable Used for debug */
     bool irqEnable;
 
+    /** MSIX Register */
+    Addr msixRegAddr;
+    uint32_t msixReg;
+
     /** software generated interrupt
      * @param data data to decode that indicates which cpus to interrupt
      */
@@ -314,6 +322,11 @@
      */
     Tick readCpu(PacketPtr pkt);
 
+    /** Handle a read to the MSI-X register on the GIC
+     *  @param pkt packet to respond to
+     */
+    Tick readMsix(PacketPtr pkt);
+
     /** Handle a write to the distributor poriton of the GIC
      * @param pkt packet to respond to
      */
@@ -323,6 +336,11 @@
      * @param pkt packet to respond to
      */
     Tick writeCpu(PacketPtr pkt);
+
+    /** Handle a write to the MSI-X register on the GIC
+     *  @param pkt packet to process
+     */
+    Tick writeMsix(PacketPtr pkt);
 };
 
 #endif //__DEV_ARM_GIC_H__
diff -r 6f2b525b8f16 -r 1e239f3a1927 src/dev/pcidev.cc
--- a/src/dev/pcidev.cc Thu Oct 31 13:41:13 2013 -0500
+++ b/src/dev/pcidev.cc Thu Oct 31 13:41:13 2013 -0500
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2004-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -83,7 +95,13 @@
 
 
 PciDevice::PciDevice(const Params *p)
-    : DmaDevice(p), platform(p->platform), pioDelay(p->pio_latency),
+    : DmaDevice(p),
+      PMCAP_BASE(p->PMCAPBaseOffset),
+      MSICAP_BASE(p->MSICAPBaseOffset),
+      MSIXCAP_BASE(p->MSIXCAPBaseOffset),
+      PXCAP_BASE(p->PXCAPBaseOffset),
+      platform(p->platform),
+      pioDelay(p->pio_latency),
       configDelay(p->config_latency),
       configPort(this, params()->pci_bus, params()->pci_dev,
                  params()->pci_func, params()->platform)
@@ -111,13 +129,74 @@
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to