summaryrefslogtreecommitdiff
path: root/src/dev/arm
diff options
context:
space:
mode:
authorGeoffrey Blake <Geoffrey.Blake@arm.com>2013-10-31 13:41:13 -0500
committerGeoffrey Blake <Geoffrey.Blake@arm.com>2013-10-31 13:41:13 -0500
commitc32fbb7c008d86abc59f56c93b1ff5876fff0ab3 (patch)
tree7ea346abfcb7bf1c55d6fccec0d358e042993856 /src/dev/arm
parentbe4aa2b6ba0b70b13df2ad84a372320c5a7ea939 (diff)
downloadgem5-c32fbb7c008d86abc59f56c93b1ff5876fff0ab3.tar.xz
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 (limited to 'src/dev/arm')
-rw-r--r--src/dev/arm/Gic.py2
-rw-r--r--src/dev/arm/gic_pl390.cc63
-rw-r--r--src/dev/arm/gic_pl390.hh18
3 files changed, 81 insertions, 2 deletions
diff --git a/src/dev/arm/Gic.py b/src/dev/arm/Gic.py
index 0461758ed..766049296 100644
--- a/src/dev/arm/Gic.py
+++ b/src/dev/arm/Gic.py
@@ -54,8 +54,8 @@ class Pl390(BaseGic):
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 --git a/src/dev/arm/gic_pl390.cc b/src/dev/arm/gic_pl390.cc
index fc49aa63e..d2a660e88 100644
--- a/src/dev/arm/gic_pl390.cc
+++ b/src/dev/arm/gic_pl390.cc
@@ -56,7 +56,8 @@ Pl390::Pl390(const Params *p)
: 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 @@ Pl390::read(PacketPtr pkt)
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 @@ Pl390::write(PacketPtr pkt)
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 @@ Pl390::readCpu(PacketPtr pkt)
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 @@ Pl390::writeCpu(PacketPtr pkt)
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 @@ Pl390::getAddrRanges() const
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 @@ Pl390::serialize(std::ostream &os)
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 @@ Pl390::unserialize(Checkpoint *cp, const std::string &section)
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 --git a/src/dev/arm/gic_pl390.hh b/src/dev/arm/gic_pl390.hh
index 2621e1a27..5b84ea92b 100644
--- a/src/dev/arm/gic_pl390.hh
+++ b/src/dev/arm/gic_pl390.hh
@@ -113,6 +113,10 @@ class Pl390 : public BaseGic
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 @@ class Pl390 : public BaseGic
/** 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 @@ class Pl390 : public BaseGic
*/
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 @@ class Pl390 : public BaseGic
* @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__