diff options
author | Thomas Huth <thuth@redhat.com> | 2019-09-10 16:41:20 +0200 |
---|---|---|
committer | Thomas Huth <thuth@redhat.com> | 2020-01-12 11:42:41 +0100 |
commit | 1cf4323ecd03235984e43a416a42f10c975cf785 (patch) | |
tree | 57ad5475a4cbbbe0088aecf86b682d8e11150b9f /tests/libqos/virtio-pci-modern.c | |
parent | 833884f37adc9f125fa2f345704d7019b8651619 (diff) |
tests/libqos: Move the libqos files under tests/qtest/
The qos stuff belongs to qtest, so move it into that directory, too.
Message-Id: <20191218103059.11729-8-thuth@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Diffstat (limited to 'tests/libqos/virtio-pci-modern.c')
-rw-r--r-- | tests/libqos/virtio-pci-modern.c | 443 |
1 files changed, 0 insertions, 443 deletions
diff --git a/tests/libqos/virtio-pci-modern.c b/tests/libqos/virtio-pci-modern.c deleted file mode 100644 index 18d118866f..0000000000 --- a/tests/libqos/virtio-pci-modern.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * libqos VIRTIO 1.0 PCI driver - * - * Copyright (c) 2019 Red Hat, Inc - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "standard-headers/linux/pci_regs.h" -#include "standard-headers/linux/virtio_pci.h" -#include "standard-headers/linux/virtio_config.h" -#include "virtio-pci-modern.h" - -static uint8_t config_readb(QVirtioDevice *d, uint64_t addr) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - return qpci_io_readb(dev->pdev, dev->bar, dev->device_cfg_offset + addr); -} - -static uint16_t config_readw(QVirtioDevice *d, uint64_t addr) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - return qpci_io_readw(dev->pdev, dev->bar, dev->device_cfg_offset + addr); -} - -static uint32_t config_readl(QVirtioDevice *d, uint64_t addr) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - return qpci_io_readl(dev->pdev, dev->bar, dev->device_cfg_offset + addr); -} - -static uint64_t config_readq(QVirtioDevice *d, uint64_t addr) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - return qpci_io_readq(dev->pdev, dev->bar, dev->device_cfg_offset + addr); -} - -static uint64_t get_features(QVirtioDevice *d) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - uint64_t lo, hi; - - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - device_feature_select), - 0); - lo = qpci_io_readl(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, device_feature)); - - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - device_feature_select), - 1); - hi = qpci_io_readl(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, device_feature)); - - return (hi << 32) | lo; -} - -static void set_features(QVirtioDevice *d, uint64_t features) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - - /* Drivers must enable VIRTIO 1.0 or else use the Legacy interface */ - g_assert_cmphex(features & (1ull << VIRTIO_F_VERSION_1), !=, 0); - - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - guest_feature_select), - 0); - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - guest_feature), - features); - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - guest_feature_select), - 1); - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - guest_feature), - features >> 32); -} - -static uint64_t get_guest_features(QVirtioDevice *d) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - uint64_t lo, hi; - - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - guest_feature_select), - 0); - lo = qpci_io_readl(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, guest_feature)); - - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - guest_feature_select), - 1); - hi = qpci_io_readl(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, guest_feature)); - - return (hi << 32) | lo; -} - -static uint8_t get_status(QVirtioDevice *d) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - - return qpci_io_readb(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - device_status)); -} - -static void set_status(QVirtioDevice *d, uint8_t status) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - - return qpci_io_writeb(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - device_status), - status); -} - -static bool get_msix_status(QVirtioPCIDevice *dev, uint32_t msix_entry, - uint32_t msix_addr, uint32_t msix_data) -{ - uint32_t data; - - g_assert_cmpint(msix_entry, !=, -1); - if (qpci_msix_masked(dev->pdev, msix_entry)) { - /* No ISR checking should be done if masked, but read anyway */ - return qpci_msix_pending(dev->pdev, msix_entry); - } - - data = qtest_readl(dev->pdev->bus->qts, msix_addr); - if (data == msix_data) { - qtest_writel(dev->pdev->bus->qts, msix_addr, 0); - return true; - } else { - return false; - } -} - -static bool get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - - if (dev->pdev->msix_enabled) { - QVirtQueuePCI *vqpci = container_of(vq, QVirtQueuePCI, vq); - - return get_msix_status(dev, vqpci->msix_entry, vqpci->msix_addr, - vqpci->msix_data); - } - - return qpci_io_readb(dev->pdev, dev->bar, dev->isr_cfg_offset) & 1; -} - -static bool get_config_isr_status(QVirtioDevice *d) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - - if (dev->pdev->msix_enabled) { - return get_msix_status(dev, dev->config_msix_entry, - dev->config_msix_addr, dev->config_msix_data); - } - - return qpci_io_readb(dev->pdev, dev->bar, dev->isr_cfg_offset) & 2; -} - -static void wait_config_isr_status(QVirtioDevice *d, gint64 timeout_us) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - gint64 start_time = g_get_monotonic_time(); - - do { - g_assert(g_get_monotonic_time() - start_time <= timeout_us); - qtest_clock_step(dev->pdev->bus->qts, 100); - } while (!get_config_isr_status(d)); -} - -static void queue_select(QVirtioDevice *d, uint16_t index) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - - qpci_io_writew(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, queue_select), - index); -} - -static uint16_t get_queue_size(QVirtioDevice *d) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - - return qpci_io_readw(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, queue_size)); -} - -static void set_queue_address(QVirtioDevice *d, QVirtQueue *vq) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, queue_desc_lo), - vq->desc); - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, queue_desc_hi), - vq->desc >> 32); - - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, queue_avail_lo), - vq->avail); - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, queue_avail_hi), - vq->avail >> 32); - - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, queue_used_lo), - vq->used); - qpci_io_writel(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, queue_used_hi), - vq->used >> 32); -} - -static QVirtQueue *virtqueue_setup(QVirtioDevice *d, QGuestAllocator *alloc, - uint16_t index) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - QVirtQueue *vq; - QVirtQueuePCI *vqpci; - uint16_t notify_off; - - vq = qvirtio_pci_virtqueue_setup_common(d, alloc, index); - vqpci = container_of(vq, QVirtQueuePCI, vq); - - notify_off = qpci_io_readw(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - queue_notify_off)); - - vqpci->notify_offset = dev->notify_cfg_offset + - notify_off * dev->notify_off_multiplier; - - qpci_io_writew(dev->pdev, dev->bar, dev->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, queue_enable), 1); - - return vq; -} - -static void virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq) -{ - QVirtioPCIDevice *dev = container_of(d, QVirtioPCIDevice, vdev); - QVirtQueuePCI *vqpci = container_of(vq, QVirtQueuePCI, vq); - - qpci_io_writew(dev->pdev, dev->bar, vqpci->notify_offset, vq->index); -} - -static const QVirtioBus qvirtio_pci_virtio_1 = { - .config_readb = config_readb, - .config_readw = config_readw, - .config_readl = config_readl, - .config_readq = config_readq, - .get_features = get_features, - .set_features = set_features, - .get_guest_features = get_guest_features, - .get_status = get_status, - .set_status = set_status, - .get_queue_isr_status = get_queue_isr_status, - .wait_config_isr_status = wait_config_isr_status, - .queue_select = queue_select, - .get_queue_size = get_queue_size, - .set_queue_address = set_queue_address, - .virtqueue_setup = virtqueue_setup, - .virtqueue_cleanup = qvirtio_pci_virtqueue_cleanup_common, - .virtqueue_kick = virtqueue_kick, -}; - -static void set_config_vector(QVirtioPCIDevice *d, uint16_t entry) -{ - uint16_t vector; - - qpci_io_writew(d->pdev, d->bar, d->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, msix_config), entry); - vector = qpci_io_readw(d->pdev, d->bar, d->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - msix_config)); - g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR); -} - -static void set_queue_vector(QVirtioPCIDevice *d, uint16_t vq_idx, - uint16_t entry) -{ - uint16_t vector; - - queue_select(&d->vdev, vq_idx); - qpci_io_writew(d->pdev, d->bar, d->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, queue_msix_vector), - entry); - vector = qpci_io_readw(d->pdev, d->bar, d->common_cfg_offset + - offsetof(struct virtio_pci_common_cfg, - queue_msix_vector)); - g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR); -} - -static const QVirtioPCIMSIXOps qvirtio_pci_msix_ops_virtio_1 = { - .set_config_vector = set_config_vector, - .set_queue_vector = set_queue_vector, -}; - -static bool probe_device_type(QVirtioPCIDevice *dev) -{ - uint16_t vendor_id; - uint16_t device_id; - - /* "Drivers MUST match devices with the PCI Vendor ID 0x1AF4" */ - vendor_id = qpci_config_readw(dev->pdev, PCI_VENDOR_ID); - if (vendor_id != 0x1af4) { - return false; - } - - /* - * "Any PCI device with ... PCI Device ID 0x1000 through 0x107F inclusive - * is a virtio device" - */ - device_id = qpci_config_readw(dev->pdev, PCI_DEVICE_ID); - if (device_id < 0x1000 || device_id > 0x107f) { - return false; - } - - /* - * "Devices MAY utilize a Transitional PCI Device ID range, 0x1000 to - * 0x103F depending on the device type" - */ - if (device_id < 0x1040) { - /* - * "Transitional devices MUST have the PCI Subsystem Device ID matching - * the Virtio Device ID" - */ - dev->vdev.device_type = qpci_config_readw(dev->pdev, PCI_SUBSYSTEM_ID); - } else { - /* - * "The PCI Device ID is calculated by adding 0x1040 to the Virtio - * Device ID" - */ - dev->vdev.device_type = device_id - 0x1040; - } - - return true; -} - -/* Find the first VIRTIO 1.0 PCI structure for a given type */ -static bool find_structure(QVirtioPCIDevice *dev, uint8_t cfg_type, - uint8_t *bar, uint32_t *offset, uint32_t *length, - uint8_t *cfg_addr) -{ - uint8_t addr = 0; - - while ((addr = qpci_find_capability(dev->pdev, PCI_CAP_ID_VNDR, - addr)) != 0) { - uint8_t type; - - type = qpci_config_readb(dev->pdev, - addr + offsetof(struct virtio_pci_cap, cfg_type)); - if (type != cfg_type) { - continue; - } - - *bar = qpci_config_readb(dev->pdev, - addr + offsetof(struct virtio_pci_cap, bar)); - *offset = qpci_config_readl(dev->pdev, - addr + offsetof(struct virtio_pci_cap, offset)); - *length = qpci_config_readl(dev->pdev, - addr + offsetof(struct virtio_pci_cap, length)); - if (cfg_addr) { - *cfg_addr = addr; - } - - return true; - } - - return false; -} - -static bool probe_device_layout(QVirtioPCIDevice *dev) -{ - uint8_t bar; - uint8_t cfg_addr; - uint32_t length; - - /* - * Due to the qpci_iomap() API we only support devices that put all - * structures in the same PCI BAR. Luckily this is true with QEMU. - */ - - if (!find_structure(dev, VIRTIO_PCI_CAP_COMMON_CFG, &bar, - &dev->common_cfg_offset, &length, NULL)) { - return false; - } - dev->bar_idx = bar; - - if (!find_structure(dev, VIRTIO_PCI_CAP_NOTIFY_CFG, &bar, - &dev->notify_cfg_offset, &length, &cfg_addr)) { - return false; - } - g_assert_cmphex(bar, ==, dev->bar_idx); - - dev->notify_off_multiplier = qpci_config_readl(dev->pdev, - cfg_addr + offsetof(struct virtio_pci_notify_cap, - notify_off_multiplier)); - - if (!find_structure(dev, VIRTIO_PCI_CAP_ISR_CFG, &bar, - &dev->isr_cfg_offset, &length, NULL)) { - return false; - } - g_assert_cmphex(bar, ==, dev->bar_idx); - - if (!find_structure(dev, VIRTIO_PCI_CAP_DEVICE_CFG, &bar, - &dev->device_cfg_offset, &length, NULL)) { - return false; - } - g_assert_cmphex(bar, ==, dev->bar_idx); - - return true; -} - -/* Probe a VIRTIO 1.0 device */ -bool qvirtio_pci_init_virtio_1(QVirtioPCIDevice *dev) -{ - if (!probe_device_type(dev)) { - return false; - } - - if (!probe_device_layout(dev)) { - return false; - } - - dev->vdev.bus = &qvirtio_pci_virtio_1; - dev->msix_ops = &qvirtio_pci_msix_ops_virtio_1; - dev->vdev.big_endian = false; - return true; -} |