gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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/misc.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->set<uint8_t>(0);
232  break;
233  case sizeof(uint16_t):
234  pkt->set<uint16_t>(0);
235  break;
236  case sizeof(uint32_t):
237  pkt->set<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->set<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->get<uint8_t>());
253  break;
254  case sizeof(uint16_t):
255  pkt->set<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->get<uint16_t>());
260  break;
261  case sizeof(uint32_t):
262  pkt->set<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->get<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->get<uint8_t>();
314  break;
315  case PCI_CACHE_LINE_SIZE:
316  config.cacheLineSize = pkt->get<uint8_t>();
317  break;
318  case PCI_LATENCY_TIMER:
319  config.latencyTimer = pkt->get<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->get<uint8_t>());
335  break;
336  case sizeof(uint16_t):
337  switch (offset) {
338  case PCI_COMMAND:
339  config.command = pkt->get<uint8_t>();
340  break;
341  case PCI_STATUS:
342  config.status = pkt->get<uint8_t>();
343  break;
344  case PCI_CACHE_LINE_SIZE:
345  config.cacheLineSize = pkt->get<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->get<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->get<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  BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ?
384  hostInterface.pioAddr(he_new_bar) :
385  hostInterface.memAddr(he_new_bar);
387  }
388  }
389  config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) |
390  (he_old_bar & bar_mask));
391  }
392  }
393  break;
394 
395  case PCI0_ROM_BASE_ADDR:
396  if (letoh(pkt->get<uint32_t>()) == 0xfffffffe)
397  config.expansionROM = htole((uint32_t)0xffffffff);
398  else
399  config.expansionROM = pkt->get<uint32_t>();
400  break;
401 
402  case PCI_COMMAND:
403  // This could also clear some of the error bits in the Status
404  // register. However they should never get set, so lets ignore
405  // it for now
406  config.command = pkt->get<uint32_t>();
407  break;
408 
409  default:
410  DPRINTF(PciDevice, "Writing to a read only register");
411  }
413  "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
414  _busAddr.dev, _busAddr.func, offset,
415  (uint32_t)pkt->get<uint32_t>());
416  break;
417  default:
418  panic("invalid access size(?) for PCI configspace!\n");
419  }
420  pkt->makeAtomicResponse();
421  return configDelay;
422 }
423 
424 void
426 {
427  SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
428  SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
429  SERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0]));
430 
431  // serialize the capability list registers
432  paramOut(cp, csprintf("pmcap.pid"), uint16_t(pmcap.pid));
433  paramOut(cp, csprintf("pmcap.pc"), uint16_t(pmcap.pc));
434  paramOut(cp, csprintf("pmcap.pmcs"), uint16_t(pmcap.pmcs));
435 
436  paramOut(cp, csprintf("msicap.mid"), uint16_t(msicap.mid));
437  paramOut(cp, csprintf("msicap.mc"), uint16_t(msicap.mc));
438  paramOut(cp, csprintf("msicap.ma"), uint32_t(msicap.ma));
440  paramOut(cp, csprintf("msicap.md"), uint16_t(msicap.md));
443 
444  paramOut(cp, csprintf("msixcap.mxid"), uint16_t(msixcap.mxid));
445  paramOut(cp, csprintf("msixcap.mxc"), uint16_t(msixcap.mxc));
446  paramOut(cp, csprintf("msixcap.mtab"), uint32_t(msixcap.mtab));
447  paramOut(cp, csprintf("msixcap.mpba"), uint32_t(msixcap.mpba));
448 
449  // Only serialize if we have a non-zero base address
450  if (MSIXCAP_BASE != 0x0) {
451  uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff;
452  int msix_array_size = msixcap_mxc_ts + 1;
453  int pba_array_size = msix_array_size/MSIXVECS_PER_PBA;
454  if ((msix_array_size % MSIXVECS_PER_PBA) > 0) {
455  pba_array_size++;
456  }
457 
458  SERIALIZE_SCALAR(msix_array_size);
459  SERIALIZE_SCALAR(pba_array_size);
460 
461  for (int i = 0; i < msix_array_size; i++) {
462  paramOut(cp, csprintf("msix_table[%d].addr_lo", i),
463  msix_table[i].fields.addr_lo);
464  paramOut(cp, csprintf("msix_table[%d].addr_hi", i),
465  msix_table[i].fields.addr_hi);
466  paramOut(cp, csprintf("msix_table[%d].msg_data", i),
467  msix_table[i].fields.msg_data);
468  paramOut(cp, csprintf("msix_table[%d].vec_ctrl", i),
469  msix_table[i].fields.vec_ctrl);
470  }
471  for (int i = 0; i < pba_array_size; i++) {
472  paramOut(cp, csprintf("msix_pba[%d].bits", i),
473  msix_pba[i].bits);
474  }
475  }
476 
477  paramOut(cp, csprintf("pxcap.pxid"), uint16_t(pxcap.pxid));
478  paramOut(cp, csprintf("pxcap.pxcap"), uint16_t(pxcap.pxcap));
479  paramOut(cp, csprintf("pxcap.pxdcap"), uint32_t(pxcap.pxdcap));
480  paramOut(cp, csprintf("pxcap.pxdc"), uint16_t(pxcap.pxdc));
481  paramOut(cp, csprintf("pxcap.pxds"), uint16_t(pxcap.pxds));
482  paramOut(cp, csprintf("pxcap.pxlcap"), uint32_t(pxcap.pxlcap));
483  paramOut(cp, csprintf("pxcap.pxlc"), uint16_t(pxcap.pxlc));
484  paramOut(cp, csprintf("pxcap.pxls"), uint16_t(pxcap.pxls));
485  paramOut(cp, csprintf("pxcap.pxdcap2"), uint32_t(pxcap.pxdcap2));
486  paramOut(cp, csprintf("pxcap.pxdc2"), uint32_t(pxcap.pxdc2));
487 }
488 
489 void
491 {
492  UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
493  UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
495  sizeof(config.data) / sizeof(config.data[0]));
496 
497  // unserialize the capability list registers
498  uint16_t tmp16;
499  uint32_t tmp32;
500  paramIn(cp, csprintf("pmcap.pid"), tmp16);
501  pmcap.pid = tmp16;
502  paramIn(cp, csprintf("pmcap.pc"), tmp16);
503  pmcap.pc = tmp16;
504  paramIn(cp, csprintf("pmcap.pmcs"), tmp16);
505  pmcap.pmcs = tmp16;
506 
507  paramIn(cp, csprintf("msicap.mid"), tmp16);
508  msicap.mid = tmp16;
509  paramIn(cp, csprintf("msicap.mc"), tmp16);
510  msicap.mc = tmp16;
511  paramIn(cp, csprintf("msicap.ma"), tmp32);
512  msicap.ma = tmp32;
514  paramIn(cp, csprintf("msicap.md"), tmp16);;
515  msicap.md = tmp16;
518 
519  paramIn(cp, csprintf("msixcap.mxid"), tmp16);
520  msixcap.mxid = tmp16;
521  paramIn(cp, csprintf("msixcap.mxc"), tmp16);
522  msixcap.mxc = tmp16;
523  paramIn(cp, csprintf("msixcap.mtab"), tmp32);
524  msixcap.mtab = tmp32;
525  paramIn(cp, csprintf("msixcap.mpba"), tmp32);
526  msixcap.mpba = tmp32;
527 
528  // Only allocate if MSIXCAP_BASE is not 0x0
529  if (MSIXCAP_BASE != 0x0) {
530  int msix_array_size;
531  int pba_array_size;
532 
533  UNSERIALIZE_SCALAR(msix_array_size);
534  UNSERIALIZE_SCALAR(pba_array_size);
535 
536  MSIXTable tmp1 = {{0UL, 0UL, 0UL, 0UL}};
537  msix_table.resize(msix_array_size, tmp1);
538 
539  MSIXPbaEntry tmp2 = {0};
540  msix_pba.resize(pba_array_size, tmp2);
541 
542  for (int i = 0; i < msix_array_size; i++) {
543  paramIn(cp, csprintf("msix_table[%d].addr_lo", i),
544  msix_table[i].fields.addr_lo);
545  paramIn(cp, csprintf("msix_table[%d].addr_hi", i),
546  msix_table[i].fields.addr_hi);
547  paramIn(cp, csprintf("msix_table[%d].msg_data", i),
548  msix_table[i].fields.msg_data);
549  paramIn(cp, csprintf("msix_table[%d].vec_ctrl", i),
550  msix_table[i].fields.vec_ctrl);
551  }
552  for (int i = 0; i < pba_array_size; i++) {
553  paramIn(cp, csprintf("msix_pba[%d].bits", i),
554  msix_pba[i].bits);
555  }
556  }
557 
558  paramIn(cp, csprintf("pxcap.pxid"), tmp16);
559  pxcap.pxid = tmp16;
560  paramIn(cp, csprintf("pxcap.pxcap"), tmp16);
561  pxcap.pxcap = tmp16;
562  paramIn(cp, csprintf("pxcap.pxdcap"), tmp32);
563  pxcap.pxdcap = tmp32;
564  paramIn(cp, csprintf("pxcap.pxdc"), tmp16);
565  pxcap.pxdc = tmp16;
566  paramIn(cp, csprintf("pxcap.pxds"), tmp16);
567  pxcap.pxds = tmp16;
568  paramIn(cp, csprintf("pxcap.pxlcap"), tmp32);
569  pxcap.pxlcap = tmp32;
570  paramIn(cp, csprintf("pxcap.pxlc"), tmp16);
571  pxcap.pxlc = tmp16;
572  paramIn(cp, csprintf("pxcap.pxls"), tmp16);
573  pxcap.pxls = tmp16;
574  paramIn(cp, csprintf("pxcap.pxdcap2"), tmp32);
575  pxcap.pxdcap2 = tmp32;
576  paramIn(cp, csprintf("pxcap.pxdc2"), tmp32);
577  pxcap.pxdc2 = tmp32;
579 }
580 
MSICAP msicap
Definition: device.hh:88
#define DPRINTF(x,...)
Definition: trace.hh:212
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:398
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
#define BAR_IO_MASK
Definition: device.hh:61
Addr memAddr(Addr addr) const
Calculate the physical address of a non-prefetchable memory location in the PCI address space...
Definition: host.hh:139
uint32_t mtab
Definition: pcireg.h:279
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition: device.cc:490
Bitfield< 7 > i
Definition: miscregs.hh:1378
uint8_t dev
Definition: types.hh:56
#define panic(...)
Definition: misc.hh:153
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
#define warn_once(...)
Definition: misc.hh:226
uint32_t mpba
Definition: pcireg.h:282
Bitfield< 23, 0 > offset
Definition: types.hh:149
#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:152
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
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
PXCAP pxcap
Definition: device.hh:102
PioPort pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
Definition: io_device.hh:91
#define PCI0_MAXIMUM_LATENCY
Definition: pcireg.h:124
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:145
T htole(T value)
Definition: byteswap.hh:151
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:161
Addr pioAddr(Addr addr) const
Calculate the physical address of an IO location on the PCI bus.
Definition: host.hh:130
#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:857
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 fatal(...)
Definition: misc.hh:163
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:158
int MSIX_PBA_END
Definition: device.hh:98
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:73
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:186
Declaration of IniFile object.
uint8_t classCode
Definition: pcireg.h:67
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:245
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
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:410
#define PCI0_ROM_BASE_ADDR
Definition: pcireg.h:118
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:143
uint16_t subsystemVendorID
Definition: pcireg.h:74
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:161
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
virtual const std::string name() const
Definition: sim_object.hh:117
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:67
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
#define PCI0_BASE_ADDR5
Definition: pcireg.h:114
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
unsigned getSize() const
Definition: packet.hh:649
uint8_t cacheLineSize
Definition: pcireg.h:68
#define BAR_NUMBER(x)
Definition: device.hh:65
PciHost::DeviceInterface hostInterface
Definition: device.hh:183
fatal_if(p->js_features.size() > 16,"Too many job slot feature registers specified (%i)\n", p->js_features.size())
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
Definition: bitfield.hh:67
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:425
uint32_t BARSize[6]
The size of the BARs.
Definition: device.hh:110
Addr getAddr() const
Definition: packet.hh:639
uint32_t cardbusCIS
Definition: pcireg.h:73
#define PCI_COMMAND
Definition: pcireg.h:92
uint8_t revision
Definition: pcireg.h:64

Generated on Fri Jun 9 2017 13:03:42 for gem5 by doxygen 1.8.6