diff options
author | Geoffrey Blake <Geoffrey.Blake@arm.com> | 2013-10-31 13:41:13 -0500 |
---|---|---|
committer | Geoffrey Blake <Geoffrey.Blake@arm.com> | 2013-10-31 13:41:13 -0500 |
commit | c32fbb7c008d86abc59f56c93b1ff5876fff0ab3 (patch) | |
tree | 7ea346abfcb7bf1c55d6fccec0d358e042993856 /src/dev/arm | |
parent | be4aa2b6ba0b70b13df2ad84a372320c5a7ea939 (diff) | |
download | gem5-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.py | 2 | ||||
-rw-r--r-- | src/dev/arm/gic_pl390.cc | 63 | ||||
-rw-r--r-- | src/dev/arm/gic_pl390.hh | 18 |
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 §ion) 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__ |