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
qpci_device_foreach(QPCIBus * bus,int vendor_id,int device_id,void (* func)(QPCIDevice * dev,int devfn,void * data),void * data)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
qpci_has_buggy_msi(QPCIDevice * dev)56 bool qpci_has_buggy_msi(QPCIDevice *dev)
57 {
58 return dev->bus->has_buggy_msi;
59 }
60
qpci_check_buggy_msi(QPCIDevice * dev)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
qpci_device_set(QPCIDevice * dev,QPCIBus * bus,int devfn)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
qpci_device_find(QPCIBus * bus,int devfn)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
qpci_device_init(QPCIDevice * dev,QPCIBus * bus,QPCIAddress * addr)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
qpci_find_resource_reserve_capability(QPCIDevice * dev)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
qpci_secondary_buses_rec(QPCIBus * qbus,int bus,int * pci_bus)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
qpci_secondary_buses_init(QPCIBus * bus)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
qpci_device_enable(QPCIDevice * dev)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 */
qpci_find_capability(QPCIDevice * dev,uint8_t id,uint8_t start_addr)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
qpci_msix_enable(QPCIDevice * dev)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
qpci_msix_disable(QPCIDevice * dev)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
qpci_msix_pending(QPCIDevice * dev,uint16_t entry)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 return (pba_entry & (1 << bit_n)) != 0;
332 }
333
qpci_msix_masked(QPCIDevice * dev,uint16_t entry)334 bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
335 {
336 uint8_t addr;
337 uint16_t val;
338 uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE;
339
340 g_assert(dev->msix_enabled);
341 addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
342 g_assert_cmphex(addr, !=, 0);
343 val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
344
345 if (val & PCI_MSIX_FLAGS_MASKALL) {
346 return true;
347 } else {
348 return (qpci_io_readl(dev, dev->msix_table_bar,
349 vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL)
350 & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
351 }
352 }
353
qpci_msix_table_size(QPCIDevice * dev)354 uint16_t qpci_msix_table_size(QPCIDevice *dev)
355 {
356 uint8_t addr;
357 uint16_t control;
358
359 addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
360 g_assert_cmphex(addr, !=, 0);
361
362 control = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
363 return (control & PCI_MSIX_FLAGS_QSIZE) + 1;
364 }
365
qpci_config_readb(QPCIDevice * dev,uint8_t offset)366 uint8_t qpci_config_readb(QPCIDevice *dev, uint8_t offset)
367 {
368 return dev->bus->config_readb(dev->bus, dev->devfn, offset);
369 }
370
qpci_config_readw(QPCIDevice * dev,uint8_t offset)371 uint16_t qpci_config_readw(QPCIDevice *dev, uint8_t offset)
372 {
373 return dev->bus->config_readw(dev->bus, dev->devfn, offset);
374 }
375
qpci_config_readl(QPCIDevice * dev,uint8_t offset)376 uint32_t qpci_config_readl(QPCIDevice *dev, uint8_t offset)
377 {
378 return dev->bus->config_readl(dev->bus, dev->devfn, offset);
379 }
380
381
qpci_config_writeb(QPCIDevice * dev,uint8_t offset,uint8_t value)382 void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value)
383 {
384 dev->bus->config_writeb(dev->bus, dev->devfn, offset, value);
385 }
386
qpci_config_writew(QPCIDevice * dev,uint8_t offset,uint16_t value)387 void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value)
388 {
389 dev->bus->config_writew(dev->bus, dev->devfn, offset, value);
390 }
391
qpci_config_writel(QPCIDevice * dev,uint8_t offset,uint32_t value)392 void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
393 {
394 dev->bus->config_writel(dev->bus, dev->devfn, offset, value);
395 }
396
qpci_io_readb(QPCIDevice * dev,QPCIBar token,uint64_t off)397 uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off)
398 {
399 QPCIBus *bus = dev->bus;
400
401 if (token.is_io) {
402 return bus->pio_readb(bus, token.addr + off);
403 } else {
404 uint8_t val;
405
406 bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
407 return val;
408 }
409 }
410
qpci_io_readw(QPCIDevice * dev,QPCIBar token,uint64_t off)411 uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
412 {
413 QPCIBus *bus = dev->bus;
414
415 if (token.is_io) {
416 return bus->pio_readw(bus, token.addr + off);
417 } else {
418 uint16_t val;
419
420 bus->memread(bus, token.addr + off, &val, sizeof(val));
421 return le16_to_cpu(val);
422 }
423 }
424
qpci_io_readl(QPCIDevice * dev,QPCIBar token,uint64_t off)425 uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
426 {
427 QPCIBus *bus = dev->bus;
428
429 if (token.is_io) {
430 return bus->pio_readl(bus, token.addr + off);
431 } else {
432 uint32_t val;
433
434 bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
435 return le32_to_cpu(val);
436 }
437 }
438
qpci_io_readq(QPCIDevice * dev,QPCIBar token,uint64_t off)439 uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off)
440 {
441 QPCIBus *bus = dev->bus;
442
443 if (token.is_io) {
444 return bus->pio_readq(bus, token.addr + off);
445 } else {
446 uint64_t val;
447
448 bus->memread(bus, token.addr + off, &val, sizeof(val));
449 return le64_to_cpu(val);
450 }
451 }
452
qpci_io_writeb(QPCIDevice * dev,QPCIBar token,uint64_t off,uint8_t value)453 void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
454 uint8_t value)
455 {
456 QPCIBus *bus = dev->bus;
457
458 if (token.is_io) {
459 bus->pio_writeb(bus, token.addr + off, value);
460 } else {
461 bus->memwrite(bus, token.addr + off, &value, sizeof(value));
462 }
463 }
464
qpci_io_writew(QPCIDevice * dev,QPCIBar token,uint64_t off,uint16_t value)465 void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
466 uint16_t value)
467 {
468 QPCIBus *bus = dev->bus;
469
470 if (token.is_io) {
471 bus->pio_writew(bus, token.addr + off, value);
472 } else {
473 value = cpu_to_le16(value);
474 bus->memwrite(bus, token.addr + off, &value, sizeof(value));
475 }
476 }
477
qpci_io_writel(QPCIDevice * dev,QPCIBar token,uint64_t off,uint32_t value)478 void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
479 uint32_t value)
480 {
481 QPCIBus *bus = dev->bus;
482
483 if (token.is_io) {
484 bus->pio_writel(bus, token.addr + off, value);
485 } else {
486 value = cpu_to_le32(value);
487 bus->memwrite(bus, token.addr + off, &value, sizeof(value));
488 }
489 }
490
qpci_io_writeq(QPCIDevice * dev,QPCIBar token,uint64_t off,uint64_t value)491 void qpci_io_writeq(QPCIDevice *dev, QPCIBar token, uint64_t off,
492 uint64_t value)
493 {
494 QPCIBus *bus = dev->bus;
495
496 if (token.is_io) {
497 bus->pio_writeq(bus, token.addr + off, value);
498 } else {
499 value = cpu_to_le64(value);
500 bus->memwrite(bus, token.addr + off, &value, sizeof(value));
501 }
502 }
503
qpci_memread(QPCIDevice * dev,QPCIBar token,uint64_t off,void * buf,size_t len)504 void qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off,
505 void *buf, size_t len)
506 {
507 g_assert(!token.is_io);
508 dev->bus->memread(dev->bus, token.addr + off, buf, len);
509 }
510
qpci_memwrite(QPCIDevice * dev,QPCIBar token,uint64_t off,const void * buf,size_t len)511 void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
512 const void *buf, size_t len)
513 {
514 g_assert(!token.is_io);
515 dev->bus->memwrite(dev->bus, token.addr + off, buf, len);
516 }
517
qpci_iomap(QPCIDevice * dev,int barno,uint64_t * sizeptr)518 QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
519 {
520 QPCIBus *bus = dev->bus;
521 static const int bar_reg_map[] = {
522 PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
523 PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
524 };
525 QPCIBar bar;
526 int bar_reg;
527 uint32_t addr, size;
528 uint32_t io_type;
529 uint64_t loc;
530
531 g_assert(barno >= 0 && barno <= 5);
532 bar_reg = bar_reg_map[barno];
533
534 qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
535 addr = qpci_config_readl(dev, bar_reg);
536
537 io_type = addr & PCI_BASE_ADDRESS_SPACE;
538 if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
539 addr &= PCI_BASE_ADDRESS_IO_MASK;
540 } else {
541 addr &= PCI_BASE_ADDRESS_MEM_MASK;
542 }
543
544 g_assert(addr); /* Must have *some* size bits */
545
546 size = 1U << ctz32(addr);
547 if (sizeptr) {
548 *sizeptr = size;
549 }
550
551 if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
552 loc = QEMU_ALIGN_UP(bus->pio_alloc_ptr, size);
553
554 g_assert(loc >= bus->pio_alloc_ptr);
555 g_assert(loc + size <= bus->pio_limit);
556
557 bus->pio_alloc_ptr = loc + size;
558 bar.is_io = true;
559
560 qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
561 } else {
562 loc = QEMU_ALIGN_UP(bus->mmio_alloc_ptr, size);
563
564 /* Check for space */
565 g_assert(loc >= bus->mmio_alloc_ptr);
566 g_assert(loc + size <= bus->mmio_limit);
567
568 bus->mmio_alloc_ptr = loc + size;
569 bar.is_io = false;
570
571 qpci_config_writel(dev, bar_reg, loc);
572 }
573
574 bar.addr = loc;
575 return bar;
576 }
577
qpci_iounmap(QPCIDevice * dev,QPCIBar bar)578 void qpci_iounmap(QPCIDevice *dev, QPCIBar bar)
579 {
580 /* FIXME */
581 }
582
qpci_legacy_iomap(QPCIDevice * dev,uint16_t addr)583 QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
584 {
585 QPCIBar bar = { .addr = addr, .is_io = true };
586 return bar;
587 }
588
add_qpci_address(QOSGraphEdgeOptions * opts,QPCIAddress * addr)589 void add_qpci_address(QOSGraphEdgeOptions *opts, QPCIAddress *addr)
590 {
591 g_assert(addr);
592 g_assert(opts);
593
594 opts->arg = addr;
595 opts->size_arg = sizeof(QPCIAddress);
596 }
597