gem5  v19.0.0.0
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  * Authors: Ali Saidi
41  * Andrew Schultz
42  * Miguel Serrano
43  */
44 
45 /* @file
46  * A single PCI device configuration space entry.
47  */
48 
49 #include "dev/pci/device.hh"
50 
51 #include <list>
52 #include <string>
53 #include <vector>
54 
55 #include "base/inifile.hh"
56 #include "base/intmath.hh"
57 #include "base/logging.hh"
58 #include "base/str.hh"
59 #include "base/trace.hh"
60 #include "debug/PciDevice.hh"
61 #include "mem/packet.hh"
62 #include "mem/packet_access.hh"
63 #include "sim/byteswap.hh"
64 #include "sim/core.hh"
65 
66 PciDevice::PciDevice(const PciDeviceParams *p)
67  : DmaDevice(p),
68  _busAddr(p->pci_bus, p->pci_dev, p->pci_func),
69  PMCAP_BASE(p->PMCAPBaseOffset),
70  PMCAP_ID_OFFSET(p->PMCAPBaseOffset+PMCAP_ID),
71  PMCAP_PC_OFFSET(p->PMCAPBaseOffset+PMCAP_PC),
72  PMCAP_PMCS_OFFSET(p->PMCAPBaseOffset+PMCAP_PMCS),
73  MSICAP_BASE(p->MSICAPBaseOffset),
74  MSIXCAP_BASE(p->MSIXCAPBaseOffset),
75  MSIXCAP_ID_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_ID),
76  MSIXCAP_MXC_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MXC),
77  MSIXCAP_MTAB_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MTAB),
78  MSIXCAP_MPBA_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MPBA),
79  PXCAP_BASE(p->PXCAPBaseOffset),
80 
81  hostInterface(p->host->registerDevice(this, _busAddr,
82  (PciIntPin)p->InterruptPin)),
83  pioDelay(p->pio_latency),
84  configDelay(p->config_latency)
85 {
86  fatal_if(p->InterruptPin >= 5,
87  "Invalid PCI interrupt '%i' specified.", p->InterruptPin);
88 
89  config.vendor = htole(p->VendorID);
90  config.device = htole(p->DeviceID);
91  config.command = htole(p->Command);
92  config.status = htole(p->Status);
93  config.revision = htole(p->Revision);
94  config.progIF = htole(p->ProgIF);
95  config.subClassCode = htole(p->SubClassCode);
96  config.classCode = htole(p->ClassCode);
97  config.cacheLineSize = htole(p->CacheLineSize);
98  config.latencyTimer = htole(p->LatencyTimer);
99  config.headerType = htole(p->HeaderType);
100  config.bist = htole(p->BIST);
101 
102  config.baseAddr[0] = htole(p->BAR0);
103  config.baseAddr[1] = htole(p->BAR1);
104  config.baseAddr[2] = htole(p->BAR2);
105  config.baseAddr[3] = htole(p->BAR3);
106  config.baseAddr[4] = htole(p->BAR4);
107  config.baseAddr[5] = htole(p->BAR5);
108  config.cardbusCIS = htole(p->CardbusCIS);
109  config.subsystemVendorID = htole(p->SubsystemVendorID);
110  config.subsystemID = htole(p->SubsystemID);
111  config.expansionROM = htole(p->ExpansionROM);
112  config.capabilityPtr = htole(p->CapabilityPtr);
113  // Zero out the 7 bytes of reserved space in the PCI Config space register.
114  bzero(config.reserved, 7*sizeof(uint8_t));
115  config.interruptLine = htole(p->InterruptLine);
116  config.interruptPin = htole(p->InterruptPin);
117  config.minimumGrant = htole(p->MinimumGrant);
118  config.maximumLatency = htole(p->MaximumLatency);
119 
120  // Initialize the capability lists
121  // These structs are bitunions, meaning the data is stored in host
122  // endianess and must be converted to Little Endian when accessed
123  // by the guest
124  // PMCAP
125  pmcap.pid = (uint16_t)p->PMCAPCapId; // pid.cid
126  pmcap.pid |= (uint16_t)p->PMCAPNextCapability << 8; //pid.next
127  pmcap.pc = p->PMCAPCapabilities;
128  pmcap.pmcs = p->PMCAPCtrlStatus;
129 
130  // MSICAP
131  msicap.mid = (uint16_t)p->MSICAPCapId; //mid.cid
132  msicap.mid |= (uint16_t)p->MSICAPNextCapability << 8; //mid.next
133  msicap.mc = p->MSICAPMsgCtrl;
134  msicap.ma = p->MSICAPMsgAddr;
135  msicap.mua = p->MSICAPMsgUpperAddr;
136  msicap.md = p->MSICAPMsgData;
137  msicap.mmask = p->MSICAPMaskBits;
138  msicap.mpend = p->MSICAPPendingBits;
139 
140  // MSIXCAP
141  msixcap.mxid = (uint16_t)p->MSIXCAPCapId; //mxid.cid
142  msixcap.mxid |= (uint16_t)p->MSIXCAPNextCapability << 8; //mxid.next
143  msixcap.mxc = p->MSIXMsgCtrl;
144  msixcap.mtab = p->MSIXTableOffset;
145  msixcap.mpba = p->MSIXPbaOffset;
146 
147  // allocate MSIX structures if MSIXCAP_BASE
148  // indicates the MSIXCAP is being used by having a
149  // non-zero base address.
150  // The MSIX tables are stored by the guest in
151  // little endian byte-order as according the
152  // PCIe specification. Make sure to take the proper
153  // actions when manipulating these tables on the host
154  uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff;
155  if (MSIXCAP_BASE != 0x0) {
156  int msix_vecs = msixcap_mxc_ts + 1;
157  MSIXTable tmp1 = {{0UL,0UL,0UL,0UL}};
158  msix_table.resize(msix_vecs, tmp1);
159 
160  MSIXPbaEntry tmp2 = {0};
161  int pba_size = msix_vecs / MSIXVECS_PER_PBA;
162  if ((msix_vecs % MSIXVECS_PER_PBA) > 0) {
163  pba_size++;
164  }
165  msix_pba.resize(pba_size, tmp2);
166  }
167  MSIX_TABLE_OFFSET = msixcap.mtab & 0xfffffffc;
169  (msixcap_mxc_ts + 1) * sizeof(MSIXTable);
170  MSIX_PBA_OFFSET = msixcap.mpba & 0xfffffffc;
172  ((msixcap_mxc_ts + 1) / MSIXVECS_PER_PBA)
173  * sizeof(MSIXPbaEntry);
174  if (((msixcap_mxc_ts + 1) % MSIXVECS_PER_PBA) > 0) {
175  MSIX_PBA_END += sizeof(MSIXPbaEntry);
176  }
177 
178  // PXCAP
179  pxcap.pxid = (uint16_t)p->PXCAPCapId; //pxid.cid
180  pxcap.pxid |= (uint16_t)p->PXCAPNextCapability << 8; //pxid.next
181  pxcap.pxcap = p->PXCAPCapabilities;
182  pxcap.pxdcap = p->PXCAPDevCapabilities;
183  pxcap.pxdc = p->PXCAPDevCtrl;
184  pxcap.pxds = p->PXCAPDevStatus;
185  pxcap.pxlcap = p->PXCAPLinkCap;
186  pxcap.pxlc = p->PXCAPLinkCtrl;
187  pxcap.pxls = p->PXCAPLinkStatus;
188  pxcap.pxdcap2 = p->PXCAPDevCap2;
189  pxcap.pxdc2 = p->PXCAPDevCtrl2;
190 
191  BARSize[0] = p->BAR0Size;
192  BARSize[1] = p->BAR1Size;
193  BARSize[2] = p->BAR2Size;
194  BARSize[3] = p->BAR3Size;
195  BARSize[4] = p->BAR4Size;
196  BARSize[5] = p->BAR5Size;
197 
198  legacyIO[0] = p->BAR0LegacyIO;
199  legacyIO[1] = p->BAR1LegacyIO;
200  legacyIO[2] = p->BAR2LegacyIO;
201  legacyIO[3] = p->BAR3LegacyIO;
202  legacyIO[4] = p->BAR4LegacyIO;
203  legacyIO[5] = p->BAR5LegacyIO;
204 
205  for (int i = 0; i < 6; ++i) {
206  if (legacyIO[i]) {
207  BARAddrs[i] = p->LegacyIOBase + letoh(config.baseAddr[i]);
208  config.baseAddr[i] = 0;
209  } else {
210  BARAddrs[i] = 0;
211  uint32_t barsize = BARSize[i];
212  if (barsize != 0 && !isPowerOf2(barsize)) {
213  fatal("BAR %d size %d is not a power of 2\n", i, BARSize[i]);
214  }
215  }
216  }
217 }
218 
219 Tick
221 {
222  int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
223 
224  /* Return 0 for accesses to unimplemented PCI configspace areas */
225  if (offset >= PCI_DEVICE_SPECIFIC &&
226  offset < PCI_CONFIG_SIZE) {
227  warn_once("Device specific PCI config space "
228  "not implemented for %s!\n", this->name());
229  switch (pkt->getSize()) {
230  case sizeof(uint8_t):
231  pkt->setLE<uint8_t>(0);
232  break;
233  case sizeof(uint16_t):
234  pkt->setLE<uint16_t>(0);
235  break;
236  case sizeof(uint32_t):
237  pkt->setLE<uint32_t>(0);
238  break;
239  default:
240  panic("invalid access size(?) for PCI configspace!\n");
241  }
242  } else if (offset > PCI_CONFIG_SIZE) {
243  panic("Out-of-range access to PCI config space!\n");
244  }
245 
246  switch (pkt->getSize()) {
247  case sizeof(uint8_t):
248  pkt->setLE<uint8_t>(config.data[offset]);
250  "readConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
251  _busAddr.dev, _busAddr.func, offset,
252  (uint32_t)pkt->getLE<uint8_t>());
253  break;
254  case sizeof(uint16_t):
255  pkt->setLE<uint16_t>(*(uint16_t*)&config.data[offset]);
257  "readConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
258  _busAddr.dev, _busAddr.func, offset,
259  (uint32_t)pkt->getLE<uint16_t>());
260  break;
261  case sizeof(uint32_t):
262  pkt->setLE<uint32_t>(*(uint32_t*)&config.data[offset]);
264  "readConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
265  _busAddr.dev, _busAddr.func, offset,
266  (uint32_t)pkt->getLE<uint32_t>());
267  break;
268  default:
269  panic("invalid access size(?) for PCI configspace!\n");
270  }
271  pkt->makeAtomicResponse();
272  return configDelay;
273 
274 }
275 
278 {
279  AddrRangeList ranges;
280  int x = 0;
281  for (x = 0; x < 6; x++)
282  if (BARAddrs[x] != 0)
283  ranges.push_back(RangeSize(BARAddrs[x],BARSize[x]));
284  return ranges;
285 }
286 
287 Tick
289 {
290  int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
291 
292  /* No effect if we write to config space that is not implemented*/
293  if (offset >= PCI_DEVICE_SPECIFIC &&
294  offset < PCI_CONFIG_SIZE) {
295  warn_once("Device specific PCI config space "
296  "not implemented for %s!\n", this->name());
297  switch (pkt->getSize()) {
298  case sizeof(uint8_t):
299  case sizeof(uint16_t):
300  case sizeof(uint32_t):
301  break;
302  default:
303  panic("invalid access size(?) for PCI configspace!\n");
304  }
305  } else if (offset > PCI_CONFIG_SIZE) {
306  panic("Out-of-range access to PCI config space!\n");
307  }
308 
309  switch (pkt->getSize()) {
310  case sizeof(uint8_t):
311  switch (offset) {
312  case PCI0_INTERRUPT_LINE:
313  config.interruptLine = pkt->getLE<uint8_t>();
314  break;
315  case PCI_CACHE_LINE_SIZE:
316  config.cacheLineSize = pkt->getLE<uint8_t>();
317  break;
318  case PCI_LATENCY_TIMER:
319  config.latencyTimer = pkt->getLE<uint8_t>();
320  break;
321  /* Do nothing for these read-only registers */
322  case PCI0_INTERRUPT_PIN:
323  case PCI0_MINIMUM_GRANT:
325  case PCI_CLASS_CODE:
326  case PCI_REVISION_ID:
327  break;
328  default:
329  panic("writing to a read only register");
330  }
332  "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
333  _busAddr.dev, _busAddr.func, offset,
334  (uint32_t)pkt->getLE<uint8_t>());
335  break;
336  case sizeof(uint16_t):
337  switch (offset) {
338  case PCI_COMMAND:
339  config.command = pkt->getLE<uint8_t>();
340  break;
341  case PCI_STATUS:
342  config.status = pkt->getLE<uint8_t>();
343  break;
344  case PCI_CACHE_LINE_SIZE:
345  config.cacheLineSize = pkt->getLE<uint8_t>();
346  break;
347  default:
348  panic("writing to a read only register");
349  }
351  "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
352  _busAddr.dev, _busAddr.func, offset,
353  (uint32_t)pkt->getLE<uint16_t>());
354  break;
355  case sizeof(uint32_t):
356  switch (offset) {
357  case PCI0_BASE_ADDR0:
358  case PCI0_BASE_ADDR1:
359  case PCI0_BASE_ADDR2:
360  case PCI0_BASE_ADDR3:
361  case PCI0_BASE_ADDR4:
362  case PCI0_BASE_ADDR5:
363  {
364  int barnum = BAR_NUMBER(offset);
365 
366  if (!legacyIO[barnum]) {
367  // convert BAR values to host endianness
368  uint32_t he_old_bar = letoh(config.baseAddr[barnum]);
369  uint32_t he_new_bar = letoh(pkt->getLE<uint32_t>());
370 
371  uint32_t bar_mask =
372  BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK;
373 
374  // Writing 0xffffffff to a BAR tells the card to set the
375  // value of the bar to a bitmask indicating the size of
376  // memory it needs
377  if (he_new_bar == 0xffffffff) {
378  he_new_bar = ~(BARSize[barnum] - 1);
379  } else {
380  // does it mean something special to write 0 to a BAR?
381  he_new_bar &= ~bar_mask;
382  if (he_new_bar) {
383  if (isLargeBAR(barnum)) {
384  if (BAR_IO_SPACE(he_old_bar))
385  warn("IO BARs can't be set as large BAR");
386  uint64_t he_large_bar =
387  letoh(config.baseAddr[barnum + 1]);
388  he_large_bar = he_large_bar << 32;
389  he_large_bar += he_new_bar;
390  BARAddrs[barnum] =
391  hostInterface.memAddr(he_large_bar);
392  } else if (isLargeBAR(barnum - 1)) {
393  BARAddrs[barnum] = 0;
394  uint64_t he_large_bar = he_new_bar;
395  he_large_bar = he_large_bar << 32;
396  // We need to apply mask to lower bits
397  he_large_bar +=
398  letoh(config.baseAddr[barnum - 1]
399  & ~bar_mask);
400  BARAddrs[barnum - 1] =
401  hostInterface.memAddr(he_large_bar);
402  } else {
403  BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ?
404  hostInterface.pioAddr(he_new_bar) :
405  hostInterface.memAddr(he_new_bar);
406  }
408  }
409  }
410  config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) |
411  (he_old_bar & bar_mask));
412  }
413  }
414  break;
415 
416  case PCI0_ROM_BASE_ADDR:
417  if (letoh(pkt->getLE<uint32_t>()) == 0xfffffffe)
418  config.expansionROM = htole((uint32_t)0xffffffff);
419  else
420  config.expansionROM = pkt->getLE<uint32_t>();
421  break;
422 
423  case PCI_COMMAND:
424  // This could also clear some of the error bits in the Status
425  // register. However they should never get set, so lets ignore
426  // it for now
427  config.command = pkt->getLE<uint32_t>();
428  break;
429 
430  default:
431  DPRINTF(PciDevice, "Writing to a read only register");
432  }
434  "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
435  _busAddr.dev, _busAddr.func, offset,
436  (uint32_t)pkt->getLE<uint32_t>());
437  break;
438  default:
439  panic("invalid access size(?) for PCI configspace!\n");
440  }
441  pkt->makeAtomicResponse();
442  return configDelay;
443 }
444 
445 void
447 {
448  SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
449  SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
450  SERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0]));
451 
452  // serialize the capability list registers
453  paramOut(cp, csprintf("pmcap.pid"), uint16_t(pmcap.pid));
454  paramOut(cp, csprintf("pmcap.pc"), uint16_t(pmcap.pc));
455  paramOut(cp, csprintf("pmcap.pmcs"), uint16_t(pmcap.pmcs));
456 
457  paramOut(cp, csprintf("msicap.mid"), uint16_t(msicap.mid));
458  paramOut(cp, csprintf("msicap.mc"), uint16_t(msicap.mc));
459  paramOut(cp, csprintf("msicap.ma"), uint32_t(msicap.ma));
461  paramOut(cp, csprintf("msicap.md"), uint16_t(msicap.md));
464 
465  paramOut(cp, csprintf("msixcap.mxid"), uint16_t(msixcap.mxid));
466  paramOut(cp, csprintf("msixcap.mxc"), uint16_t(msixcap.mxc));
467  paramOut(cp, csprintf("msixcap.mtab"), uint32_t(msixcap.mtab));
468  paramOut(cp, csprintf("msixcap.mpba"), uint32_t(msixcap.mpba));
469 
470  // Only serialize if we have a non-zero base address
471  if (MSIXCAP_BASE != 0x0) {
472  uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff;
473  int msix_array_size = msixcap_mxc_ts + 1;
474  int pba_array_size = msix_array_size/MSIXVECS_PER_PBA;
475  if ((msix_array_size % MSIXVECS_PER_PBA) > 0) {
476  pba_array_size++;
477  }
478 
479  SERIALIZE_SCALAR(msix_array_size);
480  SERIALIZE_SCALAR(pba_array_size);
481 
482  for (int i = 0; i < msix_array_size; i++) {
483  paramOut(cp, csprintf("msix_table[%d].addr_lo", i),
484  msix_table[i].fields.addr_lo);
485  paramOut(cp, csprintf("msix_table[%d].addr_hi", i),
486  msix_table[i].fields.addr_hi);
487  paramOut(cp, csprintf("msix_table[%d].msg_data", i),
488  msix_table[i].fields.msg_data);
489  paramOut(cp, csprintf("msix_table[%d].vec_ctrl", i),
490  msix_table[i].fields.vec_ctrl);
491  }
492  for (int i = 0; i < pba_array_size; i++) {
493  paramOut(cp, csprintf("msix_pba[%d].bits", i),
494  msix_pba[i].bits);
495  }
496  }
497 
498  paramOut(cp, csprintf("pxcap.pxid"), uint16_t(pxcap.pxid));
499  paramOut(cp, csprintf("pxcap.pxcap"), uint16_t(pxcap.pxcap));
500  paramOut(cp, csprintf("pxcap.pxdcap"), uint32_t(pxcap.pxdcap));
501  paramOut(cp, csprintf("pxcap.pxdc"), uint16_t(pxcap.pxdc));
502  paramOut(cp, csprintf("pxcap.pxds"), uint16_t(pxcap.pxds));
503  paramOut(cp, csprintf("pxcap.pxlcap"), uint32_t(pxcap.pxlcap));
504  paramOut(cp, csprintf("pxcap.pxlc"), uint16_t(pxcap.pxlc));
505  paramOut(cp, csprintf("pxcap.pxls"), uint16_t(pxcap.pxls));
506  paramOut(cp, csprintf("pxcap.pxdcap2"), uint32_t(pxcap.pxdcap2));
507  paramOut(cp, csprintf("pxcap.pxdc2"), uint32_t(pxcap.pxdc2));
508 }
509 
510 void
512 {
513  UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
514  UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
516  sizeof(config.data) / sizeof(config.data[0]));
517 
518  // unserialize the capability list registers
519  uint16_t tmp16;
520  uint32_t tmp32;
521  paramIn(cp, csprintf("pmcap.pid"), tmp16);
522  pmcap.pid = tmp16;
523  paramIn(cp, csprintf("pmcap.pc"), tmp16);
524  pmcap.pc = tmp16;
525  paramIn(cp, csprintf("pmcap.pmcs"), tmp16);
526  pmcap.pmcs = tmp16;
527 
528  paramIn(cp, csprintf("msicap.mid"), tmp16);
529  msicap.mid = tmp16;
530  paramIn(cp, csprintf("msicap.mc"), tmp16);
531  msicap.mc = tmp16;
532  paramIn(cp, csprintf("msicap.ma"), tmp32);
533  msicap.ma = tmp32;
535  paramIn(cp, csprintf("msicap.md"), tmp16);;
536  msicap.md = tmp16;
539 
540  paramIn(cp, csprintf("msixcap.mxid"), tmp16);
541  msixcap.mxid = tmp16;
542  paramIn(cp, csprintf("msixcap.mxc"), tmp16);
543  msixcap.mxc = tmp16;
544  paramIn(cp, csprintf("msixcap.mtab"), tmp32);
545  msixcap.mtab = tmp32;
546  paramIn(cp, csprintf("msixcap.mpba"), tmp32);
547  msixcap.mpba = tmp32;
548 
549  // Only allocate if MSIXCAP_BASE is not 0x0
550  if (MSIXCAP_BASE != 0x0) {
551  int msix_array_size;
552  int pba_array_size;
553 
554  UNSERIALIZE_SCALAR(msix_array_size);
555  UNSERIALIZE_SCALAR(pba_array_size);
556 
557  MSIXTable tmp1 = {{0UL, 0UL, 0UL, 0UL}};
558  msix_table.resize(msix_array_size, tmp1);
559 
560  MSIXPbaEntry tmp2 = {0};
561  msix_pba.resize(pba_array_size, tmp2);
562 
563  for (int i = 0; i < msix_array_size; i++) {
564  paramIn(cp, csprintf("msix_table[%d].addr_lo", i),
565  msix_table[i].fields.addr_lo);
566  paramIn(cp, csprintf("msix_table[%d].addr_hi", i),
567  msix_table[i].fields.addr_hi);
568  paramIn(cp, csprintf("msix_table[%d].msg_data", i),
569  msix_table[i].fields.msg_data);
570  paramIn(cp, csprintf("msix_table[%d].vec_ctrl", i),
571  msix_table[i].fields.vec_ctrl);
572  }
573  for (int i = 0; i < pba_array_size; i++) {
574  paramIn(cp, csprintf("msix_pba[%d].bits", i),
575  msix_pba[i].bits);
576  }
577  }
578 
579  paramIn(cp, csprintf("pxcap.pxid"), tmp16);
580  pxcap.pxid = tmp16;
581  paramIn(cp, csprintf("pxcap.pxcap"), tmp16);
582  pxcap.pxcap = tmp16;
583  paramIn(cp, csprintf("pxcap.pxdcap"), tmp32);
584  pxcap.pxdcap = tmp32;
585  paramIn(cp, csprintf("pxcap.pxdc"), tmp16);
586  pxcap.pxdc = tmp16;
587  paramIn(cp, csprintf("pxcap.pxds"), tmp16);
588  pxcap.pxds = tmp16;
589  paramIn(cp, csprintf("pxcap.pxlcap"), tmp32);
590  pxcap.pxlcap = tmp32;
591  paramIn(cp, csprintf("pxcap.pxlc"), tmp16);
592  pxcap.pxlc = tmp16;
593  paramIn(cp, csprintf("pxcap.pxls"), tmp16);
594  pxcap.pxls = tmp16;
595  paramIn(cp, csprintf("pxcap.pxdcap2"), tmp32);
596  pxcap.pxdcap2 = tmp32;
597  paramIn(cp, csprintf("pxcap.pxdc2"), tmp32);
598  pxcap.pxdc2 = tmp32;
600 }
601 
MSICAP msicap
Definition: device.hh:88
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:229
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:584
#define BAR_IO_MASK
Definition: device.hh:61
uint32_t mtab
Definition: pcireg.h:279
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:286
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition: device.cc:511
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:175
Bitfield< 7 > i
uint8_t dev
Definition: types.hh:56
uint8_t headerType
Definition: pcireg.h:70
PCI device, base implementation is only config space.
Definition: device.hh:70
uint8_t minimumGrant
Definition: pcireg.h:84
#define PMCAP_PMCS
Definition: pcireg.h:174
#define PCI_CONFIG_SIZE
Definition: pcireg.h:152
uint8_t progIF
Definition: pcireg.h:65
uint16_t pc
Definition: pcireg.h:214
#define MSIXCAP_ID
Definition: pcireg.h:186
#define PCI0_BASE_ADDR3
Definition: pcireg.h:112
const PciBusAddr _busAddr
Definition: device.hh:73
#define PCI_STATUS
Definition: pcireg.h:93
MSIXCAP msixcap
Definition: device.hh:99
uint8_t maximumLatency
Definition: pcireg.h:85
uint32_t mpba
Definition: pcireg.h:282
Bitfield< 23, 0 > offset
Definition: types.hh:154
#define PCI0_MINIMUM_GRANT
Definition: pcireg.h:123
uint8_t interruptLine
Definition: pcireg.h:82
PMCAP pmcap
Definition: device.hh:85
uint16_t status
Definition: pcireg.h:63
uint16_t pxls
Definition: pcireg.h:375
uint16_t pxid
Definition: pcireg.h:310
#define MSIXVECS_PER_PBA
Definition: pcireg.h:298
#define PCI_REVISION_ID
Definition: pcireg.h:94
T letoh(T value)
Definition: byteswap.hh:145
Definition: cprintf.cc:42
uint16_t subsystemID
Definition: pcireg.h:75
uint32_t mmask
Definition: pcireg.h:259
#define PCI_CACHE_LINE_SIZE
Definition: pcireg.h:98
PciDevice(const PciDeviceParams *params)
Constructor for PCI Dev.
Definition: device.cc:66
#define PMCAP_PC
Definition: pcireg.h:173
uint16_t mid
Definition: pcireg.h:244
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:109
PXCAP pxcap
Definition: device.hh:102
bool isLargeBAR(int bar) const
Does the given BAR represent 32 lower bits of a 64-bit address?
Definition: device.hh:122
#define PCI0_MAXIMUM_LATENCY
Definition: pcireg.h:124
unsigned getSize() const
Definition: packet.hh:736
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:645
Addr memAddr(Addr addr) const
Calculate the physical address of a non-prefetchable memory location in the PCI address space...
Definition: host.hh:139
T htole(T value)
Definition: byteswap.hh:144
int MSIX_TABLE_END
Definition: device.hh:96
uint32_t pxlcap
Definition: pcireg.h:353
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:162
#define MSIXCAP_MXC
Definition: pcireg.h:187
bool legacyIO[6]
Whether the BARs are really hardwired legacy IO locations.
Definition: device.hh:116
uint32_t expansionROM
Definition: pcireg.h:76
#define PCI0_BASE_ADDR2
Definition: pcireg.h:111
void makeAtomicResponse()
Definition: packet.hh:949
uint64_t Tick
Tick count type.
Definition: types.hh:63
uint16_t mxid
Definition: pcireg.h:271
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
Definition: device.cc:288
void paramOut(CheckpointOut &cp, const string &name, ExtMachInst const &machInst)
Definition: types.cc:40
uint32_t pxdcap
Definition: pcireg.h:319
uint16_t device
Definition: pcireg.h:61
uint32_t pxdc2
Definition: pcireg.h:399
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:658
int MSIX_PBA_END
Definition: device.hh:98
Addr getAddr() const
Definition: packet.hh:726
virtual Tick readConfig(PacketPtr pkt)
Read from the PCI config space data that is stored locally.
Definition: device.cc:220
uint16_t pxcap
Definition: pcireg.h:313
bool isPowerOf2(const T &n)
Definition: intmath.hh:146
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:203
uint32_t mua
Definition: pcireg.h:257
uint16_t mxc
Definition: pcireg.h:274
#define PCI_DEVICE_SPECIFIC
Definition: pcireg.h:151
int MSIX_TABLE_OFFSET
Definition: device.hh:95
#define PCI0_BASE_ADDR1
Definition: pcireg.h:110
uint8_t bist
Definition: pcireg.h:71
Tick configDelay
Definition: device.hh:195
Declaration of IniFile object.
uint8_t classCode
Definition: pcireg.h:67
virtual const std::string name() const
Definition: sim_object.hh:120
std::vector< MSIXTable > msix_table
MSIX Table and PBA Structures.
Definition: device.hh:106
#define MSIXCAP_MTAB
Definition: pcireg.h:188
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
#define warn_once(...)
Definition: logging.hh:216
uint16_t vendor
Definition: pcireg.h:60
uint16_t pxdc
Definition: pcireg.h:332
Addr BARAddrs[6]
The current address mapping of the BARs.
Definition: device.hh:113
uint16_t command
Definition: pcireg.h:62
#define PCI0_ROM_BASE_ADDR
Definition: pcireg.h:118
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:643
uint16_t subsystemVendorID
Definition: pcireg.h:74
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:661
uint8_t reserved[7]
Definition: pcireg.h:81
uint32_t ma
Definition: pcireg.h:254
AddrRangeList getAddrRanges() const override
Determine the address ranges that this device responds to.
Definition: device.cc:277
#define PCI0_INTERRUPT_LINE
Definition: pcireg.h:121
int MSIX_PBA_OFFSET
Definition: device.hh:97
uint32_t mpend
Definition: pcireg.h:260
#define PMCAP_ID
PCIe capability list offsets internal to the entry.
Definition: pcireg.h:172
#define PCI_LATENCY_TIMER
Definition: pcireg.h:99
#define PCI0_INTERRUPT_PIN
Definition: pcireg.h:122
Declaration of the Packet class.
std::ostream CheckpointOut
Definition: serialize.hh:68
uint8_t func
Definition: types.hh:57
#define BAR_IO_SPACE(x)
Definition: device.hh:64
uint8_t subClassCode
Definition: pcireg.h:66
uint8_t data[64]
Definition: pcireg.h:57
#define PCI0_BASE_ADDR0
Definition: pcireg.h:109
uint32_t pxdcap2
Definition: pcireg.h:382
uint16_t mc
Definition: pcireg.h:247
std::vector< MSIXPbaEntry > msix_pba
Definition: device.hh:107
uint16_t pmcs
Definition: pcireg.h:223
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
Definition: types.cc:71
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:130
#define PCI0_BASE_ADDR5
Definition: pcireg.h:114
#define warn(...)
Definition: logging.hh:212
uint16_t md
Definition: pcireg.h:258
PciIntPin
Definition: types.hh:65
uint16_t pxlc
Definition: pcireg.h:365
uint16_t pid
Definition: pcireg.h:211
#define BAR_MEM_MASK
Definition: device.hh:62
uint8_t cacheLineSize
Definition: pcireg.h:68
#define BAR_NUMBER(x)
Definition: device.hh:65
PciHost::DeviceInterface hostInterface
Definition: device.hh:192
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:72
uint8_t interruptPin
Definition: pcireg.h:83
uint8_t capabilityPtr
Definition: pcireg.h:77
uint16_t pxds
Definition: pcireg.h:345
PCIConfig config
The current config space.
Definition: device.hh:76
Bitfield< 0 > p
Bitfield< 1 > x
Definition: types.hh:105
uint8_t latencyTimer
Definition: pcireg.h:69
uint32_t baseAddr[6]
Definition: pcireg.h:72
const int MSIXCAP_BASE
Definition: device.hh:90
#define PCI0_BASE_ADDR4
Definition: pcireg.h:113
#define PCI_CLASS_CODE
Definition: pcireg.h:95
#define MSIXCAP_MPBA
Definition: pcireg.h:189
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Definition: device.cc:446
uint32_t BARSize[6]
The size of the BARs.
Definition: device.hh:110
uint32_t cardbusCIS
Definition: pcireg.h:73
#define PCI_COMMAND
Definition: pcireg.h:92
uint8_t revision
Definition: pcireg.h:64

Generated on Fri Feb 28 2020 16:26:59 for gem5 by doxygen 1.8.13