gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
device.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, 2015 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2004-2005 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 /* @file
42  * A single PCI device configuration space entry.
43  */
44 
45 #include "dev/pci/device.hh"
46 
47 #include <list>
48 #include <string>
49 #include <vector>
50 
51 #include "base/inifile.hh"
52 #include "base/intmath.hh"
53 #include "base/logging.hh"
54 #include "base/str.hh"
55 #include "base/trace.hh"
56 #include "debug/PciDevice.hh"
57 #include "mem/packet.hh"
58 #include "mem/packet_access.hh"
59 #include "sim/byteswap.hh"
60 #include "sim/core.hh"
61 
62 PciDevice::PciDevice(const PciDeviceParams *p)
63  : DmaDevice(p),
64  _busAddr(p->pci_bus, p->pci_dev, p->pci_func),
65  PMCAP_BASE(p->PMCAPBaseOffset),
66  PMCAP_ID_OFFSET(p->PMCAPBaseOffset+PMCAP_ID),
67  PMCAP_PC_OFFSET(p->PMCAPBaseOffset+PMCAP_PC),
68  PMCAP_PMCS_OFFSET(p->PMCAPBaseOffset+PMCAP_PMCS),
69  MSICAP_BASE(p->MSICAPBaseOffset),
70  MSIXCAP_BASE(p->MSIXCAPBaseOffset),
71  MSIXCAP_ID_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_ID),
72  MSIXCAP_MXC_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MXC),
73  MSIXCAP_MTAB_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MTAB),
74  MSIXCAP_MPBA_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MPBA),
75  PXCAP_BASE(p->PXCAPBaseOffset),
76 
77  hostInterface(p->host->registerDevice(this, _busAddr,
78  (PciIntPin)p->InterruptPin)),
79  pioDelay(p->pio_latency),
80  configDelay(p->config_latency)
81 {
82  fatal_if(p->InterruptPin >= 5,
83  "Invalid PCI interrupt '%i' specified.", p->InterruptPin);
84 
85  config.vendor = htole(p->VendorID);
86  config.device = htole(p->DeviceID);
87  config.command = htole(p->Command);
88  config.status = htole(p->Status);
89  config.revision = htole(p->Revision);
90  config.progIF = htole(p->ProgIF);
91  config.subClassCode = htole(p->SubClassCode);
92  config.classCode = htole(p->ClassCode);
93  config.cacheLineSize = htole(p->CacheLineSize);
94  config.latencyTimer = htole(p->LatencyTimer);
95  config.headerType = htole(p->HeaderType);
96  config.bist = htole(p->BIST);
97 
98  config.baseAddr[0] = htole(p->BAR0);
99  config.baseAddr[1] = htole(p->BAR1);
100  config.baseAddr[2] = htole(p->BAR2);
101  config.baseAddr[3] = htole(p->BAR3);
102  config.baseAddr[4] = htole(p->BAR4);
103  config.baseAddr[5] = htole(p->BAR5);
104  config.cardbusCIS = htole(p->CardbusCIS);
105  config.subsystemVendorID = htole(p->SubsystemVendorID);
106  config.subsystemID = htole(p->SubsystemID);
107  config.expansionROM = htole(p->ExpansionROM);
108  config.capabilityPtr = htole(p->CapabilityPtr);
109  // Zero out the 7 bytes of reserved space in the PCI Config space register.
110  bzero(config.reserved, 7*sizeof(uint8_t));
111  config.interruptLine = htole(p->InterruptLine);
112  config.interruptPin = htole(p->InterruptPin);
113  config.minimumGrant = htole(p->MinimumGrant);
114  config.maximumLatency = htole(p->MaximumLatency);
115 
116  // Initialize the capability lists
117  // These structs are bitunions, meaning the data is stored in host
118  // endianess and must be converted to Little Endian when accessed
119  // by the guest
120  // PMCAP
121  pmcap.pid = (uint16_t)p->PMCAPCapId; // pid.cid
122  pmcap.pid |= (uint16_t)p->PMCAPNextCapability << 8; //pid.next
123  pmcap.pc = p->PMCAPCapabilities;
124  pmcap.pmcs = p->PMCAPCtrlStatus;
125 
126  // MSICAP
127  msicap.mid = (uint16_t)p->MSICAPCapId; //mid.cid
128  msicap.mid |= (uint16_t)p->MSICAPNextCapability << 8; //mid.next
129  msicap.mc = p->MSICAPMsgCtrl;
130  msicap.ma = p->MSICAPMsgAddr;
131  msicap.mua = p->MSICAPMsgUpperAddr;
132  msicap.md = p->MSICAPMsgData;
133  msicap.mmask = p->MSICAPMaskBits;
134  msicap.mpend = p->MSICAPPendingBits;
135 
136  // MSIXCAP
137  msixcap.mxid = (uint16_t)p->MSIXCAPCapId; //mxid.cid
138  msixcap.mxid |= (uint16_t)p->MSIXCAPNextCapability << 8; //mxid.next
139  msixcap.mxc = p->MSIXMsgCtrl;
140  msixcap.mtab = p->MSIXTableOffset;
141  msixcap.mpba = p->MSIXPbaOffset;
142 
143  // allocate MSIX structures if MSIXCAP_BASE
144  // indicates the MSIXCAP is being used by having a
145  // non-zero base address.
146  // The MSIX tables are stored by the guest in
147  // little endian byte-order as according the
148  // PCIe specification. Make sure to take the proper
149  // actions when manipulating these tables on the host
150  uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff;
151  if (MSIXCAP_BASE != 0x0) {
152  int msix_vecs = msixcap_mxc_ts + 1;
153  MSIXTable tmp1 = {{0UL,0UL,0UL,0UL}};
154  msix_table.resize(msix_vecs, tmp1);
155 
156  MSIXPbaEntry tmp2 = {0};
157  int pba_size = msix_vecs / MSIXVECS_PER_PBA;
158  if ((msix_vecs % MSIXVECS_PER_PBA) > 0) {
159  pba_size++;
160  }
161  msix_pba.resize(pba_size, tmp2);
162  }
163  MSIX_TABLE_OFFSET = msixcap.mtab & 0xfffffffc;
165  (msixcap_mxc_ts + 1) * sizeof(MSIXTable);
166  MSIX_PBA_OFFSET = msixcap.mpba & 0xfffffffc;
168  ((msixcap_mxc_ts + 1) / MSIXVECS_PER_PBA)
169  * sizeof(MSIXPbaEntry);
170  if (((msixcap_mxc_ts + 1) % MSIXVECS_PER_PBA) > 0) {
171  MSIX_PBA_END += sizeof(MSIXPbaEntry);
172  }
173 
174  // PXCAP
175  pxcap.pxid = (uint16_t)p->PXCAPCapId; //pxid.cid
176  pxcap.pxid |= (uint16_t)p->PXCAPNextCapability << 8; //pxid.next
177  pxcap.pxcap = p->PXCAPCapabilities;
178  pxcap.pxdcap = p->PXCAPDevCapabilities;
179  pxcap.pxdc = p->PXCAPDevCtrl;
180  pxcap.pxds = p->PXCAPDevStatus;
181  pxcap.pxlcap = p->PXCAPLinkCap;
182  pxcap.pxlc = p->PXCAPLinkCtrl;
183  pxcap.pxls = p->PXCAPLinkStatus;
184  pxcap.pxdcap2 = p->PXCAPDevCap2;
185  pxcap.pxdc2 = p->PXCAPDevCtrl2;
186 
187  BARSize[0] = p->BAR0Size;
188  BARSize[1] = p->BAR1Size;
189  BARSize[2] = p->BAR2Size;
190  BARSize[3] = p->BAR3Size;
191  BARSize[4] = p->BAR4Size;
192  BARSize[5] = p->BAR5Size;
193 
194  legacyIO[0] = p->BAR0LegacyIO;
195  legacyIO[1] = p->BAR1LegacyIO;
196  legacyIO[2] = p->BAR2LegacyIO;
197  legacyIO[3] = p->BAR3LegacyIO;
198  legacyIO[4] = p->BAR4LegacyIO;
199  legacyIO[5] = p->BAR5LegacyIO;
200 
201  for (int i = 0; i < 6; ++i) {
202  if (legacyIO[i]) {
203  BARAddrs[i] = p->LegacyIOBase + letoh(config.baseAddr[i]);
204  config.baseAddr[i] = 0;
205  } else {
206  BARAddrs[i] = 0;
207  uint32_t barsize = BARSize[i];
208  if (barsize != 0 && !isPowerOf2(barsize)) {
209  fatal("BAR %d size %d is not a power of 2\n", i, BARSize[i]);
210  }
211  }
212  }
213 }
214 
215 Tick
217 {
218  int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
219 
220  /* Return 0 for accesses to unimplemented PCI configspace areas */
221  if (offset >= PCI_DEVICE_SPECIFIC &&
222  offset < PCI_CONFIG_SIZE) {
223  warn_once("Device specific PCI config space "
224  "not implemented for %s!\n", this->name());
225  switch (pkt->getSize()) {
226  case sizeof(uint8_t):
227  pkt->setLE<uint8_t>(0);
228  break;
229  case sizeof(uint16_t):
230  pkt->setLE<uint16_t>(0);
231  break;
232  case sizeof(uint32_t):
233  pkt->setLE<uint32_t>(0);
234  break;
235  default:
236  panic("invalid access size(?) for PCI configspace!\n");
237  }
238  } else if (offset > PCI_CONFIG_SIZE) {
239  panic("Out-of-range access to PCI config space!\n");
240  }
241 
242  switch (pkt->getSize()) {
243  case sizeof(uint8_t):
244  pkt->setLE<uint8_t>(config.data[offset]);
246  "readConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
247  _busAddr.dev, _busAddr.func, offset,
248  (uint32_t)pkt->getLE<uint8_t>());
249  break;
250  case sizeof(uint16_t):
251  pkt->setLE<uint16_t>(*(uint16_t*)&config.data[offset]);
253  "readConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
254  _busAddr.dev, _busAddr.func, offset,
255  (uint32_t)pkt->getLE<uint16_t>());
256  break;
257  case sizeof(uint32_t):
258  pkt->setLE<uint32_t>(*(uint32_t*)&config.data[offset]);
260  "readConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
261  _busAddr.dev, _busAddr.func, offset,
262  (uint32_t)pkt->getLE<uint32_t>());
263  break;
264  default:
265  panic("invalid access size(?) for PCI configspace!\n");
266  }
267  pkt->makeAtomicResponse();
268  return configDelay;
269 
270 }
271 
274 {
275  AddrRangeList ranges;
276  int x = 0;
277  for (x = 0; x < 6; x++)
278  if (BARAddrs[x] != 0)
279  ranges.push_back(RangeSize(BARAddrs[x],BARSize[x]));
280  return ranges;
281 }
282 
283 Tick
285 {
286  int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
287 
288  /* No effect if we write to config space that is not implemented*/
289  if (offset >= PCI_DEVICE_SPECIFIC &&
290  offset < PCI_CONFIG_SIZE) {
291  warn_once("Device specific PCI config space "
292  "not implemented for %s!\n", this->name());
293  switch (pkt->getSize()) {
294  case sizeof(uint8_t):
295  case sizeof(uint16_t):
296  case sizeof(uint32_t):
297  break;
298  default:
299  panic("invalid access size(?) for PCI configspace!\n");
300  }
301  } else if (offset > PCI_CONFIG_SIZE) {
302  panic("Out-of-range access to PCI config space!\n");
303  }
304 
305  switch (pkt->getSize()) {
306  case sizeof(uint8_t):
307  switch (offset) {
308  case PCI0_INTERRUPT_LINE:
309  config.interruptLine = pkt->getLE<uint8_t>();
310  break;
311  case PCI_CACHE_LINE_SIZE:
312  config.cacheLineSize = pkt->getLE<uint8_t>();
313  break;
314  case PCI_LATENCY_TIMER:
315  config.latencyTimer = pkt->getLE<uint8_t>();
316  break;
317  /* Do nothing for these read-only registers */
318  case PCI0_INTERRUPT_PIN:
319  case PCI0_MINIMUM_GRANT:
321  case PCI_CLASS_CODE:
322  case PCI_REVISION_ID:
323  break;
324  default:
325  panic("writing to a read only register");
326  }
328  "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
329  _busAddr.dev, _busAddr.func, offset,
330  (uint32_t)pkt->getLE<uint8_t>());
331  break;
332  case sizeof(uint16_t):
333  switch (offset) {
334  case PCI_COMMAND:
335  config.command = pkt->getLE<uint8_t>();
336  break;
337  case PCI_STATUS:
338  config.status = pkt->getLE<uint8_t>();
339  break;
340  case PCI_CACHE_LINE_SIZE:
341  config.cacheLineSize = pkt->getLE<uint8_t>();
342  break;
343  default:
344  panic("writing to a read only register");
345  }
347  "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
348  _busAddr.dev, _busAddr.func, offset,
349  (uint32_t)pkt->getLE<uint16_t>());
350  break;
351  case sizeof(uint32_t):
352  switch (offset) {
353  case PCI0_BASE_ADDR0:
354  case PCI0_BASE_ADDR1:
355  case PCI0_BASE_ADDR2:
356  case PCI0_BASE_ADDR3:
357  case PCI0_BASE_ADDR4:
358  case PCI0_BASE_ADDR5:
359  {
360  int barnum = BAR_NUMBER(offset);
361 
362  if (!legacyIO[barnum]) {
363  // convert BAR values to host endianness
364  uint32_t he_old_bar = letoh(config.baseAddr[barnum]);
365  uint32_t he_new_bar = letoh(pkt->getLE<uint32_t>());
366 
367  uint32_t bar_mask =
368  BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK;
369 
370  // Writing 0xffffffff to a BAR tells the card to set the
371  // value of the bar to a bitmask indicating the size of
372  // memory it needs
373  if (he_new_bar == 0xffffffff) {
374  he_new_bar = ~(BARSize[barnum] - 1);
375  } else {
376  // does it mean something special to write 0 to a BAR?
377  he_new_bar &= ~bar_mask;
378  if (he_new_bar) {
379  if (isLargeBAR(barnum)) {
380  if (BAR_IO_SPACE(he_old_bar))
381  warn("IO BARs can't be set as large BAR");
382  uint64_t he_large_bar =
383  letoh(config.baseAddr[barnum + 1]);
384  he_large_bar = he_large_bar << 32;
385  he_large_bar += he_new_bar;
386  BARAddrs[barnum] =
387  hostInterface.memAddr(he_large_bar);
388  } else if (isLargeBAR(barnum - 1)) {
389  BARAddrs[barnum] = 0;
390  uint64_t he_large_bar = he_new_bar;
391  he_large_bar = he_large_bar << 32;
392  // We need to apply mask to lower bits
393  he_large_bar +=
394  letoh(config.baseAddr[barnum - 1]
395  & ~bar_mask);
396  BARAddrs[barnum - 1] =
397  hostInterface.memAddr(he_large_bar);
398  } else {
399  BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ?
400  hostInterface.pioAddr(he_new_bar) :
401  hostInterface.memAddr(he_new_bar);
402  }
404  }
405  }
406  config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) |
407  (he_old_bar & bar_mask));
408  }
409  }
410  break;
411 
412  case PCI0_ROM_BASE_ADDR:
413  if (letoh(pkt->getLE<uint32_t>()) == 0xfffffffe)
414  config.expansionROM = htole((uint32_t)0xffffffff);
415  else
416  config.expansionROM = pkt->getLE<uint32_t>();
417  break;
418 
419  case PCI_COMMAND:
420  // This could also clear some of the error bits in the Status
421  // register. However they should never get set, so lets ignore
422  // it for now
423  config.command = pkt->getLE<uint32_t>();
424  break;
425 
426  default:
427  DPRINTF(PciDevice, "Writing to a read only register");
428  }
430  "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
431  _busAddr.dev, _busAddr.func, offset,
432  (uint32_t)pkt->getLE<uint32_t>());
433  break;
434  default:
435  panic("invalid access size(?) for PCI configspace!\n");
436  }
437  pkt->makeAtomicResponse();
438  return configDelay;
439 }
440 
441 void
443 {
444  SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
445  SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
446  SERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0]));
447 
448  // serialize the capability list registers
449  paramOut(cp, csprintf("pmcap.pid"), uint16_t(pmcap.pid));
450  paramOut(cp, csprintf("pmcap.pc"), uint16_t(pmcap.pc));
451  paramOut(cp, csprintf("pmcap.pmcs"), uint16_t(pmcap.pmcs));
452 
453  paramOut(cp, csprintf("msicap.mid"), uint16_t(msicap.mid));
454  paramOut(cp, csprintf("msicap.mc"), uint16_t(msicap.mc));
455  paramOut(cp, csprintf("msicap.ma"), uint32_t(msicap.ma));
457  paramOut(cp, csprintf("msicap.md"), uint16_t(msicap.md));
460 
461  paramOut(cp, csprintf("msixcap.mxid"), uint16_t(msixcap.mxid));
462  paramOut(cp, csprintf("msixcap.mxc"), uint16_t(msixcap.mxc));
463  paramOut(cp, csprintf("msixcap.mtab"), uint32_t(msixcap.mtab));
464  paramOut(cp, csprintf("msixcap.mpba"), uint32_t(msixcap.mpba));
465 
466  // Only serialize if we have a non-zero base address
467  if (MSIXCAP_BASE != 0x0) {
468  uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff;
469  int msix_array_size = msixcap_mxc_ts + 1;
470  int pba_array_size = msix_array_size/MSIXVECS_PER_PBA;
471  if ((msix_array_size % MSIXVECS_PER_PBA) > 0) {
472  pba_array_size++;
473  }
474 
475  SERIALIZE_SCALAR(msix_array_size);
476  SERIALIZE_SCALAR(pba_array_size);
477 
478  for (int i = 0; i < msix_array_size; i++) {
479  paramOut(cp, csprintf("msix_table[%d].addr_lo", i),
480  msix_table[i].fields.addr_lo);
481  paramOut(cp, csprintf("msix_table[%d].addr_hi", i),
482  msix_table[i].fields.addr_hi);
483  paramOut(cp, csprintf("msix_table[%d].msg_data", i),
484  msix_table[i].fields.msg_data);
485  paramOut(cp, csprintf("msix_table[%d].vec_ctrl", i),
486  msix_table[i].fields.vec_ctrl);
487  }
488  for (int i = 0; i < pba_array_size; i++) {
489  paramOut(cp, csprintf("msix_pba[%d].bits", i),
490  msix_pba[i].bits);
491  }
492  }
493 
494  paramOut(cp, csprintf("pxcap.pxid"), uint16_t(pxcap.pxid));
495  paramOut(cp, csprintf("pxcap.pxcap"), uint16_t(pxcap.pxcap));
496  paramOut(cp, csprintf("pxcap.pxdcap"), uint32_t(pxcap.pxdcap));
497  paramOut(cp, csprintf("pxcap.pxdc"), uint16_t(pxcap.pxdc));
498  paramOut(cp, csprintf("pxcap.pxds"), uint16_t(pxcap.pxds));
499  paramOut(cp, csprintf("pxcap.pxlcap"), uint32_t(pxcap.pxlcap));
500  paramOut(cp, csprintf("pxcap.pxlc"), uint16_t(pxcap.pxlc));
501  paramOut(cp, csprintf("pxcap.pxls"), uint16_t(pxcap.pxls));
502  paramOut(cp, csprintf("pxcap.pxdcap2"), uint32_t(pxcap.pxdcap2));
503  paramOut(cp, csprintf("pxcap.pxdc2"), uint32_t(pxcap.pxdc2));
504 }
505 
506 void
508 {
509  UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
510  UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
512  sizeof(config.data) / sizeof(config.data[0]));
513 
514  // unserialize the capability list registers
515  uint16_t tmp16;
516  uint32_t tmp32;
517  paramIn(cp, csprintf("pmcap.pid"), tmp16);
518  pmcap.pid = tmp16;
519  paramIn(cp, csprintf("pmcap.pc"), tmp16);
520  pmcap.pc = tmp16;
521  paramIn(cp, csprintf("pmcap.pmcs"), tmp16);
522  pmcap.pmcs = tmp16;
523 
524  paramIn(cp, csprintf("msicap.mid"), tmp16);
525  msicap.mid = tmp16;
526  paramIn(cp, csprintf("msicap.mc"), tmp16);
527  msicap.mc = tmp16;
528  paramIn(cp, csprintf("msicap.ma"), tmp32);
529  msicap.ma = tmp32;
531  paramIn(cp, csprintf("msicap.md"), tmp16);;
532  msicap.md = tmp16;
535 
536  paramIn(cp, csprintf("msixcap.mxid"), tmp16);
537  msixcap.mxid = tmp16;
538  paramIn(cp, csprintf("msixcap.mxc"), tmp16);
539  msixcap.mxc = tmp16;
540  paramIn(cp, csprintf("msixcap.mtab"), tmp32);
541  msixcap.mtab = tmp32;
542  paramIn(cp, csprintf("msixcap.mpba"), tmp32);
543  msixcap.mpba = tmp32;
544 
545  // Only allocate if MSIXCAP_BASE is not 0x0
546  if (MSIXCAP_BASE != 0x0) {
547  int msix_array_size;
548  int pba_array_size;
549 
550  UNSERIALIZE_SCALAR(msix_array_size);
551  UNSERIALIZE_SCALAR(pba_array_size);
552 
553  MSIXTable tmp1 = {{0UL, 0UL, 0UL, 0UL}};
554  msix_table.resize(msix_array_size, tmp1);
555 
556  MSIXPbaEntry tmp2 = {0};
557  msix_pba.resize(pba_array_size, tmp2);
558 
559  for (int i = 0; i < msix_array_size; i++) {
560  paramIn(cp, csprintf("msix_table[%d].addr_lo", i),
561  msix_table[i].fields.addr_lo);
562  paramIn(cp, csprintf("msix_table[%d].addr_hi", i),
563  msix_table[i].fields.addr_hi);
564  paramIn(cp, csprintf("msix_table[%d].msg_data", i),
565  msix_table[i].fields.msg_data);
566  paramIn(cp, csprintf("msix_table[%d].vec_ctrl", i),
567  msix_table[i].fields.vec_ctrl);
568  }
569  for (int i = 0; i < pba_array_size; i++) {
570  paramIn(cp, csprintf("msix_pba[%d].bits", i),
571  msix_pba[i].bits);
572  }
573  }
574 
575  paramIn(cp, csprintf("pxcap.pxid"), tmp16);
576  pxcap.pxid = tmp16;
577  paramIn(cp, csprintf("pxcap.pxcap"), tmp16);
578  pxcap.pxcap = tmp16;
579  paramIn(cp, csprintf("pxcap.pxdcap"), tmp32);
580  pxcap.pxdcap = tmp32;
581  paramIn(cp, csprintf("pxcap.pxdc"), tmp16);
582  pxcap.pxdc = tmp16;
583  paramIn(cp, csprintf("pxcap.pxds"), tmp16);
584  pxcap.pxds = tmp16;
585  paramIn(cp, csprintf("pxcap.pxlcap"), tmp32);
586  pxcap.pxlcap = tmp32;
587  paramIn(cp, csprintf("pxcap.pxlc"), tmp16);
588  pxcap.pxlc = tmp16;
589  paramIn(cp, csprintf("pxcap.pxls"), tmp16);
590  pxcap.pxls = tmp16;
591  paramIn(cp, csprintf("pxcap.pxdcap2"), tmp32);
592  pxcap.pxdcap2 = tmp32;
593  paramIn(cp, csprintf("pxcap.pxdc2"), tmp32);
594  pxcap.pxdc2 = tmp32;
596 }
597 
MSICAP msicap
Definition: device.hh:84
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:163
#define DPRINTF(x,...)
Definition: trace.hh:222
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:580
#define BAR_IO_MASK
Definition: device.hh:57
uint32_t mtab
Definition: pcireg.h:276
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:282
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition: device.cc:507
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:171
Bitfield< 7 > i
uint8_t dev
Definition: types.hh:54
uint8_t headerType
Definition: pcireg.h:67
PCI device, base implementation is only config space.
Definition: device.hh:66
uint8_t minimumGrant
Definition: pcireg.h:81
#define PMCAP_PMCS
Definition: pcireg.h:171
#define PCI_CONFIG_SIZE
Definition: pcireg.h:149
uint8_t progIF
Definition: pcireg.h:62
uint16_t pc
Definition: pcireg.h:211
#define MSIXCAP_ID
Definition: pcireg.h:183
#define PCI0_BASE_ADDR3
Definition: pcireg.h:109
const PciBusAddr _busAddr
Definition: device.hh:69
#define PCI_STATUS
Definition: pcireg.h:90
MSIXCAP msixcap
Definition: device.hh:95
uint8_t maximumLatency
Definition: pcireg.h:82
uint32_t mpba
Definition: pcireg.h:279
Bitfield< 23, 0 > offset
Definition: types.hh:152
#define PCI0_MINIMUM_GRANT
Definition: pcireg.h:120
uint8_t interruptLine
Definition: pcireg.h:79
PMCAP pmcap
Definition: device.hh:81
uint16_t status
Definition: pcireg.h:60
uint16_t pxls
Definition: pcireg.h:372
uint16_t pxid
Definition: pcireg.h:307
#define MSIXVECS_PER_PBA
Definition: pcireg.h:295
#define PCI_REVISION_ID
Definition: pcireg.h:91
T letoh(T value)
Definition: byteswap.hh:141
Definition: cprintf.cc:40
uint16_t subsystemID
Definition: pcireg.h:72
uint32_t mmask
Definition: pcireg.h:256
#define PCI_CACHE_LINE_SIZE
Definition: pcireg.h:95
PciDevice(const PciDeviceParams *params)
Constructor for PCI Dev.
Definition: device.cc:62
#define PMCAP_PC
Definition: pcireg.h:170
uint16_t mid
Definition: pcireg.h:241
void setLE(T v)
Set the value in the data pointer to v as little endian.
PioPort< PioDevice > pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
Definition: io_device.hh:106
PXCAP pxcap
Definition: device.hh:98
bool isLargeBAR(int bar) const
Does the given BAR represent 32 lower bits of a 64-bit address?
Definition: device.hh:118
Bitfield< 3 > x
Definition: pagetable.hh:69
#define PCI0_MAXIMUM_LATENCY
Definition: pcireg.h:121
unsigned getSize() const
Definition: packet.hh:730
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:770
Addr memAddr(Addr addr) const
Calculate the physical address of a non-prefetchable memory location in the PCI address space...
Definition: host.hh:137
T htole(T value)
Definition: byteswap.hh:140
int MSIX_TABLE_END
Definition: device.hh:92
uint32_t pxlcap
Definition: pcireg.h:350
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:158
#define MSIXCAP_MXC
Definition: pcireg.h:184
bool legacyIO[6]
Whether the BARs are really hardwired legacy IO locations.
Definition: device.hh:112
uint32_t expansionROM
Definition: pcireg.h:73
#define PCI0_BASE_ADDR2
Definition: pcireg.h:108
void makeAtomicResponse()
Definition: packet.hh:943
uint64_t Tick
Tick count type.
Definition: types.hh:61
uint16_t mxid
Definition: pcireg.h:268
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
Definition: device.cc:284
void paramOut(CheckpointOut &cp, const string &name, ExtMachInst const &machInst)
Definition: types.cc:38
uint32_t pxdcap
Definition: pcireg.h:316
uint16_t device
Definition: pcireg.h:58
uint32_t pxdc2
Definition: pcireg.h:396
int MSIX_PBA_END
Definition: device.hh:94
Addr getAddr() const
Definition: packet.hh:720
virtual Tick readConfig(PacketPtr pkt)
Read from the PCI config space data that is stored locally.
Definition: device.cc:216
uint16_t pxcap
Definition: pcireg.h:310
bool isPowerOf2(const T &n)
Definition: intmath.hh:90
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:199
uint32_t mua
Definition: pcireg.h:254
uint16_t mxc
Definition: pcireg.h:271
#define PCI_DEVICE_SPECIFIC
Definition: pcireg.h:148
int MSIX_TABLE_OFFSET
Definition: device.hh:91
#define PCI0_BASE_ADDR1
Definition: pcireg.h:107
uint8_t bist
Definition: pcireg.h:68
Tick configDelay
Definition: device.hh:191
Declaration of IniFile object.
uint8_t classCode
Definition: pcireg.h:64
std::vector< MSIXTable > msix_table
MSIX Table and PBA Structures.
Definition: device.hh:102
#define MSIXCAP_MTAB
Definition: pcireg.h:185
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:805
#define warn_once(...)
Definition: logging.hh:212
uint16_t vendor
Definition: pcireg.h:57
uint16_t pxdc
Definition: pcireg.h:329
Addr BARAddrs[6]
The current address mapping of the BARs.
Definition: device.hh:109
uint16_t command
Definition: pcireg.h:59
#define PCI0_ROM_BASE_ADDR
Definition: pcireg.h:115
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:763
uint16_t subsystemVendorID
Definition: pcireg.h:71
uint8_t reserved[7]
Definition: pcireg.h:78
uint32_t ma
Definition: pcireg.h:251
AddrRangeList getAddrRanges() const override
Determine the address ranges that this device responds to.
Definition: device.cc:273
virtual const std::string name() const
Definition: sim_object.hh:128
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:813
#define PCI0_INTERRUPT_LINE
Definition: pcireg.h:118
int MSIX_PBA_OFFSET
Definition: device.hh:93
uint32_t mpend
Definition: pcireg.h:257
#define PMCAP_ID
PCIe capability list offsets internal to the entry.
Definition: pcireg.h:169
#define PCI_LATENCY_TIMER
Definition: pcireg.h:96
#define PCI0_INTERRUPT_PIN
Definition: pcireg.h:119
Declaration of the Packet class.
std::ostream CheckpointOut
Definition: serialize.hh:63
uint8_t func
Definition: types.hh:55
#define BAR_IO_SPACE(x)
Definition: device.hh:60
uint8_t subClassCode
Definition: pcireg.h:63
uint8_t data[64]
Definition: pcireg.h:54
#define PCI0_BASE_ADDR0
Definition: pcireg.h:106
uint32_t pxdcap2
Definition: pcireg.h:379
uint16_t mc
Definition: pcireg.h:244
std::vector< MSIXPbaEntry > msix_pba
Definition: device.hh:103
uint16_t pmcs
Definition: pcireg.h:220
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
Definition: types.cc:69
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Addr pioAddr(Addr addr) const
Calculate the physical address of an IO location on the PCI bus.
Definition: host.hh:128
#define PCI0_BASE_ADDR5
Definition: pcireg.h:111
#define warn(...)
Definition: logging.hh:208
uint16_t md
Definition: pcireg.h:255
PciIntPin
Definition: types.hh:63
uint16_t pxlc
Definition: pcireg.h:362
uint16_t pid
Definition: pcireg.h:208
#define BAR_MEM_MASK
Definition: device.hh:58
uint8_t cacheLineSize
Definition: pcireg.h:65
#define BAR_NUMBER(x)
Definition: device.hh:61
PciHost::DeviceInterface hostInterface
Definition: device.hh:188
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:71
uint8_t interruptPin
Definition: pcireg.h:80
uint8_t capabilityPtr
Definition: pcireg.h:74
uint16_t pxds
Definition: pcireg.h:342
PCIConfig config
The current config space.
Definition: device.hh:72
Bitfield< 0 > p
uint8_t latencyTimer
Definition: pcireg.h:66
uint32_t baseAddr[6]
Definition: pcireg.h:69
const int MSIXCAP_BASE
Definition: device.hh:86
#define PCI0_BASE_ADDR4
Definition: pcireg.h:110
#define PCI_CLASS_CODE
Definition: pcireg.h:92
#define MSIXCAP_MPBA
Definition: pcireg.h:186
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Definition: device.cc:442
uint32_t BARSize[6]
The size of the BARs.
Definition: device.hh:106
uint32_t cardbusCIS
Definition: pcireg.h:70
#define PCI_COMMAND
Definition: pcireg.h:89
uint8_t revision
Definition: pcireg.h:61

Generated on Mon Jun 8 2020 15:45:08 for gem5 by doxygen 1.8.13