1 // Copyright 2016 The Fuchsia Authors
2 // Copyright (c) 2016, Google, Inc. All rights reserved
3 //
4 // Use of this source code is governed by a MIT-style
5 // license that can be found in the LICENSE file or at
6 // https://opensource.org/licenses/MIT
7 
8 #include <assert.h>
9 #include <debug.h>
10 #include <err.h>
11 #include <string.h>
12 #include <trace.h>
13 #include <fbl/algorithm.h>
14 #include <dev/pci_config.h>
15 #include <dev/pcie_device.h>
16 
17 #include <fbl/alloc_checker.h>
18 
19 #define LOCAL_TRACE 0
20 
21 /*
22  * TODO(cja) Re-add the paranoid sanity checks on capability placement
23  * and size that was in the old code. Doing this sanely likely involves keeping
24  * the various C style structures for the capabilities in pcie_caps.h originally
25 */
26 
quirk_should_force_pcie(const PcieDevice & dev)27 static bool quirk_should_force_pcie(const PcieDevice& dev) {
28     static const struct {
29         uint16_t vendor_id;
30         uint16_t device_id;
31     } QUIRK_LIST[] = {
32         { .vendor_id = 0x8086, .device_id = 0x1616 },  // Wildcat Point GPU
33     };
34 
35     for (size_t i = 0; i < fbl::count_of(QUIRK_LIST); ++i) {
36         if ((QUIRK_LIST[i].vendor_id == dev.vendor_id()) &&
37             (QUIRK_LIST[i].device_id == dev.device_id()))
38             return true;
39     }
40 
41     return false;
42 }
43 
44 
45 /*
46  * Advanced Capabilities for Conventional PCI ECN
47  */
PciCapAdvFeatures(const PcieDevice & dev,uint16_t base,uint8_t id)48 PciCapAdvFeatures::PciCapAdvFeatures(const PcieDevice& dev, uint16_t base, uint8_t id)
49     : PciStdCapability(dev, base, id) {
50     DEBUG_ASSERT(id == PCIE_CAP_ID_ADVANCED_FEATURES);
51     auto cfg = dev.config();
52 
53     length_    = PciReg8(static_cast<uint16_t>(base_ + kLengthOffset));
54     af_caps_   = PciReg8(static_cast<uint16_t>(base_ + kAFCapsOffset));
55     af_ctrl_   = PciReg8(static_cast<uint16_t>(base_ + kAFControlOffset));
56     af_status_ = PciReg8(static_cast<uint16_t>(base_ + kAFStatusOffset));
57 
58     uint8_t caps = cfg->Read(af_caps_);
59     has_flr_ = PCS_ADVCAPS_CAP_HAS_FUNC_LEVEL_RESET(caps);
60     has_tp_  = PCS_ADVCAPS_CAP_HAS_TRANS_PENDING(caps);
61 
62     uint8_t length = cfg->Read(length_);
63     if (length != PCS_ADVCAPS_LENGTH) {
64         TRACEF("Length of %u does not match the spec length of %u!\n", length, PCS_ADVCAPS_LENGTH);
65         return;
66     }
67 
68     is_valid_ = true;
69 }
70 
71 /*
72  * PCI Express Base Specification 1.1  Section 7.8 (version 1)
73  * PCI Express Base Specification 3.1a Section 7.8 (version 2)
74  */
PciCapPcie(const PcieDevice & dev,uint16_t base,uint8_t id)75 PciCapPcie::PciCapPcie(const PcieDevice& dev, uint16_t base, uint8_t id)
76     : PciStdCapability(dev, base, id) {
77     DEBUG_ASSERT(id == PCIE_CAP_ID_PCI_EXPRESS);
78     auto cfg = dev.config();
79 
80     /* Have we already initialized PCIE? */
81     if (is_valid_) {
82         TRACEF("Device %02x:%02x.%01x (%04hx:%04hx) has more than one PCI "
83                 "Express capability structure!\n",
84                dev.bus_id(), dev.dev_id(), dev.func_id(),
85                dev.vendor_id(), dev.device_id());
86         return;
87     }
88 
89     caps_ = PciReg16(static_cast<uint16_t>(base_ + kPcieCapsOffset));
90     auto cap_val = cfg->Read(caps_);
91     version_ = PCS_CAPS_VERSION(cap_val);
92     devtype_ = PCS_CAPS_DEVTYPE(cap_val);
93 
94     /*
95      * Set up all the offsets for the various chunks in the device. Some may
96      * not be supported, but regardless of whether they are there the final
97      * structure will be the same.
98      */
99     device.caps_    = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kDeviceOffset)));
100     device.ctrl_    = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kDeviceOffset)));
101     device.status_  = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kDeviceOffset)));
102 
103     link.caps_      = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kLinkOffset)));
104     link.ctrl_      = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kLinkOffset)));
105     link.status_    = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kLinkOffset)));
106 
107     slot.caps_      = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kSlotOffset)));
108     slot.ctrl_      = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kSlotOffset)));
109     slot.status_    = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kSlotOffset)));
110 
111     root.caps_      = PciReg16(static_cast<uint16_t>(base_ + kRootCapsOffset));
112     root.ctrl_      = PciReg16(static_cast<uint16_t>(base_ + kRootControlOffset));
113     root.status_    = PciReg32(static_cast<uint16_t>(base_ + kRootStatusOffset));
114 
115     device2.caps_   = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kDevice2Offset)));
116     device2.ctrl_   = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kDevice2Offset)));
117     device2.status_ = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kDevice2Offset)));
118 
119     link2.caps_     = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kLinkOffset)));
120     link2.ctrl_     = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kLinkOffset)));
121     link2.status_   = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kLinkOffset)));
122 
123     slot2.caps_     = PciReg32(static_cast<uint16_t>(base_ + kCapsOffset(kSlotOffset)));
124     slot2.ctrl_     = PciReg16(static_cast<uint16_t>(base_ + kControlOffset(kSlotOffset)));
125     slot2.status_   = PciReg16(static_cast<uint16_t>(base_ + kStatusOffset(kSlotOffset)));
126 
127     /* Sanity check the device/port type */
128     switch (devtype_) {
129         // Type 0 config header types
130         case PCIE_DEVTYPE_PCIE_ENDPOINT:
131         case PCIE_DEVTYPE_LEGACY_PCIE_ENDPOINT:
132         case PCIE_DEVTYPE_RC_INTEGRATED_ENDPOINT:
133         case PCIE_DEVTYPE_RC_EVENT_COLLECTOR:
134             if (dev.is_bridge()) {
135                 TRACEF("Device %02x:%02x.%01x (%04hx:%04hx) has a Type 0 PCIe "
136                        "device type (0x%x) in PCIe capabilities structure, but "
137                        "does not have a Type 0 config header.\n",
138                        dev.bus_id(), dev.dev_id(), dev.func_id(),
139                        dev.vendor_id(), dev.device_id(),
140                        devtype_);
141                 return;
142             }
143             break;
144 
145         // Type 1 config header types
146         case PCIE_DEVTYPE_RC_ROOT_PORT:
147         case PCIE_DEVTYPE_SWITCH_UPSTREAM_PORT:
148         case PCIE_DEVTYPE_SWITCH_DOWNSTREAM_PORT:
149         case PCIE_DEVTYPE_PCIE_TO_PCI_BRIDGE:
150         case PCIE_DEVTYPE_PCI_TO_PCIE_BRIDGE:
151             if (!dev.is_bridge()) {
152                 TRACEF("Device %02x:%02x.%01x (%04hx:%04hx) has a Type 1 PCIe "
153                        "device type (0x%x) in PCIe capabilities structure, but "
154                        "does not have a Type 1 config header.\n",
155                        dev.bus_id(), dev.dev_id(), dev.func_id(),
156                        dev.vendor_id(), dev.device_id(),
157                        devtype_);
158                 return;
159             }
160             break;
161 
162         default:
163             TRACEF("Device %02x:%02x.%01x (%04hx:%04hx) has an illegal PCIe "
164                    "device type (0x%x) in PCIe capabilities structure.\n",
165                    dev.bus_id(), dev.dev_id(), dev.func_id(),
166                    dev.vendor_id(), dev.device_id(),
167                    devtype_);
168             return;
169     }
170 
171     /* TODO(johngro): remember to read the MSI/MSI-X interrupt message number
172      * field when setting up for MSI/MSI-X.  We almost certainly need to hook
173      * this IRQ in order to be aware of any changes to the extended
174      * capabilities.  It is unclear whether or not we should allow this IRQ to
175      * be passed thru to the device driver or not.
176      */
177 
178     /* Check device capabilities to see if we support function level reset or
179      * not */
180     uint32_t devcaps = cfg->Read(device.caps());
181     has_flr_ = (PCS_DEV_CAPS_FUNC_LEVEL_RESET(devcaps) != 0);
182 
183     is_valid_ = true;
184 }
185 
186 /*
187  * @see PCI Local Bus Specification 3.0 Section 6.8.1
188  */
PciCapMsi(const PcieDevice & dev,uint16_t base,uint8_t id)189 PciCapMsi::PciCapMsi(const PcieDevice& dev, uint16_t base, uint8_t id)
190     : PciStdCapability(dev, base, id) {
191     DEBUG_ASSERT(id == PCIE_CAP_ID_MSI);
192     auto cfg = dev.config();
193 
194     // Set up the rest of the registers based on whether we're 64 bit or not.
195     ctrl_     = PciReg16(static_cast<uint16_t>(base_ + kControlOffset));
196     addr_     = PciReg32(static_cast<uint16_t>(base_ + kAddrOffset));
197 
198     uint16_t ctrl = cfg->Read(ctrl_reg());
199     has_pvm_      = PCIE_CAP_MSI_CTRL_PVM_SUPPORTED(ctrl);
200     is_64_bit_    = PCIE_CAP_MSI_CTRL_64BIT_SUPPORTED(ctrl);
201     msi_size_     = (has_pvm_ ? (is_64_bit_ ? k64BitPvmSize : k32BitPvmSize)
202                               : (is_64_bit_ ? k64BitNoPvmSize : k32BitNoPvmSize));
203 
204     if (is_64_bit_) {
205         addr_upper_   = PciReg32(static_cast<uint16_t>(base_ + kAddrUpperOffset));
206         data_         = PciReg16(static_cast<uint16_t>(base_ + kData64Offset));
207         mask_bits_    = PciReg32(static_cast<uint16_t>(base_ + kMaskBits64Offset));
208         pending_bits_ = PciReg32(static_cast<uint16_t>(base_ + kPendingBits64Offset));
209     } else {
210         data_         = PciReg16(static_cast<uint16_t>(base_ + kData32Offset));
211         mask_bits_    = PciReg32(static_cast<uint16_t>(base_ + kMaskBits32Offset));
212         pending_bits_ = PciReg32(static_cast<uint16_t>(base_ + kPendingBits32Offset));
213     }
214 
215     memset(&irq_block_, 0, sizeof(irq_block_));
216     uint16_t msi_end = static_cast<uint16_t>(base_ + msi_size_);
217     uint16_t cfgend = PCIE_BASE_CONFIG_SIZE;
218 
219     if (msi_end >= cfgend) {
220         TRACEF("Device %02x:%02x.%01x (%04hx:%04hx) has illegally positioned MSI "
221                "capability structure.  Structure %s 64-bit addressing and %s "
222                "per-vector masking and should be %u bytes long, but the "
223                "structure ends at %u, %u bytes past the end of config "
224                "space\n",
225                dev.bus_id(), dev.dev_id(), dev.func_id(),
226                dev.vendor_id(), dev.device_id(),
227                is_64_bit_ ? "supports" : "does not support",
228                has_pvm_ ? "supports" : "does not support",
229                msi_size_, msi_end, static_cast<unsigned int>(cfgend - msi_end));
230         return;
231     }
232 
233     /* Sanity check the Multi-Message Capable field */
234     max_irqs_ = 0x1u << PCIE_CAP_MSI_CTRL_GET_MMC(ctrl);
235     if (max_irqs_ > PCIE_MAX_MSI_IRQS) {
236         TRACEF("Device %02x:%02x.%01x (%04hx:%04hx) has invalid Multi-Message "
237                "Capable value in MSI capability structure (%d).  Structure "
238                "claims to support %u vectors, but %u is the maximum allowed.\n",
239                dev.bus_id(), dev.dev_id(), dev.func_id(),
240                dev.vendor_id(), dev.device_id(),
241                PCIE_CAP_MSI_CTRL_GET_MMC(ctrl), max_irqs_, PCIE_MAX_MSI_IRQS);
242         return;
243     }
244 
245     /* Success!
246      *
247      * Make sure that MSI is disabled and that the Multi-Message Enable field is
248      * set to 1-vector (multi-message disabled).  Then record our capabilities
249      * in the device's bookkeeping and we are done.
250      */
251     cfg->Write(ctrl_reg(), PCIE_CAP_MSI_CTRL_SET_MME(0,
252                            PCIE_CAP_MSI_CTRL_SET_ENB(0, ctrl)));
253     if (has_pvm_)
254         cfg->Write(mask_bits_reg(), 0xFFFFFFFF);
255 
256     is_valid_ = true;
257 }
258 
259 /* Catch quirks and invalid capability offsets we may see */
validate_capability_offset(uint8_t offset)260 inline zx_status_t validate_capability_offset(uint8_t offset) {
261     if (offset == 0xFF
262         || offset < PCIE_CAP_PTR_MIN_VALID
263         || offset > PCIE_CAP_PTR_MAX_VALID) {
264         return ZX_ERR_INVALID_ARGS;
265     }
266 
267     return ZX_OK;
268 }
269 
270 /*
271  * TODO(cja): It may be worth moving to table based solution like we had before
272  * where we have a single parse function and a function table for it to use,
273  * but it involves a bit more worrying about ownership of capabilities and
274  * std / ext attributes.
275  */
276 
ParseStdCapabilitiesLocked()277 zx_status_t PcieDevice::ParseStdCapabilitiesLocked() {
278     zx_status_t res = ZX_OK;
279     uint8_t cap_offset = cfg_->Read(PciConfig::kCapabilitiesPtr);
280     uint8_t caps_found = 0;
281     fbl::AllocChecker ac;
282 
283     /*
284      * Walk the pointer list for the standard capabilities table. As a safety,
285      * keep track of how many capabilities we've looked at to prevent potential
286      * cycles from walking forever. Any supported capability will be parsed
287      * by their object in the PcieDevice, and are additionally stored in a list
288      * for reference later.
289      */
290     LTRACEF("Scanning for capabilities at %02x:%02x.%01x (%04hx:%04hx)\n",
291             bus_id(), dev_id(), func_id(), vendor_id(), device_id());
292     while (cap_offset != PCIE_CAP_PTR_NULL && caps_found < PCIE_MAX_CAPABILITIES) {
293         if ((res = validate_capability_offset(cap_offset)) != ZX_OK) {
294             TRACEF("Device %02x:%02x.%01x (%04hx:%04hx) has invalid cptr (%#02x)\n",
295                     bus_id(), dev_id(), func_id(),
296                     vendor_id(), device_id(), cap_offset);
297             break;
298         }
299 
300         uint8_t id = cfg_->Read(PciReg8(cap_offset));
301 
302         LTRACEF("Found capability (#%u, id = 0x%02x) for device %02x:%02x.%01x (%04hx:%04hx)\n",
303                 caps_found, id,
304                 bus_id(), dev_id(), func_id(),
305                 vendor_id(), device_id());
306         /*
307          * Depending on the capability found we allocate a structure of the appropriate type
308          * and add it to the bookkeeping tree. For important things like MSI/PCIE we cache a raw
309          * pointer to it for fast access, but otherwise everything is found via the capability list.
310          *
311          * TODO(cja): if we make this a two stage allocation/initialization in the future we can do
312          * away with is_valid() style checks that are done in additional checking if pcie_/msi_ are
313          * valid pointers.
314          */
315         PciStdCapability* cap;
316         switch(id) {
317             case PCIE_CAP_ID_MSI:
318                 cap = irq_.msi = new (&ac) PciCapMsi(*this, cap_offset, id); break;
319             case PCIE_CAP_ID_PCI_EXPRESS:
320                 cap = pcie_ = new (&ac) PciCapPcie(*this, cap_offset, id); break;
321             case PCIE_CAP_ID_ADVANCED_FEATURES:
322                 cap = pci_af_ = new (&ac) PciCapAdvFeatures(*this, cap_offset, id); break;
323 
324             default:
325                 cap = new (&ac) PciStdCapability(*this, cap_offset, id); break;
326         }
327 
328         if (!ac.check()) {
329             TRACEF("Could not allocate memory fori capability 0x%02x\n", id);
330             return ZX_ERR_NO_MEMORY;
331         }
332 
333         caps_.detected.push_front(ktl::unique_ptr<PciStdCapability>(cap));
334         cap_offset  = cfg_->Read(PciReg8(static_cast<uint16_t>(cap_offset + 0x1))) & 0xFC;
335         caps_found++;
336     }
337 
338     return res;
339 }
340 
ParseExtCapabilitiesLocked()341 zx_status_t PcieDevice::ParseExtCapabilitiesLocked() {
342     /*
343      * TODO(cja): Since ExtCaps are a no-op right now (we had nothing in the table for
344      * supported extended capabilities) this is a stub for now.
345      */
346     return ZX_OK;
347 }
348 
349 // Parse PCI Standard Capabilities starting with the pointer in the PCI
350 // config structure.
ProbeCapabilitiesLocked()351 zx_status_t PcieDevice::ProbeCapabilitiesLocked() {
352     zx_status_t ret = ParseStdCapabilitiesLocked();
353     if (ret != ZX_OK) {
354         return ret;
355     }
356 
357     /* If this device is PCIe device, the parse the extended configuration
358      * section of the PCI config looking for extended capabilities.  Based on
359      * the spec, we should only need to look for a PCI Express Capability
360      * Structure in the standard config section to make the determination that
361      * this device is a legit PCIe device.
362      *
363      * This said, I have encountered at least one device (the graphics
364      * controller in the Wildcat Point PCH) which clearly is PCIe and clearly
365      * has extended capabilities, but which is not spec compliant and does not
366      * contain a proper PCI Express Capability Structure.  Because of this, we
367      * maintain a quirks list of non compliant devices which are actually PCIe,
368      * but do not appear to be so at first glance. */
369     if ((is_pcie() || quirk_should_force_pcie(*this)) && pcie_->is_valid()) {
370         ret = ParseExtCapabilitiesLocked();
371     }
372 
373     return ret;
374 }
375