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