gem5  v22.1.0.0
device.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 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  * Interface for devices using PCI configuration
43  */
44 
45 #ifndef __DEV_PCI_DEVICE_HH__
46 #define __DEV_PCI_DEVICE_HH__
47 
48 #include <array>
49 #include <cstring>
50 #include <vector>
51 
52 #include "dev/dma_device.hh"
53 #include "dev/pci/host.hh"
54 #include "dev/pci/pcireg.h"
55 #include "params/PciBar.hh"
56 #include "params/PciBarNone.hh"
57 #include "params/PciDevice.hh"
58 #include "params/PciIoBar.hh"
59 #include "params/PciLegacyIoBar.hh"
60 #include "params/PciMemBar.hh"
61 #include "params/PciMemUpperBar.hh"
62 #include "sim/byteswap.hh"
63 
64 #define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
65 
66 namespace gem5
67 {
68 
69 class PciBar : public SimObject
70 {
71  protected:
72  // The address and size of the region this decoder recognizes.
73  Addr _addr = 0;
74  Addr _size = 0;
75 
76  public:
77  PciBar(const PciBarParams &p) : SimObject(p) {}
78 
79  virtual bool isMem() const { return false; }
80  virtual bool isIo() const { return false; }
81 
82  // Accepts a value written to config space, consumes it, and returns what
83  // value config space should actually be set to. Both should be in host
84  // endian format.
85  virtual uint32_t write(const PciHost::DeviceInterface &host,
86  uint32_t val) = 0;
87 
88  AddrRange range() const { return AddrRange(_addr, _addr + _size); }
89  Addr addr() const { return _addr; }
90  Addr size() const { return _size; }
91 
92  // Hack for devices that don't know their BAR sizes ahead of time :-o.
93  // Don't use unless you have to, since this may not propogate properly
94  // outside of a small window.
95  void size(Addr value) { _size = value; }
96 };
97 
98 class PciBarNone : public PciBar
99 {
100  public:
101  PciBarNone(const PciBarNoneParams &p) : PciBar(p) {}
102 
103  uint32_t
104  write(const PciHost::DeviceInterface &host, uint32_t val) override
105  {
106  return 0;
107  }
108 };
109 
110 class PciIoBar : public PciBar
111 {
112  protected:
114  Bitfield<31, 2> addr;
115  Bitfield<1> reserved;
116  Bitfield<0> io;
118 
119  public:
120  PciIoBar(const PciIoBarParams &p, bool legacy=false) : PciBar(p)
121  {
122  _size = p.size;
123  if (!legacy) {
124  Bar bar = _size;
125  fatal_if(!_size || !isPowerOf2(_size) || bar.io || bar.reserved,
126  "Illegal size %d for bar %s.", _size, name());
127  }
128  }
129 
130  bool isIo() const override { return true; }
131 
132  uint32_t
133  write(const PciHost::DeviceInterface &host, uint32_t val) override
134  {
135  // Mask away the bits fixed by hardware.
136  Bar bar = val & ~(_size - 1);
137  // Set the fixed bits to their correct values.
138  bar.reserved = 0;
139  bar.io = 1;
140 
141  // Update our address.
142  _addr = host.pioAddr(bar.addr << 2);
143 
144  // Return what should go into config space.
145  return bar;
146  }
147 };
148 
149 class PciLegacyIoBar : public PciIoBar
150 {
151  protected:
153 
154  public:
155  PciLegacyIoBar(const PciLegacyIoBarParams &p) : PciIoBar(p, true)
156  {
157  // Save the address until we get a host to translate it.
158  fixedAddr = p.addr;
159  }
160 
161  uint32_t
162  write(const PciHost::DeviceInterface &host, uint32_t val) override
163  {
164  // Update the address now that we have a host to translate it.
165  _addr = host.pioAddr(fixedAddr);
166  // Ignore writes.
167  return 0;
168  }
169 };
170 
171 class PciMemBar : public PciBar
172 {
173  private:
175  Bitfield<31, 3> addr;
177  Bitfield<2> wide;
178  Bitfield<1> reserved;
180  Bitfield<0> io;
182 
183  bool _wide = false;
184  uint64_t _lower = 0;
185  uint64_t _upper = 0;
186 
187  public:
188  PciMemBar(const PciMemBarParams &p) : PciBar(p)
189  {
190  _size = p.size;
191  Bar bar = _size;
192  fatal_if(!_size || !isPowerOf2(_size) || bar.io || bar.type,
193  "Illegal size %d for bar %s.", _size, name());
194  }
195 
196  bool isMem() const override { return true; }
197 
198  uint32_t
199  write(const PciHost::DeviceInterface &host, uint32_t val) override
200  {
201  // Mask away the bits fixed by hardware.
202  Bar bar = val & ~(_size - 1);
203  // Set the fixed bits to their correct values.
204  bar.type.wide = wide() ? 1 : 0;
205  bar.type.reserved = 0;
206  bar.io = 0;
207 
208  // Keep track of our lower 32 bits.
209  _lower = bar.addr << 3;
210 
211  // Update our address.
212  _addr = host.memAddr(upper() + lower());
213 
214  // Return what should go into config space.
215  return bar;
216  }
217 
218  bool wide() const { return _wide; }
219  void wide(bool val) { _wide = val; }
220 
221  uint64_t upper() const { return _upper; }
222  void
223  upper(const PciHost::DeviceInterface &host, uint32_t val)
224  {
225  _upper = (uint64_t)val << 32;
226 
227  // Update our address.
228  _addr = host.memAddr(upper() + lower());
229  }
230 
231  uint64_t lower() const { return _lower; }
232 };
233 
234 class PciMemUpperBar : public PciBar
235 {
236  private:
237  PciMemBar *_lower = nullptr;
238 
239  public:
240  PciMemUpperBar(const PciMemUpperBarParams &p) : PciBar(p)
241  {}
242 
243  void
245  {
246  _lower = val;
247  // Let our lower half know we're up here.
248  _lower->wide(true);
249  }
250 
251  uint32_t
252  write(const PciHost::DeviceInterface &host, uint32_t val) override
253  {
254  assert(_lower);
255 
256  // Mask away bits fixed by hardware, if any.
257  Addr upper = val & ~((_lower->size() - 1) >> 32);
258 
259  // Let our lower half know about the update.
260  _lower->upper(host, upper);
261 
262  return upper;
263  }
264 };
265 
269 class PciDevice : public DmaDevice
270 {
271  protected:
273 
275  PCIConfig config;
276 
280  const int PMCAP_BASE;
281  const int PMCAP_ID_OFFSET;
282  const int PMCAP_PC_OFFSET;
283  const int PMCAP_PMCS_OFFSET;
285 
286  const int MSICAP_BASE;
288 
289  const int MSIXCAP_BASE;
290  const int MSIXCAP_ID_OFFSET;
299 
300  const int PXCAP_BASE;
307 
308  std::array<PciBar *, 6> BARs{};
309 
319  bool
320  getBAR(Addr addr, int &num, Addr &offs)
321  {
322  for (int i = 0; i < BARs.size(); i++) {
323  auto *bar = BARs[i];
324  if (!bar || !bar->range().contains(addr))
325  continue;
326  num = i;
327  offs = addr - bar->addr();
328  return true;
329  }
330  return false;
331  }
332 
333  public: // Host configuration interface
340  virtual Tick writeConfig(PacketPtr pkt);
341 
342 
349  virtual Tick readConfig(PacketPtr pkt);
350 
351  protected:
353 
356 
357  public:
358  Addr
359  pciToDma(Addr pci_addr) const
360  {
361  return hostInterface.dmaAddr(pci_addr);
362  }
363 
366 
367  uint8_t interruptLine() const { return letoh(config.interruptLine); }
368 
374  AddrRangeList getAddrRanges() const override;
375 
381  PciDevice(const PciDeviceParams &params);
382 
387  void serialize(CheckpointOut &cp) const override;
388 
394  void unserialize(CheckpointIn &cp) override;
395 
396  const PciBusAddr &busAddr() const { return _busAddr; }
397 };
398 
399 } // namespace gem5
400 
401 #endif // __DEV_PCI_DEVICE_HH__
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition: addr_range.hh:82
virtual std::string name() const
Definition: named.hh:47
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
PciBarNone(const PciBarNoneParams &p)
Definition: device.hh:101
uint32_t write(const PciHost::DeviceInterface &host, uint32_t val) override
Definition: device.hh:104
virtual bool isIo() const
Definition: device.hh:80
PciBar(const PciBarParams &p)
Definition: device.hh:77
Addr _addr
Definition: device.hh:73
Addr size() const
Definition: device.hh:90
virtual uint32_t write(const PciHost::DeviceInterface &host, uint32_t val)=0
Addr _size
Definition: device.hh:74
AddrRange range() const
Definition: device.hh:88
Addr addr() const
Definition: device.hh:89
void size(Addr value)
Definition: device.hh:95
virtual bool isMem() const
Definition: device.hh:79
PCI device, base implementation is only config space.
Definition: device.hh:270
const int PMCAP_PC_OFFSET
Definition: device.hh:282
PciHost::DeviceInterface hostInterface
Definition: device.hh:352
PCIConfig config
The current config space.
Definition: device.hh:275
const int MSIXCAP_MTAB_OFFSET
Definition: device.hh:292
MSICAP msicap
Definition: device.hh:287
void intrClear()
Definition: device.hh:365
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition: device.cc:464
std::vector< MSIXTable > msix_table
MSIX Table and PBA Structures.
Definition: device.hh:305
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Definition: device.cc:401
bool getBAR(Addr addr, int &num, Addr &offs)
Which base address register (if any) maps the given address?
Definition: device.hh:320
const int MSIXCAP_BASE
Definition: device.hh:289
const int PMCAP_BASE
The capability list structures and base addresses.
Definition: device.hh:280
Addr pciToDma(Addr pci_addr) const
Definition: device.hh:359
std::array< PciBar *, 6 > BARs
Definition: device.hh:308
AddrRangeList getAddrRanges() const override
Determine the address ranges that this device responds to.
Definition: device.cc:269
int MSIX_PBA_OFFSET
Definition: device.hh:296
const int PMCAP_PMCS_OFFSET
Definition: device.hh:283
const PciBusAddr _busAddr
Definition: device.hh:272
std::vector< MSIXPbaEntry > msix_pba
Definition: device.hh:306
virtual Tick readConfig(PacketPtr pkt)
Read from the PCI config space data that is stored locally.
Definition: device.cc:212
MSIXCAP msixcap
Definition: device.hh:298
int MSIX_PBA_END
Definition: device.hh:297
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
Definition: device.cc:283
int MSIX_TABLE_OFFSET
Definition: device.hh:294
const int MSIXCAP_ID_OFFSET
Definition: device.hh:290
const int MSIXCAP_MPBA_OFFSET
Definition: device.hh:293
void intrPost()
Definition: device.hh:364
PciDevice(const PciDeviceParams &params)
Constructor for PCI Dev.
Definition: device.cc:64
uint8_t interruptLine() const
Definition: device.hh:367
const int PMCAP_ID_OFFSET
Definition: device.hh:281
const PciBusAddr & busAddr() const
Definition: device.hh:396
const int MSIXCAP_MXC_OFFSET
Definition: device.hh:291
const int PXCAP_BASE
Definition: device.hh:300
Tick configDelay
Definition: device.hh:355
int MSIX_TABLE_END
Definition: device.hh:295
const int MSICAP_BASE
Definition: device.hh:286
Callback interface from PCI devices to the host.
Definition: host.hh:95
void postInt()
Post a PCI interrupt to the CPU.
Definition: host.cc:105
Addr pioAddr(Addr addr) const
Calculate the physical address of an IO location on the PCI bus.
Definition: host.hh:131
Addr dmaAddr(Addr addr) const
Calculate the physical address of a prefetchable memory location in the PCI address space.
Definition: host.hh:149
Addr memAddr(Addr addr) const
Calculate the physical address of a non-prefetchable memory location in the PCI address space.
Definition: host.hh:140
void clearInt()
Clear a posted PCI interrupt.
Definition: host.cc:113
Bitfield< 1 > reserved
Definition: device.hh:115
EndBitUnion(Bar) public
Definition: device.hh:117
BitUnion32(Bar) Bitfield< 31
Bitfield< 0 > io
Definition: device.hh:116
bool isIo() const override
Definition: device.hh:130
uint32_t write(const PciHost::DeviceInterface &host, uint32_t val) override
Definition: device.hh:133
PciLegacyIoBar(const PciLegacyIoBarParams &p)
Definition: device.hh:155
uint32_t write(const PciHost::DeviceInterface &host, uint32_t val) override
Definition: device.hh:162
bool isMem() const override
Definition: device.hh:196
uint64_t lower() const
Definition: device.hh:231
uint32_t write(const PciHost::DeviceInterface &host, uint32_t val) override
Definition: device.hh:199
SubBitUnion(type, 2, 1) Bitfield< 2 > wide
uint64_t _upper
Definition: device.hh:185
void wide(bool val)
Definition: device.hh:219
uint64_t _lower
Definition: device.hh:184
EndSubBitUnion(type) Bitfield< 0 > io
EndBitUnion(Bar) bool _wide
Bitfield< 1 > reserved
Definition: device.hh:178
void upper(const PciHost::DeviceInterface &host, uint32_t val)
Definition: device.hh:223
uint64_t upper() const
Definition: device.hh:221
BitUnion32(Bar) Bitfield< 31
bool wide() const
Definition: device.hh:218
PciMemBar * _lower
Definition: device.hh:237
PciMemUpperBar(const PciMemUpperBarParams &p)
Definition: device.hh:240
void lower(PciMemBar *val)
Definition: device.hh:244
uint32_t write(const PciHost::DeviceInterface &host, uint32_t val) override
Definition: device.hh:252
Abstract superclass for simulation objects.
Definition: sim_object.hh:148
static constexpr bool isPowerOf2(const T &n)
Definition: intmath.hh:98
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:226
const Params & params() const
Definition: sim_object.hh:176
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 26 > io
Definition: dt_constants.hh:78
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 63 > val
Definition: misc.hh:776
Bitfield< 3 > addr
Definition: types.hh:84
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
T letoh(T value)
Definition: byteswap.hh:173
std::ostream CheckpointOut
Definition: serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
uint64_t Tick
Tick count type.
Definition: types.hh:58
Defines the PCI Express capability register and its associated bitfields for a PCIe device.
Definition: pcireg.h:330
Defines the MSI Capability register and its associated bitfields for the a PCI/PCIe device.
Definition: pcireg.h:257
Defines the Power Management capability register and all its associated bitfields for a PCIe device.
Definition: pcireg.h:222

Generated on Wed Dec 21 2022 10:22:30 for gem5 by doxygen 1.9.1