xref: /openbmc/qemu/tests/qtest/libqos/pci.c (revision cbb45ff0)
1 /*
2  * libqos PCI bindings
3  *
4  * Copyright IBM, Corp. 2012-2013
5  *
6  * Authors:
7  *  Anthony Liguori   <aliguori@us.ibm.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  */
12 
13 #include "qemu/osdep.h"
14 #include "pci.h"
15 
16 #include "hw/pci/pci.h"
17 #include "hw/pci/pci_bridge.h"
18 #include "hw/pci/pci_regs.h"
19 #include "qemu/host-utils.h"
20 #include "qgraph.h"
21 
22 void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
23                          void (*func)(QPCIDevice *dev, int devfn, void *data),
24                          void *data)
25 {
26     int slot;
27 
28     for (slot = 0; slot < 32; slot++) {
29         int fn;
30 
31         for (fn = 0; fn < 8; fn++) {
32             QPCIDevice *dev;
33 
34             dev = qpci_device_find(bus, QPCI_DEVFN(slot, fn));
35             if (!dev) {
36                 continue;
37             }
38 
39             if (vendor_id != -1 &&
40                 qpci_config_readw(dev, PCI_VENDOR_ID) != vendor_id) {
41                 g_free(dev);
42                 continue;
43             }
44 
45             if (device_id != -1 &&
46                 qpci_config_readw(dev, PCI_DEVICE_ID) != device_id) {
47                 g_free(dev);
48                 continue;
49             }
50 
51             func(dev, QPCI_DEVFN(slot, fn), data);
52         }
53     }
54 }
55 
56 bool qpci_has_buggy_msi(QPCIDevice *dev)
57 {
58     return dev->bus->has_buggy_msi;
59 }
60 
61 bool qpci_check_buggy_msi(QPCIDevice *dev)
62 {
63     if (qpci_has_buggy_msi(dev)) {
64         g_test_skip("Skipping due to incomplete support for MSI");
65         return true;
66     }
67     return false;
68 }
69 
70 static void qpci_device_set(QPCIDevice *dev, QPCIBus *bus, int devfn)
71 {
72     g_assert(dev);
73 
74     dev->bus = bus;
75     dev->devfn = devfn;
76 }
77 
78 QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn)
79 {
80     QPCIDevice *dev;
81 
82     dev = g_malloc0(sizeof(*dev));
83     qpci_device_set(dev, bus, devfn);
84 
85     if (qpci_config_readw(dev, PCI_VENDOR_ID) == 0xFFFF) {
86         g_free(dev);
87         return NULL;
88     }
89 
90     return dev;
91 }
92 
93 void qpci_device_init(QPCIDevice *dev, QPCIBus *bus, QPCIAddress *addr)
94 {
95     uint16_t vendor_id, device_id;
96 
97     qpci_device_set(dev, bus, addr->devfn);
98     vendor_id = qpci_config_readw(dev, PCI_VENDOR_ID);
99     device_id = qpci_config_readw(dev, PCI_DEVICE_ID);
100     g_assert(!addr->vendor_id || vendor_id == addr->vendor_id);
101     g_assert(!addr->device_id || device_id == addr->device_id);
102 }
103 
104 static uint8_t qpci_find_resource_reserve_capability(QPCIDevice *dev)
105 {
106     uint16_t device_id;
107     uint8_t cap = 0;
108 
109     if (qpci_config_readw(dev, PCI_VENDOR_ID) != PCI_VENDOR_ID_REDHAT) {
110         return 0;
111     }
112 
113     device_id = qpci_config_readw(dev, PCI_DEVICE_ID);
114 
115     if (device_id != PCI_DEVICE_ID_REDHAT_PCIE_RP &&
116         device_id != PCI_DEVICE_ID_REDHAT_BRIDGE) {
117         return 0;
118     }
119 
120     do {
121         cap = qpci_find_capability(dev, PCI_CAP_ID_VNDR, cap);
122     } while (cap &&
123              qpci_config_readb(dev, cap + REDHAT_PCI_CAP_TYPE_OFFSET) !=
124              REDHAT_PCI_CAP_RESOURCE_RESERVE);
125     if (cap) {
126         uint8_t cap_len = qpci_config_readb(dev, cap + PCI_CAP_FLAGS);
127         if (cap_len < REDHAT_PCI_CAP_RES_RESERVE_CAP_SIZE) {
128             return 0;
129         }
130     }
131     return cap;
132 }
133 
134 static void qpci_secondary_buses_rec(QPCIBus *qbus, int bus, int *pci_bus)
135 {
136     QPCIDevice *dev;
137     uint16_t class;
138     uint8_t pribus, secbus, subbus;
139     int index;
140 
141     for (index = 0; index < 32; index++) {
142         dev = qpci_device_find(qbus, QPCI_DEVFN(bus + index, 0));
143         if (dev == NULL) {
144             continue;
145         }
146         class = qpci_config_readw(dev, PCI_CLASS_DEVICE);
147         if (class == PCI_CLASS_BRIDGE_PCI) {
148             qpci_config_writeb(dev, PCI_SECONDARY_BUS, 255);
149             qpci_config_writeb(dev, PCI_SUBORDINATE_BUS, 0);
150         }
151         g_free(dev);
152     }
153 
154     for (index = 0; index < 32; index++) {
155         dev = qpci_device_find(qbus, QPCI_DEVFN(bus + index, 0));
156         if (dev == NULL) {
157             continue;
158         }
159         class = qpci_config_readw(dev, PCI_CLASS_DEVICE);
160         if (class != PCI_CLASS_BRIDGE_PCI) {
161             g_free(dev);
162             continue;
163         }
164 
165         pribus = qpci_config_readb(dev, PCI_PRIMARY_BUS);
166         if (pribus != bus) {
167             qpci_config_writeb(dev, PCI_PRIMARY_BUS, bus);
168         }
169 
170         secbus = qpci_config_readb(dev, PCI_SECONDARY_BUS);
171         (*pci_bus)++;
172         if (*pci_bus != secbus) {
173             secbus = *pci_bus;
174             qpci_config_writeb(dev, PCI_SECONDARY_BUS, secbus);
175         }
176 
177         subbus = qpci_config_readb(dev, PCI_SUBORDINATE_BUS);
178         qpci_config_writeb(dev, PCI_SUBORDINATE_BUS, 255);
179 
180         qpci_secondary_buses_rec(qbus, secbus << 5, pci_bus);
181 
182         if (subbus != *pci_bus) {
183             uint8_t res_bus = *pci_bus;
184             uint8_t cap = qpci_find_resource_reserve_capability(dev);
185 
186             if (cap) {
187                 uint32_t tmp_res_bus;
188 
189                 tmp_res_bus = qpci_config_readl(dev, cap +
190                                             REDHAT_PCI_CAP_RES_RESERVE_BUS_RES);
191                 if (tmp_res_bus != (uint32_t)-1) {
192                     res_bus = tmp_res_bus & 0xFF;
193                     if ((uint8_t)(res_bus + secbus) < secbus ||
194                         (uint8_t)(res_bus + secbus) < res_bus) {
195                         res_bus = 0;
196                     }
197                     if (secbus + res_bus > *pci_bus) {
198                         res_bus = secbus + res_bus;
199                     }
200                 }
201             }
202             subbus = res_bus;
203             *pci_bus = res_bus;
204         }
205 
206         qpci_config_writeb(dev, PCI_SUBORDINATE_BUS, subbus);
207         g_free(dev);
208     }
209 }
210 
211 int qpci_secondary_buses_init(QPCIBus *bus)
212 {
213     int last_bus = 0;
214 
215     qpci_secondary_buses_rec(bus, 0, &last_bus);
216 
217     return last_bus;
218 }
219 
220 
221 void qpci_device_enable(QPCIDevice *dev)
222 {
223     uint16_t cmd;
224 
225     /* FIXME -- does this need to be a bus callout? */
226     cmd = qpci_config_readw(dev, PCI_COMMAND);
227     cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
228     qpci_config_writew(dev, PCI_COMMAND, cmd);
229 
230     /* Verify the bits are now set. */
231     cmd = qpci_config_readw(dev, PCI_COMMAND);
232     g_assert_cmphex(cmd & PCI_COMMAND_IO, ==, PCI_COMMAND_IO);
233     g_assert_cmphex(cmd & PCI_COMMAND_MEMORY, ==, PCI_COMMAND_MEMORY);
234     g_assert_cmphex(cmd & PCI_COMMAND_MASTER, ==, PCI_COMMAND_MASTER);
235 }
236 
237 /**
238  * qpci_find_capability:
239  * @dev: the PCI device
240  * @id: the PCI Capability ID (PCI_CAP_ID_*)
241  * @start_addr: 0 to begin iteration or the last return value to continue
242  *              iteration
243  *
244  * Iterate over the PCI Capabilities List.
245  *
246  * Returns: PCI Configuration Space offset of the capabililty structure or
247  *          0 if no further matching capability is found
248  */
249 uint8_t qpci_find_capability(QPCIDevice *dev, uint8_t id, uint8_t start_addr)
250 {
251     uint8_t cap;
252     uint8_t addr;
253 
254     if (start_addr) {
255         addr = qpci_config_readb(dev, start_addr + PCI_CAP_LIST_NEXT);
256     } else {
257         addr = qpci_config_readb(dev, PCI_CAPABILITY_LIST);
258     }
259 
260     do {
261         cap = qpci_config_readb(dev, addr);
262         if (cap != id) {
263             addr = qpci_config_readb(dev, addr + PCI_CAP_LIST_NEXT);
264         }
265     } while (cap != id && addr != 0);
266 
267     return addr;
268 }
269 
270 void qpci_msix_enable(QPCIDevice *dev)
271 {
272     uint8_t addr;
273     uint16_t val;
274     uint32_t table;
275     uint8_t bir_table;
276     uint8_t bir_pba;
277 
278     addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
279     g_assert_cmphex(addr, !=, 0);
280 
281     val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
282     qpci_config_writew(dev, addr + PCI_MSIX_FLAGS, val | PCI_MSIX_FLAGS_ENABLE);
283 
284     table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE);
285     bir_table = table & PCI_MSIX_FLAGS_BIRMASK;
286     dev->msix_table_bar = qpci_iomap(dev, bir_table, NULL);
287     dev->msix_table_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
288 
289     table = qpci_config_readl(dev, addr + PCI_MSIX_PBA);
290     bir_pba = table & PCI_MSIX_FLAGS_BIRMASK;
291     if (bir_pba != bir_table) {
292         dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL);
293     } else {
294         dev->msix_pba_bar = dev->msix_table_bar;
295     }
296     dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
297 
298     dev->msix_enabled = true;
299 }
300 
301 void qpci_msix_disable(QPCIDevice *dev)
302 {
303     uint8_t addr;
304     uint16_t val;
305 
306     g_assert(dev->msix_enabled);
307     addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
308     g_assert_cmphex(addr, !=, 0);
309     val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
310     qpci_config_writew(dev, addr + PCI_MSIX_FLAGS,
311                                                 val & ~PCI_MSIX_FLAGS_ENABLE);
312 
313     if (dev->msix_pba_bar.addr != dev->msix_table_bar.addr) {
314         qpci_iounmap(dev, dev->msix_pba_bar);
315     }
316     qpci_iounmap(dev, dev->msix_table_bar);
317 
318     dev->msix_enabled = 0;
319     dev->msix_table_off = 0;
320     dev->msix_pba_off = 0;
321 }
322 
323 bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry)
324 {
325     uint32_t pba_entry;
326     uint8_t bit_n = entry % 32;
327     uint64_t  off = (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
328 
329     g_assert(dev->msix_enabled);
330     pba_entry = qpci_io_readl(dev, dev->msix_pba_bar, dev->msix_pba_off + off);
331     qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off,
332                    pba_entry & ~(1 << bit_n));
333     return (pba_entry & (1 << bit_n)) != 0;
334 }
335 
336 bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
337 {
338     uint8_t addr;
339     uint16_t val;
340     uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE;
341 
342     g_assert(dev->msix_enabled);
343     addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
344     g_assert_cmphex(addr, !=, 0);
345     val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
346 
347     if (val & PCI_MSIX_FLAGS_MASKALL) {
348         return true;
349     } else {
350         return (qpci_io_readl(dev, dev->msix_table_bar,
351                               vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL)
352                 & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
353     }
354 }
355 
356 uint16_t qpci_msix_table_size(QPCIDevice *dev)
357 {
358     uint8_t addr;
359     uint16_t control;
360 
361     addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
362     g_assert_cmphex(addr, !=, 0);
363 
364     control = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
365     return (control & PCI_MSIX_FLAGS_QSIZE) + 1;
366 }
367 
368 uint8_t qpci_config_readb(QPCIDevice *dev, uint8_t offset)
369 {
370     return dev->bus->config_readb(dev->bus, dev->devfn, offset);
371 }
372 
373 uint16_t qpci_config_readw(QPCIDevice *dev, uint8_t offset)
374 {
375     return dev->bus->config_readw(dev->bus, dev->devfn, offset);
376 }
377 
378 uint32_t qpci_config_readl(QPCIDevice *dev, uint8_t offset)
379 {
380     return dev->bus->config_readl(dev->bus, dev->devfn, offset);
381 }
382 
383 
384 void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value)
385 {
386     dev->bus->config_writeb(dev->bus, dev->devfn, offset, value);
387 }
388 
389 void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value)
390 {
391     dev->bus->config_writew(dev->bus, dev->devfn, offset, value);
392 }
393 
394 void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
395 {
396     dev->bus->config_writel(dev->bus, dev->devfn, offset, value);
397 }
398 
399 uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off)
400 {
401     if (token.addr < QPCI_PIO_LIMIT) {
402         return dev->bus->pio_readb(dev->bus, token.addr + off);
403     } else {
404         uint8_t val;
405         dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
406         return val;
407     }
408 }
409 
410 uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
411 {
412     if (token.addr < QPCI_PIO_LIMIT) {
413         return dev->bus->pio_readw(dev->bus, token.addr + off);
414     } else {
415         uint16_t val;
416         dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
417         return le16_to_cpu(val);
418     }
419 }
420 
421 uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
422 {
423     if (token.addr < QPCI_PIO_LIMIT) {
424         return dev->bus->pio_readl(dev->bus, token.addr + off);
425     } else {
426         uint32_t val;
427         dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
428         return le32_to_cpu(val);
429     }
430 }
431 
432 uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off)
433 {
434     if (token.addr < QPCI_PIO_LIMIT) {
435         return dev->bus->pio_readq(dev->bus, token.addr + off);
436     } else {
437         uint64_t val;
438         dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
439         return le64_to_cpu(val);
440     }
441 }
442 
443 void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
444                     uint8_t value)
445 {
446     if (token.addr < QPCI_PIO_LIMIT) {
447         dev->bus->pio_writeb(dev->bus, token.addr + off, value);
448     } else {
449         dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
450     }
451 }
452 
453 void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
454                     uint16_t value)
455 {
456     if (token.addr < QPCI_PIO_LIMIT) {
457         dev->bus->pio_writew(dev->bus, token.addr + off, value);
458     } else {
459         value = cpu_to_le16(value);
460         dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
461     }
462 }
463 
464 void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
465                     uint32_t value)
466 {
467     if (token.addr < QPCI_PIO_LIMIT) {
468         dev->bus->pio_writel(dev->bus, token.addr + off, value);
469     } else {
470         value = cpu_to_le32(value);
471         dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
472     }
473 }
474 
475 void qpci_io_writeq(QPCIDevice *dev, QPCIBar token, uint64_t off,
476                     uint64_t value)
477 {
478     if (token.addr < QPCI_PIO_LIMIT) {
479         dev->bus->pio_writeq(dev->bus, token.addr + off, value);
480     } else {
481         value = cpu_to_le64(value);
482         dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
483     }
484 }
485 
486 void qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off,
487                   void *buf, size_t len)
488 {
489     g_assert(token.addr >= QPCI_PIO_LIMIT);
490     dev->bus->memread(dev->bus, token.addr + off, buf, len);
491 }
492 
493 void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
494                    const void *buf, size_t len)
495 {
496     g_assert(token.addr >= QPCI_PIO_LIMIT);
497     dev->bus->memwrite(dev->bus, token.addr + off, buf, len);
498 }
499 
500 QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
501 {
502     QPCIBus *bus = dev->bus;
503     static const int bar_reg_map[] = {
504         PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
505         PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
506     };
507     QPCIBar bar;
508     int bar_reg;
509     uint32_t addr, size;
510     uint32_t io_type;
511     uint64_t loc;
512 
513     g_assert(barno >= 0 && barno <= 5);
514     bar_reg = bar_reg_map[barno];
515 
516     qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
517     addr = qpci_config_readl(dev, bar_reg);
518 
519     io_type = addr & PCI_BASE_ADDRESS_SPACE;
520     if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
521         addr &= PCI_BASE_ADDRESS_IO_MASK;
522     } else {
523         addr &= PCI_BASE_ADDRESS_MEM_MASK;
524     }
525 
526     g_assert(addr); /* Must have *some* size bits */
527 
528     size = 1U << ctz32(addr);
529     if (sizeptr) {
530         *sizeptr = size;
531     }
532 
533     if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
534         loc = QEMU_ALIGN_UP(bus->pio_alloc_ptr, size);
535 
536         g_assert(loc >= bus->pio_alloc_ptr);
537         g_assert(loc + size <= QPCI_PIO_LIMIT); /* Keep PIO below 64kiB */
538 
539         bus->pio_alloc_ptr = loc + size;
540 
541         qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
542     } else {
543         loc = QEMU_ALIGN_UP(bus->mmio_alloc_ptr, size);
544 
545         /* Check for space */
546         g_assert(loc >= bus->mmio_alloc_ptr);
547         g_assert(loc + size <= bus->mmio_limit);
548 
549         bus->mmio_alloc_ptr = loc + size;
550 
551         qpci_config_writel(dev, bar_reg, loc);
552     }
553 
554     bar.addr = loc;
555     return bar;
556 }
557 
558 void qpci_iounmap(QPCIDevice *dev, QPCIBar bar)
559 {
560     /* FIXME */
561 }
562 
563 QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
564 {
565     QPCIBar bar = { .addr = addr };
566     return bar;
567 }
568 
569 void add_qpci_address(QOSGraphEdgeOptions *opts, QPCIAddress *addr)
570 {
571     g_assert(addr);
572     g_assert(opts);
573 
574     opts->arg = addr;
575     opts->size_arg = sizeof(QPCIAddress);
576 }
577