changeset 60b4471a8181 in /z/repo/gem5 details: http://repo.gem5.org/gem5?cmd=changeset;node=60b4471a8181 description: dev: refactor pci config space for sysfs scanning
Sysfs on ubuntu scrapes the entire PCI config space when it discovers a device using 4 byte accesses. This was not supported by our devices, in particular the NIC that implemented the extended PCI config space. This change allows the extended PCI config space to be accessed by sysfs properly. diffstat: src/dev/pcidev.cc | 84 ++++++++++-- src/dev/pcidev.hh | 11 + src/dev/pcireg.h | 377 +++++++++++++++++++++++------------------------------ 3 files changed, 245 insertions(+), 227 deletions(-) diffs (truncated from 585 to 300 lines): diff -r 7135f938ff28 -r 60b4471a8181 src/dev/pcidev.cc --- a/src/dev/pcidev.cc Thu Oct 16 05:49:56 2014 -0400 +++ b/src/dev/pcidev.cc Thu Oct 16 05:49:57 2014 -0400 @@ -97,8 +97,15 @@ PciDevice::PciDevice(const Params *p) : DmaDevice(p), PMCAP_BASE(p->PMCAPBaseOffset), + PMCAP_ID_OFFSET(p->PMCAPBaseOffset+PMCAP_ID), + PMCAP_PC_OFFSET(p->PMCAPBaseOffset+PMCAP_PC), + PMCAP_PMCS_OFFSET(p->PMCAPBaseOffset+PMCAP_PMCS), MSICAP_BASE(p->MSICAPBaseOffset), MSIXCAP_BASE(p->MSIXCAPBaseOffset), + MSIXCAP_ID_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_ID), + MSIXCAP_MXC_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MXC), + MSIXCAP_MTAB_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MTAB), + MSIXCAP_MPBA_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MPBA), PXCAP_BASE(p->PXCAPBaseOffset), platform(p->platform), pioDelay(p->pio_latency), @@ -142,14 +149,14 @@ // endianess and must be converted to Little Endian when accessed // by the guest // PMCAP - pmcap.pid.cid = p->PMCAPCapId; - pmcap.pid.next = p->PMCAPNextCapability; + pmcap.pid = (uint16_t)p->PMCAPCapId; // pid.cid + pmcap.pid |= (uint16_t)p->PMCAPNextCapability << 8; //pid.next pmcap.pc = p->PMCAPCapabilities; pmcap.pmcs = p->PMCAPCtrlStatus; // MSICAP - msicap.mid.cid = p->MSICAPCapId; - msicap.mid.next = p->MSICAPNextCapability; + msicap.mid = (uint16_t)p->MSICAPCapId; //mid.cid + msicap.mid |= (uint16_t)p->MSICAPNextCapability << 8; //mid.next msicap.mc = p->MSICAPMsgCtrl; msicap.ma = p->MSICAPMsgAddr; msicap.mua = p->MSICAPMsgUpperAddr; @@ -158,8 +165,8 @@ msicap.mpend = p->MSICAPPendingBits; // MSIXCAP - msixcap.mxid.cid = p->MSIXCAPCapId; - msixcap.mxid.next = p->MSIXCAPNextCapability; + msixcap.mxid = (uint16_t)p->MSIXCAPCapId; //mxid.cid + msixcap.mxid |= (uint16_t)p->MSIXCAPNextCapability << 8; //mxid.next msixcap.mxc = p->MSIXMsgCtrl; msixcap.mtab = p->MSIXTableOffset; msixcap.mpba = p->MSIXPbaOffset; @@ -171,8 +178,9 @@ // little endian byte-order as according the // PCIe specification. Make sure to take the proper // actions when manipulating these tables on the host + uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff; if (MSIXCAP_BASE != 0x0) { - int msix_vecs = msixcap.mxc.ts + 1; + int msix_vecs = msixcap_mxc_ts + 1; MSIXTable tmp1 = {{0UL,0UL,0UL,0UL}}; msix_table.resize(msix_vecs, tmp1); @@ -183,10 +191,20 @@ } msix_pba.resize(pba_size, tmp2); } + MSIX_TABLE_OFFSET = msixcap.mtab & 0xfffffffc; + MSIX_TABLE_END = MSIX_TABLE_OFFSET + + (msixcap_mxc_ts + 1) * sizeof(MSIXTable); + MSIX_PBA_OFFSET = msixcap.mpba & 0xfffffffc; + MSIX_PBA_END = MSIX_PBA_OFFSET + + ((msixcap_mxc_ts + 1) / MSIXVECS_PER_PBA) + * sizeof(MSIXPbaEntry); + if (((msixcap_mxc_ts + 1) % MSIXVECS_PER_PBA) > 0) { + MSIX_PBA_END += sizeof(MSIXPbaEntry); + } // PXCAP - pxcap.pxid.cid = p->PXCAPCapId; - pxcap.pxid.next = p->PXCAPNextCapability; + pxcap.pxid = (uint16_t)p->PXCAPCapId; //pxid.cid + pxcap.pxid |= (uint16_t)p->PXCAPNextCapability << 8; //pxid.next pxcap.pxcap = p->PXCAPCapabilities; pxcap.pxdcap = p->PXCAPDevCapabilities; pxcap.pxdc = p->PXCAPDevCtrl; @@ -253,8 +271,30 @@ PciDevice::readConfig(PacketPtr pkt) { int offset = pkt->getAddr() & PCI_CONFIG_SIZE; - if (offset >= PCI_DEVICE_SPECIFIC) - panic("Device specific PCI config space not implemented!\n"); + + /* Return 0 for accesses to unimplemented PCI configspace areas */ + if (offset >= PCI_DEVICE_SPECIFIC && + offset < PCI_CONFIG_SIZE) { + warn_once("Device specific PCI config space " + "not implemented for %s!\n", this->name()); + switch (pkt->getSize()) { + case sizeof(uint8_t): + pkt->set<uint8_t>(0); + break; + case sizeof(uint16_t): + pkt->set<uint16_t>(0); + break; + case sizeof(uint32_t): + pkt->set<uint32_t>(0); + break; + default: + panic("invalid access size(?) for PCI configspace!\n"); + } + } else if (offset > PCI_CONFIG_SIZE) { + panic("Out-of-range access to PCI config space!\n"); + } + + pkt->allocate(); @@ -303,8 +343,23 @@ PciDevice::writeConfig(PacketPtr pkt) { int offset = pkt->getAddr() & PCI_CONFIG_SIZE; - if (offset >= PCI_DEVICE_SPECIFIC) - panic("Device specific PCI config space not implemented!\n"); + + /* No effect if we write to config space that is not implemented*/ + if (offset >= PCI_DEVICE_SPECIFIC && + offset < PCI_CONFIG_SIZE) { + warn_once("Device specific PCI config space " + "not implemented for %s!\n", this->name()); + switch (pkt->getSize()) { + case sizeof(uint8_t): + case sizeof(uint16_t): + case sizeof(uint32_t): + break; + default: + panic("invalid access size(?) for PCI configspace!\n"); + } + } else if (offset > PCI_CONFIG_SIZE) { + panic("Out-of-range access to PCI config space!\n"); + } switch (pkt->getSize()) { case sizeof(uint8_t): @@ -448,7 +503,8 @@ // Only serialize if we have a non-zero base address if (MSIXCAP_BASE != 0x0) { - int msix_array_size = msixcap.mxc.ts + 1; + uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff; + int msix_array_size = msixcap_mxc_ts + 1; int pba_array_size = msix_array_size/MSIXVECS_PER_PBA; if ((msix_array_size % MSIXVECS_PER_PBA) > 0) { pba_array_size++; diff -r 7135f938ff28 -r 60b4471a8181 src/dev/pcidev.hh --- a/src/dev/pcidev.hh Thu Oct 16 05:49:56 2014 -0400 +++ b/src/dev/pcidev.hh Thu Oct 16 05:49:57 2014 -0400 @@ -108,12 +108,23 @@ * @{ */ const int PMCAP_BASE; + const int PMCAP_ID_OFFSET; + const int PMCAP_PC_OFFSET; + const int PMCAP_PMCS_OFFSET; PMCAP pmcap; const int MSICAP_BASE; MSICAP msicap; const int MSIXCAP_BASE; + const int MSIXCAP_ID_OFFSET; + const int MSIXCAP_MXC_OFFSET; + const int MSIXCAP_MTAB_OFFSET; + const int MSIXCAP_MPBA_OFFSET; + int MSIX_TABLE_OFFSET; + int MSIX_TABLE_END; + int MSIX_PBA_OFFSET; + int MSIX_PBA_END; MSIXCAP msixcap; const int PXCAP_BASE; diff -r 7135f938ff28 -r 60b4471a8181 src/dev/pcireg.h --- a/src/dev/pcireg.h Thu Oct 16 05:49:56 2014 -0400 +++ b/src/dev/pcireg.h Thu Oct 16 05:49:57 2014 -0400 @@ -205,36 +205,31 @@ * Defines the Power Management capability register and all its associated * bitfields for a PCIe device. */ -struct PMCAP { - BitUnion16(PID) - Bitfield<7,0> cid; - Bitfield<15,8> next; - EndBitUnion(PID) - PID pid; - - BitUnion16(PC) - Bitfield<2,0> vs; - Bitfield<3> pmec; - Bitfield<4> reserved; - Bitfield<5> dsi; - Bitfield<8,6> auxc; - Bitfield<9> d1s; - Bitfield<10> d2s; - Bitfield<15,11> psup; - EndBitUnion(PC) - PC pc; - - BitUnion16(PMCS) - Bitfield<1,0> ps; - Bitfield<2> reserved0; - Bitfield<3> nsfrst; - Bitfield<7,4> reserved1; - Bitfield<8> pmee; - Bitfield<12,9> dse; - Bitfield<14,13> dsc; - Bitfield<15> pmes; - EndBitUnion(PMCS) - PMCS pmcs; +union PMCAP { + uint8_t data[6]; + struct { + uint16_t pid; /* 0:7 cid + * 8:15 next + */ + uint16_t pc; /* 0:2 vs + * 3 pmec + * 4 reserved + * 5 dsi + * 6:8 auxc + * 9 d1s + * 10 d2s + * 11:15 psup + */ + uint16_t pmcs; /* 0:1 ps + * 2 reserved + * 3 nsfrst + * 4:7 reserved + * 8 pmee + * 9:12 dse + * 13:14 dsc + * 15 pmes + */ + }; }; /** @struct MSICAP @@ -243,70 +238,51 @@ * can be filled in if a device model supports both, but only 1 of * MSI/MSIX/INTx interrupt mode can be selected at a given time. */ -struct MSICAP { - BitUnion16(MID) - Bitfield<7,0> cid; - Bitfield<15,8> next; - EndBitUnion(MID) - MID mid; - - BitUnion16(MC) - Bitfield<0> msie; - Bitfield<3,1> mmc; - Bitfield<6,4> mme; - Bitfield<7> c64; - Bitfield<8> pvm; - Bitfield<15,9> reserved; - EndBitUnion(MC) - MC mc; - - BitUnion32(MA) - Bitfield<1,0> reserved; - Bitfield<31,2> addr; - EndBitUnion(MA) - MA ma; - - uint32_t mua; - - BitUnion16(MD) - Bitfield<15,0> data; - EndBitUnion(MD) - MD md; - - uint32_t mmask; - uint32_t mpend; +union MSICAP { + uint8_t data[24]; + struct { + uint16_t mid; /* 0:7 cid + * 8:15 next + */ + uint16_t mc; /* 0 msie; + * 1:3 mmc; + * 4:6 mme; + * 7 c64; + * 8 pvm; + * 9:15 reserved; + */ + uint32_t ma; /* 0:1 reserved + * 2:31 addr + */ + uint32_t mua; + uint16_t md; + uint32_t mmask; + uint32_t mpend; _______________________________________________ gem5-dev mailing list gem5-dev@gem5.org http://m5sim.org/mailman/listinfo/gem5-dev