qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

pci.c (16015B)


      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     QPCIBus *bus = dev->bus;
    402 
    403     if (token.is_io) {
    404         return bus->pio_readb(bus, token.addr + off);
    405     } else {
    406         uint8_t val;
    407 
    408         bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
    409         return val;
    410     }
    411 }
    412 
    413 uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
    414 {
    415     QPCIBus *bus = dev->bus;
    416 
    417     if (token.is_io) {
    418         return bus->pio_readw(bus, token.addr + off);
    419     } else {
    420         uint16_t val;
    421 
    422         bus->memread(bus, token.addr + off, &val, sizeof(val));
    423         return le16_to_cpu(val);
    424     }
    425 }
    426 
    427 uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
    428 {
    429     QPCIBus *bus = dev->bus;
    430 
    431     if (token.is_io) {
    432         return bus->pio_readl(bus, token.addr + off);
    433     } else {
    434         uint32_t val;
    435 
    436         bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
    437         return le32_to_cpu(val);
    438     }
    439 }
    440 
    441 uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off)
    442 {
    443     QPCIBus *bus = dev->bus;
    444 
    445     if (token.is_io) {
    446         return bus->pio_readq(bus, token.addr + off);
    447     } else {
    448         uint64_t val;
    449 
    450         bus->memread(bus, token.addr + off, &val, sizeof(val));
    451         return le64_to_cpu(val);
    452     }
    453 }
    454 
    455 void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
    456                     uint8_t value)
    457 {
    458     QPCIBus *bus = dev->bus;
    459 
    460     if (token.is_io) {
    461         bus->pio_writeb(bus, token.addr + off, value);
    462     } else {
    463         bus->memwrite(bus, token.addr + off, &value, sizeof(value));
    464     }
    465 }
    466 
    467 void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
    468                     uint16_t value)
    469 {
    470     QPCIBus *bus = dev->bus;
    471 
    472     if (token.is_io) {
    473         bus->pio_writew(bus, token.addr + off, value);
    474     } else {
    475         value = cpu_to_le16(value);
    476         bus->memwrite(bus, token.addr + off, &value, sizeof(value));
    477     }
    478 }
    479 
    480 void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
    481                     uint32_t value)
    482 {
    483     QPCIBus *bus = dev->bus;
    484 
    485     if (token.is_io) {
    486         bus->pio_writel(bus, token.addr + off, value);
    487     } else {
    488         value = cpu_to_le32(value);
    489         bus->memwrite(bus, token.addr + off, &value, sizeof(value));
    490     }
    491 }
    492 
    493 void qpci_io_writeq(QPCIDevice *dev, QPCIBar token, uint64_t off,
    494                     uint64_t value)
    495 {
    496     QPCIBus *bus = dev->bus;
    497 
    498     if (token.is_io) {
    499         bus->pio_writeq(bus, token.addr + off, value);
    500     } else {
    501         value = cpu_to_le64(value);
    502         bus->memwrite(bus, token.addr + off, &value, sizeof(value));
    503     }
    504 }
    505 
    506 void qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off,
    507                   void *buf, size_t len)
    508 {
    509     g_assert(!token.is_io);
    510     dev->bus->memread(dev->bus, token.addr + off, buf, len);
    511 }
    512 
    513 void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
    514                    const void *buf, size_t len)
    515 {
    516     g_assert(!token.is_io);
    517     dev->bus->memwrite(dev->bus, token.addr + off, buf, len);
    518 }
    519 
    520 QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
    521 {
    522     QPCIBus *bus = dev->bus;
    523     static const int bar_reg_map[] = {
    524         PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
    525         PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
    526     };
    527     QPCIBar bar;
    528     int bar_reg;
    529     uint32_t addr, size;
    530     uint32_t io_type;
    531     uint64_t loc;
    532 
    533     g_assert(barno >= 0 && barno <= 5);
    534     bar_reg = bar_reg_map[barno];
    535 
    536     qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
    537     addr = qpci_config_readl(dev, bar_reg);
    538 
    539     io_type = addr & PCI_BASE_ADDRESS_SPACE;
    540     if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
    541         addr &= PCI_BASE_ADDRESS_IO_MASK;
    542     } else {
    543         addr &= PCI_BASE_ADDRESS_MEM_MASK;
    544     }
    545 
    546     g_assert(addr); /* Must have *some* size bits */
    547 
    548     size = 1U << ctz32(addr);
    549     if (sizeptr) {
    550         *sizeptr = size;
    551     }
    552 
    553     if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
    554         loc = QEMU_ALIGN_UP(bus->pio_alloc_ptr, size);
    555 
    556         g_assert(loc >= bus->pio_alloc_ptr);
    557         g_assert(loc + size <= bus->pio_limit);
    558 
    559         bus->pio_alloc_ptr = loc + size;
    560         bar.is_io = true;
    561 
    562         qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
    563     } else {
    564         loc = QEMU_ALIGN_UP(bus->mmio_alloc_ptr, size);
    565 
    566         /* Check for space */
    567         g_assert(loc >= bus->mmio_alloc_ptr);
    568         g_assert(loc + size <= bus->mmio_limit);
    569 
    570         bus->mmio_alloc_ptr = loc + size;
    571         bar.is_io = false;
    572 
    573         qpci_config_writel(dev, bar_reg, loc);
    574     }
    575 
    576     bar.addr = loc;
    577     return bar;
    578 }
    579 
    580 void qpci_iounmap(QPCIDevice *dev, QPCIBar bar)
    581 {
    582     /* FIXME */
    583 }
    584 
    585 QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
    586 {
    587     QPCIBar bar = { .addr = addr, .is_io = true };
    588     return bar;
    589 }
    590 
    591 void add_qpci_address(QOSGraphEdgeOptions *opts, QPCIAddress *addr)
    592 {
    593     g_assert(addr);
    594     g_assert(opts);
    595 
    596     opts->arg = addr;
    597     opts->size_arg = sizeof(QPCIAddress);
    598 }