Add functions to read and write virtio header fields. Add feature checking and status bit setting in virtio-blk-device.
Signed-off-by: Marc Marí <marc.mari.barc...@gmail.com> --- tests/Makefile | 2 +- tests/libqos/virtio-pci.c | 32 ++++++++++++++++++++++++++++++++ tests/libqos/virtio-pci.h | 17 +++++++++++++++++ tests/libqos/virtio.c | 31 +++++++++++++++++++++++++++++++ tests/libqos/virtio.h | 19 +++++++++++++++++++ tests/virtio-blk-test.c | 14 ++++++++++++++ 6 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 tests/libqos/virtio.c diff --git a/tests/Makefile b/tests/Makefile index c40a75d..bdb7d0a 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -292,7 +292,7 @@ libqos-obj-y += tests/libqos/i2c.o libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o libqos-pc-obj-y += tests/libqos/malloc-pc.o libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o -libqos-virtio-obj-y = $(libqos-obj-y) $(libqos-pc-obj-y) tests/libqos/virtio-pci.o +libqos-virtio-obj-y = $(libqos-obj-y) $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/rtc-test$(EXESUF): tests/rtc-test.o tests/m48t59-test$(EXESUF): tests/m48t59-test.o diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c index 2bd1006..a514a7a 100644 --- a/tests/libqos/virtio-pci.c +++ b/tests/libqos/virtio-pci.c @@ -56,6 +56,30 @@ static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data) vpcidev->vdev.device_type = ((QVirtioPCIDevice *)d)->vdev.device_type; } +static uint32_t qvirtio_pci_get_features(QVirtioDevice *d) +{ + QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + return qpci_io_readl(dev->pdev, dev->addr + QVIRTIO_DEVICE_FEATURES); +} + +static uint8_t qvirtio_pci_get_status(QVirtioDevice *d) +{ + QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_DEVICE_STATUS); +} + +static void qvirtio_pci_set_status(QVirtioDevice *d, uint8_t val) +{ + QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d; + qpci_io_writeb(dev->pdev, dev->addr + QVIRTIO_DEVICE_STATUS, val); +} + +const QVirtioBus qvirtio_pci = { + .get_features = qvirtio_pci_get_features, + .get_status = qvirtio_pci_get_status, + .set_status = qvirtio_pci_set_status, +}; + void qvirtio_pci_foreach(QPCIBus *bus, uint16_t device_type, void (*func)(QVirtioDevice *d, void *data), void *data) { @@ -80,3 +104,11 @@ QVirtioPCIDevice *qvirtio_pci_device_find(QPCIBus *bus, uint16_t device_type) return dev; } } + +void qvirtio_pci_enable_device(QVirtioPCIDevice *d) +{ + qpci_device_enable(d->pdev); + d->addr = qpci_iomap(d->pdev, 0); + g_assert(d->addr != NULL); +} + diff --git a/tests/libqos/virtio-pci.h b/tests/libqos/virtio-pci.h index 5101abb..ef7744e 100644 --- a/tests/libqos/virtio-pci.h +++ b/tests/libqos/virtio-pci.h @@ -13,12 +13,29 @@ #include "libqos/virtio.h" #include "libqos/pci.h" +#define QVIRTIO_DEVICE_FEATURES 0x00 +#define QVIRTIO_GUEST_FEATURES 0x04 +#define QVIRTIO_QUEUE_ADDRESS 0x08 +#define QVIRTIO_QUEUE_SIZE 0x0C +#define QVIRTIO_QUEUE_SELECT 0x0E +#define QVIRTIO_QUEUE_NOTIFY 0x10 +#define QVIRTIO_DEVICE_STATUS 0x12 +#define QVIRTIO_ISR_STATUS 0x13 +#define QVIRTIO_MSIX_CONF_VECTOR 0x14 +#define QVIRTIO_MSIX_QUEUE_VECTOR 0x16 +#define QVIRTIO_DEVICE_SPECIFIC_MSIX 0x18 +#define QVIRTIO_DEVICE_SPECIFIC_NO_MSIX 0x14 + typedef struct QVirtioPCIDevice { QVirtioDevice vdev; QPCIDevice *pdev; + void *addr; } QVirtioPCIDevice; +extern const QVirtioBus qvirtio_pci; + void qvirtio_pci_foreach(QPCIBus *bus, uint16_t device_type, void (*func)(QVirtioDevice *d, void *data), void *data); QVirtioPCIDevice *qvirtio_pci_device_find(QPCIBus *bus, uint16_t device_type); +void qvirtio_pci_enable_device(QVirtioPCIDevice *d); #endif diff --git a/tests/libqos/virtio.c b/tests/libqos/virtio.c new file mode 100644 index 0000000..118cb15 --- /dev/null +++ b/tests/libqos/virtio.c @@ -0,0 +1,31 @@ +/* + * libqos virtio driver + * + * Copyright (c) 2014 Marc Marí + * + * 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 <glib.h> +#include "libqtest.h" +#include "libqos/virtio.h" + +void qvirtio_reset(const QVirtioBus *bus, QVirtioDevice *d) +{ + bus->set_status(d, QVIRTIO_RESET); + g_assert_cmphex(bus->get_status(d), ==, QVIRTIO_RESET); +} + +void qvirtio_set_acknowledge(const QVirtioBus *bus, QVirtioDevice *d) +{ + bus->set_status(d, bus->get_status(d) | QVIRTIO_ACKNOWLEDGE); + g_assert_cmphex(bus->get_status(d), ==, QVIRTIO_ACKNOWLEDGE); +} + +void qvirtio_set_driver(const QVirtioBus *bus, QVirtioDevice *d) +{ + bus->set_status(d, bus->get_status(d) | QVIRTIO_DRIVER); + g_assert_cmphex(bus->get_status(d), ==, + QVIRTIO_DRIVER | QVIRTIO_ACKNOWLEDGE); +} diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h index 2a05798..a2e3219 100644 --- a/tests/libqos/virtio.h +++ b/tests/libqos/virtio.h @@ -12,6 +12,10 @@ #define QVIRTIO_VENDOR_ID 0x1AF4 +#define QVIRTIO_RESET 0x0 +#define QVIRTIO_ACKNOWLEDGE 0x1 +#define QVIRTIO_DRIVER 0x2 + #define QVIRTIO_NET_DEVICE_ID 0x1 #define QVIRTIO_BLK_DEVICE_ID 0x2 @@ -20,4 +24,19 @@ typedef struct QVirtioDevice { uint16_t device_type; } QVirtioDevice; +typedef struct QVirtioBus { + /* Get features of the device */ + uint32_t (*get_features)(QVirtioDevice *d); + + /* Get status of the device */ + uint8_t (*get_status)(QVirtioDevice *d); + + /* Set status of the device */ + void (*set_status)(QVirtioDevice *d, uint8_t val); +} QVirtioBus; + +void qvirtio_reset(const QVirtioBus *bus, QVirtioDevice *d); +void qvirtio_set_acknowledge(const QVirtioBus *bus, QVirtioDevice *d); +void qvirtio_set_driver(const QVirtioBus *bus, QVirtioDevice *d); + #endif diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index 52894f4..83be520 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -59,6 +59,8 @@ static void pci_basic(void) { QVirtioPCIDevice *dev; QPCIBus *bus; + void *addr; + uint64_t capacity; bus = test_start(); @@ -67,6 +69,18 @@ static void pci_basic(void) g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_BLK_DEVICE_ID); g_assert_cmphex(dev->pdev->devfn, ==, ((PCI_SLOT << 3) | PCI_FN)); + qvirtio_pci_enable_device(dev); + qvirtio_reset(&qvirtio_pci, &dev->vdev); + qvirtio_set_acknowledge(&qvirtio_pci, &dev->vdev); + qvirtio_set_driver(&qvirtio_pci, &dev->vdev); + + /* MSI-X is not enabled */ + addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX; + + capacity = qpci_io_readl(dev->pdev, addr) | + qpci_io_readl(dev->pdev, addr+4); + g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE/512); + g_free(dev); test_end(); } -- 1.7.10.4