All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling
@ 2016-10-18 10:52 David Gibson
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 1/8] libqos: Give qvirtio_config_read*() consistent semantics David Gibson
                   ` (8 more replies)
  0 siblings, 9 replies; 28+ messages in thread
From: David Gibson @ 2016-10-18 10:52 UTC (permalink / raw)
  To: pbonzini, qemu-devel
  Cc: qemu-ppc, lvivier, agraf, stefanha, mst, aik, mdroth, groug,
	thuth, David Gibson

This series contains a number of cleanups to the libqos code for
accessing PCI devices, and to tests which use it.

The general aim is to improve the consistency of semantics across
functions, and reduce the amount of intimate knowledge of the libqos
PCI layer needed by tests.

This should make it easier to write PCI tests which will be portable
to different guest machines with different PCI host bridge
arrangements.

David Gibson (8):
  libqos: Give qvirtio_config_read*() consistent semantics
  libqos: Handle PCI IO de-multiplexing in common code
  libqos: Move BAR assignment to common code
  tests: Better handle legacy IO addresses in tco-test
  libqos: Add streaming accessors for PCI MMIO
  libqos: Implement mmio accessors in terms of mem{read,write}
  tests: Use qpci_mem{read,write} in ivshmem-test
  libqos: Change PCI accessors to take opaque BAR handle

 tests/ahci-test.c          |   4 +-
 tests/e1000e-test.c        |   7 +-
 tests/ide-test.c           |  23 +++---
 tests/ivshmem-test.c       |  28 ++++----
 tests/libqos/ahci.c        |   3 +-
 tests/libqos/ahci.h        |   6 +-
 tests/libqos/pci-pc.c      | 170 +++++++++-----------------------------------
 tests/libqos/pci-spapr.c   | 172 ++++++++++-----------------------------------
 tests/libqos/pci.c         | 168 ++++++++++++++++++++++++++++++++++---------
 tests/libqos/pci.h         |  60 ++++++++++------
 tests/libqos/usb.c         |   6 +-
 tests/libqos/usb.h         |   2 +-
 tests/libqos/virtio-mmio.c |  16 ++---
 tests/libqos/virtio-pci.c  | 117 ++++++++++++++++--------------
 tests/libqos/virtio-pci.h  |   2 +-
 tests/rtl8139-test.c       |  10 ++-
 tests/tco-test.c           |  87 +++++++++++------------
 tests/usb-hcd-ehci-test.c  |   5 +-
 tests/virtio-9p-test.c     |   9 +--
 tests/virtio-blk-test.c    |  51 +++-----------
 tests/virtio-scsi-test.c   |   5 +-
 21 files changed, 418 insertions(+), 533 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 1/8] libqos: Give qvirtio_config_read*() consistent semantics
  2016-10-18 10:52 [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling David Gibson
@ 2016-10-18 10:52 ` David Gibson
  2016-10-18 12:41   ` Laurent Vivier
  2016-10-18 13:27   ` Greg Kurz
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 2/8] libqos: Handle PCI IO de-multiplexing in common code David Gibson
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 28+ messages in thread
From: David Gibson @ 2016-10-18 10:52 UTC (permalink / raw)
  To: pbonzini, qemu-devel
  Cc: qemu-ppc, lvivier, agraf, stefanha, mst, aik, mdroth, groug,
	thuth, David Gibson

The 'addr' parameter to qvirtio_config_read*() doesn't have a consistent
meaning: when using the virtio-pci versions, it's a full PCI space address,
but for virtio-mmio, it's an offset from the device's base mmio address.

This means that the callers need to do different things to calculate the
addresses in the two cases, which rather defeats the purpose of function
pointer backends.

All the current users of these functions are using them to retrieve
variables from the device specific portion of the virtio config space.
So, this patch alters the semantics to always be an offset into that
device specific config area.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/libqos/virtio-mmio.c | 16 +++++++--------
 tests/libqos/virtio-pci.c  | 22 ++++++++++++--------
 tests/virtio-9p-test.c     |  9 ++------
 tests/virtio-blk-test.c    | 51 ++++++++++------------------------------------
 tests/virtio-scsi-test.c   |  5 +----
 5 files changed, 35 insertions(+), 68 deletions(-)

diff --git a/tests/libqos/virtio-mmio.c b/tests/libqos/virtio-mmio.c
index 0cab38f..b0b74dc 100644
--- a/tests/libqos/virtio-mmio.c
+++ b/tests/libqos/virtio-mmio.c
@@ -15,28 +15,28 @@
 #include "libqos/malloc-generic.h"
 #include "standard-headers/linux/virtio_ring.h"
 
-static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t addr)
+static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t off)
 {
     QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
-    return readb(dev->addr + addr);
+    return readb(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
 }
 
-static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t addr)
+static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t off)
 {
     QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
-    return readw(dev->addr + addr);
+    return readw(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
 }
 
-static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t addr)
+static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t off)
 {
     QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
-    return readl(dev->addr + addr);
+    return readl(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
 }
 
-static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t addr)
+static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t off)
 {
     QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
-    return readq(dev->addr + addr);
+    return readq(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
 }
 
 static uint32_t qvirtio_mmio_get_features(QVirtioDevice *d)
diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
index 6e005c1..8037724 100644
--- a/tests/libqos/virtio-pci.c
+++ b/tests/libqos/virtio-pci.c
@@ -62,39 +62,43 @@ static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data)
     *vpcidev = (QVirtioPCIDevice *)d;
 }
 
-static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t addr)
+static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t off)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    return qpci_io_readb(dev->pdev, (void *)(uintptr_t)addr);
+    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
+    return qpci_io_readb(dev->pdev, base + off);
 }
 
-static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t addr)
+static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t off)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    return qpci_io_readw(dev->pdev, (void *)(uintptr_t)addr);
+    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
+    return qpci_io_readw(dev->pdev, base + off);
 }
 
-static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t addr)
+static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t off)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    return qpci_io_readl(dev->pdev, (void *)(uintptr_t)addr);
+    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
+    return qpci_io_readl(dev->pdev, base + off);
 }
 
-static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t addr)
+static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
     int i;
     uint64_t u64 = 0;
+    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
 
     if (target_big_endian()) {
         for (i = 0; i < 8; ++i) {
             u64 |= (uint64_t)qpci_io_readb(dev->pdev,
-                                (void *)(uintptr_t)addr + i) << (7 - i) * 8;
+                                           base + off + i) << (7 - i) * 8;
         }
     } else {
         for (i = 0; i < 8; ++i) {
             u64 |= (uint64_t)qpci_io_readb(dev->pdev,
-                                (void *)(uintptr_t)addr + i) << i * 8;
+                                           base + off + i) << i * 8;
         }
     }
 
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index e8b2196..620e523 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -92,7 +92,6 @@ static void qvirtio_9p_pci_free(QVirtIO9P *v9p)
 static void pci_basic_config(void)
 {
     QVirtIO9P *v9p;
-    void *addr;
     size_t tag_len;
     char *tag;
     int i;
@@ -100,16 +99,12 @@ static void pci_basic_config(void)
     qvirtio_9p_start();
     v9p = qvirtio_9p_pci_init();
 
-    addr = ((QVirtioPCIDevice *) v9p->dev)->addr + VIRTIO_PCI_CONFIG_OFF(false);
-    tag_len = qvirtio_config_readw(&qvirtio_pci, v9p->dev,
-                                   (uint64_t)(uintptr_t)addr);
+    tag_len = qvirtio_config_readw(&qvirtio_pci, v9p->dev, 0);
     g_assert_cmpint(tag_len, ==, strlen(mount_tag));
-    addr += sizeof(uint16_t);
 
     tag = g_malloc(tag_len);
     for (i = 0; i < tag_len; i++) {
-        tag[i] = qvirtio_config_readb(&qvirtio_pci, v9p->dev,
-                                      (uint64_t)(uintptr_t)addr + i);
+        tag[i] = qvirtio_config_readb(&qvirtio_pci, v9p->dev, i + 2);
     }
     g_assert_cmpmem(tag, tag_len, mount_tag, tag_len);
     g_free(tag);
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
index 0506917..9162a5d 100644
--- a/tests/virtio-blk-test.c
+++ b/tests/virtio-blk-test.c
@@ -151,7 +151,7 @@ static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioBlkReq *req,
 }
 
 static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
-            QGuestAllocator *alloc, QVirtQueue *vq, uint64_t device_specific)
+                       QGuestAllocator *alloc, QVirtQueue *vq)
 {
     QVirtioBlkReq req;
     uint64_t req_addr;
@@ -161,7 +161,7 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
     uint8_t status;
     char *data;
 
-    capacity = qvirtio_config_readq(bus, dev, device_specific);
+    capacity = qvirtio_config_readq(bus, dev, 0);
 
     g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
 
@@ -282,7 +282,6 @@ static void pci_basic(void)
     QPCIBus *bus;
     QVirtQueuePCI *vqpci;
     QGuestAllocator *alloc;
-    void *addr;
 
     bus = pci_test_start();
     dev = virtio_blk_pci_init(bus, PCI_SLOT);
@@ -291,11 +290,7 @@ static void pci_basic(void)
     vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
                                                                     alloc, 0);
 
-    /* MSI-X is not enabled */
-    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
-
-    test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq,
-                                                    (uint64_t)(uintptr_t)addr);
+    test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq);
 
     /* End test */
     qvirtqueue_cleanup(&qvirtio_pci, &vqpci->vq, alloc);
@@ -314,7 +309,6 @@ static void pci_indirect(void)
     QGuestAllocator *alloc;
     QVirtioBlkReq req;
     QVRingIndirectDesc *indirect;
-    void *addr;
     uint64_t req_addr;
     uint64_t capacity;
     uint32_t features;
@@ -326,11 +320,7 @@ static void pci_indirect(void)
 
     dev = virtio_blk_pci_init(bus, PCI_SLOT);
 
-    /* MSI-X is not enabled */
-    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
-
-    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
-                                                    (uint64_t)(uintptr_t)addr);
+    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
     g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
 
     features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
@@ -414,18 +404,13 @@ static void pci_config(void)
     QVirtioPCIDevice *dev;
     QPCIBus *bus;
     int n_size = TEST_IMAGE_SIZE / 2;
-    void *addr;
     uint64_t capacity;
 
     bus = pci_test_start();
 
     dev = virtio_blk_pci_init(bus, PCI_SLOT);
 
-    /* MSI-X is not enabled */
-    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
-
-    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
-                                                    (uint64_t)(uintptr_t)addr);
+    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
     g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
 
     qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
@@ -434,8 +419,7 @@ static void pci_config(void)
                                                     " 'size': %d } }", n_size);
     qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
 
-    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
-                                                    (uint64_t)(uintptr_t)addr);
+    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
     g_assert_cmpint(capacity, ==, n_size / 512);
 
     qvirtio_pci_device_disable(dev);
@@ -452,7 +436,6 @@ static void pci_msix(void)
     QGuestAllocator *alloc;
     QVirtioBlkReq req;
     int n_size = TEST_IMAGE_SIZE / 2;
-    void *addr;
     uint64_t req_addr;
     uint64_t capacity;
     uint32_t features;
@@ -468,11 +451,7 @@ static void pci_msix(void)
 
     qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
 
-    /* MSI-X is enabled */
-    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
-
-    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
-                                                    (uint64_t)(uintptr_t)addr);
+    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
     g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
 
     features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
@@ -493,8 +472,7 @@ static void pci_msix(void)
 
     qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
 
-    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
-                                                    (uint64_t)(uintptr_t)addr);
+    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
     g_assert_cmpint(capacity, ==, n_size / 512);
 
     /* Write request */
@@ -568,7 +546,6 @@ static void pci_idx(void)
     QVirtQueuePCI *vqpci;
     QGuestAllocator *alloc;
     QVirtioBlkReq req;
-    void *addr;
     uint64_t req_addr;
     uint64_t capacity;
     uint32_t features;
@@ -584,11 +561,7 @@ static void pci_idx(void)
 
     qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
 
-    /* MSI-X is enabled */
-    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
-
-    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
-                                                    (uint64_t)(uintptr_t)addr);
+    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
     g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
 
     features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
@@ -731,8 +704,7 @@ static void mmio_basic(void)
     alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
     vq = qvirtqueue_setup(&qvirtio_mmio, &dev->vdev, alloc, 0);
 
-    test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq,
-                            QVIRTIO_MMIO_DEVICE_SPECIFIC);
+    test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq);
 
     qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
                                                     " 'size': %d } }", n_size);
@@ -740,8 +712,7 @@ static void mmio_basic(void)
     qvirtio_wait_queue_isr(&qvirtio_mmio, &dev->vdev, vq,
                            QVIRTIO_BLK_TIMEOUT_US);
 
-    capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev,
-                                                QVIRTIO_MMIO_DEVICE_SPECIFIC);
+    capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev, 0);
     g_assert_cmpint(capacity, ==, n_size / 512);
 
     /* End test */
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
index 79088bb..2df8f9a 100644
--- a/tests/virtio-scsi-test.c
+++ b/tests/virtio-scsi-test.c
@@ -141,7 +141,6 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
     QVirtIOSCSI *vs;
     QVirtioPCIDevice *dev;
     struct virtio_scsi_cmd_resp resp;
-    void *addr;
     int i;
 
     vs = g_new0(QVirtIOSCSI, 1);
@@ -158,9 +157,7 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
     qvirtio_set_acknowledge(&qvirtio_pci, vs->dev);
     qvirtio_set_driver(&qvirtio_pci, vs->dev);
 
-    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
-    vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev,
-                                          (uint64_t)(uintptr_t)addr);
+    vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev, 0);
 
     g_assert_cmpint(vs->num_queues, <, MAX_NUM_QUEUES);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 2/8] libqos: Handle PCI IO de-multiplexing in common code
  2016-10-18 10:52 [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling David Gibson
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 1/8] libqos: Give qvirtio_config_read*() consistent semantics David Gibson
@ 2016-10-18 10:52 ` David Gibson
  2016-10-18 13:28   ` Laurent Vivier
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 3/8] libqos: Move BAR assignment to " David Gibson
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: David Gibson @ 2016-10-18 10:52 UTC (permalink / raw)
  To: pbonzini, qemu-devel
  Cc: qemu-ppc, lvivier, agraf, stefanha, mst, aik, mdroth, groug,
	thuth, David Gibson

The PCI IO space (aka PIO, aka legacy IO) and PCI memory space (aka MMIO)
are distinct address spaces by the PCI spec (although parts of one might be
aliased to parts of the other in some cases).

However, qpci_io_read*() and qpci_io_write*() can perform accesses to
either space depending on parameter.  That's convenient for test case
drivers, since there are a fair few devices which can be controlled via
either a PIO or MMIO BAR but with an otherwise identical driver.

This is implemented by having addresses below 64kiB treated as PIO, and
those above treated as MMIO.  This works because low addresses in memory
space are generally reserved for DMA rather than MMIO.

At the moment, this demultiplexing must be handled by each PCI backend
(pc and spapr, so far).  There's no real reason for this - the current
encoding is likely to work for all platforms, and even if it doesn't we
can still use a more complex common encoding since the value returned from
iomap are semi-opaque.

This patch moves the demultiplexing into the common part of the libqos PCI
code, with the backends having simpler, separate accessors for PIO and
MMIO space.  This also means we have a way of explicitly accessing either
space if it's necessary for some special case.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/libqos/pci-pc.c    | 107 ++++++++++++++++++++----------------------
 tests/libqos/pci-spapr.c | 118 +++++++++++++++++++++++++----------------------
 tests/libqos/pci.c       |  49 +++++++++++++++++---
 tests/libqos/pci.h       |  22 ++++++---
 4 files changed, 170 insertions(+), 126 deletions(-)

diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index 9600ed6..51dff8a 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -36,79 +36,64 @@ typedef struct QPCIBusPC
     uint16_t pci_iohole_alloc;
 } QPCIBusPC;
 
-static uint8_t qpci_pc_io_readb(QPCIBus *bus, void *addr)
+static uint8_t qpci_pc_pio_readb(QPCIBus *bus, uint32_t addr)
 {
-    uintptr_t port = (uintptr_t)addr;
-    uint8_t value;
-
-    if (port < 0x10000) {
-        value = inb(port);
-    } else {
-        value = readb(port);
-    }
-
-    return value;
+    return inb(addr);
 }
 
-static uint16_t qpci_pc_io_readw(QPCIBus *bus, void *addr)
+static uint8_t qpci_pc_mmio_readb(QPCIBus *bus, uint32_t addr)
 {
-    uintptr_t port = (uintptr_t)addr;
-    uint16_t value;
-
-    if (port < 0x10000) {
-        value = inw(port);
-    } else {
-        value = readw(port);
-    }
+    return readb(addr);
+}
 
-    return value;
+static void qpci_pc_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
+{
+    outb(addr, val);
 }
 
-static uint32_t qpci_pc_io_readl(QPCIBus *bus, void *addr)
+static void qpci_pc_mmio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
 {
-    uintptr_t port = (uintptr_t)addr;
-    uint32_t value;
+    writeb(addr, val);
+}
 
-    if (port < 0x10000) {
-        value = inl(port);
-    } else {
-        value = readl(port);
-    }
+static uint16_t qpci_pc_pio_readw(QPCIBus *bus, uint32_t addr)
+{
+    return inw(addr);
+}
 
-    return value;
+static uint16_t qpci_pc_mmio_readw(QPCIBus *bus, uint32_t addr)
+{
+    return readw(addr);
 }
 
-static void qpci_pc_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
+static void qpci_pc_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
 {
-    uintptr_t port = (uintptr_t)addr;
+    outw(addr, val);
+}
 
-    if (port < 0x10000) {
-        outb(port, value);
-    } else {
-        writeb(port, value);
-    }
+static void qpci_pc_mmio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
+{
+    writew(addr, val);
 }
 
-static void qpci_pc_io_writew(QPCIBus *bus, void *addr, uint16_t value)
+static uint32_t qpci_pc_pio_readl(QPCIBus *bus, uint32_t addr)
 {
-    uintptr_t port = (uintptr_t)addr;
+    return inl(addr);
+}
 
-    if (port < 0x10000) {
-        outw(port, value);
-    } else {
-        writew(port, value);
-    }
+static uint32_t qpci_pc_mmio_readl(QPCIBus *bus, uint32_t addr)
+{
+    return readl(addr);
 }
 
-static void qpci_pc_io_writel(QPCIBus *bus, void *addr, uint32_t value)
+static void qpci_pc_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
 {
-    uintptr_t port = (uintptr_t)addr;
+    outl(addr, val);
+}
 
-    if (port < 0x10000) {
-        outl(port, value);
-    } else {
-        writel(port, value);
-    }
+static void qpci_pc_mmio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
+{
+    writel(addr, val);
 }
 
 static uint8_t qpci_pc_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
@@ -218,13 +203,21 @@ QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
 
     ret = g_malloc(sizeof(*ret));
 
-    ret->bus.io_readb = qpci_pc_io_readb;
-    ret->bus.io_readw = qpci_pc_io_readw;
-    ret->bus.io_readl = qpci_pc_io_readl;
+    ret->bus.pio_readb = qpci_pc_pio_readb;
+    ret->bus.pio_readw = qpci_pc_pio_readw;
+    ret->bus.pio_readl = qpci_pc_pio_readl;
+
+    ret->bus.pio_writeb = qpci_pc_pio_writeb;
+    ret->bus.pio_writew = qpci_pc_pio_writew;
+    ret->bus.pio_writel = qpci_pc_pio_writel;
+
+    ret->bus.mmio_readb = qpci_pc_mmio_readb;
+    ret->bus.mmio_readw = qpci_pc_mmio_readw;
+    ret->bus.mmio_readl = qpci_pc_mmio_readl;
 
-    ret->bus.io_writeb = qpci_pc_io_writeb;
-    ret->bus.io_writew = qpci_pc_io_writew;
-    ret->bus.io_writel = qpci_pc_io_writel;
+    ret->bus.mmio_writeb = qpci_pc_mmio_writeb;
+    ret->bus.mmio_writew = qpci_pc_mmio_writew;
+    ret->bus.mmio_writel = qpci_pc_mmio_writel;
 
     ret->bus.config_readb = qpci_pc_config_readb;
     ret->bus.config_readw = qpci_pc_config_readw;
diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
index 2eaaf91..2d26a94 100644
--- a/tests/libqos/pci-spapr.c
+++ b/tests/libqos/pci-spapr.c
@@ -50,78 +50,76 @@ typedef struct QPCIBusSPAPR {
  * so PCI accessors need to swap data endianness
  */
 
-static uint8_t qpci_spapr_io_readb(QPCIBus *bus, void *addr)
+static uint8_t qpci_spapr_pio_readb(QPCIBus *bus, uint32_t addr)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    uint64_t port = (uintptr_t)addr;
-    uint8_t v;
-    if (port < s->pio.size) {
-        v = readb(s->pio_cpu_base + port);
-    } else {
-        v = readb(s->mmio32_cpu_base + port);
-    }
-    return v;
+    return readb(s->pio_cpu_base + addr);
 }
 
-static uint16_t qpci_spapr_io_readw(QPCIBus *bus, void *addr)
+static uint8_t qpci_spapr_mmio32_readb(QPCIBus *bus, uint32_t addr)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    uint64_t port = (uintptr_t)addr;
-    uint16_t v;
-    if (port < s->pio.size) {
-        v = readw(s->pio_cpu_base + port);
-    } else {
-        v = readw(s->mmio32_cpu_base + port);
-    }
-    return bswap16(v);
+    return readb(s->mmio32_cpu_base + addr);
 }
 
-static uint32_t qpci_spapr_io_readl(QPCIBus *bus, void *addr)
+static void qpci_spapr_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    uint64_t port = (uintptr_t)addr;
-    uint32_t v;
-    if (port < s->pio.size) {
-        v = readl(s->pio_cpu_base + port);
-    } else {
-        v = readl(s->mmio32_cpu_base + port);
-    }
-    return bswap32(v);
+    writeb(s->pio_cpu_base + addr, val);
 }
 
-static void qpci_spapr_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
+static void qpci_spapr_mmio32_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    uint64_t port = (uintptr_t)addr;
-    if (port < s->pio.size) {
-        writeb(s->pio_cpu_base + port, value);
-    } else {
-        writeb(s->mmio32_cpu_base + port, value);
-    }
+    writeb(s->mmio32_cpu_base + addr, val);
 }
 
-static void qpci_spapr_io_writew(QPCIBus *bus, void *addr, uint16_t value)
+static uint16_t qpci_spapr_pio_readw(QPCIBus *bus, uint32_t addr)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    uint64_t port = (uintptr_t)addr;
-    value = bswap16(value);
-    if (port < s->pio.size) {
-        writew(s->pio_cpu_base + port, value);
-    } else {
-        writew(s->mmio32_cpu_base + port, value);
-    }
+    return bswap16(readw(s->pio_cpu_base + addr));
 }
 
-static void qpci_spapr_io_writel(QPCIBus *bus, void *addr, uint32_t value)
+static uint16_t qpci_spapr_mmio32_readw(QPCIBus *bus, uint32_t addr)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    uint64_t port = (uintptr_t)addr;
-    value = bswap32(value);
-    if (port < s->pio.size) {
-        writel(s->pio_cpu_base + port, value);
-    } else {
-        writel(s->mmio32_cpu_base + port, value);
-    }
+    return bswap16(readw(s->mmio32_cpu_base + addr));
+}
+
+static void qpci_spapr_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    writew(s->pio_cpu_base + addr, bswap16(val));
+}
+
+static void qpci_spapr_mmio32_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    writew(s->mmio32_cpu_base + addr, bswap16(val));
+}
+
+static uint32_t qpci_spapr_pio_readl(QPCIBus *bus, uint32_t addr)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    return bswap32(readl(s->pio_cpu_base + addr));
+}
+
+static uint32_t qpci_spapr_mmio32_readl(QPCIBus *bus, uint32_t addr)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    return bswap32(readl(s->mmio32_cpu_base + addr));
+}
+
+static void qpci_spapr_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    writel(s->pio_cpu_base + addr, bswap32(val));
+}
+
+static void qpci_spapr_mmio32_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    writel(s->mmio32_cpu_base + addr, bswap32(val));
 }
 
 static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
@@ -248,13 +246,21 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
 
     ret->alloc = alloc;
 
-    ret->bus.io_readb = qpci_spapr_io_readb;
-    ret->bus.io_readw = qpci_spapr_io_readw;
-    ret->bus.io_readl = qpci_spapr_io_readl;
+    ret->bus.pio_readb = qpci_spapr_pio_readb;
+    ret->bus.pio_readw = qpci_spapr_pio_readw;
+    ret->bus.pio_readl = qpci_spapr_pio_readl;
+
+    ret->bus.pio_writeb = qpci_spapr_pio_writeb;
+    ret->bus.pio_writew = qpci_spapr_pio_writew;
+    ret->bus.pio_writel = qpci_spapr_pio_writel;
+
+    ret->bus.mmio_readb = qpci_spapr_mmio32_readb;
+    ret->bus.mmio_readw = qpci_spapr_mmio32_readw;
+    ret->bus.mmio_readl = qpci_spapr_mmio32_readl;
 
-    ret->bus.io_writeb = qpci_spapr_io_writeb;
-    ret->bus.io_writew = qpci_spapr_io_writew;
-    ret->bus.io_writel = qpci_spapr_io_writel;
+    ret->bus.mmio_writeb = qpci_spapr_mmio32_writeb;
+    ret->bus.mmio_writew = qpci_spapr_mmio32_writew;
+    ret->bus.mmio_writel = qpci_spapr_mmio32_writel;
 
     ret->bus.config_readb = qpci_spapr_config_readb;
     ret->bus.config_readw = qpci_spapr_config_readw;
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
index c3f3382..55b01df 100644
--- a/tests/libqos/pci.c
+++ b/tests/libqos/pci.c
@@ -224,33 +224,68 @@ void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
 
 uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
 {
-    return dev->bus->io_readb(dev->bus, data);
+    uintptr_t addr = (uintptr_t)data;
+
+    if (addr < QPCI_PIO_LIMIT) {
+        return dev->bus->pio_readb(dev->bus, addr);
+    } else {
+        return dev->bus->mmio_readb(dev->bus, addr);
+    }
 }
 
 uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
 {
-    return dev->bus->io_readw(dev->bus, data);
+    uintptr_t addr = (uintptr_t)data;
+
+    if (addr < QPCI_PIO_LIMIT) {
+        return dev->bus->pio_readw(dev->bus, addr);
+    } else {
+        return dev->bus->mmio_readw(dev->bus, addr);
+    }
 }
 
 uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
 {
-    return dev->bus->io_readl(dev->bus, data);
-}
+    uintptr_t addr = (uintptr_t)data;
 
+    if (addr < QPCI_PIO_LIMIT) {
+        return dev->bus->pio_readl(dev->bus, addr);
+    } else {
+        return dev->bus->mmio_readl(dev->bus, addr);
+    }
+}
 
 void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
 {
-    dev->bus->io_writeb(dev->bus, data, value);
+    uintptr_t addr = (uintptr_t)data;
+
+    if (addr < QPCI_PIO_LIMIT) {
+        dev->bus->pio_writeb(dev->bus, addr, value);
+    } else {
+        dev->bus->mmio_writeb(dev->bus, addr, value);
+    }
 }
 
 void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
 {
-    dev->bus->io_writew(dev->bus, data, value);
+    uintptr_t addr = (uintptr_t)data;
+
+    if (addr < QPCI_PIO_LIMIT) {
+        dev->bus->pio_writew(dev->bus, addr, value);
+    } else {
+        dev->bus->mmio_writew(dev->bus, addr, value);
+    }
 }
 
 void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
 {
-    dev->bus->io_writel(dev->bus, data, value);
+    uintptr_t addr = (uintptr_t)data;
+
+    if (addr < QPCI_PIO_LIMIT) {
+        dev->bus->pio_writel(dev->bus, addr, value);
+    } else {
+        dev->bus->mmio_writel(dev->bus, addr, value);
+    }
 }
 
 void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
index c06add8..72a2245 100644
--- a/tests/libqos/pci.h
+++ b/tests/libqos/pci.h
@@ -15,6 +15,8 @@
 
 #include "libqtest.h"
 
+#define QPCI_PIO_LIMIT    0x10000
+
 #define QPCI_DEVFN(dev, fn) (((dev) << 3) | (fn))
 
 typedef struct QPCIDevice QPCIDevice;
@@ -22,13 +24,21 @@ typedef struct QPCIBus QPCIBus;
 
 struct QPCIBus
 {
-    uint8_t (*io_readb)(QPCIBus *bus, void *addr);
-    uint16_t (*io_readw)(QPCIBus *bus, void *addr);
-    uint32_t (*io_readl)(QPCIBus *bus, void *addr);
+    uint8_t (*pio_readb)(QPCIBus *bus, uint32_t addr);
+    uint16_t (*pio_readw)(QPCIBus *bus, uint32_t addr);
+    uint32_t (*pio_readl)(QPCIBus *bus, uint32_t addr);
+
+    uint8_t (*mmio_readb)(QPCIBus *bus, uint32_t addr);
+    uint16_t (*mmio_readw)(QPCIBus *bus, uint32_t addr);
+    uint32_t (*mmio_readl)(QPCIBus *bus, uint32_t addr);
+
+    void (*pio_writeb)(QPCIBus *bus, uint32_t addr, uint8_t value);
+    void (*pio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
+    void (*pio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
 
-    void (*io_writeb)(QPCIBus *bus, void *addr, uint8_t value);
-    void (*io_writew)(QPCIBus *bus, void *addr, uint16_t value);
-    void (*io_writel)(QPCIBus *bus, void *addr, uint32_t value);
+    void (*mmio_writeb)(QPCIBus *bus, uint32_t addr, uint8_t value);
+    void (*mmio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
+    void (*mmio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
 
     uint8_t (*config_readb)(QPCIBus *bus, int devfn, uint8_t offset);
     uint16_t (*config_readw)(QPCIBus *bus, int devfn, uint8_t offset);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 3/8] libqos: Move BAR assignment to common code
  2016-10-18 10:52 [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling David Gibson
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 1/8] libqos: Give qvirtio_config_read*() consistent semantics David Gibson
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 2/8] libqos: Handle PCI IO de-multiplexing in common code David Gibson
@ 2016-10-18 10:52 ` David Gibson
  2016-10-18 15:00   ` Laurent Vivier
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 4/8] tests: Better handle legacy IO addresses in tco-test David Gibson
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: David Gibson @ 2016-10-18 10:52 UTC (permalink / raw)
  To: pbonzini, qemu-devel
  Cc: qemu-ppc, lvivier, agraf, stefanha, mst, aik, mdroth, groug,
	thuth, David Gibson

The PCI backends in libqos each supply an iomap() and iounmap() function
which is used to set up a specified PCI BAR.  But PCI BAR allocation takes
place entirely within PCI space, so doesn't really need per-backend
versions.  For example, Linux includes generic BAR allocation code used on
platforms where that isn't done by firmware.

This patch merges the BAR allocation from the two existing backends into a
single simplified copy.  The back ends just need to set up some parameters
describing the window of PCI IO and PCI memory addresses which are
available for allocation.  Like both the existing versions the new one uses
a simple bump allocator.

Note that (again like the existing versions) this doesn't really handle
64-bit memory BARs properly.  It is actually used for such a BAR by the
ivshmem test, and apparently the 32-bit MMIO BAR logic is close enough to
work, as long as the BAR isn't too big.  Fixing that to properly handle
64-bit BAR allocation is a problem for another time.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/libqos/pci-pc.c    | 79 ++--------------------------------------------
 tests/libqos/pci-spapr.c | 81 ++----------------------------------------------
 tests/libqos/pci.c       | 56 +++++++++++++++++++++++++++++++--
 tests/libqos/pci.h       |  7 ++---
 4 files changed, 63 insertions(+), 160 deletions(-)

diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index 51dff8a..b087d13 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -17,7 +17,6 @@
 #include "hw/pci/pci_regs.h"
 
 #include "qemu-common.h"
-#include "qemu/host-utils.h"
 
 
 #define ACPI_PCIHP_ADDR         0xae00
@@ -132,71 +131,6 @@ static void qpci_pc_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint3
     outl(0xcfc, value);
 }
 
-static void *qpci_pc_iomap(QPCIBus *bus, QPCIDevice *dev, int barno, uint64_t *sizeptr)
-{
-    QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
-    static const int bar_reg_map[] = {
-        PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
-        PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
-    };
-    int bar_reg;
-    uint32_t addr;
-    uint64_t size;
-    uint32_t io_type;
-
-    g_assert(barno >= 0 && barno <= 5);
-    bar_reg = bar_reg_map[barno];
-
-    qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
-    addr = qpci_config_readl(dev, bar_reg);
-
-    io_type = addr & PCI_BASE_ADDRESS_SPACE;
-    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
-        addr &= PCI_BASE_ADDRESS_IO_MASK;
-    } else {
-        addr &= PCI_BASE_ADDRESS_MEM_MASK;
-    }
-
-    size = (1ULL << ctzl(addr));
-    if (size == 0) {
-        return NULL;
-    }
-    if (sizeptr) {
-        *sizeptr = size;
-    }
-
-    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
-        uint16_t loc;
-
-        g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
-                 <= s->pci_iohole_size);
-        s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
-        loc = s->pci_iohole_start + s->pci_iohole_alloc;
-        s->pci_iohole_alloc += size;
-
-        qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
-
-        return (void *)(intptr_t)loc;
-    } else {
-        uint64_t loc;
-
-        g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
-                 <= s->pci_hole_size);
-        s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
-        loc = s->pci_hole_start + s->pci_hole_alloc;
-        s->pci_hole_alloc += size;
-
-        qpci_config_writel(dev, bar_reg, loc);
-
-        return (void *)(intptr_t)loc;
-    }
-}
-
-static void qpci_pc_iounmap(QPCIBus *bus, void *data)
-{
-    /* FIXME */
-}
-
 QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
 {
     QPCIBusPC *ret;
@@ -227,16 +161,9 @@ QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
     ret->bus.config_writew = qpci_pc_config_writew;
     ret->bus.config_writel = qpci_pc_config_writel;
 
-    ret->bus.iomap = qpci_pc_iomap;
-    ret->bus.iounmap = qpci_pc_iounmap;
-
-    ret->pci_hole_start = 0xE0000000;
-    ret->pci_hole_size = 0x20000000;
-    ret->pci_hole_alloc = 0;
-
-    ret->pci_iohole_start = 0xc000;
-    ret->pci_iohole_size = 0x4000;
-    ret->pci_iohole_alloc = 0;
+    ret->bus.pio_alloc_ptr = 0xc000;
+    ret->bus.mmio_alloc_ptr = 0xE0000000;
+    ret->bus.mmio_limit = 0x100000000ULL;
 
     return &ret->bus;
 }
diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
index 2d26a94..9a18d8a 100644
--- a/tests/libqos/pci-spapr.c
+++ b/tests/libqos/pci-spapr.c
@@ -167,72 +167,6 @@ static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset,
     qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 4, value);
 }
 
-static void *qpci_spapr_iomap(QPCIBus *bus, QPCIDevice *dev, int barno,
-                              uint64_t *sizeptr)
-{
-    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    static const int bar_reg_map[] = {
-        PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
-        PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
-    };
-    int bar_reg;
-    uint32_t addr;
-    uint64_t size;
-    uint32_t io_type;
-
-    g_assert(barno >= 0 && barno <= 5);
-    bar_reg = bar_reg_map[barno];
-
-    qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
-    addr = qpci_config_readl(dev, bar_reg);
-
-    io_type = addr & PCI_BASE_ADDRESS_SPACE;
-    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
-        addr &= PCI_BASE_ADDRESS_IO_MASK;
-    } else {
-        addr &= PCI_BASE_ADDRESS_MEM_MASK;
-    }
-
-    size = (1ULL << ctzl(addr));
-    if (size == 0) {
-        return NULL;
-    }
-    if (sizeptr) {
-        *sizeptr = size;
-    }
-
-    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
-        uint16_t loc;
-
-        g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
-                 <= s->pci_iohole_size);
-        s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
-        loc = s->pci_iohole_start + s->pci_iohole_alloc;
-        s->pci_iohole_alloc += size;
-
-        qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
-
-        return (void *)(unsigned long)loc;
-    } else {
-        uint64_t loc;
-
-        g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
-                 <= s->pci_hole_size);
-        s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
-        loc = s->pci_hole_start + s->pci_hole_alloc;
-        s->pci_hole_alloc += size;
-
-        qpci_config_writel(dev, bar_reg, loc);
-
-        return (void *)(unsigned long)loc;
-    }
-}
-
-static void qpci_spapr_iounmap(QPCIBus *bus, void *data)
-{
-    /* FIXME */
-}
-
 #define SPAPR_PCI_BASE               (1ULL << 45)
 
 #define SPAPR_PCI_MMIO32_WIN_SIZE    0x80000000 /* 2 GiB */
@@ -270,9 +204,6 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
     ret->bus.config_writew = qpci_spapr_config_writew;
     ret->bus.config_writel = qpci_spapr_config_writel;
 
-    ret->bus.iomap = qpci_spapr_iomap;
-    ret->bus.iounmap = qpci_spapr_iounmap;
-
     /* FIXME: We assume the default location of the PHB for now.
      * Ideally we'd parse the device tree deposited in the guest to
      * get the window locations */
@@ -287,15 +218,9 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
     ret->mmio32.pci_base = 0x80000000; /* 2 GiB */
     ret->mmio32.size = SPAPR_PCI_MMIO32_WIN_SIZE;
 
-    ret->pci_hole_start = 0xC0000000;
-    ret->pci_hole_size =
-        ret->mmio32.pci_base + ret->mmio32.size - ret->pci_hole_start;
-    ret->pci_hole_alloc = 0;
-
-    ret->pci_iohole_start = 0xc000;
-    ret->pci_iohole_size =
-        ret->pio.pci_base + ret->pio.size - ret->pci_iohole_start;
-    ret->pci_iohole_alloc = 0;
+    ret->bus.pio_alloc_ptr = 0xc000;
+    ret->bus.mmio_alloc_ptr = ret->mmio32.pci_base;
+    ret->bus.mmio_limit = ret->mmio32.pci_base + ret->mmio32.size;
 
     return &ret->bus;
 }
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
index 55b01df..bf1c532 100644
--- a/tests/libqos/pci.c
+++ b/tests/libqos/pci.c
@@ -14,6 +14,7 @@
 #include "libqos/pci.h"
 
 #include "hw/pci/pci_regs.h"
+#include "qemu/host-utils.h"
 
 void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
                          void (*func)(QPCIDevice *dev, int devfn, void *data),
@@ -290,12 +291,63 @@ void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
 
 void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
 {
-    return dev->bus->iomap(dev->bus, dev, barno, sizeptr);
+    QPCIBus *bus = dev->bus;
+    static const int bar_reg_map[] = {
+        PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
+        PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
+    };
+    int bar_reg;
+    uint32_t addr, size;
+    uint32_t io_type;
+    uint64_t loc;
+
+    g_assert(barno >= 0 && barno <= 5);
+    bar_reg = bar_reg_map[barno];
+
+    qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
+    addr = qpci_config_readl(dev, bar_reg);
+
+    io_type = addr & PCI_BASE_ADDRESS_SPACE;
+    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+        addr &= PCI_BASE_ADDRESS_IO_MASK;
+    } else {
+        addr &= PCI_BASE_ADDRESS_MEM_MASK;
+    }
+
+    g_assert(addr); /* Must have *some* size bits */
+
+    size = 1U << ctz32(addr);
+    if (sizeptr) {
+        *sizeptr = size;
+    }
+
+    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+        loc = QEMU_ALIGN_UP(bus->pio_alloc_ptr, size);
+
+        g_assert(loc >= bus->pio_alloc_ptr);
+        g_assert(loc + size <= QPCI_PIO_LIMIT); /* Keep PIO below 64kiB */
+
+        bus->pio_alloc_ptr = loc + size;
+
+        qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
+    } else {
+        loc = QEMU_ALIGN_UP(bus->mmio_alloc_ptr, size);
+
+        /* Check for space */
+        g_assert(loc >= bus->mmio_alloc_ptr);
+        g_assert(loc + size <= bus->mmio_limit);
+
+        bus->mmio_alloc_ptr = loc + size;
+
+        qpci_config_writel(dev, bar_reg, loc);
+    }
+
+    return (void *)(uintptr_t)loc;
 }
 
 void qpci_iounmap(QPCIDevice *dev, void *data)
 {
-    dev->bus->iounmap(dev->bus, data);
+    /* FIXME */
 }
 
 void qpci_plug_device_test(const char *driver, const char *id,
diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
index 72a2245..f6f916d 100644
--- a/tests/libqos/pci.h
+++ b/tests/libqos/pci.h
@@ -22,8 +22,7 @@
 typedef struct QPCIDevice QPCIDevice;
 typedef struct QPCIBus QPCIBus;
 
-struct QPCIBus
-{
+struct QPCIBus {
     uint8_t (*pio_readb)(QPCIBus *bus, uint32_t addr);
     uint16_t (*pio_readw)(QPCIBus *bus, uint32_t addr);
     uint32_t (*pio_readl)(QPCIBus *bus, uint32_t addr);
@@ -51,8 +50,8 @@ struct QPCIBus
     void (*config_writel)(QPCIBus *bus, int devfn,
                           uint8_t offset, uint32_t value);
 
-    void *(*iomap)(QPCIBus *bus, QPCIDevice *dev, int barno, uint64_t *sizeptr);
-    void (*iounmap)(QPCIBus *bus, void *data);
+    uint16_t pio_alloc_ptr;
+    uint64_t mmio_alloc_ptr, mmio_limit;
 };
 
 struct QPCIDevice
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 4/8] tests: Better handle legacy IO addresses in tco-test
  2016-10-18 10:52 [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling David Gibson
                   ` (2 preceding siblings ...)
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 3/8] libqos: Move BAR assignment to " David Gibson
@ 2016-10-18 10:52 ` David Gibson
  2016-10-18 15:14   ` Laurent Vivier
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 5/8] libqos: Add streaming accessors for PCI MMIO David Gibson
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: David Gibson @ 2016-10-18 10:52 UTC (permalink / raw)
  To: pbonzini, qemu-devel
  Cc: qemu-ppc, lvivier, agraf, stefanha, mst, aik, mdroth, groug,
	thuth, David Gibson

tco_test uses the libqos PCI code to access the device.  This makes perfect
sense for the PCI config space accesses.  However for IO, rather than the
usual PCI approach of mapping a PCI BAR, then accessing that, it instead
uses the legacy approach of fixed, known addresses in PCI IO space.

That doesn't work very well with the qpci_io_{read,write} functions because
we never use qpci_iomap() and so have to make assumptions about the
internal encoding of the address tokens iomap() returns.

This patch avoids that, by directly using the bus's pio_{read,write}
callbacks, which are defined to take addresses within the PCI IO space.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/tco-test.c | 87 ++++++++++++++++++++++++++++----------------------------
 1 file changed, 44 insertions(+), 43 deletions(-)

diff --git a/tests/tco-test.c b/tests/tco-test.c
index 0d201b1..e668630 100644
--- a/tests/tco-test.c
+++ b/tests/tco-test.c
@@ -40,13 +40,13 @@ enum {
 typedef struct {
     const char *args;
     bool noreboot;
+    QPCIBus *bus;
     QPCIDevice *dev;
-    void *tco_io_base;
+    uint16_t tco_io_base;
 } TestData;
 
 static void test_init(TestData *d)
 {
-    QPCIBus *bus;
     QTestState *qs;
     char *s;
 
@@ -57,8 +57,8 @@ static void test_init(TestData *d)
     qtest_irq_intercept_in(qs, "ioapic");
     g_free(s);
 
-    bus = qpci_init_pc(NULL);
-    d->dev = qpci_device_find(bus, QPCI_DEVFN(0x1f, 0x00));
+    d->bus = qpci_init_pc(NULL);
+    d->dev = qpci_device_find(d->bus, QPCI_DEVFN(0x1f, 0x00));
     g_assert(d->dev != NULL);
 
     qpci_device_enable(d->dev);
@@ -70,42 +70,42 @@ static void test_init(TestData *d)
     /* set Root Complex BAR */
     qpci_config_writel(d->dev, ICH9_LPC_RCBA, RCBA_BASE_ADDR | 0x1);
 
-    d->tco_io_base = (void *)((uintptr_t)PM_IO_BASE_ADDR + 0x60);
+    d->tco_io_base = PM_IO_BASE_ADDR + 0x60;
 }
 
 static void stop_tco(const TestData *d)
 {
     uint32_t val;
 
-    val = qpci_io_readw(d->dev, d->tco_io_base + TCO1_CNT);
+    val = d->bus->pio_readw(d->bus, d->tco_io_base + TCO1_CNT);
     val |= TCO_TMR_HLT;
-    qpci_io_writew(d->dev, d->tco_io_base + TCO1_CNT, val);
+    d->bus->pio_writew(d->bus, d->tco_io_base + TCO1_CNT, val);
 }
 
 static void start_tco(const TestData *d)
 {
     uint32_t val;
 
-    val = qpci_io_readw(d->dev, d->tco_io_base + TCO1_CNT);
+    val = d->bus->pio_readw(d->bus, d->tco_io_base + TCO1_CNT);
     val &= ~TCO_TMR_HLT;
-    qpci_io_writew(d->dev, d->tco_io_base + TCO1_CNT, val);
+    d->bus->pio_writew(d->bus, d->tco_io_base + TCO1_CNT, val);
 }
 
 static void load_tco(const TestData *d)
 {
-    qpci_io_writew(d->dev, d->tco_io_base + TCO_RLD, 4);
+    d->bus->pio_writew(d->bus, d->tco_io_base + TCO_RLD, 4);
 }
 
 static void set_tco_timeout(const TestData *d, uint16_t ticks)
 {
-    qpci_io_writew(d->dev, d->tco_io_base + TCO_TMR, ticks);
+    d->bus->pio_writew(d->bus, d->tco_io_base + TCO_TMR, ticks);
 }
 
 static void clear_tco_status(const TestData *d)
 {
-    qpci_io_writew(d->dev, d->tco_io_base + TCO1_STS, 0x0008);
-    qpci_io_writew(d->dev, d->tco_io_base + TCO2_STS, 0x0002);
-    qpci_io_writew(d->dev, d->tco_io_base + TCO2_STS, 0x0004);
+    d->bus->pio_writew(d->bus, d->tco_io_base + TCO1_STS, 0x0008);
+    d->bus->pio_writew(d->bus, d->tco_io_base + TCO2_STS, 0x0002);
+    d->bus->pio_writew(d->bus, d->tco_io_base + TCO2_STS, 0x0004);
 }
 
 static void reset_on_second_timeout(bool enable)
@@ -128,25 +128,25 @@ static void test_tco_defaults(void)
     d.args = NULL;
     d.noreboot = true;
     test_init(&d);
-    g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO_RLD), ==,
+    g_assert_cmpint(d.bus->pio_readw(d.bus, d.tco_io_base + TCO_RLD), ==,
                     TCO_RLD_DEFAULT);
     /* TCO_DAT_IN & TCO_DAT_OUT */
-    g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO_DAT_IN), ==,
+    g_assert_cmpint(d.bus->pio_readw(d.bus, d.tco_io_base + TCO_DAT_IN), ==,
                     (TCO_DAT_OUT_DEFAULT << 8) | TCO_DAT_IN_DEFAULT);
     /* TCO1_STS & TCO2_STS */
-    g_assert_cmpint(qpci_io_readl(d.dev, d.tco_io_base + TCO1_STS), ==,
+    g_assert_cmpint(d.bus->pio_readl(d.bus, d.tco_io_base + TCO1_STS), ==,
                     (TCO2_STS_DEFAULT << 16) | TCO1_STS_DEFAULT);
     /* TCO1_CNT & TCO2_CNT */
-    g_assert_cmpint(qpci_io_readl(d.dev, d.tco_io_base + TCO1_CNT), ==,
+    g_assert_cmpint(d.bus->pio_readl(d.bus, d.tco_io_base + TCO1_CNT), ==,
                     (TCO2_CNT_DEFAULT << 16) | TCO1_CNT_DEFAULT);
     /* TCO_MESSAGE1 & TCO_MESSAGE2 */
-    g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO_MESSAGE1), ==,
+    g_assert_cmpint(d.bus->pio_readw(d.bus, d.tco_io_base + TCO_MESSAGE1), ==,
                     (TCO_MESSAGE2_DEFAULT << 8) | TCO_MESSAGE1_DEFAULT);
-    g_assert_cmpint(qpci_io_readb(d.dev, d.tco_io_base + TCO_WDCNT), ==,
+    g_assert_cmpint(d.bus->pio_readb(d.bus, d.tco_io_base + TCO_WDCNT), ==,
                     TCO_WDCNT_DEFAULT);
-    g_assert_cmpint(qpci_io_readb(d.dev, d.tco_io_base + SW_IRQ_GEN), ==,
+    g_assert_cmpint(d.bus->pio_readb(d.bus, d.tco_io_base + SW_IRQ_GEN), ==,
                     SW_IRQ_GEN_DEFAULT);
-    g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO_TMR), ==,
+    g_assert_cmpint(d.bus->pio_readw(d.bus, d.tco_io_base + TCO_TMR), ==,
                     TCO_TMR_DEFAULT);
     qtest_end();
 }
@@ -171,23 +171,23 @@ static void test_tco_timeout(void)
     clock_step(ticks * TCO_TICK_NSEC);
 
     /* test first timeout */
-    val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
+    val = d.bus->pio_readw(d.bus, d.tco_io_base + TCO1_STS);
     ret = val & TCO_TIMEOUT ? 1 : 0;
     g_assert(ret == 1);
 
     /* test clearing timeout bit */
     val |= TCO_TIMEOUT;
-    qpci_io_writew(d.dev, d.tco_io_base + TCO1_STS, val);
-    val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
+    d.bus->pio_writew(d.bus, d.tco_io_base + TCO1_STS, val);
+    val = d.bus->pio_readw(d.bus, d.tco_io_base + TCO1_STS);
     ret = val & TCO_TIMEOUT ? 1 : 0;
     g_assert(ret == 0);
 
     /* test second timeout */
     clock_step(ticks * TCO_TICK_NSEC);
-    val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
+    val = d.bus->pio_readw(d.bus, d.tco_io_base + TCO1_STS);
     ret = val & TCO_TIMEOUT ? 1 : 0;
     g_assert(ret == 1);
-    val = qpci_io_readw(d.dev, d.tco_io_base + TCO2_STS);
+    val = d.bus->pio_readw(d.bus, d.tco_io_base + TCO2_STS);
     ret = val & TCO_SECOND_TO_STS ? 1 : 0;
     g_assert(ret == 1);
 
@@ -214,13 +214,13 @@ static void test_tco_max_timeout(void)
     start_tco(&d);
     clock_step(((ticks & TCO_TMR_MASK) - 1) * TCO_TICK_NSEC);
 
-    val = qpci_io_readw(d.dev, d.tco_io_base + TCO_RLD);
+    val = d.bus->pio_readw(d.bus, d.tco_io_base + TCO_RLD);
     g_assert_cmpint(val & TCO_RLD_MASK, ==, 1);
-    val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
+    val = d.bus->pio_readw(d.bus, d.tco_io_base + TCO1_STS);
     ret = val & TCO_TIMEOUT ? 1 : 0;
     g_assert(ret == 0);
     clock_step(TCO_TICK_NSEC);
-    val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
+    val = d.bus->pio_readw(d.bus, d.tco_io_base + TCO1_STS);
     ret = val & TCO_TIMEOUT ? 1 : 0;
     g_assert(ret == 1);
 
@@ -358,11 +358,12 @@ static void test_tco_ticks_counter(void)
     start_tco(&d);
 
     do {
-        rld = qpci_io_readw(d.dev, d.tco_io_base + TCO_RLD) & TCO_RLD_MASK;
+        rld = d.bus->pio_readw(d.bus, d.tco_io_base + TCO_RLD) & TCO_RLD_MASK;
         g_assert_cmpint(rld, ==, ticks);
         clock_step(TCO_TICK_NSEC);
         ticks--;
-    } while (!(qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS) & TCO_TIMEOUT));
+    } while (!(d.bus->pio_readw(d.bus,
+                                d.tco_io_base + TCO1_STS) & TCO_TIMEOUT));
 
     stop_tco(&d);
     qtest_end();
@@ -378,10 +379,10 @@ static void test_tco1_control_bits(void)
     test_init(&d);
 
     val = TCO_LOCK;
-    qpci_io_writew(d.dev, d.tco_io_base + TCO1_CNT, val);
+    d.bus->pio_writew(d.bus, d.tco_io_base + TCO1_CNT, val);
     val &= ~TCO_LOCK;
-    qpci_io_writew(d.dev, d.tco_io_base + TCO1_CNT, val);
-    g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO1_CNT), ==,
+    d.bus->pio_writew(d.bus, d.tco_io_base + TCO1_CNT, val);
+    g_assert_cmpint(d.bus->pio_readw(d.bus, d.tco_io_base + TCO1_CNT), ==,
                     TCO_LOCK);
     qtest_end();
 }
@@ -405,13 +406,13 @@ static void test_tco1_status_bits(void)
     start_tco(&d);
     clock_step(ticks * TCO_TICK_NSEC);
 
-    qpci_io_writeb(d.dev, d.tco_io_base + TCO_DAT_IN, 0);
-    qpci_io_writeb(d.dev, d.tco_io_base + TCO_DAT_OUT, 0);
-    val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
+    d.bus->pio_writeb(d.bus, d.tco_io_base + TCO_DAT_IN, 0);
+    d.bus->pio_writeb(d.bus, d.tco_io_base + TCO_DAT_OUT, 0);
+    val = d.bus->pio_readw(d.bus, d.tco_io_base + TCO1_STS);
     ret = val & (TCO_TIMEOUT | SW_TCO_SMI | TCO_INT_STS) ? 1 : 0;
     g_assert(ret == 1);
-    qpci_io_writew(d.dev, d.tco_io_base + TCO1_STS, val);
-    g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS), ==, 0);
+    d.bus->pio_writew(d.bus, d.tco_io_base + TCO1_STS, val);
+    g_assert_cmpint(d.bus->pio_readw(d.bus, d.tco_io_base + TCO1_STS), ==, 0);
     qtest_end();
 }
 
@@ -434,11 +435,11 @@ static void test_tco2_status_bits(void)
     start_tco(&d);
     clock_step(ticks * TCO_TICK_NSEC * 2);
 
-    val = qpci_io_readw(d.dev, d.tco_io_base + TCO2_STS);
+    val = d.bus->pio_readw(d.bus, d.tco_io_base + TCO2_STS);
     ret = val & (TCO_SECOND_TO_STS | TCO_BOOT_STS) ? 1 : 0;
     g_assert(ret == 1);
-    qpci_io_writew(d.dev, d.tco_io_base + TCO2_STS, val);
-    g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO2_STS), ==, 0);
+    d.bus->pio_writew(d.bus, d.tco_io_base + TCO2_STS, val);
+    g_assert_cmpint(d.bus->pio_readw(d.bus, d.tco_io_base + TCO2_STS), ==, 0);
     qtest_end();
 }
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 5/8] libqos: Add streaming accessors for PCI MMIO
  2016-10-18 10:52 [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling David Gibson
                   ` (3 preceding siblings ...)
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 4/8] tests: Better handle legacy IO addresses in tco-test David Gibson
@ 2016-10-18 10:52 ` David Gibson
  2016-10-18 15:17   ` Laurent Vivier
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 6/8] libqos: Implement mmio accessors in terms of mem{read, write} David Gibson
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: David Gibson @ 2016-10-18 10:52 UTC (permalink / raw)
  To: pbonzini, qemu-devel
  Cc: qemu-ppc, lvivier, agraf, stefanha, mst, aik, mdroth, groug,
	thuth, David Gibson

Currently PCI memory (aka MMIO) space is accessed via a set of readb/writeb
style accessors.  This is what we want for accessing discrete registers of
a certain size.  However, there are a few cases where we instead need a
"bag of bytes" style streaming interface to PCI MMIO space.  This can be
either for streaming data style registers or when there's actual memory
rather than registers in PCI space, for example frame buffers or ivshmem.

This patch adds backend callbacks, and libqos wrappers for this type of
byte address order preserving accesses.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/libqos/pci-pc.c    | 14 ++++++++++++++
 tests/libqos/pci-spapr.c | 17 +++++++++++++++++
 tests/libqos/pci.c       | 16 ++++++++++++++++
 tests/libqos/pci.h       |  6 ++++++
 4 files changed, 53 insertions(+)

diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index b087d13..0e95772 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -95,6 +95,17 @@ static void qpci_pc_mmio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
     writel(addr, val);
 }
 
+static void qpci_pc_memread(QPCIBus *bus, uint32_t addr, void *buf, size_t len)
+{
+    memread(addr, buf, len);
+}
+
+static void qpci_pc_memwrite(QPCIBus *bus, uint32_t addr,
+                             const void *buf, size_t len)
+{
+    memwrite(addr, buf, len);
+}
+
 static uint8_t qpci_pc_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
 {
     outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
@@ -153,6 +164,9 @@ QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
     ret->bus.mmio_writew = qpci_pc_mmio_writew;
     ret->bus.mmio_writel = qpci_pc_mmio_writel;
 
+    ret->bus.memread = qpci_pc_memread;
+    ret->bus.memwrite = qpci_pc_memwrite;
+
     ret->bus.config_readb = qpci_pc_config_readb;
     ret->bus.config_readw = qpci_pc_config_readw;
     ret->bus.config_readl = qpci_pc_config_readl;
diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
index 9a18d8a..b4c4b81 100644
--- a/tests/libqos/pci-spapr.c
+++ b/tests/libqos/pci-spapr.c
@@ -122,6 +122,20 @@ static void qpci_spapr_mmio32_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
     writel(s->mmio32_cpu_base + addr, bswap32(val));
 }
 
+static void qpci_spapr_memread(QPCIBus *bus, uint32_t addr,
+                               void *buf, size_t len)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    memread(s->mmio32_cpu_base + addr, buf, len);
+}
+
+static void qpci_spapr_memwrite(QPCIBus *bus, uint32_t addr,
+                                const void *buf, size_t len)
+{
+    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
+    memwrite(s->mmio32_cpu_base + addr, buf, len);
+}
+
 static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
@@ -196,6 +210,9 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
     ret->bus.mmio_writew = qpci_spapr_mmio32_writew;
     ret->bus.mmio_writel = qpci_spapr_mmio32_writel;
 
+    ret->bus.memread = qpci_spapr_memread;
+    ret->bus.memwrite = qpci_spapr_memwrite;
+
     ret->bus.config_readb = qpci_spapr_config_readb;
     ret->bus.config_readw = qpci_spapr_config_readw;
     ret->bus.config_readl = qpci_spapr_config_readl;
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
index bf1c532..1e242f9 100644
--- a/tests/libqos/pci.c
+++ b/tests/libqos/pci.c
@@ -289,6 +289,22 @@ void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
     }
 }
 
+void qpci_memread(QPCIDevice *dev, void *data, void *buf, size_t len)
+{
+    uintptr_t addr = (uintptr_t)data;
+
+    g_assert(addr >= QPCI_PIO_LIMIT);
+    dev->bus->memread(dev->bus, addr, buf, len);
+}
+
+void qpci_memwrite(QPCIDevice *dev, void *data, const void *buf, size_t len)
+{
+    uintptr_t addr = (uintptr_t)data;
+
+    g_assert(addr >= QPCI_PIO_LIMIT);
+    dev->bus->memwrite(dev->bus, addr, buf, len);
+}
+
 void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
 {
     QPCIBus *bus = dev->bus;
diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
index f6f916d..2fa5b4f 100644
--- a/tests/libqos/pci.h
+++ b/tests/libqos/pci.h
@@ -39,6 +39,9 @@ struct QPCIBus {
     void (*mmio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
     void (*mmio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
 
+    void (*memread)(QPCIBus *bus, uint32_t addr, void *buf, size_t len);
+    void (*memwrite)(QPCIBus *bus, uint32_t addr, const void *buf, size_t len);
+
     uint8_t (*config_readb)(QPCIBus *bus, int devfn, uint8_t offset);
     uint16_t (*config_readw)(QPCIBus *bus, int devfn, uint8_t offset);
     uint32_t (*config_readl)(QPCIBus *bus, int devfn, uint8_t offset);
@@ -92,6 +95,9 @@ void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value);
 void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value);
 void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value);
 
+void qpci_memread(QPCIDevice *bus, void *data, void *buf, size_t len);
+void qpci_memwrite(QPCIDevice *bus, void *data, const void *buf, size_t len);
+
 void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
 void qpci_iounmap(QPCIDevice *dev, void *data);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 6/8] libqos: Implement mmio accessors in terms of mem{read, write}
  2016-10-18 10:52 [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling David Gibson
                   ` (4 preceding siblings ...)
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 5/8] libqos: Add streaming accessors for PCI MMIO David Gibson
@ 2016-10-18 10:52 ` David Gibson
  2016-10-18 16:04   ` Laurent Vivier
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 7/8] tests: Use qpci_mem{read, write} in ivshmem-test David Gibson
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: David Gibson @ 2016-10-18 10:52 UTC (permalink / raw)
  To: pbonzini, qemu-devel
  Cc: qemu-ppc, lvivier, agraf, stefanha, mst, aik, mdroth, groug,
	thuth, David Gibson

In the libqos PCI code we now have accessors both for registers (byte
significance preserving) and for streaming data (byte address order
preserving).  These exist in both the interface for qtest drivers and in
the machine specific backends.

However, the register-style accessors aren't actually necessary in the
backend.  They can be implemented in terms of the byte address order
preserving accessors by the libqos wrappers.  This works because PCI is
always little endian.

This does assume that the back end byte address order preserving accessors
will perform the equivalent of a single bus transaction for short lengths.
This is the case, and in fact they currently end up using the same
cpu_physical_memory_rw() implementation within the qtest accelerator.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/libqos/pci-pc.c    | 38 --------------------------------------
 tests/libqos/pci-spapr.c | 44 --------------------------------------------
 tests/libqos/pci.c       | 20 ++++++++++++++------
 tests/libqos/pci.h       |  8 --------
 4 files changed, 14 insertions(+), 96 deletions(-)

diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index 0e95772..e8b885a 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -40,61 +40,31 @@ static uint8_t qpci_pc_pio_readb(QPCIBus *bus, uint32_t addr)
     return inb(addr);
 }
 
-static uint8_t qpci_pc_mmio_readb(QPCIBus *bus, uint32_t addr)
-{
-    return readb(addr);
-}
-
 static void qpci_pc_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
 {
     outb(addr, val);
 }
 
-static void qpci_pc_mmio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
-{
-    writeb(addr, val);
-}
-
 static uint16_t qpci_pc_pio_readw(QPCIBus *bus, uint32_t addr)
 {
     return inw(addr);
 }
 
-static uint16_t qpci_pc_mmio_readw(QPCIBus *bus, uint32_t addr)
-{
-    return readw(addr);
-}
-
 static void qpci_pc_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
 {
     outw(addr, val);
 }
 
-static void qpci_pc_mmio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
-{
-    writew(addr, val);
-}
-
 static uint32_t qpci_pc_pio_readl(QPCIBus *bus, uint32_t addr)
 {
     return inl(addr);
 }
 
-static uint32_t qpci_pc_mmio_readl(QPCIBus *bus, uint32_t addr)
-{
-    return readl(addr);
-}
-
 static void qpci_pc_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
 {
     outl(addr, val);
 }
 
-static void qpci_pc_mmio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
-{
-    writel(addr, val);
-}
-
 static void qpci_pc_memread(QPCIBus *bus, uint32_t addr, void *buf, size_t len)
 {
     memread(addr, buf, len);
@@ -156,14 +126,6 @@ QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
     ret->bus.pio_writew = qpci_pc_pio_writew;
     ret->bus.pio_writel = qpci_pc_pio_writel;
 
-    ret->bus.mmio_readb = qpci_pc_mmio_readb;
-    ret->bus.mmio_readw = qpci_pc_mmio_readw;
-    ret->bus.mmio_readl = qpci_pc_mmio_readl;
-
-    ret->bus.mmio_writeb = qpci_pc_mmio_writeb;
-    ret->bus.mmio_writew = qpci_pc_mmio_writew;
-    ret->bus.mmio_writel = qpci_pc_mmio_writel;
-
     ret->bus.memread = qpci_pc_memread;
     ret->bus.memwrite = qpci_pc_memwrite;
 
diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
index b4c4b81..dc89b25 100644
--- a/tests/libqos/pci-spapr.c
+++ b/tests/libqos/pci-spapr.c
@@ -56,72 +56,36 @@ static uint8_t qpci_spapr_pio_readb(QPCIBus *bus, uint32_t addr)
     return readb(s->pio_cpu_base + addr);
 }
 
-static uint8_t qpci_spapr_mmio32_readb(QPCIBus *bus, uint32_t addr)
-{
-    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    return readb(s->mmio32_cpu_base + addr);
-}
-
 static void qpci_spapr_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
     writeb(s->pio_cpu_base + addr, val);
 }
 
-static void qpci_spapr_mmio32_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
-{
-    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    writeb(s->mmio32_cpu_base + addr, val);
-}
-
 static uint16_t qpci_spapr_pio_readw(QPCIBus *bus, uint32_t addr)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
     return bswap16(readw(s->pio_cpu_base + addr));
 }
 
-static uint16_t qpci_spapr_mmio32_readw(QPCIBus *bus, uint32_t addr)
-{
-    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    return bswap16(readw(s->mmio32_cpu_base + addr));
-}
-
 static void qpci_spapr_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
     writew(s->pio_cpu_base + addr, bswap16(val));
 }
 
-static void qpci_spapr_mmio32_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
-{
-    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    writew(s->mmio32_cpu_base + addr, bswap16(val));
-}
-
 static uint32_t qpci_spapr_pio_readl(QPCIBus *bus, uint32_t addr)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
     return bswap32(readl(s->pio_cpu_base + addr));
 }
 
-static uint32_t qpci_spapr_mmio32_readl(QPCIBus *bus, uint32_t addr)
-{
-    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    return bswap32(readl(s->mmio32_cpu_base + addr));
-}
-
 static void qpci_spapr_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
 {
     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
     writel(s->pio_cpu_base + addr, bswap32(val));
 }
 
-static void qpci_spapr_mmio32_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
-{
-    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
-    writel(s->mmio32_cpu_base + addr, bswap32(val));
-}
-
 static void qpci_spapr_memread(QPCIBus *bus, uint32_t addr,
                                void *buf, size_t len)
 {
@@ -202,14 +166,6 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
     ret->bus.pio_writew = qpci_spapr_pio_writew;
     ret->bus.pio_writel = qpci_spapr_pio_writel;
 
-    ret->bus.mmio_readb = qpci_spapr_mmio32_readb;
-    ret->bus.mmio_readw = qpci_spapr_mmio32_readw;
-    ret->bus.mmio_readl = qpci_spapr_mmio32_readl;
-
-    ret->bus.mmio_writeb = qpci_spapr_mmio32_writeb;
-    ret->bus.mmio_writew = qpci_spapr_mmio32_writew;
-    ret->bus.mmio_writel = qpci_spapr_mmio32_writel;
-
     ret->bus.memread = qpci_spapr_memread;
     ret->bus.memwrite = qpci_spapr_memwrite;
 
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
index 1e242f9..bbacbcf 100644
--- a/tests/libqos/pci.c
+++ b/tests/libqos/pci.c
@@ -230,7 +230,9 @@ uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
     if (addr < QPCI_PIO_LIMIT) {
         return dev->bus->pio_readb(dev->bus, addr);
     } else {
-        return dev->bus->mmio_readb(dev->bus, addr);
+        uint8_t val;
+        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
+        return val;
     }
 }
 
@@ -241,7 +243,9 @@ uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
     if (addr < QPCI_PIO_LIMIT) {
         return dev->bus->pio_readw(dev->bus, addr);
     } else {
-        return dev->bus->mmio_readw(dev->bus, addr);
+        uint16_t val;
+        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
+        return le16_to_cpu(val);
     }
 }
 
@@ -252,7 +256,9 @@ uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
     if (addr < QPCI_PIO_LIMIT) {
         return dev->bus->pio_readl(dev->bus, addr);
     } else {
-        return dev->bus->mmio_readl(dev->bus, addr);
+        uint32_t val;
+        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
+        return le32_to_cpu(val);
     }
 }
 
@@ -263,7 +269,7 @@ void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
     if (addr < QPCI_PIO_LIMIT) {
         dev->bus->pio_writeb(dev->bus, addr, value);
     } else {
-        dev->bus->mmio_writeb(dev->bus, addr, value);
+        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
     }
 }
 
@@ -274,7 +280,8 @@ void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
     if (addr < QPCI_PIO_LIMIT) {
         dev->bus->pio_writew(dev->bus, addr, value);
     } else {
-        dev->bus->mmio_writew(dev->bus, addr, value);
+        value = cpu_to_le16(value);
+        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
     }
 }
 
@@ -285,7 +292,8 @@ void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
     if (addr < QPCI_PIO_LIMIT) {
         dev->bus->pio_writel(dev->bus, addr, value);
     } else {
-        dev->bus->mmio_writel(dev->bus, addr, value);
+        value = cpu_to_le32(value);
+        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
     }
 }
 
diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
index 2fa5b4f..59fa3da 100644
--- a/tests/libqos/pci.h
+++ b/tests/libqos/pci.h
@@ -27,18 +27,10 @@ struct QPCIBus {
     uint16_t (*pio_readw)(QPCIBus *bus, uint32_t addr);
     uint32_t (*pio_readl)(QPCIBus *bus, uint32_t addr);
 
-    uint8_t (*mmio_readb)(QPCIBus *bus, uint32_t addr);
-    uint16_t (*mmio_readw)(QPCIBus *bus, uint32_t addr);
-    uint32_t (*mmio_readl)(QPCIBus *bus, uint32_t addr);
-
     void (*pio_writeb)(QPCIBus *bus, uint32_t addr, uint8_t value);
     void (*pio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
     void (*pio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
 
-    void (*mmio_writeb)(QPCIBus *bus, uint32_t addr, uint8_t value);
-    void (*mmio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
-    void (*mmio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
-
     void (*memread)(QPCIBus *bus, uint32_t addr, void *buf, size_t len);
     void (*memwrite)(QPCIBus *bus, uint32_t addr, const void *buf, size_t len);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 7/8] tests: Use qpci_mem{read, write} in ivshmem-test
  2016-10-18 10:52 [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling David Gibson
                   ` (5 preceding siblings ...)
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 6/8] libqos: Implement mmio accessors in terms of mem{read, write} David Gibson
@ 2016-10-18 10:52 ` David Gibson
  2016-10-18 16:14   ` Laurent Vivier
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 8/8] libqos: Change PCI accessors to take opaque BAR handle David Gibson
  2016-10-18 11:56 ` [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling Laurent Vivier
  8 siblings, 1 reply; 28+ messages in thread
From: David Gibson @ 2016-10-18 10:52 UTC (permalink / raw)
  To: pbonzini, qemu-devel
  Cc: qemu-ppc, lvivier, agraf, stefanha, mst, aik, mdroth, groug,
	thuth, David Gibson

ivshmem implements a block of shared memory in a PCI BAR.  Currently our
test case accesses this using qtest_mem{read,write}.  However, deducing
the correct addresses for these requires making assumptions about the
internel format returned by qpci_iomap(), along with some ugly casts.

This patch changes the test to use the new qpci_mem{read,write} interfaces
which is neater.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/ivshmem-test.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c
index f36bfe7..97a887e 100644
--- a/tests/ivshmem-test.c
+++ b/tests/ivshmem-test.c
@@ -169,7 +169,7 @@ static void test_ivshmem_single(void)
     for (i = 0; i < G_N_ELEMENTS(data); i++) {
         data[i] = i;
     }
-    qtest_memwrite(s->qtest, (uintptr_t)s->mem_base, data, sizeof(data));
+    qpci_memwrite(s->dev, s->mem_base, data, sizeof(data));
 
     /* verify write */
     for (i = 0; i < G_N_ELEMENTS(data); i++) {
@@ -178,7 +178,7 @@ static void test_ivshmem_single(void)
 
     /* read it back and verify read */
     memset(data, 0, sizeof(data));
-    qtest_memread(s->qtest, (uintptr_t)s->mem_base, data, sizeof(data));
+    qpci_memread(s->dev, s->mem_base, data, sizeof(data));
     for (i = 0; i < G_N_ELEMENTS(data); i++) {
         g_assert_cmpuint(data[i], ==, i);
     }
@@ -201,29 +201,29 @@ static void test_ivshmem_pair(void)
 
     /* host write, guest 1 & 2 read */
     memset(tmpshmem, 0x42, TMPSHMSIZE);
-    qtest_memread(s1->qtest, (uintptr_t)s1->mem_base, data, TMPSHMSIZE);
+    qpci_memread(s1->dev, s1->mem_base, data, TMPSHMSIZE);
     for (i = 0; i < TMPSHMSIZE; i++) {
         g_assert_cmpuint(data[i], ==, 0x42);
     }
-    qtest_memread(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
+    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
     for (i = 0; i < TMPSHMSIZE; i++) {
         g_assert_cmpuint(data[i], ==, 0x42);
     }
 
     /* guest 1 write, guest 2 read */
     memset(data, 0x43, TMPSHMSIZE);
-    qtest_memwrite(s1->qtest, (uintptr_t)s1->mem_base, data, TMPSHMSIZE);
+    qpci_memwrite(s1->dev, s1->mem_base, data, TMPSHMSIZE);
     memset(data, 0, TMPSHMSIZE);
-    qtest_memread(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
+    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
     for (i = 0; i < TMPSHMSIZE; i++) {
         g_assert_cmpuint(data[i], ==, 0x43);
     }
 
     /* guest 2 write, guest 1 read */
     memset(data, 0x44, TMPSHMSIZE);
-    qtest_memwrite(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
+    qpci_memwrite(s2->dev, s2->mem_base, data, TMPSHMSIZE);
     memset(data, 0, TMPSHMSIZE);
-    qtest_memread(s1->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
+    qpci_memread(s1->dev, s2->mem_base, data, TMPSHMSIZE);
     for (i = 0; i < TMPSHMSIZE; i++) {
         g_assert_cmpuint(data[i], ==, 0x44);
     }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 8/8] libqos: Change PCI accessors to take opaque BAR handle
  2016-10-18 10:52 [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling David Gibson
                   ` (6 preceding siblings ...)
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 7/8] tests: Use qpci_mem{read, write} in ivshmem-test David Gibson
@ 2016-10-18 10:52 ` David Gibson
  2016-10-18 16:48   ` Laurent Vivier
  2016-10-18 11:56 ` [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling Laurent Vivier
  8 siblings, 1 reply; 28+ messages in thread
From: David Gibson @ 2016-10-18 10:52 UTC (permalink / raw)
  To: pbonzini, qemu-devel
  Cc: qemu-ppc, lvivier, agraf, stefanha, mst, aik, mdroth, groug,
	thuth, David Gibson

The usual use model for the libqos PCI functions is to map a specific PCI
BAR using qpci_iomap() then pass the returned token into IO accessor
functions.  This, and the fact that iomap() returns a (void *) which
actually contains a PCI space address, kind of suggests that the return
value from iomap is supposed to be an opaque token.

..except that the callers expect to be able to add offsets to it.  Which
also assumes the compiler will support pointer arithmetic on a (void *),
and treat it as working with byte offsets.

To clarify this situation change iomap() and the IO accessors to take
a definitely opaque BAR handle (enforced with a wrapper struct) along with
an offset within the BAR.  This changes both the functions and all the
callers.

A few notes:
    * Asserts that iomap() returns non-NULL are removed in some places;
iomap() already asserts if it can't map the BAR
    * In ide-test.c we change explicit outb() etc. calls to matching
qpci_io_writeb() calls.  That makes the test more portable, and removes
assumptions that the test case shouldn't be making about how iomap()'s
return value is formatted internally.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

# Conflicts:
#	tests/libqos/virtio-pci.c
---
 tests/ahci-test.c         |   4 +-
 tests/e1000e-test.c       |   7 ++-
 tests/ide-test.c          |  23 +++++----
 tests/ivshmem-test.c      |  28 +++++------
 tests/libqos/ahci.c       |   3 +-
 tests/libqos/ahci.h       |   6 +--
 tests/libqos/pci.c        | 125 +++++++++++++++++++++-------------------------
 tests/libqos/pci.h        |  39 +++++++++------
 tests/libqos/usb.c        |   6 +--
 tests/libqos/usb.h        |   2 +-
 tests/libqos/virtio-pci.c | 113 +++++++++++++++++++++--------------------
 tests/libqos/virtio-pci.h |   2 +-
 tests/rtl8139-test.c      |  10 ++--
 tests/usb-hcd-ehci-test.c |   5 +-
 14 files changed, 186 insertions(+), 187 deletions(-)

diff --git a/tests/ahci-test.c b/tests/ahci-test.c
index 9c0adce..4358631 100644
--- a/tests/ahci-test.c
+++ b/tests/ahci-test.c
@@ -90,12 +90,12 @@ static void verify_state(AHCIQState *ahci)
     g_assert_cmphex(ahci_fingerprint, ==, ahci->fingerprint);
 
     /* If we haven't initialized, this is as much as can be validated. */
-    if (!ahci->hba_base) {
+    if (!ahci->hba_bar.addr) {
         return;
     }
 
     hba_base = (uint64_t)qpci_config_readl(ahci->dev, PCI_BASE_ADDRESS_5);
-    hba_stored = (uint64_t)(uintptr_t)ahci->hba_base;
+    hba_stored = ahci->hba_bar.addr;
     g_assert_cmphex(hba_base, ==, hba_stored);
 
     g_assert_cmphex(ahci_rreg(ahci, AHCI_CAP), ==, ahci->cap);
diff --git a/tests/e1000e-test.c b/tests/e1000e-test.c
index 3979b20..8c42ca9 100644
--- a/tests/e1000e-test.c
+++ b/tests/e1000e-test.c
@@ -87,7 +87,7 @@
 
 typedef struct e1000e_device {
     QPCIDevice *pci_dev;
-    void *mac_regs;
+    QPCIBar mac_regs;
 
     uint64_t tx_ring;
     uint64_t rx_ring;
@@ -119,12 +119,12 @@ static QPCIDevice *e1000e_device_find(QPCIBus *bus)
 
 static void e1000e_macreg_write(e1000e_device *d, uint32_t reg, uint32_t val)
 {
-    qpci_io_writel(d->pci_dev, d->mac_regs + reg, val);
+    qpci_io_writel(d->pci_dev, d->mac_regs, reg, val);
 }
 
 static uint32_t e1000e_macreg_read(e1000e_device *d, uint32_t reg)
 {
-    return qpci_io_readl(d->pci_dev, d->mac_regs + reg);
+    return qpci_io_readl(d->pci_dev, d->mac_regs, reg);
 }
 
 static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
@@ -138,7 +138,6 @@ static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
 
     /* Map BAR0 (mac registers) */
     d->mac_regs = qpci_iomap(d->pci_dev, 0, NULL);
-    g_assert_nonnull(d->mac_regs);
 
     /* Reset the device */
     val = e1000e_macreg_read(d, E1000E_CTRL);
diff --git a/tests/ide-test.c b/tests/ide-test.c
index a8a4081..dc08536 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -137,7 +137,7 @@ static void ide_test_quit(void)
     qtest_end();
 }
 
-static QPCIDevice *get_pci_device(uint16_t *bmdma_base)
+static QPCIDevice *get_pci_device(QPCIBar *bmdma_bar)
 {
     QPCIDevice *dev;
     uint16_t vendor_id, device_id;
@@ -156,7 +156,7 @@ static QPCIDevice *get_pci_device(uint16_t *bmdma_base)
     g_assert(device_id == PCI_DEVICE_ID_INTEL_82371SB_1);
 
     /* Map bmdma BAR */
-    *bmdma_base = (uint16_t)(uintptr_t) qpci_iomap(dev, 4, NULL);
+    *bmdma_bar = qpci_iomap(dev, 4, NULL);
 
     qpci_device_enable(dev);
 
@@ -182,14 +182,14 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
                             void(*post_exec)(uint64_t sector, int nb_sectors))
 {
     QPCIDevice *dev;
-    uint16_t bmdma_base;
+    QPCIBar bmdma_bar;
     uintptr_t guest_prdt;
     size_t len;
     bool from_dev;
     uint8_t status;
     int flags;
 
-    dev = get_pci_device(&bmdma_base);
+    dev = get_pci_device(&bmdma_bar);
 
     flags = cmd & ~0xff;
     cmd &= 0xff;
@@ -217,14 +217,14 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
     outb(IDE_BASE + reg_device, 0 | LBA);
 
     /* Stop any running transfer, clear any pending interrupt */
-    outb(bmdma_base + bmreg_cmd, 0);
-    outb(bmdma_base + bmreg_status, BM_STS_INTR);
+    qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
+    qpci_io_writeb(dev, bmdma_bar, bmreg_status, BM_STS_INTR);
 
     /* Setup PRDT */
     len = sizeof(*prdt) * prdt_entries;
     guest_prdt = guest_alloc(guest_malloc, len);
     memwrite(guest_prdt, prdt, len);
-    outl(bmdma_base + bmreg_prdt, guest_prdt);
+    qpci_io_writel(dev, bmdma_bar, bmreg_prdt, guest_prdt);
 
     /* ATA DMA command */
     if (cmd == CMD_PACKET) {
@@ -244,15 +244,16 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
     }
 
     /* Start DMA transfer */
-    outb(bmdma_base + bmreg_cmd, BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));
+    qpci_io_writeb(dev, bmdma_bar, bmreg_cmd,
+                   BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));
 
     if (flags & CMDF_ABORT) {
-        outb(bmdma_base + bmreg_cmd, 0);
+        qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
     }
 
     /* Wait for the DMA transfer to complete */
     do {
-        status = inb(bmdma_base + bmreg_status);
+        status = qpci_io_readb(dev, bmdma_bar, bmreg_status);
     } while ((status & (BM_STS_ACTIVE | BM_STS_INTR)) == BM_STS_ACTIVE);
 
     g_assert_cmpint(get_irq(IDE_PRIMARY_IRQ), ==, !!(status & BM_STS_INTR));
@@ -266,7 +267,7 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
 
     /* Stop DMA transfer if still active */
     if (status & BM_STS_ACTIVE) {
-        outb(bmdma_base + bmreg_cmd, 0);
+        qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
     }
 
     free_pci_device(dev);
diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c
index 97a887e..f7c5bf4 100644
--- a/tests/ivshmem-test.c
+++ b/tests/ivshmem-test.c
@@ -41,7 +41,7 @@ static QPCIDevice *get_device(QPCIBus *pcibus)
 
 typedef struct _IVState {
     QTestState *qtest;
-    void *reg_base, *mem_base;
+    QPCIBar reg_bar, mem_bar;
     QPCIBus *pcibus;
     QPCIDevice *dev;
 } IVState;
@@ -75,7 +75,7 @@ static inline unsigned in_reg(IVState *s, enum Reg reg)
     unsigned res;
 
     global_qtest = s->qtest;
-    res = qpci_io_readl(s->dev, s->reg_base + reg);
+    res = qpci_io_readl(s->dev, s->reg_bar, reg);
     g_test_message("*%s -> %x\n", name, res);
     global_qtest = qtest;
 
@@ -89,7 +89,7 @@ static inline void out_reg(IVState *s, enum Reg reg, unsigned v)
 
     global_qtest = s->qtest;
     g_test_message("%x -> *%s\n", v, name);
-    qpci_io_writel(s->dev, s->reg_base + reg, v);
+    qpci_io_writel(s->dev, s->reg_bar, reg, v);
     global_qtest = qtest;
 }
 
@@ -108,16 +108,14 @@ static void setup_vm_cmd(IVState *s, const char *cmd, bool msix)
     s->pcibus = qpci_init_pc(NULL);
     s->dev = get_device(s->pcibus);
 
-    s->reg_base = qpci_iomap(s->dev, 0, &barsize);
-    g_assert_nonnull(s->reg_base);
+    s->reg_bar = qpci_iomap(s->dev, 0, &barsize);
     g_assert_cmpuint(barsize, ==, 256);
 
     if (msix) {
         qpci_msix_enable(s->dev);
     }
 
-    s->mem_base = qpci_iomap(s->dev, 2, &barsize);
-    g_assert_nonnull(s->mem_base);
+    s->mem_bar = qpci_iomap(s->dev, 2, &barsize);
     g_assert_cmpuint(barsize, ==, TMPSHMSIZE);
 
     qpci_device_enable(s->dev);
@@ -169,7 +167,7 @@ static void test_ivshmem_single(void)
     for (i = 0; i < G_N_ELEMENTS(data); i++) {
         data[i] = i;
     }
-    qpci_memwrite(s->dev, s->mem_base, data, sizeof(data));
+    qpci_memwrite(s->dev, s->mem_bar, 0, data, sizeof(data));
 
     /* verify write */
     for (i = 0; i < G_N_ELEMENTS(data); i++) {
@@ -178,7 +176,7 @@ static void test_ivshmem_single(void)
 
     /* read it back and verify read */
     memset(data, 0, sizeof(data));
-    qpci_memread(s->dev, s->mem_base, data, sizeof(data));
+    qpci_memread(s->dev, s->mem_bar, 0, data, sizeof(data));
     for (i = 0; i < G_N_ELEMENTS(data); i++) {
         g_assert_cmpuint(data[i], ==, i);
     }
@@ -201,29 +199,29 @@ static void test_ivshmem_pair(void)
 
     /* host write, guest 1 & 2 read */
     memset(tmpshmem, 0x42, TMPSHMSIZE);
-    qpci_memread(s1->dev, s1->mem_base, data, TMPSHMSIZE);
+    qpci_memread(s1->dev, s1->mem_bar, 0, data, TMPSHMSIZE);
     for (i = 0; i < TMPSHMSIZE; i++) {
         g_assert_cmpuint(data[i], ==, 0x42);
     }
-    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
+    qpci_memread(s2->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
     for (i = 0; i < TMPSHMSIZE; i++) {
         g_assert_cmpuint(data[i], ==, 0x42);
     }
 
     /* guest 1 write, guest 2 read */
     memset(data, 0x43, TMPSHMSIZE);
-    qpci_memwrite(s1->dev, s1->mem_base, data, TMPSHMSIZE);
+    qpci_memwrite(s1->dev, s1->mem_bar, 0, data, TMPSHMSIZE);
     memset(data, 0, TMPSHMSIZE);
-    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
+    qpci_memread(s2->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
     for (i = 0; i < TMPSHMSIZE; i++) {
         g_assert_cmpuint(data[i], ==, 0x43);
     }
 
     /* guest 2 write, guest 1 read */
     memset(data, 0x44, TMPSHMSIZE);
-    qpci_memwrite(s2->dev, s2->mem_base, data, TMPSHMSIZE);
+    qpci_memwrite(s2->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
     memset(data, 0, TMPSHMSIZE);
-    qpci_memread(s1->dev, s2->mem_base, data, TMPSHMSIZE);
+    qpci_memread(s1->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
     for (i = 0; i < TMPSHMSIZE; i++) {
         g_assert_cmpuint(data[i], ==, 0x44);
     }
diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c
index 716ab79..43b6695 100644
--- a/tests/libqos/ahci.c
+++ b/tests/libqos/ahci.c
@@ -210,8 +210,7 @@ void ahci_pci_enable(AHCIQState *ahci)
 void start_ahci_device(AHCIQState *ahci)
 {
     /* Map AHCI's ABAR (BAR5) */
-    ahci->hba_base = qpci_iomap(ahci->dev, 5, &ahci->barsize);
-    g_assert(ahci->hba_base);
+    ahci->hba_bar = qpci_iomap(ahci->dev, 5, &ahci->barsize);
 
     /* turns on pci.cmd.iose, pci.cmd.mse and pci.cmd.bme */
     qpci_device_enable(ahci->dev);
diff --git a/tests/libqos/ahci.h b/tests/libqos/ahci.h
index c69fb5a..6c4abf6 100644
--- a/tests/libqos/ahci.h
+++ b/tests/libqos/ahci.h
@@ -321,7 +321,7 @@ typedef struct AHCIPortQState {
 typedef struct AHCIQState {
     QOSState *parent;
     QPCIDevice *dev;
-    void *hba_base;
+    QPCIBar hba_bar;
     uint64_t barsize;
     uint32_t fingerprint;
     uint32_t cap;
@@ -488,12 +488,12 @@ typedef struct AHCIOpts {
 
 static inline uint32_t ahci_mread(AHCIQState *ahci, size_t offset)
 {
-    return qpci_io_readl(ahci->dev, ahci->hba_base + offset);
+    return qpci_io_readl(ahci->dev, ahci->hba_bar, offset);
 }
 
 static inline void ahci_mwrite(AHCIQState *ahci, size_t offset, uint32_t value)
 {
-    qpci_io_writel(ahci->dev, ahci->hba_base + offset, value);
+    qpci_io_writel(ahci->dev, ahci->hba_bar, offset, value);
 }
 
 static inline uint32_t ahci_rreg(AHCIQState *ahci, uint32_t reg_num)
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
index bbacbcf..875c517 100644
--- a/tests/libqos/pci.c
+++ b/tests/libqos/pci.c
@@ -104,7 +104,6 @@ void qpci_msix_enable(QPCIDevice *dev)
     uint32_t table;
     uint8_t bir_table;
     uint8_t bir_pba;
-    void *offset;
 
     addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
     g_assert_cmphex(addr, !=, 0);
@@ -114,18 +113,16 @@ void qpci_msix_enable(QPCIDevice *dev)
 
     table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE);
     bir_table = table & PCI_MSIX_FLAGS_BIRMASK;
-    offset = qpci_iomap(dev, bir_table, NULL);
-    dev->msix_table = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK);
+    dev->msix_table_bar = qpci_iomap(dev, bir_table, NULL);
+    dev->msix_table_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
 
     table = qpci_config_readl(dev, addr + PCI_MSIX_PBA);
     bir_pba = table & PCI_MSIX_FLAGS_BIRMASK;
     if (bir_pba != bir_table) {
-        offset = qpci_iomap(dev, bir_pba, NULL);
+        dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL);
     }
-    dev->msix_pba = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK);
+    dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
 
-    g_assert(dev->msix_table != NULL);
-    g_assert(dev->msix_pba != NULL);
     dev->msix_enabled = true;
 }
 
@@ -141,22 +138,25 @@ void qpci_msix_disable(QPCIDevice *dev)
     qpci_config_writew(dev, addr + PCI_MSIX_FLAGS,
                                                 val & ~PCI_MSIX_FLAGS_ENABLE);
 
-    qpci_iounmap(dev, dev->msix_table);
-    qpci_iounmap(dev, dev->msix_pba);
+    qpci_iounmap(dev, dev->msix_table_bar);
+    qpci_iounmap(dev, dev->msix_pba_bar);
     dev->msix_enabled = 0;
-    dev->msix_table = NULL;
-    dev->msix_pba = NULL;
+    memset(&dev->msix_table_bar, 0, sizeof(dev->msix_table_bar));
+    memset(&dev->msix_pba_bar, 0, sizeof(dev->msix_pba_bar));
+    dev->msix_table_off = 0;
+    dev->msix_pba_off = 0;
 }
 
 bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry)
 {
     uint32_t pba_entry;
     uint8_t bit_n = entry % 32;
-    void *addr = dev->msix_pba + (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
+    uint64_t  off = (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
 
     g_assert(dev->msix_enabled);
-    pba_entry = qpci_io_readl(dev, addr);
-    qpci_io_writel(dev, addr, pba_entry & ~(1 << bit_n));
+    pba_entry = qpci_io_readl(dev, dev->msix_pba_bar, dev->msix_pba_off + off);
+    qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off,
+                   pba_entry & ~(1 << bit_n));
     return (pba_entry & (1 << bit_n)) != 0;
 }
 
@@ -164,7 +164,7 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
 {
     uint8_t addr;
     uint16_t val;
-    void *vector_addr = dev->msix_table + (entry * PCI_MSIX_ENTRY_SIZE);
+    uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE;
 
     g_assert(dev->msix_enabled);
     addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
@@ -174,8 +174,9 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
     if (val & PCI_MSIX_FLAGS_MASKALL) {
         return true;
     } else {
-        return (qpci_io_readl(dev, vector_addr + PCI_MSIX_ENTRY_VECTOR_CTRL)
-                                            & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
+        return (qpci_io_readl(dev, dev->msix_table_bar,
+                              vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL)
+                & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
     }
 }
 
@@ -222,104 +223,93 @@ void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
     dev->bus->config_writel(dev->bus, dev->devfn, offset, value);
 }
 
-
-uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
+uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off)
 {
-    uintptr_t addr = (uintptr_t)data;
-
-    if (addr < QPCI_PIO_LIMIT) {
-        return dev->bus->pio_readb(dev->bus, addr);
+    if (token.addr < QPCI_PIO_LIMIT) {
+        return dev->bus->pio_readb(dev->bus, token.addr + off);
     } else {
         uint8_t val;
-        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
+        dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
         return val;
     }
 }
 
-uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
+uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
 {
-    uintptr_t addr = (uintptr_t)data;
-
-    if (addr < QPCI_PIO_LIMIT) {
-        return dev->bus->pio_readw(dev->bus, addr);
+    if (token.addr < QPCI_PIO_LIMIT) {
+        return dev->bus->pio_readw(dev->bus, token.addr + off);
     } else {
         uint16_t val;
-        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
+        dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
         return le16_to_cpu(val);
     }
 }
 
-uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
+uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
 {
-    uintptr_t addr = (uintptr_t)data;
-
-    if (addr < QPCI_PIO_LIMIT) {
-        return dev->bus->pio_readl(dev->bus, addr);
+    if (token.addr < QPCI_PIO_LIMIT) {
+        return dev->bus->pio_readl(dev->bus, token.addr + off);
     } else {
         uint32_t val;
-        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
+        dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
         return le32_to_cpu(val);
     }
 }
 
-void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
+void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
+                    uint8_t value)
 {
-    uintptr_t addr = (uintptr_t)data;
-
-    if (addr < QPCI_PIO_LIMIT) {
-        dev->bus->pio_writeb(dev->bus, addr, value);
+    if (token.addr < QPCI_PIO_LIMIT) {
+        dev->bus->pio_writeb(dev->bus, token.addr + off, value);
     } else {
-        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
+        dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
     }
 }
 
-void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
+void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
+                    uint16_t value)
 {
-    uintptr_t addr = (uintptr_t)data;
-
-    if (addr < QPCI_PIO_LIMIT) {
-        dev->bus->pio_writew(dev->bus, addr, value);
+    if (token.addr < QPCI_PIO_LIMIT) {
+        dev->bus->pio_writew(dev->bus, token.addr + off, value);
     } else {
         value = cpu_to_le16(value);
-        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
+        dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
     }
 }
 
-void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
+void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
+                    uint32_t value)
 {
-    uintptr_t addr = (uintptr_t)data;
-
-    if (addr < QPCI_PIO_LIMIT) {
-        dev->bus->pio_writel(dev->bus, addr, value);
+    if (token.addr < QPCI_PIO_LIMIT) {
+        dev->bus->pio_writel(dev->bus, token.addr + off, value);
     } else {
         value = cpu_to_le32(value);
-        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
+        dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
     }
 }
 
-void qpci_memread(QPCIDevice *dev, void *data, void *buf, size_t len)
+void qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off,
+                  void *buf, size_t len)
 {
-    uintptr_t addr = (uintptr_t)data;
-
-    g_assert(addr >= QPCI_PIO_LIMIT);
-    dev->bus->memread(dev->bus, addr, buf, len);
+    g_assert(token.addr >= QPCI_PIO_LIMIT);
+    dev->bus->memread(dev->bus, token.addr + off, buf, len);
 }
 
-void qpci_memwrite(QPCIDevice *dev, void *data, const void *buf, size_t len)
+void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
+                   const void *buf, size_t len)
 {
-    uintptr_t addr = (uintptr_t)data;
-
-    g_assert(addr >= QPCI_PIO_LIMIT);
-    dev->bus->memwrite(dev->bus, addr, buf, len);
+    g_assert(token.addr >= QPCI_PIO_LIMIT);
+    dev->bus->memwrite(dev->bus, token.addr + off, buf, len);
 }
 
-void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
+QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
 {
     QPCIBus *bus = dev->bus;
     static const int bar_reg_map[] = {
         PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
         PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
     };
+    QPCIBar bar;
     int bar_reg;
     uint32_t addr, size;
     uint32_t io_type;
@@ -366,10 +356,11 @@ void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
         qpci_config_writel(dev, bar_reg, loc);
     }
 
-    return (void *)(uintptr_t)loc;
+    bar.addr = loc;
+    return bar;
 }
 
-void qpci_iounmap(QPCIDevice *dev, void *data)
+void qpci_iounmap(QPCIDevice *dev, QPCIBar bar)
 {
     /* FIXME */
 }
diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
index 59fa3da..40b277c 100644
--- a/tests/libqos/pci.h
+++ b/tests/libqos/pci.h
@@ -21,6 +21,7 @@
 
 typedef struct QPCIDevice QPCIDevice;
 typedef struct QPCIBus QPCIBus;
+typedef struct QPCIBar QPCIBar;
 
 struct QPCIBus {
     uint8_t (*pio_readb)(QPCIBus *bus, uint32_t addr);
@@ -49,13 +50,17 @@ struct QPCIBus {
     uint64_t mmio_alloc_ptr, mmio_limit;
 };
 
+struct QPCIBar {
+    uint64_t addr;
+};
+
 struct QPCIDevice
 {
     QPCIBus *bus;
     int devfn;
     bool msix_enabled;
-    void *msix_table;
-    void *msix_pba;
+    QPCIBar msix_table_bar, msix_pba_bar;
+    uint64_t msix_table_off, msix_pba_off;
 };
 
 void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
@@ -79,19 +84,23 @@ void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value);
 void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value);
 void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value);
 
-uint8_t qpci_io_readb(QPCIDevice *dev, void *data);
-uint16_t qpci_io_readw(QPCIDevice *dev, void *data);
-uint32_t qpci_io_readl(QPCIDevice *dev, void *data);
-
-void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value);
-void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value);
-void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value);
-
-void qpci_memread(QPCIDevice *bus, void *data, void *buf, size_t len);
-void qpci_memwrite(QPCIDevice *bus, void *data, const void *buf, size_t len);
-
-void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
-void qpci_iounmap(QPCIDevice *dev, void *data);
+uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off);
+uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off);
+uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off);
+
+void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
+                    uint8_t value);
+void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
+                    uint16_t value);
+void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
+                    uint32_t value);
+
+void qpci_memread(QPCIDevice *bus, QPCIBar token, uint64_t off,
+                  void *buf, size_t len);
+void qpci_memwrite(QPCIDevice *bus, QPCIBar token, uint64_t off,
+                   const void *buf, size_t len);
+QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
+void qpci_iounmap(QPCIDevice *dev, QPCIBar addr);
 
 void qpci_plug_device_test(const char *driver, const char *id,
                            uint8_t slot, const char *opts);
diff --git a/tests/libqos/usb.c b/tests/libqos/usb.c
index f794d92..72d7a96 100644
--- a/tests/libqos/usb.c
+++ b/tests/libqos/usb.c
@@ -21,14 +21,12 @@ void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc, uint32_t devfn, int bar)
     hc->dev = qpci_device_find(pcibus, devfn);
     g_assert(hc->dev != NULL);
     qpci_device_enable(hc->dev);
-    hc->base = qpci_iomap(hc->dev, bar, NULL);
-    g_assert(hc->base != NULL);
+    hc->bar = qpci_iomap(hc->dev, bar, NULL);
 }
 
 void uhci_port_test(struct qhc *hc, int port, uint16_t expect)
 {
-    void *addr = hc->base + 0x10 + 2 * port;
-    uint16_t value = qpci_io_readw(hc->dev, addr);
+    uint16_t value = qpci_io_readw(hc->dev, hc->bar, 0x10 + 2 * port);
     uint16_t mask = ~(UHCI_PORT_WRITE_CLEAR | UHCI_PORT_RSVD1);
 
     g_assert((value & mask) == (expect & mask));
diff --git a/tests/libqos/usb.h b/tests/libqos/usb.h
index 8fe5687..423dcfd 100644
--- a/tests/libqos/usb.h
+++ b/tests/libqos/usb.h
@@ -5,7 +5,7 @@
 
 struct qhc {
     QPCIDevice *dev;
-    void *base;
+    QPCIBar bar;
 };
 
 void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc,
diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
index 8037724..5b78d30 100644
--- a/tests/libqos/virtio-pci.c
+++ b/tests/libqos/virtio-pci.c
@@ -65,22 +65,22 @@ static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data)
 static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t off)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
-    return qpci_io_readb(dev->pdev, base + off);
+    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
+    return qpci_io_readb(dev->pdev, dev->bar, base + off);
 }
 
 static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t off)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
-    return qpci_io_readw(dev->pdev, base + off);
+    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
+    return qpci_io_readw(dev->pdev, dev->bar, base + off);
 }
 
 static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t off)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
-    return qpci_io_readl(dev->pdev, base + off);
+    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
+    return qpci_io_readl(dev->pdev, dev->bar, base + off);
 }
 
 static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
@@ -88,17 +88,17 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
     int i;
     uint64_t u64 = 0;
-    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
+    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled) + off;
 
     if (target_big_endian()) {
         for (i = 0; i < 8; ++i) {
-            u64 |= (uint64_t)qpci_io_readb(dev->pdev,
-                                           base + off + i) << (7 - i) * 8;
+            u64 |= (uint64_t)qpci_io_readb(dev->pdev, dev->bar,
+                                           base + i) << (7 - i) * 8;
         }
     } else {
         for (i = 0; i < 8; ++i) {
-            u64 |= (uint64_t)qpci_io_readb(dev->pdev,
-                                           base + off + i) << i * 8;
+            u64 |= (uint64_t)qpci_io_readb(dev->pdev, dev->bar,
+                                           base + i) << i * 8;
         }
     }
 
@@ -108,31 +108,31 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
 static uint32_t qvirtio_pci_get_features(QVirtioDevice *d)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    return qpci_io_readl(dev->pdev, dev->addr + VIRTIO_PCI_HOST_FEATURES);
+    return qpci_io_readl(dev->pdev, dev->bar, VIRTIO_PCI_HOST_FEATURES);
 }
 
 static void qvirtio_pci_set_features(QVirtioDevice *d, uint32_t features)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    qpci_io_writel(dev->pdev, dev->addr + VIRTIO_PCI_GUEST_FEATURES, features);
+    qpci_io_writel(dev->pdev, dev->bar, VIRTIO_PCI_GUEST_FEATURES, features);
 }
 
 static uint32_t qvirtio_pci_get_guest_features(QVirtioDevice *d)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    return qpci_io_readl(dev->pdev, dev->addr + VIRTIO_PCI_GUEST_FEATURES);
+    return qpci_io_readl(dev->pdev, dev->bar, VIRTIO_PCI_GUEST_FEATURES);
 }
 
 static uint8_t qvirtio_pci_get_status(QVirtioDevice *d)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    return qpci_io_readb(dev->pdev, dev->addr + VIRTIO_PCI_STATUS);
+    return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_STATUS);
 }
 
 static void qvirtio_pci_set_status(QVirtioDevice *d, uint8_t status)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    qpci_io_writeb(dev->pdev, dev->addr + VIRTIO_PCI_STATUS, status);
+    qpci_io_writeb(dev->pdev, dev->bar, VIRTIO_PCI_STATUS, status);
 }
 
 static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
@@ -156,7 +156,7 @@ static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
             }
         }
     } else {
-        return qpci_io_readb(dev->pdev, dev->addr + VIRTIO_PCI_ISR) & 1;
+        return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_ISR) & 1;
     }
 }
 
@@ -180,26 +180,26 @@ static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d)
             }
         }
     } else {
-        return qpci_io_readb(dev->pdev, dev->addr + VIRTIO_PCI_ISR) & 2;
+        return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_ISR) & 2;
     }
 }
 
 static void qvirtio_pci_queue_select(QVirtioDevice *d, uint16_t index)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    qpci_io_writeb(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_SEL, index);
+    qpci_io_writeb(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_SEL, index);
 }
 
 static uint16_t qvirtio_pci_get_queue_size(QVirtioDevice *d)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    return qpci_io_readw(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_NUM);
+    return qpci_io_readw(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_NUM);
 }
 
 static void qvirtio_pci_set_queue_address(QVirtioDevice *d, uint32_t pfn)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    qpci_io_writel(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_PFN, pfn);
+    qpci_io_writel(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_PFN, pfn);
 }
 
 static QVirtQueue *qvirtio_pci_virtqueue_setup(QVirtioDevice *d,
@@ -251,7 +251,7 @@ static void qvirtio_pci_virtqueue_cleanup(QVirtQueue *vq,
 static void qvirtio_pci_virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq)
 {
     QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
-    qpci_io_writew(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_NOTIFY, vq->index);
+    qpci_io_writew(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_NOTIFY, vq->index);
 }
 
 const QVirtioBus qvirtio_pci = {
@@ -296,14 +296,13 @@ QVirtioPCIDevice *qvirtio_pci_device_find(QPCIBus *bus, uint16_t device_type)
 void qvirtio_pci_device_enable(QVirtioPCIDevice *d)
 {
     qpci_device_enable(d->pdev);
-    d->addr = qpci_iomap(d->pdev, 0, NULL);
-    g_assert(d->addr != NULL);
+    d->bar = qpci_iomap(d->pdev, 0, NULL);
 }
 
 void qvirtio_pci_device_disable(QVirtioPCIDevice *d)
 {
-    qpci_iounmap(d->pdev, d->addr);
-    d->addr = NULL;
+    qpci_iounmap(d->pdev, d->bar);
+    memset(&d->bar, 0, sizeof(d->bar));
 }
 
 void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
@@ -311,29 +310,33 @@ void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
 {
     uint16_t vector;
     uint32_t control;
-    void *addr;
+    uint64_t off;
 
     g_assert(d->pdev->msix_enabled);
-    addr = d->pdev->msix_table + (entry * 16);
+    off = d->pdev->msix_table_off + (entry * 16);
 
     g_assert_cmpint(entry, >=, 0);
     g_assert_cmpint(entry, <, qpci_msix_table_size(d->pdev));
     vqpci->msix_entry = entry;
 
     vqpci->msix_addr = guest_alloc(alloc, 4);
-    qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_LOWER_ADDR,
-                                                    vqpci->msix_addr & ~0UL);
-    qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_UPPER_ADDR,
-                                            (vqpci->msix_addr >> 32) & ~0UL);
-    qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_DATA, vqpci->msix_data);
-
-    control = qpci_io_readl(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
-    qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL,
-                                        control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
+    qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
+                   off + PCI_MSIX_ENTRY_LOWER_ADDR, vqpci->msix_addr & ~0UL);
+    qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
+                   off + PCI_MSIX_ENTRY_UPPER_ADDR,
+                   (vqpci->msix_addr >> 32) & ~0UL);
+    qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
+                   off + PCI_MSIX_ENTRY_DATA, vqpci->msix_data);
+
+    control = qpci_io_readl(d->pdev, d->pdev->msix_table_bar,
+                            off + PCI_MSIX_ENTRY_VECTOR_CTRL);
+    qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
+                   off + PCI_MSIX_ENTRY_VECTOR_CTRL,
+                   control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
 
     qvirtio_pci_queue_select(&d->vdev, vqpci->vq.index);
-    qpci_io_writew(d->pdev, d->addr + VIRTIO_MSI_QUEUE_VECTOR, entry);
-    vector = qpci_io_readw(d->pdev, d->addr + VIRTIO_MSI_QUEUE_VECTOR);
+    qpci_io_writew(d->pdev, d->bar, VIRTIO_MSI_QUEUE_VECTOR, entry);
+    vector = qpci_io_readw(d->pdev, d->bar, VIRTIO_MSI_QUEUE_VECTOR);
     g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR);
 }
 
@@ -342,10 +345,10 @@ void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
 {
     uint16_t vector;
     uint32_t control;
-    void *addr;
+    uint64_t off;
 
     g_assert(d->pdev->msix_enabled);
-    addr = d->pdev->msix_table + (entry * 16);
+    off = d->pdev->msix_table_off + (entry * 16);
 
     g_assert_cmpint(entry, >=, 0);
     g_assert_cmpint(entry, <, qpci_msix_table_size(d->pdev));
@@ -354,17 +357,21 @@ void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
     d->config_msix_data = 0x12345678;
     d->config_msix_addr = guest_alloc(alloc, 4);
 
-    qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_LOWER_ADDR,
-                                                    d->config_msix_addr & ~0UL);
-    qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_UPPER_ADDR,
-                                            (d->config_msix_addr >> 32) & ~0UL);
-    qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_DATA, d->config_msix_data);
-
-    control = qpci_io_readl(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
-    qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL,
-                                        control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
-
-    qpci_io_writew(d->pdev, d->addr + VIRTIO_MSI_CONFIG_VECTOR, entry);
-    vector = qpci_io_readw(d->pdev, d->addr + VIRTIO_MSI_CONFIG_VECTOR);
+    qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
+                   off + PCI_MSIX_ENTRY_LOWER_ADDR, d->config_msix_addr & ~0UL);
+    qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
+                   off + PCI_MSIX_ENTRY_UPPER_ADDR,
+                   (d->config_msix_addr >> 32) & ~0UL);
+    qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
+                   off + PCI_MSIX_ENTRY_DATA, d->config_msix_data);
+
+    control = qpci_io_readl(d->pdev, d->pdev->msix_table_bar,
+                            off + PCI_MSIX_ENTRY_VECTOR_CTRL);
+    qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
+                   off + PCI_MSIX_ENTRY_VECTOR_CTRL,
+                   control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
+
+    qpci_io_writew(d->pdev, d->bar, VIRTIO_MSI_CONFIG_VECTOR, entry);
+    vector = qpci_io_readw(d->pdev, d->bar, VIRTIO_MSI_CONFIG_VECTOR);
     g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR);
 }
diff --git a/tests/libqos/virtio-pci.h b/tests/libqos/virtio-pci.h
index efcac2d..38c54c6 100644
--- a/tests/libqos/virtio-pci.h
+++ b/tests/libqos/virtio-pci.h
@@ -16,7 +16,7 @@
 typedef struct QVirtioPCIDevice {
     QVirtioDevice vdev;
     QPCIDevice *pdev;
-    void *addr;
+    QPCIBar bar;
     uint16_t config_msix_entry;
     uint64_t config_msix_addr;
     uint32_t config_msix_data;
diff --git a/tests/rtl8139-test.c b/tests/rtl8139-test.c
index c2f601a..7de7dc4 100644
--- a/tests/rtl8139-test.c
+++ b/tests/rtl8139-test.c
@@ -22,7 +22,7 @@ static void nop(void)
 
 static QPCIBus *pcibus;
 static QPCIDevice *dev;
-static void *dev_base;
+static QPCIBar dev_bar;
 
 static void save_fn(QPCIDevice *dev, int devfn, void *data)
 {
@@ -45,14 +45,14 @@ static QPCIDevice *get_device(void)
 #define PORT(name, len, val) \
 static unsigned __attribute__((unused)) in_##name(void) \
 { \
-    unsigned res = qpci_io_read##len(dev, dev_base+(val)); \
+    unsigned res = qpci_io_read##len(dev, dev_bar, (val));     \
     g_test_message("*%s -> %x\n", #name, res); \
     return res; \
 } \
 static void out_##name(unsigned v) \
 { \
     g_test_message("%x -> *%s\n", v, #name); \
-    qpci_io_write##len(dev, dev_base+(val), v); \
+    qpci_io_write##len(dev, dev_bar, (val), v);        \
 }
 
 PORT(Timer, l, 0x48)
@@ -186,9 +186,7 @@ static void test_init(void)
 
     dev = get_device();
 
-    dev_base = qpci_iomap(dev, 0, &barsize);
-
-    g_assert(dev_base != NULL);
+    dev_bar = qpci_iomap(dev, 0, &barsize);
 
     qpci_device_enable(dev);
 
diff --git a/tests/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c
index a4ceeaa..57af8a0 100644
--- a/tests/usb-hcd-ehci-test.c
+++ b/tests/usb-hcd-ehci-test.c
@@ -38,8 +38,7 @@ static void uhci_port_update(struct qhc *hc, int port,
 
 static void ehci_port_test(struct qhc *hc, int port, uint32_t expect)
 {
-    void *addr = hc->base + 0x64 + 4 * port;
-    uint32_t value = qpci_io_readl(hc->dev, addr);
+    uint32_t value = qpci_io_readl(hc->dev, hc->bar, 0x64 + 4 * port);
     uint16_t mask = ~(PORTSC_CSC | PORTSC_PEDC | PORTSC_OCC);
 
 #if 0
@@ -91,7 +90,7 @@ static void pci_ehci_port_1(void)
 static void pci_ehci_config(void)
 {
     /* hands over all ports from companion uhci to ehci */
-    qpci_io_writew(ehci1.dev, ehci1.base + 0x60, 1);
+    qpci_io_writew(ehci1.dev, ehci1.bar, 0x60, 1);
 }
 
 static void pci_uhci_port_2(void)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling
  2016-10-18 10:52 [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling David Gibson
                   ` (7 preceding siblings ...)
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 8/8] libqos: Change PCI accessors to take opaque BAR handle David Gibson
@ 2016-10-18 11:56 ` Laurent Vivier
  2016-10-19  1:11   ` David Gibson
  8 siblings, 1 reply; 28+ messages in thread
From: Laurent Vivier @ 2016-10-18 11:56 UTC (permalink / raw)
  To: David Gibson, pbonzini, qemu-devel
  Cc: qemu-ppc, agraf, stefanha, mst, aik, mdroth, groug, thuth



On 18/10/2016 12:52, David Gibson wrote:
> This series contains a number of cleanups to the libqos code for
> accessing PCI devices, and to tests which use it.
> 
> The general aim is to improve the consistency of semantics across
> functions, and reduce the amount of intimate knowledge of the libqos
> PCI layer needed by tests.
> 
> This should make it easier to write PCI tests which will be portable
> to different guest machines with different PCI host bridge
> arrangements.
> 
> David Gibson (8):
>   libqos: Give qvirtio_config_read*() consistent semantics
>   libqos: Handle PCI IO de-multiplexing in common code
>   libqos: Move BAR assignment to common code
>   tests: Better handle legacy IO addresses in tco-test
>   libqos: Add streaming accessors for PCI MMIO
>   libqos: Implement mmio accessors in terms of mem{read,write}
>   tests: Use qpci_mem{read,write} in ivshmem-test
>   libqos: Change PCI accessors to take opaque BAR handle
> 
>  tests/ahci-test.c          |   4 +-
>  tests/e1000e-test.c        |   7 +-
>  tests/ide-test.c           |  23 +++---
>  tests/ivshmem-test.c       |  28 ++++----
>  tests/libqos/ahci.c        |   3 +-
>  tests/libqos/ahci.h        |   6 +-
>  tests/libqos/pci-pc.c      | 170 +++++++++-----------------------------------
>  tests/libqos/pci-spapr.c   | 172 ++++++++++-----------------------------------
>  tests/libqos/pci.c         | 168 ++++++++++++++++++++++++++++++++++---------
>  tests/libqos/pci.h         |  60 ++++++++++------
>  tests/libqos/usb.c         |   6 +-
>  tests/libqos/usb.h         |   2 +-
>  tests/libqos/virtio-mmio.c |  16 ++---
>  tests/libqos/virtio-pci.c  | 117 ++++++++++++++++--------------
>  tests/libqos/virtio-pci.h  |   2 +-
>  tests/rtl8139-test.c       |  10 ++-
>  tests/tco-test.c           |  87 +++++++++++------------
>  tests/usb-hcd-ehci-test.c  |   5 +-
>  tests/virtio-9p-test.c     |   9 +--
>  tests/virtio-blk-test.c    |  51 +++-----------
>  tests/virtio-scsi-test.c   |   5 +-
>  21 files changed, 418 insertions(+), 533 deletions(-)
> 

This series conflicts with series "tests: enable virtio tests on SPAPR".

Which one will you apply first?

Thanks,
Laurent

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 1/8] libqos: Give qvirtio_config_read*() consistent semantics
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 1/8] libqos: Give qvirtio_config_read*() consistent semantics David Gibson
@ 2016-10-18 12:41   ` Laurent Vivier
  2016-10-18 13:27   ` Greg Kurz
  1 sibling, 0 replies; 28+ messages in thread
From: Laurent Vivier @ 2016-10-18 12:41 UTC (permalink / raw)
  To: David Gibson, pbonzini, qemu-devel
  Cc: qemu-ppc, agraf, stefanha, mst, aik, mdroth, groug, thuth



On 18/10/2016 12:52, David Gibson wrote:
> The 'addr' parameter to qvirtio_config_read*() doesn't have a consistent
> meaning: when using the virtio-pci versions, it's a full PCI space address,
> but for virtio-mmio, it's an offset from the device's base mmio address.
> 
> This means that the callers need to do different things to calculate the
> addresses in the two cases, which rather defeats the purpose of function
> pointer backends.
> 
> All the current users of these functions are using them to retrieve
> variables from the device specific portion of the virtio config space.
> So, this patch alters the semantics to always be an offset into that
> device specific config area.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

Reviewed-by: Laurent Vivier <lvivier@redhat.com>

> ---
>  tests/libqos/virtio-mmio.c | 16 +++++++--------
>  tests/libqos/virtio-pci.c  | 22 ++++++++++++--------
>  tests/virtio-9p-test.c     |  9 ++------
>  tests/virtio-blk-test.c    | 51 ++++++++++------------------------------------
>  tests/virtio-scsi-test.c   |  5 +----
>  5 files changed, 35 insertions(+), 68 deletions(-)
> 
> diff --git a/tests/libqos/virtio-mmio.c b/tests/libqos/virtio-mmio.c
> index 0cab38f..b0b74dc 100644
> --- a/tests/libqos/virtio-mmio.c
> +++ b/tests/libqos/virtio-mmio.c
> @@ -15,28 +15,28 @@
>  #include "libqos/malloc-generic.h"
>  #include "standard-headers/linux/virtio_ring.h"
>  
> -static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t addr)
> +static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> -    return readb(dev->addr + addr);
> +    return readb(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
>  }
>  
> -static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t addr)
> +static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> -    return readw(dev->addr + addr);
> +    return readw(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
>  }
>  
> -static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t addr)
> +static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> -    return readl(dev->addr + addr);
> +    return readl(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
>  }
>  
> -static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t addr)
> +static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> -    return readq(dev->addr + addr);
> +    return readq(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
>  }
>  
>  static uint32_t qvirtio_mmio_get_features(QVirtioDevice *d)
> diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
> index 6e005c1..8037724 100644
> --- a/tests/libqos/virtio-pci.c
> +++ b/tests/libqos/virtio-pci.c
> @@ -62,39 +62,43 @@ static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data)
>      *vpcidev = (QVirtioPCIDevice *)d;
>  }
>  
> -static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t addr)
> +static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> -    return qpci_io_readb(dev->pdev, (void *)(uintptr_t)addr);
> +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> +    return qpci_io_readb(dev->pdev, base + off);
>  }
>  
> -static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t addr)
> +static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> -    return qpci_io_readw(dev->pdev, (void *)(uintptr_t)addr);
> +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> +    return qpci_io_readw(dev->pdev, base + off);
>  }
>  
> -static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t addr)
> +static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> -    return qpci_io_readl(dev->pdev, (void *)(uintptr_t)addr);
> +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> +    return qpci_io_readl(dev->pdev, base + off);
>  }
>  
> -static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t addr)
> +static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
>      int i;
>      uint64_t u64 = 0;
> +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
>  
>      if (target_big_endian()) {
>          for (i = 0; i < 8; ++i) {
>              u64 |= (uint64_t)qpci_io_readb(dev->pdev,
> -                                (void *)(uintptr_t)addr + i) << (7 - i) * 8;
> +                                           base + off + i) << (7 - i) * 8;
>          }
>      } else {
>          for (i = 0; i < 8; ++i) {
>              u64 |= (uint64_t)qpci_io_readb(dev->pdev,
> -                                (void *)(uintptr_t)addr + i) << i * 8;
> +                                           base + off + i) << i * 8;
>          }
>      }
>  
> diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
> index e8b2196..620e523 100644
> --- a/tests/virtio-9p-test.c
> +++ b/tests/virtio-9p-test.c
> @@ -92,7 +92,6 @@ static void qvirtio_9p_pci_free(QVirtIO9P *v9p)
>  static void pci_basic_config(void)
>  {
>      QVirtIO9P *v9p;
> -    void *addr;
>      size_t tag_len;
>      char *tag;
>      int i;
> @@ -100,16 +99,12 @@ static void pci_basic_config(void)
>      qvirtio_9p_start();
>      v9p = qvirtio_9p_pci_init();
>  
> -    addr = ((QVirtioPCIDevice *) v9p->dev)->addr + VIRTIO_PCI_CONFIG_OFF(false);
> -    tag_len = qvirtio_config_readw(&qvirtio_pci, v9p->dev,
> -                                   (uint64_t)(uintptr_t)addr);
> +    tag_len = qvirtio_config_readw(&qvirtio_pci, v9p->dev, 0);
>      g_assert_cmpint(tag_len, ==, strlen(mount_tag));
> -    addr += sizeof(uint16_t);
>  
>      tag = g_malloc(tag_len);
>      for (i = 0; i < tag_len; i++) {
> -        tag[i] = qvirtio_config_readb(&qvirtio_pci, v9p->dev,
> -                                      (uint64_t)(uintptr_t)addr + i);
> +        tag[i] = qvirtio_config_readb(&qvirtio_pci, v9p->dev, i + 2);
>      }
>      g_assert_cmpmem(tag, tag_len, mount_tag, tag_len);
>      g_free(tag);
> diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
> index 0506917..9162a5d 100644
> --- a/tests/virtio-blk-test.c
> +++ b/tests/virtio-blk-test.c
> @@ -151,7 +151,7 @@ static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioBlkReq *req,
>  }
>  
>  static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
> -            QGuestAllocator *alloc, QVirtQueue *vq, uint64_t device_specific)
> +                       QGuestAllocator *alloc, QVirtQueue *vq)
>  {
>      QVirtioBlkReq req;
>      uint64_t req_addr;
> @@ -161,7 +161,7 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
>      uint8_t status;
>      char *data;
>  
> -    capacity = qvirtio_config_readq(bus, dev, device_specific);
> +    capacity = qvirtio_config_readq(bus, dev, 0);
>  
>      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
>  
> @@ -282,7 +282,6 @@ static void pci_basic(void)
>      QPCIBus *bus;
>      QVirtQueuePCI *vqpci;
>      QGuestAllocator *alloc;
> -    void *addr;
>  
>      bus = pci_test_start();
>      dev = virtio_blk_pci_init(bus, PCI_SLOT);
> @@ -291,11 +290,7 @@ static void pci_basic(void)
>      vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
>                                                                      alloc, 0);
>  
> -    /* MSI-X is not enabled */
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> -
> -    test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq);
>  
>      /* End test */
>      qvirtqueue_cleanup(&qvirtio_pci, &vqpci->vq, alloc);
> @@ -314,7 +309,6 @@ static void pci_indirect(void)
>      QGuestAllocator *alloc;
>      QVirtioBlkReq req;
>      QVRingIndirectDesc *indirect;
> -    void *addr;
>      uint64_t req_addr;
>      uint64_t capacity;
>      uint32_t features;
> @@ -326,11 +320,7 @@ static void pci_indirect(void)
>  
>      dev = virtio_blk_pci_init(bus, PCI_SLOT);
>  
> -    /* MSI-X is not enabled */
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> -
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
>  
>      features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
> @@ -414,18 +404,13 @@ static void pci_config(void)
>      QVirtioPCIDevice *dev;
>      QPCIBus *bus;
>      int n_size = TEST_IMAGE_SIZE / 2;
> -    void *addr;
>      uint64_t capacity;
>  
>      bus = pci_test_start();
>  
>      dev = virtio_blk_pci_init(bus, PCI_SLOT);
>  
> -    /* MSI-X is not enabled */
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> -
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
>  
>      qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
> @@ -434,8 +419,7 @@ static void pci_config(void)
>                                                      " 'size': %d } }", n_size);
>      qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
>  
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, n_size / 512);
>  
>      qvirtio_pci_device_disable(dev);
> @@ -452,7 +436,6 @@ static void pci_msix(void)
>      QGuestAllocator *alloc;
>      QVirtioBlkReq req;
>      int n_size = TEST_IMAGE_SIZE / 2;
> -    void *addr;
>      uint64_t req_addr;
>      uint64_t capacity;
>      uint32_t features;
> @@ -468,11 +451,7 @@ static void pci_msix(void)
>  
>      qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
>  
> -    /* MSI-X is enabled */
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
> -
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
>  
>      features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
> @@ -493,8 +472,7 @@ static void pci_msix(void)
>  
>      qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
>  
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, n_size / 512);
>  
>      /* Write request */
> @@ -568,7 +546,6 @@ static void pci_idx(void)
>      QVirtQueuePCI *vqpci;
>      QGuestAllocator *alloc;
>      QVirtioBlkReq req;
> -    void *addr;
>      uint64_t req_addr;
>      uint64_t capacity;
>      uint32_t features;
> @@ -584,11 +561,7 @@ static void pci_idx(void)
>  
>      qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
>  
> -    /* MSI-X is enabled */
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
> -
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
>  
>      features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
> @@ -731,8 +704,7 @@ static void mmio_basic(void)
>      alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
>      vq = qvirtqueue_setup(&qvirtio_mmio, &dev->vdev, alloc, 0);
>  
> -    test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq,
> -                            QVIRTIO_MMIO_DEVICE_SPECIFIC);
> +    test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq);
>  
>      qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
>                                                      " 'size': %d } }", n_size);
> @@ -740,8 +712,7 @@ static void mmio_basic(void)
>      qvirtio_wait_queue_isr(&qvirtio_mmio, &dev->vdev, vq,
>                             QVIRTIO_BLK_TIMEOUT_US);
>  
> -    capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev,
> -                                                QVIRTIO_MMIO_DEVICE_SPECIFIC);
> +    capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, n_size / 512);
>  
>      /* End test */
> diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
> index 79088bb..2df8f9a 100644
> --- a/tests/virtio-scsi-test.c
> +++ b/tests/virtio-scsi-test.c
> @@ -141,7 +141,6 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
>      QVirtIOSCSI *vs;
>      QVirtioPCIDevice *dev;
>      struct virtio_scsi_cmd_resp resp;
> -    void *addr;
>      int i;
>  
>      vs = g_new0(QVirtIOSCSI, 1);
> @@ -158,9 +157,7 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
>      qvirtio_set_acknowledge(&qvirtio_pci, vs->dev);
>      qvirtio_set_driver(&qvirtio_pci, vs->dev);
>  
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> -    vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev,
> -                                          (uint64_t)(uintptr_t)addr);
> +    vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev, 0);
>  
>      g_assert_cmpint(vs->num_queues, <, MAX_NUM_QUEUES);
>  
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 1/8] libqos: Give qvirtio_config_read*() consistent semantics
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 1/8] libqos: Give qvirtio_config_read*() consistent semantics David Gibson
  2016-10-18 12:41   ` Laurent Vivier
@ 2016-10-18 13:27   ` Greg Kurz
  2016-10-19  2:41     ` David Gibson
  1 sibling, 1 reply; 28+ messages in thread
From: Greg Kurz @ 2016-10-18 13:27 UTC (permalink / raw)
  To: David Gibson
  Cc: pbonzini, qemu-devel, qemu-ppc, lvivier, agraf, stefanha, mst,
	aik, mdroth, thuth

On Tue, 18 Oct 2016 21:52:06 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> The 'addr' parameter to qvirtio_config_read*() doesn't have a consistent
> meaning: when using the virtio-pci versions, it's a full PCI space address,
> but for virtio-mmio, it's an offset from the device's base mmio address.
> 
> This means that the callers need to do different things to calculate the
> addresses in the two cases, which rather defeats the purpose of function
> pointer backends.
> 
> All the current users of these functions are using them to retrieve
> variables from the device specific portion of the virtio config space.
> So, this patch alters the semantics to always be an offset into that
> device specific config area.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  tests/libqos/virtio-mmio.c | 16 +++++++--------
>  tests/libqos/virtio-pci.c  | 22 ++++++++++++--------
>  tests/virtio-9p-test.c     |  9 ++------
>  tests/virtio-blk-test.c    | 51 ++++++++++------------------------------------
>  tests/virtio-scsi-test.c   |  5 +----
>  5 files changed, 35 insertions(+), 68 deletions(-)
> 
> diff --git a/tests/libqos/virtio-mmio.c b/tests/libqos/virtio-mmio.c
> index 0cab38f..b0b74dc 100644
> --- a/tests/libqos/virtio-mmio.c
> +++ b/tests/libqos/virtio-mmio.c
> @@ -15,28 +15,28 @@
>  #include "libqos/malloc-generic.h"
>  #include "standard-headers/linux/virtio_ring.h"
>  
> -static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t addr)
> +static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> -    return readb(dev->addr + addr);
> +    return readb(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
>  }
>  
> -static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t addr)
> +static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> -    return readw(dev->addr + addr);
> +    return readw(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
>  }
>  
> -static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t addr)
> +static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> -    return readl(dev->addr + addr);
> +    return readl(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
>  }
>  
> -static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t addr)
> +static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> -    return readq(dev->addr + addr);
> +    return readq(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
>  }
>  
>  static uint32_t qvirtio_mmio_get_features(QVirtioDevice *d)
> diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
> index 6e005c1..8037724 100644
> --- a/tests/libqos/virtio-pci.c
> +++ b/tests/libqos/virtio-pci.c
> @@ -62,39 +62,43 @@ static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data)
>      *vpcidev = (QVirtioPCIDevice *)d;
>  }
>  
> -static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t addr)
> +static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> -    return qpci_io_readb(dev->pdev, (void *)(uintptr_t)addr);
> +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);

$ git grep VIRTIO_PCI_CONFIG_OFF tests
tests/libqos/virtio-pci.c:    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
tests/libqos/virtio-pci.c:    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
tests/libqos/virtio-pci.c:    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
tests/libqos/virtio-pci.c:    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);

Maybe this could be consolidated into a helper ?

Either way works for me since it is a definite improvement over what we currently have:

Reviewed-by: Greg Kurz <groug@kaod.org>

> +    return qpci_io_readb(dev->pdev, base + off);
>  }
>  
> -static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t addr)
> +static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> -    return qpci_io_readw(dev->pdev, (void *)(uintptr_t)addr);
> +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> +    return qpci_io_readw(dev->pdev, base + off);
>  }
>  
> -static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t addr)
> +static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> -    return qpci_io_readl(dev->pdev, (void *)(uintptr_t)addr);
> +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> +    return qpci_io_readl(dev->pdev, base + off);
>  }
>  
> -static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t addr)
> +static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
>      int i;
>      uint64_t u64 = 0;
> +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
>  
>      if (target_big_endian()) {
>          for (i = 0; i < 8; ++i) {
>              u64 |= (uint64_t)qpci_io_readb(dev->pdev,
> -                                (void *)(uintptr_t)addr + i) << (7 - i) * 8;
> +                                           base + off + i) << (7 - i) * 8;
>          }
>      } else {
>          for (i = 0; i < 8; ++i) {
>              u64 |= (uint64_t)qpci_io_readb(dev->pdev,
> -                                (void *)(uintptr_t)addr + i) << i * 8;
> +                                           base + off + i) << i * 8;
>          }
>      }
>  
> diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
> index e8b2196..620e523 100644
> --- a/tests/virtio-9p-test.c
> +++ b/tests/virtio-9p-test.c
> @@ -92,7 +92,6 @@ static void qvirtio_9p_pci_free(QVirtIO9P *v9p)
>  static void pci_basic_config(void)
>  {
>      QVirtIO9P *v9p;
> -    void *addr;
>      size_t tag_len;
>      char *tag;
>      int i;
> @@ -100,16 +99,12 @@ static void pci_basic_config(void)
>      qvirtio_9p_start();
>      v9p = qvirtio_9p_pci_init();
>  
> -    addr = ((QVirtioPCIDevice *) v9p->dev)->addr + VIRTIO_PCI_CONFIG_OFF(false);
> -    tag_len = qvirtio_config_readw(&qvirtio_pci, v9p->dev,
> -                                   (uint64_t)(uintptr_t)addr);
> +    tag_len = qvirtio_config_readw(&qvirtio_pci, v9p->dev, 0);
>      g_assert_cmpint(tag_len, ==, strlen(mount_tag));
> -    addr += sizeof(uint16_t);
>  
>      tag = g_malloc(tag_len);
>      for (i = 0; i < tag_len; i++) {
> -        tag[i] = qvirtio_config_readb(&qvirtio_pci, v9p->dev,
> -                                      (uint64_t)(uintptr_t)addr + i);
> +        tag[i] = qvirtio_config_readb(&qvirtio_pci, v9p->dev, i + 2);
>      }
>      g_assert_cmpmem(tag, tag_len, mount_tag, tag_len);
>      g_free(tag);
> diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
> index 0506917..9162a5d 100644
> --- a/tests/virtio-blk-test.c
> +++ b/tests/virtio-blk-test.c
> @@ -151,7 +151,7 @@ static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioBlkReq *req,
>  }
>  
>  static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
> -            QGuestAllocator *alloc, QVirtQueue *vq, uint64_t device_specific)
> +                       QGuestAllocator *alloc, QVirtQueue *vq)
>  {
>      QVirtioBlkReq req;
>      uint64_t req_addr;
> @@ -161,7 +161,7 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
>      uint8_t status;
>      char *data;
>  
> -    capacity = qvirtio_config_readq(bus, dev, device_specific);
> +    capacity = qvirtio_config_readq(bus, dev, 0);
>  
>      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
>  
> @@ -282,7 +282,6 @@ static void pci_basic(void)
>      QPCIBus *bus;
>      QVirtQueuePCI *vqpci;
>      QGuestAllocator *alloc;
> -    void *addr;
>  
>      bus = pci_test_start();
>      dev = virtio_blk_pci_init(bus, PCI_SLOT);
> @@ -291,11 +290,7 @@ static void pci_basic(void)
>      vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
>                                                                      alloc, 0);
>  
> -    /* MSI-X is not enabled */
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> -
> -    test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq);
>  
>      /* End test */
>      qvirtqueue_cleanup(&qvirtio_pci, &vqpci->vq, alloc);
> @@ -314,7 +309,6 @@ static void pci_indirect(void)
>      QGuestAllocator *alloc;
>      QVirtioBlkReq req;
>      QVRingIndirectDesc *indirect;
> -    void *addr;
>      uint64_t req_addr;
>      uint64_t capacity;
>      uint32_t features;
> @@ -326,11 +320,7 @@ static void pci_indirect(void)
>  
>      dev = virtio_blk_pci_init(bus, PCI_SLOT);
>  
> -    /* MSI-X is not enabled */
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> -
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
>  
>      features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
> @@ -414,18 +404,13 @@ static void pci_config(void)
>      QVirtioPCIDevice *dev;
>      QPCIBus *bus;
>      int n_size = TEST_IMAGE_SIZE / 2;
> -    void *addr;
>      uint64_t capacity;
>  
>      bus = pci_test_start();
>  
>      dev = virtio_blk_pci_init(bus, PCI_SLOT);
>  
> -    /* MSI-X is not enabled */
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> -
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
>  
>      qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
> @@ -434,8 +419,7 @@ static void pci_config(void)
>                                                      " 'size': %d } }", n_size);
>      qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
>  
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, n_size / 512);
>  
>      qvirtio_pci_device_disable(dev);
> @@ -452,7 +436,6 @@ static void pci_msix(void)
>      QGuestAllocator *alloc;
>      QVirtioBlkReq req;
>      int n_size = TEST_IMAGE_SIZE / 2;
> -    void *addr;
>      uint64_t req_addr;
>      uint64_t capacity;
>      uint32_t features;
> @@ -468,11 +451,7 @@ static void pci_msix(void)
>  
>      qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
>  
> -    /* MSI-X is enabled */
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
> -
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
>  
>      features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
> @@ -493,8 +472,7 @@ static void pci_msix(void)
>  
>      qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
>  
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, n_size / 512);
>  
>      /* Write request */
> @@ -568,7 +546,6 @@ static void pci_idx(void)
>      QVirtQueuePCI *vqpci;
>      QGuestAllocator *alloc;
>      QVirtioBlkReq req;
> -    void *addr;
>      uint64_t req_addr;
>      uint64_t capacity;
>      uint32_t features;
> @@ -584,11 +561,7 @@ static void pci_idx(void)
>  
>      qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
>  
> -    /* MSI-X is enabled */
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
> -
> -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> -                                                    (uint64_t)(uintptr_t)addr);
> +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
>  
>      features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
> @@ -731,8 +704,7 @@ static void mmio_basic(void)
>      alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
>      vq = qvirtqueue_setup(&qvirtio_mmio, &dev->vdev, alloc, 0);
>  
> -    test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq,
> -                            QVIRTIO_MMIO_DEVICE_SPECIFIC);
> +    test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq);
>  
>      qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
>                                                      " 'size': %d } }", n_size);
> @@ -740,8 +712,7 @@ static void mmio_basic(void)
>      qvirtio_wait_queue_isr(&qvirtio_mmio, &dev->vdev, vq,
>                             QVIRTIO_BLK_TIMEOUT_US);
>  
> -    capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev,
> -                                                QVIRTIO_MMIO_DEVICE_SPECIFIC);
> +    capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev, 0);
>      g_assert_cmpint(capacity, ==, n_size / 512);
>  
>      /* End test */
> diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
> index 79088bb..2df8f9a 100644
> --- a/tests/virtio-scsi-test.c
> +++ b/tests/virtio-scsi-test.c
> @@ -141,7 +141,6 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
>      QVirtIOSCSI *vs;
>      QVirtioPCIDevice *dev;
>      struct virtio_scsi_cmd_resp resp;
> -    void *addr;
>      int i;
>  
>      vs = g_new0(QVirtIOSCSI, 1);
> @@ -158,9 +157,7 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
>      qvirtio_set_acknowledge(&qvirtio_pci, vs->dev);
>      qvirtio_set_driver(&qvirtio_pci, vs->dev);
>  
> -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> -    vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev,
> -                                          (uint64_t)(uintptr_t)addr);
> +    vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev, 0);
>  
>      g_assert_cmpint(vs->num_queues, <, MAX_NUM_QUEUES);
>  

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 2/8] libqos: Handle PCI IO de-multiplexing in common code
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 2/8] libqos: Handle PCI IO de-multiplexing in common code David Gibson
@ 2016-10-18 13:28   ` Laurent Vivier
  2016-10-19  2:59     ` David Gibson
  0 siblings, 1 reply; 28+ messages in thread
From: Laurent Vivier @ 2016-10-18 13:28 UTC (permalink / raw)
  To: David Gibson, pbonzini, qemu-devel
  Cc: qemu-ppc, agraf, stefanha, mst, aik, mdroth, groug, thuth



On 18/10/2016 12:52, David Gibson wrote:
> The PCI IO space (aka PIO, aka legacy IO) and PCI memory space (aka MMIO)
> are distinct address spaces by the PCI spec (although parts of one might be
> aliased to parts of the other in some cases).
> 
> However, qpci_io_read*() and qpci_io_write*() can perform accesses to
> either space depending on parameter.  That's convenient for test case
> drivers, since there are a fair few devices which can be controlled via
> either a PIO or MMIO BAR but with an otherwise identical driver.
> 
> This is implemented by having addresses below 64kiB treated as PIO, and
> those above treated as MMIO.  This works because low addresses in memory
> space are generally reserved for DMA rather than MMIO.
> 
> At the moment, this demultiplexing must be handled by each PCI backend
> (pc and spapr, so far).  There's no real reason for this - the current
> encoding is likely to work for all platforms, and even if it doesn't we
> can still use a more complex common encoding since the value returned from
> iomap are semi-opaque.
> 
> This patch moves the demultiplexing into the common part of the libqos PCI
> code, with the backends having simpler, separate accessors for PIO and
> MMIO space.  This also means we have a way of explicitly accessing either
> space if it's necessary for some special case.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  tests/libqos/pci-pc.c    | 107 ++++++++++++++++++++----------------------
>  tests/libqos/pci-spapr.c | 118 +++++++++++++++++++++++++----------------------
>  tests/libqos/pci.c       |  49 +++++++++++++++++---
>  tests/libqos/pci.h       |  22 ++++++---
>  4 files changed, 170 insertions(+), 126 deletions(-)
> 
> diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
> index 9600ed6..51dff8a 100644
> --- a/tests/libqos/pci-pc.c
> +++ b/tests/libqos/pci-pc.c
> @@ -36,79 +36,64 @@ typedef struct QPCIBusPC
>      uint16_t pci_iohole_alloc;
>  } QPCIBusPC;
>  
> -static uint8_t qpci_pc_io_readb(QPCIBus *bus, void *addr)
> +static uint8_t qpci_pc_pio_readb(QPCIBus *bus, uint32_t addr)
>  {
> -    uintptr_t port = (uintptr_t)addr;
> -    uint8_t value;
> -
> -    if (port < 0x10000) {
> -        value = inb(port);
> -    } else {
> -        value = readb(port);
> -    }
> -
> -    return value;
> +    return inb(addr);
>  }
>  
> -static uint16_t qpci_pc_io_readw(QPCIBus *bus, void *addr)
> +static uint8_t qpci_pc_mmio_readb(QPCIBus *bus, uint32_t addr)
>  {
> -    uintptr_t port = (uintptr_t)addr;
> -    uint16_t value;
> -
> -    if (port < 0x10000) {
> -        value = inw(port);
> -    } else {
> -        value = readw(port);
> -    }
> +    return readb(addr);
> +}
>  
> -    return value;
> +static void qpci_pc_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
> +{
> +    outb(addr, val);
>  }
>  
> -static uint32_t qpci_pc_io_readl(QPCIBus *bus, void *addr)
> +static void qpci_pc_mmio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
>  {
> -    uintptr_t port = (uintptr_t)addr;
> -    uint32_t value;
> +    writeb(addr, val);
> +}
>  
> -    if (port < 0x10000) {
> -        value = inl(port);
> -    } else {
> -        value = readl(port);
> -    }
> +static uint16_t qpci_pc_pio_readw(QPCIBus *bus, uint32_t addr)
> +{
> +    return inw(addr);
> +}
>  
> -    return value;
> +static uint16_t qpci_pc_mmio_readw(QPCIBus *bus, uint32_t addr)
> +{
> +    return readw(addr);
>  }
>  
> -static void qpci_pc_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
> +static void qpci_pc_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
>  {
> -    uintptr_t port = (uintptr_t)addr;
> +    outw(addr, val);
> +}
>  
> -    if (port < 0x10000) {
> -        outb(port, value);
> -    } else {
> -        writeb(port, value);
> -    }
> +static void qpci_pc_mmio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
> +{
> +    writew(addr, val);
>  }
>  
> -static void qpci_pc_io_writew(QPCIBus *bus, void *addr, uint16_t value)
> +static uint32_t qpci_pc_pio_readl(QPCIBus *bus, uint32_t addr)
>  {
> -    uintptr_t port = (uintptr_t)addr;
> +    return inl(addr);
> +}
>  
> -    if (port < 0x10000) {
> -        outw(port, value);
> -    } else {
> -        writew(port, value);
> -    }
> +static uint32_t qpci_pc_mmio_readl(QPCIBus *bus, uint32_t addr)
> +{
> +    return readl(addr);
>  }
>  
> -static void qpci_pc_io_writel(QPCIBus *bus, void *addr, uint32_t value)
> +static void qpci_pc_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
>  {
> -    uintptr_t port = (uintptr_t)addr;
> +    outl(addr, val);
> +}
>  
> -    if (port < 0x10000) {
> -        outl(port, value);
> -    } else {
> -        writel(port, value);
> -    }
> +static void qpci_pc_mmio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
> +{
> +    writel(addr, val);
>  }
>  
>  static uint8_t qpci_pc_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
> @@ -218,13 +203,21 @@ QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
>  
>      ret = g_malloc(sizeof(*ret));
>  
> -    ret->bus.io_readb = qpci_pc_io_readb;
> -    ret->bus.io_readw = qpci_pc_io_readw;
> -    ret->bus.io_readl = qpci_pc_io_readl;
> +    ret->bus.pio_readb = qpci_pc_pio_readb;
> +    ret->bus.pio_readw = qpci_pc_pio_readw;
> +    ret->bus.pio_readl = qpci_pc_pio_readl;
> +
> +    ret->bus.pio_writeb = qpci_pc_pio_writeb;
> +    ret->bus.pio_writew = qpci_pc_pio_writew;
> +    ret->bus.pio_writel = qpci_pc_pio_writel;
> +
> +    ret->bus.mmio_readb = qpci_pc_mmio_readb;
> +    ret->bus.mmio_readw = qpci_pc_mmio_readw;
> +    ret->bus.mmio_readl = qpci_pc_mmio_readl;
>  
> -    ret->bus.io_writeb = qpci_pc_io_writeb;
> -    ret->bus.io_writew = qpci_pc_io_writew;
> -    ret->bus.io_writel = qpci_pc_io_writel;
> +    ret->bus.mmio_writeb = qpci_pc_mmio_writeb;
> +    ret->bus.mmio_writew = qpci_pc_mmio_writew;
> +    ret->bus.mmio_writel = qpci_pc_mmio_writel;
>  
>      ret->bus.config_readb = qpci_pc_config_readb;
>      ret->bus.config_readw = qpci_pc_config_readw;
> diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
> index 2eaaf91..2d26a94 100644
> --- a/tests/libqos/pci-spapr.c
> +++ b/tests/libqos/pci-spapr.c
> @@ -50,78 +50,76 @@ typedef struct QPCIBusSPAPR {
>   * so PCI accessors need to swap data endianness
>   */
>  
> -static uint8_t qpci_spapr_io_readb(QPCIBus *bus, void *addr)
> +static uint8_t qpci_spapr_pio_readb(QPCIBus *bus, uint32_t addr)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    uint64_t port = (uintptr_t)addr;
> -    uint8_t v;
> -    if (port < s->pio.size) {
> -        v = readb(s->pio_cpu_base + port);
> -    } else {
> -        v = readb(s->mmio32_cpu_base + port);
> -    }
> -    return v;
> +    return readb(s->pio_cpu_base + addr);
>  }
>  
> -static uint16_t qpci_spapr_io_readw(QPCIBus *bus, void *addr)
> +static uint8_t qpci_spapr_mmio32_readb(QPCIBus *bus, uint32_t addr)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    uint64_t port = (uintptr_t)addr;
> -    uint16_t v;
> -    if (port < s->pio.size) {
> -        v = readw(s->pio_cpu_base + port);
> -    } else {
> -        v = readw(s->mmio32_cpu_base + port);
> -    }
> -    return bswap16(v);
> +    return readb(s->mmio32_cpu_base + addr);
>  }
>  
> -static uint32_t qpci_spapr_io_readl(QPCIBus *bus, void *addr)
> +static void qpci_spapr_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    uint64_t port = (uintptr_t)addr;
> -    uint32_t v;
> -    if (port < s->pio.size) {
> -        v = readl(s->pio_cpu_base + port);
> -    } else {
> -        v = readl(s->mmio32_cpu_base + port);
> -    }
> -    return bswap32(v);
> +    writeb(s->pio_cpu_base + addr, val);
>  }
>  
> -static void qpci_spapr_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
> +static void qpci_spapr_mmio32_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    uint64_t port = (uintptr_t)addr;
> -    if (port < s->pio.size) {
> -        writeb(s->pio_cpu_base + port, value);
> -    } else {
> -        writeb(s->mmio32_cpu_base + port, value);
> -    }
> +    writeb(s->mmio32_cpu_base + addr, val);
>  }
>  
> -static void qpci_spapr_io_writew(QPCIBus *bus, void *addr, uint16_t value)
> +static uint16_t qpci_spapr_pio_readw(QPCIBus *bus, uint32_t addr)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    uint64_t port = (uintptr_t)addr;
> -    value = bswap16(value);
> -    if (port < s->pio.size) {
> -        writew(s->pio_cpu_base + port, value);
> -    } else {
> -        writew(s->mmio32_cpu_base + port, value);
> -    }
> +    return bswap16(readw(s->pio_cpu_base + addr));
>  }
>  
> -static void qpci_spapr_io_writel(QPCIBus *bus, void *addr, uint32_t value)
> +static uint16_t qpci_spapr_mmio32_readw(QPCIBus *bus, uint32_t addr)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    uint64_t port = (uintptr_t)addr;
> -    value = bswap32(value);
> -    if (port < s->pio.size) {
> -        writel(s->pio_cpu_base + port, value);
> -    } else {
> -        writel(s->mmio32_cpu_base + port, value);
> -    }
> +    return bswap16(readw(s->mmio32_cpu_base + addr));
> +}
> +
> +static void qpci_spapr_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
> +{
> +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> +    writew(s->pio_cpu_base + addr, bswap16(val));
> +}
> +
> +static void qpci_spapr_mmio32_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
> +{
> +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> +    writew(s->mmio32_cpu_base + addr, bswap16(val));
> +}
> +
> +static uint32_t qpci_spapr_pio_readl(QPCIBus *bus, uint32_t addr)
> +{
> +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> +    return bswap32(readl(s->pio_cpu_base + addr));
> +}
> +
> +static uint32_t qpci_spapr_mmio32_readl(QPCIBus *bus, uint32_t addr)
> +{
> +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> +    return bswap32(readl(s->mmio32_cpu_base + addr));
> +}
> +
> +static void qpci_spapr_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
> +{
> +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> +    writel(s->pio_cpu_base + addr, bswap32(val));
> +}
> +
> +static void qpci_spapr_mmio32_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
> +{
> +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> +    writel(s->mmio32_cpu_base + addr, bswap32(val));
>  }
>  
>  static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
> @@ -248,13 +246,21 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
>  
>      ret->alloc = alloc;
>  
> -    ret->bus.io_readb = qpci_spapr_io_readb;
> -    ret->bus.io_readw = qpci_spapr_io_readw;
> -    ret->bus.io_readl = qpci_spapr_io_readl;
> +    ret->bus.pio_readb = qpci_spapr_pio_readb;
> +    ret->bus.pio_readw = qpci_spapr_pio_readw;
> +    ret->bus.pio_readl = qpci_spapr_pio_readl;
> +
> +    ret->bus.pio_writeb = qpci_spapr_pio_writeb;
> +    ret->bus.pio_writew = qpci_spapr_pio_writew;
> +    ret->bus.pio_writel = qpci_spapr_pio_writel;
> +
> +    ret->bus.mmio_readb = qpci_spapr_mmio32_readb;
> +    ret->bus.mmio_readw = qpci_spapr_mmio32_readw;
> +    ret->bus.mmio_readl = qpci_spapr_mmio32_readl;
>  
> -    ret->bus.io_writeb = qpci_spapr_io_writeb;
> -    ret->bus.io_writew = qpci_spapr_io_writew;
> -    ret->bus.io_writel = qpci_spapr_io_writel;
> +    ret->bus.mmio_writeb = qpci_spapr_mmio32_writeb;
> +    ret->bus.mmio_writew = qpci_spapr_mmio32_writew;
> +    ret->bus.mmio_writel = qpci_spapr_mmio32_writel;
>  
>      ret->bus.config_readb = qpci_spapr_config_readb;
>      ret->bus.config_readw = qpci_spapr_config_readw;
> diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
> index c3f3382..55b01df 100644
> --- a/tests/libqos/pci.c
> +++ b/tests/libqos/pci.c
> @@ -224,33 +224,68 @@ void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
>  
>  uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
>  {
> -    return dev->bus->io_readb(dev->bus, data);
> +    uintptr_t addr = (uintptr_t)data;
> +
> +    if (addr < QPCI_PIO_LIMIT) {
> +        return dev->bus->pio_readb(dev->bus, addr);
> +    } else {
> +        return dev->bus->mmio_readb(dev->bus, addr);
> +    }
>  }
>  
>  uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
>  {
> -    return dev->bus->io_readw(dev->bus, data);
> +    uintptr_t addr = (uintptr_t)data;
> +
> +    if (addr < QPCI_PIO_LIMIT) {
> +        return dev->bus->pio_readw(dev->bus, addr);
> +    } else {
> +        return dev->bus->mmio_readw(dev->bus, addr);
> +    }
>  }
>  
>  uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
>  {
> -    return dev->bus->io_readl(dev->bus, data);
> -}
> +    uintptr_t addr = (uintptr_t)data;
>  
> +    if (addr < QPCI_PIO_LIMIT) {
> +        return dev->bus->pio_readl(dev->bus, addr);
> +    } else {
> +        return dev->bus->mmio_readl(dev->bus, addr);
> +    }
> +}
>  
>  void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
>  {
> -    dev->bus->io_writeb(dev->bus, data, value);
> +    uintptr_t addr = (uintptr_t)data;
> +
> +    if (addr < QPCI_PIO_LIMIT) {
> +        dev->bus->pio_writeb(dev->bus, addr, value);
> +    } else {
> +        dev->bus->mmio_writeb(dev->bus, addr, value);
> +    }
>  }
>  
>  void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
>  {
> -    dev->bus->io_writew(dev->bus, data, value);
> +    uintptr_t addr = (uintptr_t)data;
> +
> +    if (addr < QPCI_PIO_LIMIT) {
> +        dev->bus->pio_writew(dev->bus, addr, value);
> +    } else {
> +        dev->bus->mmio_writew(dev->bus, addr, value);
> +    }
>  }
>  
>  void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
>  {
> -    dev->bus->io_writel(dev->bus, data, value);
> +    uintptr_t addr = (uintptr_t)data;
> +
> +    if (addr < QPCI_PIO_LIMIT) {
> +        dev->bus->pio_writel(dev->bus, addr, value);
> +    } else {
> +        dev->bus->mmio_writel(dev->bus, addr, value);
> +    }
>  }
>  
>  void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
> diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
> index c06add8..72a2245 100644
> --- a/tests/libqos/pci.h
> +++ b/tests/libqos/pci.h
> @@ -15,6 +15,8 @@
>  
>  #include "libqtest.h"
>  
> +#define QPCI_PIO_LIMIT    0x10000

Perhaps you can remove the definition of SPAPR_PCI_IO_WIN_SIZE and use
QPCI_PIO_LIMIT instead in pci-spapr.c?
or add a QEMU_BUILD_BUG_ON(SPAPR_PCI_IO_WIN_SIZE != QPCI_PIO_LIMIT)?

> +
>  #define QPCI_DEVFN(dev, fn) (((dev) << 3) | (fn))
>  
>  typedef struct QPCIDevice QPCIDevice;
> @@ -22,13 +24,21 @@ typedef struct QPCIBus QPCIBus;
>  
>  struct QPCIBus
>  {
> -    uint8_t (*io_readb)(QPCIBus *bus, void *addr);
> -    uint16_t (*io_readw)(QPCIBus *bus, void *addr);
> -    uint32_t (*io_readl)(QPCIBus *bus, void *addr);
> +    uint8_t (*pio_readb)(QPCIBus *bus, uint32_t addr);
> +    uint16_t (*pio_readw)(QPCIBus *bus, uint32_t addr);
> +    uint32_t (*pio_readl)(QPCIBus *bus, uint32_t addr);
> +
> +    uint8_t (*mmio_readb)(QPCIBus *bus, uint32_t addr);
> +    uint16_t (*mmio_readw)(QPCIBus *bus, uint32_t addr);
> +    uint32_t (*mmio_readl)(QPCIBus *bus, uint32_t addr);
> +
> +    void (*pio_writeb)(QPCIBus *bus, uint32_t addr, uint8_t value);
> +    void (*pio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
> +    void (*pio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
>  
> -    void (*io_writeb)(QPCIBus *bus, void *addr, uint8_t value);
> -    void (*io_writew)(QPCIBus *bus, void *addr, uint16_t value);
> -    void (*io_writel)(QPCIBus *bus, void *addr, uint32_t value);
> +    void (*mmio_writeb)(QPCIBus *bus, uint32_t addr, uint8_t value);
> +    void (*mmio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
> +    void (*mmio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
>  
>      uint8_t (*config_readb)(QPCIBus *bus, int devfn, uint8_t offset);
>      uint16_t (*config_readw)(QPCIBus *bus, int devfn, uint8_t offset);
> 

Thanks,
Laurent

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 3/8] libqos: Move BAR assignment to common code
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 3/8] libqos: Move BAR assignment to " David Gibson
@ 2016-10-18 15:00   ` Laurent Vivier
  2016-10-19  3:07     ` David Gibson
  0 siblings, 1 reply; 28+ messages in thread
From: Laurent Vivier @ 2016-10-18 15:00 UTC (permalink / raw)
  To: David Gibson, pbonzini, qemu-devel
  Cc: qemu-ppc, agraf, stefanha, mst, aik, mdroth, groug, thuth



On 18/10/2016 12:52, David Gibson wrote:
> The PCI backends in libqos each supply an iomap() and iounmap() function
> which is used to set up a specified PCI BAR.  But PCI BAR allocation takes
> place entirely within PCI space, so doesn't really need per-backend
> versions.  For example, Linux includes generic BAR allocation code used on
> platforms where that isn't done by firmware.
> 
> This patch merges the BAR allocation from the two existing backends into a
> single simplified copy.  The back ends just need to set up some parameters
> describing the window of PCI IO and PCI memory addresses which are
> available for allocation.  Like both the existing versions the new one uses
> a simple bump allocator.
> 
> Note that (again like the existing versions) this doesn't really handle
> 64-bit memory BARs properly.  It is actually used for such a BAR by the
> ivshmem test, and apparently the 32-bit MMIO BAR logic is close enough to
> work, as long as the BAR isn't too big.  Fixing that to properly handle
> 64-bit BAR allocation is a problem for another time.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  tests/libqos/pci-pc.c    | 79 ++--------------------------------------------
>  tests/libqos/pci-spapr.c | 81 ++----------------------------------------------
>  tests/libqos/pci.c       | 56 +++++++++++++++++++++++++++++++--
>  tests/libqos/pci.h       |  7 ++---
>  4 files changed, 63 insertions(+), 160 deletions(-)
> 
> diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
> index 51dff8a..b087d13 100644
> --- a/tests/libqos/pci-pc.c
> +++ b/tests/libqos/pci-pc.c
> @@ -17,7 +17,6 @@
>  #include "hw/pci/pci_regs.h"
>  
>  #include "qemu-common.h"
> -#include "qemu/host-utils.h"
>  
>  
>  #define ACPI_PCIHP_ADDR         0xae00
> @@ -132,71 +131,6 @@ static void qpci_pc_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint3
>      outl(0xcfc, value);
>  }
>  
> -static void *qpci_pc_iomap(QPCIBus *bus, QPCIDevice *dev, int barno, uint64_t *sizeptr)
> -{
> -    QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
> -    static const int bar_reg_map[] = {
> -        PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
> -        PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
> -    };
> -    int bar_reg;
> -    uint32_t addr;
> -    uint64_t size;
> -    uint32_t io_type;
> -
> -    g_assert(barno >= 0 && barno <= 5);
> -    bar_reg = bar_reg_map[barno];
> -
> -    qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
> -    addr = qpci_config_readl(dev, bar_reg);
> -
> -    io_type = addr & PCI_BASE_ADDRESS_SPACE;
> -    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
> -        addr &= PCI_BASE_ADDRESS_IO_MASK;
> -    } else {
> -        addr &= PCI_BASE_ADDRESS_MEM_MASK;
> -    }
> -
> -    size = (1ULL << ctzl(addr));
> -    if (size == 0) {
> -        return NULL;
> -    }
> -    if (sizeptr) {
> -        *sizeptr = size;
> -    }
> -
> -    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
> -        uint16_t loc;
> -
> -        g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
> -                 <= s->pci_iohole_size);
> -        s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
> -        loc = s->pci_iohole_start + s->pci_iohole_alloc;
> -        s->pci_iohole_alloc += size;
> -
> -        qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
> -
> -        return (void *)(intptr_t)loc;
> -    } else {
> -        uint64_t loc;
> -
> -        g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
> -                 <= s->pci_hole_size);
> -        s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
> -        loc = s->pci_hole_start + s->pci_hole_alloc;
> -        s->pci_hole_alloc += size;
> -
> -        qpci_config_writel(dev, bar_reg, loc);
> -
> -        return (void *)(intptr_t)loc;
> -    }
> -}
> -
> -static void qpci_pc_iounmap(QPCIBus *bus, void *data)
> -{
> -    /* FIXME */
> -}
> -
>  QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
>  {
>      QPCIBusPC *ret;
> @@ -227,16 +161,9 @@ QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
>      ret->bus.config_writew = qpci_pc_config_writew;
>      ret->bus.config_writel = qpci_pc_config_writel;
>  
> -    ret->bus.iomap = qpci_pc_iomap;
> -    ret->bus.iounmap = qpci_pc_iounmap;
> -
> -    ret->pci_hole_start = 0xE0000000;
> -    ret->pci_hole_size = 0x20000000;
> -    ret->pci_hole_alloc = 0;
> -
> -    ret->pci_iohole_start = 0xc000;
> -    ret->pci_iohole_size = 0x4000;
> -    ret->pci_iohole_alloc = 0;

I think you can remove all these fields (pci_hole_.., pci_iohole_...)
from QPCIBusPC.

> +    ret->bus.pio_alloc_ptr = 0xc000;
> +    ret->bus.mmio_alloc_ptr = 0xE0000000;
> +    ret->bus.mmio_limit = 0x100000000ULL;
>  
>      return &ret->bus;
>  }
> diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
> index 2d26a94..9a18d8a 100644
> --- a/tests/libqos/pci-spapr.c
> +++ b/tests/libqos/pci-spapr.c
> @@ -167,72 +167,6 @@ static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset,
>      qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 4, value);
>  }
>  
> -static void *qpci_spapr_iomap(QPCIBus *bus, QPCIDevice *dev, int barno,
> -                              uint64_t *sizeptr)
> -{
> -    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    static const int bar_reg_map[] = {
> -        PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
> -        PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
> -    };
> -    int bar_reg;
> -    uint32_t addr;
> -    uint64_t size;
> -    uint32_t io_type;
> -
> -    g_assert(barno >= 0 && barno <= 5);
> -    bar_reg = bar_reg_map[barno];
> -
> -    qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
> -    addr = qpci_config_readl(dev, bar_reg);
> -
> -    io_type = addr & PCI_BASE_ADDRESS_SPACE;
> -    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
> -        addr &= PCI_BASE_ADDRESS_IO_MASK;
> -    } else {
> -        addr &= PCI_BASE_ADDRESS_MEM_MASK;
> -    }
> -
> -    size = (1ULL << ctzl(addr));
> -    if (size == 0) {
> -        return NULL;
> -    }
> -    if (sizeptr) {
> -        *sizeptr = size;
> -    }
> -
> -    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
> -        uint16_t loc;
> -
> -        g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
> -                 <= s->pci_iohole_size);
> -        s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
> -        loc = s->pci_iohole_start + s->pci_iohole_alloc;
> -        s->pci_iohole_alloc += size;
> -
> -        qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
> -
> -        return (void *)(unsigned long)loc;
> -    } else {
> -        uint64_t loc;
> -
> -        g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
> -                 <= s->pci_hole_size);
> -        s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
> -        loc = s->pci_hole_start + s->pci_hole_alloc;
> -        s->pci_hole_alloc += size;
> -
> -        qpci_config_writel(dev, bar_reg, loc);
> -
> -        return (void *)(unsigned long)loc;
> -    }
> -}
> -
> -static void qpci_spapr_iounmap(QPCIBus *bus, void *data)
> -{
> -    /* FIXME */
> -}
> -
>  #define SPAPR_PCI_BASE               (1ULL << 45)
>  
>  #define SPAPR_PCI_MMIO32_WIN_SIZE    0x80000000 /* 2 GiB */
> @@ -270,9 +204,6 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
>      ret->bus.config_writew = qpci_spapr_config_writew;
>      ret->bus.config_writel = qpci_spapr_config_writel;
>  
> -    ret->bus.iomap = qpci_spapr_iomap;
> -    ret->bus.iounmap = qpci_spapr_iounmap;
> -
>      /* FIXME: We assume the default location of the PHB for now.
>       * Ideally we'd parse the device tree deposited in the guest to
>       * get the window locations */
> @@ -287,15 +218,9 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
>      ret->mmio32.pci_base = 0x80000000; /* 2 GiB */
>      ret->mmio32.size = SPAPR_PCI_MMIO32_WIN_SIZE;
>  
> -    ret->pci_hole_start = 0xC0000000;
> -    ret->pci_hole_size =
> -        ret->mmio32.pci_base + ret->mmio32.size - ret->pci_hole_start;
> -    ret->pci_hole_alloc = 0;
> -
> -    ret->pci_iohole_start = 0xc000;
> -    ret->pci_iohole_size =
> -        ret->pio.pci_base + ret->pio.size - ret->pci_iohole_start;
> -    ret->pci_iohole_alloc = 0;

I think you can remove all these fields (pci_hole_.., pci_iohole_...)
from QPCIBusSPAPR.


Thanks,
Laurent

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 4/8] tests: Better handle legacy IO addresses in tco-test
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 4/8] tests: Better handle legacy IO addresses in tco-test David Gibson
@ 2016-10-18 15:14   ` Laurent Vivier
  2016-10-18 16:28     ` Laurent Vivier
  2016-10-19  3:09     ` David Gibson
  0 siblings, 2 replies; 28+ messages in thread
From: Laurent Vivier @ 2016-10-18 15:14 UTC (permalink / raw)
  To: David Gibson, pbonzini, qemu-devel
  Cc: qemu-ppc, agraf, stefanha, mst, aik, mdroth, groug, thuth



On 18/10/2016 12:52, David Gibson wrote:
> tco_test uses the libqos PCI code to access the device.  This makes perfect
> sense for the PCI config space accesses.  However for IO, rather than the
> usual PCI approach of mapping a PCI BAR, then accessing that, it instead
> uses the legacy approach of fixed, known addresses in PCI IO space.
> 
> That doesn't work very well with the qpci_io_{read,write} functions because
> we never use qpci_iomap() and so have to make assumptions about the
> internal encoding of the address tokens iomap() returns.
> 
> This patch avoids that, by directly using the bus's pio_{read,write}
> callbacks, which are defined to take addresses within the PCI IO space.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  tests/tco-test.c | 87 ++++++++++++++++++++++++++++----------------------------
>  1 file changed, 44 insertions(+), 43 deletions(-)
> 
> diff --git a/tests/tco-test.c b/tests/tco-test.c
> index 0d201b1..e668630 100644
> --- a/tests/tco-test.c
> +++ b/tests/tco-test.c
> @@ -40,13 +40,13 @@ enum {
>  typedef struct {
>      const char *args;
>      bool noreboot;
> +    QPCIBus *bus;
>      QPCIDevice *dev;
> -    void *tco_io_base;
> +    uint16_t tco_io_base;
>  } TestData;
>  
>  static void test_init(TestData *d)
>  {
> -    QPCIBus *bus;
>      QTestState *qs;
>      char *s;
>  
> @@ -57,8 +57,8 @@ static void test_init(TestData *d)
>      qtest_irq_intercept_in(qs, "ioapic");
>      g_free(s);
>  
> -    bus = qpci_init_pc(NULL);
> -    d->dev = qpci_device_find(bus, QPCI_DEVFN(0x1f, 0x00));
> +    d->bus = qpci_init_pc(NULL);

You can use qtest_pc_boot() now.

> +    d->dev = qpci_device_find(d->bus, QPCI_DEVFN(0x1f, 0x00));
>      g_assert(d->dev != NULL);
>  
>      qpci_device_enable(d->dev);
> @@ -70,42 +70,42 @@ static void test_init(TestData *d)
>      /* set Root Complex BAR */
>      qpci_config_writel(d->dev, ICH9_LPC_RCBA, RCBA_BASE_ADDR | 0x1);
>  
> -    d->tco_io_base = (void *)((uintptr_t)PM_IO_BASE_ADDR + 0x60);
> +    d->tco_io_base = PM_IO_BASE_ADDR + 0x60;

Why don't you use QPCIBar in TestData to store the address?
And you can call qpci_io_XXX() with it.

Thanks,
Laurent

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 5/8] libqos: Add streaming accessors for PCI MMIO
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 5/8] libqos: Add streaming accessors for PCI MMIO David Gibson
@ 2016-10-18 15:17   ` Laurent Vivier
  0 siblings, 0 replies; 28+ messages in thread
From: Laurent Vivier @ 2016-10-18 15:17 UTC (permalink / raw)
  To: David Gibson, pbonzini, qemu-devel
  Cc: qemu-ppc, agraf, stefanha, mst, aik, mdroth, groug, thuth



On 18/10/2016 12:52, David Gibson wrote:
> Currently PCI memory (aka MMIO) space is accessed via a set of readb/writeb
> style accessors.  This is what we want for accessing discrete registers of
> a certain size.  However, there are a few cases where we instead need a
> "bag of bytes" style streaming interface to PCI MMIO space.  This can be
> either for streaming data style registers or when there's actual memory
> rather than registers in PCI space, for example frame buffers or ivshmem.
> 
> This patch adds backend callbacks, and libqos wrappers for this type of
> byte address order preserving accesses.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

Reviewed-by: Laurent Vivier <lvivier@redhat.com>

> ---
>  tests/libqos/pci-pc.c    | 14 ++++++++++++++
>  tests/libqos/pci-spapr.c | 17 +++++++++++++++++
>  tests/libqos/pci.c       | 16 ++++++++++++++++
>  tests/libqos/pci.h       |  6 ++++++
>  4 files changed, 53 insertions(+)
> 
> diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
> index b087d13..0e95772 100644
> --- a/tests/libqos/pci-pc.c
> +++ b/tests/libqos/pci-pc.c
> @@ -95,6 +95,17 @@ static void qpci_pc_mmio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
>      writel(addr, val);
>  }
>  
> +static void qpci_pc_memread(QPCIBus *bus, uint32_t addr, void *buf, size_t len)
> +{
> +    memread(addr, buf, len);
> +}
> +
> +static void qpci_pc_memwrite(QPCIBus *bus, uint32_t addr,
> +                             const void *buf, size_t len)
> +{
> +    memwrite(addr, buf, len);
> +}
> +
>  static uint8_t qpci_pc_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
>  {
>      outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
> @@ -153,6 +164,9 @@ QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
>      ret->bus.mmio_writew = qpci_pc_mmio_writew;
>      ret->bus.mmio_writel = qpci_pc_mmio_writel;
>  
> +    ret->bus.memread = qpci_pc_memread;
> +    ret->bus.memwrite = qpci_pc_memwrite;
> +
>      ret->bus.config_readb = qpci_pc_config_readb;
>      ret->bus.config_readw = qpci_pc_config_readw;
>      ret->bus.config_readl = qpci_pc_config_readl;
> diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
> index 9a18d8a..b4c4b81 100644
> --- a/tests/libqos/pci-spapr.c
> +++ b/tests/libqos/pci-spapr.c
> @@ -122,6 +122,20 @@ static void qpci_spapr_mmio32_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
>      writel(s->mmio32_cpu_base + addr, bswap32(val));
>  }
>  
> +static void qpci_spapr_memread(QPCIBus *bus, uint32_t addr,
> +                               void *buf, size_t len)
> +{
> +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> +    memread(s->mmio32_cpu_base + addr, buf, len);
> +}
> +
> +static void qpci_spapr_memwrite(QPCIBus *bus, uint32_t addr,
> +                                const void *buf, size_t len)
> +{
> +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> +    memwrite(s->mmio32_cpu_base + addr, buf, len);
> +}
> +
>  static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> @@ -196,6 +210,9 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
>      ret->bus.mmio_writew = qpci_spapr_mmio32_writew;
>      ret->bus.mmio_writel = qpci_spapr_mmio32_writel;
>  
> +    ret->bus.memread = qpci_spapr_memread;
> +    ret->bus.memwrite = qpci_spapr_memwrite;
> +
>      ret->bus.config_readb = qpci_spapr_config_readb;
>      ret->bus.config_readw = qpci_spapr_config_readw;
>      ret->bus.config_readl = qpci_spapr_config_readl;
> diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
> index bf1c532..1e242f9 100644
> --- a/tests/libqos/pci.c
> +++ b/tests/libqos/pci.c
> @@ -289,6 +289,22 @@ void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
>      }
>  }
>  
> +void qpci_memread(QPCIDevice *dev, void *data, void *buf, size_t len)
> +{
> +    uintptr_t addr = (uintptr_t)data;
> +
> +    g_assert(addr >= QPCI_PIO_LIMIT);
> +    dev->bus->memread(dev->bus, addr, buf, len);
> +}
> +
> +void qpci_memwrite(QPCIDevice *dev, void *data, const void *buf, size_t len)
> +{
> +    uintptr_t addr = (uintptr_t)data;
> +
> +    g_assert(addr >= QPCI_PIO_LIMIT);
> +    dev->bus->memwrite(dev->bus, addr, buf, len);
> +}
> +
>  void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
>  {
>      QPCIBus *bus = dev->bus;
> diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
> index f6f916d..2fa5b4f 100644
> --- a/tests/libqos/pci.h
> +++ b/tests/libqos/pci.h
> @@ -39,6 +39,9 @@ struct QPCIBus {
>      void (*mmio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
>      void (*mmio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
>  
> +    void (*memread)(QPCIBus *bus, uint32_t addr, void *buf, size_t len);
> +    void (*memwrite)(QPCIBus *bus, uint32_t addr, const void *buf, size_t len);
> +
>      uint8_t (*config_readb)(QPCIBus *bus, int devfn, uint8_t offset);
>      uint16_t (*config_readw)(QPCIBus *bus, int devfn, uint8_t offset);
>      uint32_t (*config_readl)(QPCIBus *bus, int devfn, uint8_t offset);
> @@ -92,6 +95,9 @@ void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value);
>  void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value);
>  void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value);
>  
> +void qpci_memread(QPCIDevice *bus, void *data, void *buf, size_t len);
> +void qpci_memwrite(QPCIDevice *bus, void *data, const void *buf, size_t len);
> +
>  void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
>  void qpci_iounmap(QPCIDevice *dev, void *data);
>  
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 6/8] libqos: Implement mmio accessors in terms of mem{read, write}
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 6/8] libqos: Implement mmio accessors in terms of mem{read, write} David Gibson
@ 2016-10-18 16:04   ` Laurent Vivier
  0 siblings, 0 replies; 28+ messages in thread
From: Laurent Vivier @ 2016-10-18 16:04 UTC (permalink / raw)
  To: David Gibson, pbonzini, qemu-devel
  Cc: qemu-ppc, agraf, stefanha, mst, aik, mdroth, groug, thuth



On 18/10/2016 12:52, David Gibson wrote:
> In the libqos PCI code we now have accessors both for registers (byte
> significance preserving) and for streaming data (byte address order
> preserving).  These exist in both the interface for qtest drivers and in
> the machine specific backends.
> 
> However, the register-style accessors aren't actually necessary in the
> backend.  They can be implemented in terms of the byte address order
> preserving accessors by the libqos wrappers.  This works because PCI is
> always little endian.
> 
> This does assume that the back end byte address order preserving accessors
> will perform the equivalent of a single bus transaction for short lengths.
> This is the case, and in fact they currently end up using the same
> cpu_physical_memory_rw() implementation within the qtest accelerator.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

Reviewed-by: Laurent Vivier <lvivier@redhat.com>

> ---
>  tests/libqos/pci-pc.c    | 38 --------------------------------------
>  tests/libqos/pci-spapr.c | 44 --------------------------------------------
>  tests/libqos/pci.c       | 20 ++++++++++++++------
>  tests/libqos/pci.h       |  8 --------
>  4 files changed, 14 insertions(+), 96 deletions(-)
> 
> diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
> index 0e95772..e8b885a 100644
> --- a/tests/libqos/pci-pc.c
> +++ b/tests/libqos/pci-pc.c
> @@ -40,61 +40,31 @@ static uint8_t qpci_pc_pio_readb(QPCIBus *bus, uint32_t addr)
>      return inb(addr);
>  }
>  
> -static uint8_t qpci_pc_mmio_readb(QPCIBus *bus, uint32_t addr)
> -{
> -    return readb(addr);
> -}
> -
>  static void qpci_pc_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
>  {
>      outb(addr, val);
>  }
>  
> -static void qpci_pc_mmio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
> -{
> -    writeb(addr, val);
> -}
> -
>  static uint16_t qpci_pc_pio_readw(QPCIBus *bus, uint32_t addr)
>  {
>      return inw(addr);
>  }
>  
> -static uint16_t qpci_pc_mmio_readw(QPCIBus *bus, uint32_t addr)
> -{
> -    return readw(addr);
> -}
> -
>  static void qpci_pc_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
>  {
>      outw(addr, val);
>  }
>  
> -static void qpci_pc_mmio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
> -{
> -    writew(addr, val);
> -}
> -
>  static uint32_t qpci_pc_pio_readl(QPCIBus *bus, uint32_t addr)
>  {
>      return inl(addr);
>  }
>  
> -static uint32_t qpci_pc_mmio_readl(QPCIBus *bus, uint32_t addr)
> -{
> -    return readl(addr);
> -}
> -
>  static void qpci_pc_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
>  {
>      outl(addr, val);
>  }
>  
> -static void qpci_pc_mmio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
> -{
> -    writel(addr, val);
> -}
> -
>  static void qpci_pc_memread(QPCIBus *bus, uint32_t addr, void *buf, size_t len)
>  {
>      memread(addr, buf, len);
> @@ -156,14 +126,6 @@ QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
>      ret->bus.pio_writew = qpci_pc_pio_writew;
>      ret->bus.pio_writel = qpci_pc_pio_writel;
>  
> -    ret->bus.mmio_readb = qpci_pc_mmio_readb;
> -    ret->bus.mmio_readw = qpci_pc_mmio_readw;
> -    ret->bus.mmio_readl = qpci_pc_mmio_readl;
> -
> -    ret->bus.mmio_writeb = qpci_pc_mmio_writeb;
> -    ret->bus.mmio_writew = qpci_pc_mmio_writew;
> -    ret->bus.mmio_writel = qpci_pc_mmio_writel;
> -
>      ret->bus.memread = qpci_pc_memread;
>      ret->bus.memwrite = qpci_pc_memwrite;
>  
> diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
> index b4c4b81..dc89b25 100644
> --- a/tests/libqos/pci-spapr.c
> +++ b/tests/libqos/pci-spapr.c
> @@ -56,72 +56,36 @@ static uint8_t qpci_spapr_pio_readb(QPCIBus *bus, uint32_t addr)
>      return readb(s->pio_cpu_base + addr);
>  }
>  
> -static uint8_t qpci_spapr_mmio32_readb(QPCIBus *bus, uint32_t addr)
> -{
> -    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    return readb(s->mmio32_cpu_base + addr);
> -}
> -
>  static void qpci_spapr_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
>      writeb(s->pio_cpu_base + addr, val);
>  }
>  
> -static void qpci_spapr_mmio32_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
> -{
> -    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    writeb(s->mmio32_cpu_base + addr, val);
> -}
> -
>  static uint16_t qpci_spapr_pio_readw(QPCIBus *bus, uint32_t addr)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
>      return bswap16(readw(s->pio_cpu_base + addr));
>  }
>  
> -static uint16_t qpci_spapr_mmio32_readw(QPCIBus *bus, uint32_t addr)
> -{
> -    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    return bswap16(readw(s->mmio32_cpu_base + addr));
> -}
> -
>  static void qpci_spapr_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
>      writew(s->pio_cpu_base + addr, bswap16(val));
>  }
>  
> -static void qpci_spapr_mmio32_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
> -{
> -    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    writew(s->mmio32_cpu_base + addr, bswap16(val));
> -}
> -
>  static uint32_t qpci_spapr_pio_readl(QPCIBus *bus, uint32_t addr)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
>      return bswap32(readl(s->pio_cpu_base + addr));
>  }
>  
> -static uint32_t qpci_spapr_mmio32_readl(QPCIBus *bus, uint32_t addr)
> -{
> -    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    return bswap32(readl(s->mmio32_cpu_base + addr));
> -}
> -
>  static void qpci_spapr_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
>  {
>      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
>      writel(s->pio_cpu_base + addr, bswap32(val));
>  }
>  
> -static void qpci_spapr_mmio32_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
> -{
> -    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> -    writel(s->mmio32_cpu_base + addr, bswap32(val));
> -}
> -
>  static void qpci_spapr_memread(QPCIBus *bus, uint32_t addr,
>                                 void *buf, size_t len)
>  {
> @@ -202,14 +166,6 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
>      ret->bus.pio_writew = qpci_spapr_pio_writew;
>      ret->bus.pio_writel = qpci_spapr_pio_writel;
>  
> -    ret->bus.mmio_readb = qpci_spapr_mmio32_readb;
> -    ret->bus.mmio_readw = qpci_spapr_mmio32_readw;
> -    ret->bus.mmio_readl = qpci_spapr_mmio32_readl;
> -
> -    ret->bus.mmio_writeb = qpci_spapr_mmio32_writeb;
> -    ret->bus.mmio_writew = qpci_spapr_mmio32_writew;
> -    ret->bus.mmio_writel = qpci_spapr_mmio32_writel;
> -
>      ret->bus.memread = qpci_spapr_memread;
>      ret->bus.memwrite = qpci_spapr_memwrite;
>  
> diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
> index 1e242f9..bbacbcf 100644
> --- a/tests/libqos/pci.c
> +++ b/tests/libqos/pci.c
> @@ -230,7 +230,9 @@ uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
>      if (addr < QPCI_PIO_LIMIT) {
>          return dev->bus->pio_readb(dev->bus, addr);
>      } else {
> -        return dev->bus->mmio_readb(dev->bus, addr);
> +        uint8_t val;
> +        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
> +        return val;
>      }
>  }
>  
> @@ -241,7 +243,9 @@ uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
>      if (addr < QPCI_PIO_LIMIT) {
>          return dev->bus->pio_readw(dev->bus, addr);
>      } else {
> -        return dev->bus->mmio_readw(dev->bus, addr);
> +        uint16_t val;
> +        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
> +        return le16_to_cpu(val);
>      }
>  }
>  
> @@ -252,7 +256,9 @@ uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
>      if (addr < QPCI_PIO_LIMIT) {
>          return dev->bus->pio_readl(dev->bus, addr);
>      } else {
> -        return dev->bus->mmio_readl(dev->bus, addr);
> +        uint32_t val;
> +        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
> +        return le32_to_cpu(val);
>      }
>  }
>  
> @@ -263,7 +269,7 @@ void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
>      if (addr < QPCI_PIO_LIMIT) {
>          dev->bus->pio_writeb(dev->bus, addr, value);
>      } else {
> -        dev->bus->mmio_writeb(dev->bus, addr, value);
> +        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
>      }
>  }
>  
> @@ -274,7 +280,8 @@ void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
>      if (addr < QPCI_PIO_LIMIT) {
>          dev->bus->pio_writew(dev->bus, addr, value);
>      } else {
> -        dev->bus->mmio_writew(dev->bus, addr, value);
> +        value = cpu_to_le16(value);
> +        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
>      }
>  }
>  
> @@ -285,7 +292,8 @@ void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
>      if (addr < QPCI_PIO_LIMIT) {
>          dev->bus->pio_writel(dev->bus, addr, value);
>      } else {
> -        dev->bus->mmio_writel(dev->bus, addr, value);
> +        value = cpu_to_le32(value);
> +        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
>      }
>  }
>  
> diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
> index 2fa5b4f..59fa3da 100644
> --- a/tests/libqos/pci.h
> +++ b/tests/libqos/pci.h
> @@ -27,18 +27,10 @@ struct QPCIBus {
>      uint16_t (*pio_readw)(QPCIBus *bus, uint32_t addr);
>      uint32_t (*pio_readl)(QPCIBus *bus, uint32_t addr);
>  
> -    uint8_t (*mmio_readb)(QPCIBus *bus, uint32_t addr);
> -    uint16_t (*mmio_readw)(QPCIBus *bus, uint32_t addr);
> -    uint32_t (*mmio_readl)(QPCIBus *bus, uint32_t addr);
> -
>      void (*pio_writeb)(QPCIBus *bus, uint32_t addr, uint8_t value);
>      void (*pio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
>      void (*pio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
>  
> -    void (*mmio_writeb)(QPCIBus *bus, uint32_t addr, uint8_t value);
> -    void (*mmio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
> -    void (*mmio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
> -
>      void (*memread)(QPCIBus *bus, uint32_t addr, void *buf, size_t len);
>      void (*memwrite)(QPCIBus *bus, uint32_t addr, const void *buf, size_t len);
>  
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 7/8] tests: Use qpci_mem{read, write} in ivshmem-test
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 7/8] tests: Use qpci_mem{read, write} in ivshmem-test David Gibson
@ 2016-10-18 16:14   ` Laurent Vivier
  2016-10-19  4:13     ` David Gibson
  0 siblings, 1 reply; 28+ messages in thread
From: Laurent Vivier @ 2016-10-18 16:14 UTC (permalink / raw)
  To: David Gibson, pbonzini, qemu-devel
  Cc: qemu-ppc, agraf, stefanha, mst, aik, mdroth, groug, thuth



On 18/10/2016 12:52, David Gibson wrote:
> ivshmem implements a block of shared memory in a PCI BAR.  Currently our
> test case accesses this using qtest_mem{read,write}.  However, deducing
> the correct addresses for these requires making assumptions about the
> internel format returned by qpci_iomap(), along with some ugly casts.
> 
> This patch changes the test to use the new qpci_mem{read,write} interfaces
> which is neater.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

I think your changes break this test.

There is two guest, so we need to access them through two sockets,
defined in s1->qtest and s2->qtest.

But qpci_memXXX() always use memread(...) and thus
qtest_memread(global_qtest, ...) , so always test the last guest started.

You must swap global_qtest as it is done in in_reg()/out_reg() before
your qpci_memXXX() in test_ivshmem_pair().

Laurent

> ---
>  tests/ivshmem-test.c | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c
> index f36bfe7..97a887e 100644
> --- a/tests/ivshmem-test.c
> +++ b/tests/ivshmem-test.c
> @@ -169,7 +169,7 @@ static void test_ivshmem_single(void)
>      for (i = 0; i < G_N_ELEMENTS(data); i++) {
>          data[i] = i;
>      }
> -    qtest_memwrite(s->qtest, (uintptr_t)s->mem_base, data, sizeof(data));
> +    qpci_memwrite(s->dev, s->mem_base, data, sizeof(data));
>  
>      /* verify write */
>      for (i = 0; i < G_N_ELEMENTS(data); i++) {
> @@ -178,7 +178,7 @@ static void test_ivshmem_single(void)
>  
>      /* read it back and verify read */
>      memset(data, 0, sizeof(data));
> -    qtest_memread(s->qtest, (uintptr_t)s->mem_base, data, sizeof(data));
> +    qpci_memread(s->dev, s->mem_base, data, sizeof(data));
>      for (i = 0; i < G_N_ELEMENTS(data); i++) {
>          g_assert_cmpuint(data[i], ==, i);
>      }
> @@ -201,29 +201,29 @@ static void test_ivshmem_pair(void)
>  
>      /* host write, guest 1 & 2 read */
>      memset(tmpshmem, 0x42, TMPSHMSIZE);
> -    qtest_memread(s1->qtest, (uintptr_t)s1->mem_base, data, TMPSHMSIZE);
> +    qpci_memread(s1->dev, s1->mem_base, data, TMPSHMSIZE);
>      for (i = 0; i < TMPSHMSIZE; i++) {
>          g_assert_cmpuint(data[i], ==, 0x42);
>      }
> -    qtest_memread(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
> +    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
>      for (i = 0; i < TMPSHMSIZE; i++) {
>          g_assert_cmpuint(data[i], ==, 0x42);
>      }
>  
>      /* guest 1 write, guest 2 read */
>      memset(data, 0x43, TMPSHMSIZE);
> -    qtest_memwrite(s1->qtest, (uintptr_t)s1->mem_base, data, TMPSHMSIZE);
> +    qpci_memwrite(s1->dev, s1->mem_base, data, TMPSHMSIZE);
>      memset(data, 0, TMPSHMSIZE);
> -    qtest_memread(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
> +    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
>      for (i = 0; i < TMPSHMSIZE; i++) {
>          g_assert_cmpuint(data[i], ==, 0x43);
>      }
>  
>      /* guest 2 write, guest 1 read */
>      memset(data, 0x44, TMPSHMSIZE);
> -    qtest_memwrite(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
> +    qpci_memwrite(s2->dev, s2->mem_base, data, TMPSHMSIZE);
>      memset(data, 0, TMPSHMSIZE);
> -    qtest_memread(s1->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
> +    qpci_memread(s1->dev, s2->mem_base, data, TMPSHMSIZE);
>      for (i = 0; i < TMPSHMSIZE; i++) {
>          g_assert_cmpuint(data[i], ==, 0x44);
>      }
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 4/8] tests: Better handle legacy IO addresses in tco-test
  2016-10-18 15:14   ` Laurent Vivier
@ 2016-10-18 16:28     ` Laurent Vivier
  2016-10-19  3:19       ` David Gibson
  2016-10-19  3:09     ` David Gibson
  1 sibling, 1 reply; 28+ messages in thread
From: Laurent Vivier @ 2016-10-18 16:28 UTC (permalink / raw)
  To: David Gibson, pbonzini, qemu-devel
  Cc: qemu-ppc, agraf, stefanha, mst, aik, mdroth, groug, thuth



On 18/10/2016 17:14, Laurent Vivier wrote:
> 
> 
> On 18/10/2016 12:52, David Gibson wrote:
>> tco_test uses the libqos PCI code to access the device.  This makes perfect
>> sense for the PCI config space accesses.  However for IO, rather than the
>> usual PCI approach of mapping a PCI BAR, then accessing that, it instead
>> uses the legacy approach of fixed, known addresses in PCI IO space.
>>
>> That doesn't work very well with the qpci_io_{read,write} functions because
>> we never use qpci_iomap() and so have to make assumptions about the
>> internal encoding of the address tokens iomap() returns.
>>
>> This patch avoids that, by directly using the bus's pio_{read,write}
>> callbacks, which are defined to take addresses within the PCI IO space.
>>
>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>> ---
>>  tests/tco-test.c | 87 ++++++++++++++++++++++++++++----------------------------
>>  1 file changed, 44 insertions(+), 43 deletions(-)
>>
>> diff --git a/tests/tco-test.c b/tests/tco-test.c
>> index 0d201b1..e668630 100644
>> --- a/tests/tco-test.c
>> +++ b/tests/tco-test.c
>> @@ -40,13 +40,13 @@ enum {
>>  typedef struct {
>>      const char *args;
>>      bool noreboot;
>> +    QPCIBus *bus;
>>      QPCIDevice *dev;
>> -    void *tco_io_base;
>> +    uint16_t tco_io_base;
>>  } TestData;
>>  
>>  static void test_init(TestData *d)
>>  {
>> -    QPCIBus *bus;
>>      QTestState *qs;
>>      char *s;
>>  
>> @@ -57,8 +57,8 @@ static void test_init(TestData *d)
>>      qtest_irq_intercept_in(qs, "ioapic");
>>      g_free(s);
>>  
>> -    bus = qpci_init_pc(NULL);
>> -    d->dev = qpci_device_find(bus, QPCI_DEVFN(0x1f, 0x00));
>> +    d->bus = qpci_init_pc(NULL);
> 
> You can use qtest_pc_boot() now.
> 
>> +    d->dev = qpci_device_find(d->bus, QPCI_DEVFN(0x1f, 0x00));
>>      g_assert(d->dev != NULL);
>>  
>>      qpci_device_enable(d->dev);
>> @@ -70,42 +70,42 @@ static void test_init(TestData *d)
>>      /* set Root Complex BAR */
>>      qpci_config_writel(d->dev, ICH9_LPC_RCBA, RCBA_BASE_ADDR | 0x1);
>>  
>> -    d->tco_io_base = (void *)((uintptr_t)PM_IO_BASE_ADDR + 0x60);
>> +    d->tco_io_base = PM_IO_BASE_ADDR + 0x60;
> 
> Why don't you use QPCIBar in TestData to store the address?
> And you can call qpci_io_XXX() with it.

OK, I was watching the state of qpci_io_XXX() after the series, so you
can't do that here, but perhaps this patch should be moved to PATCH 8/8?

Laurent

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 8/8] libqos: Change PCI accessors to take opaque BAR handle
  2016-10-18 10:52 ` [Qemu-devel] [PATCH 8/8] libqos: Change PCI accessors to take opaque BAR handle David Gibson
@ 2016-10-18 16:48   ` Laurent Vivier
  2016-10-19  4:06     ` David Gibson
  0 siblings, 1 reply; 28+ messages in thread
From: Laurent Vivier @ 2016-10-18 16:48 UTC (permalink / raw)
  To: David Gibson, pbonzini, qemu-devel
  Cc: qemu-ppc, agraf, stefanha, mst, aik, mdroth, groug, thuth



On 18/10/2016 12:52, David Gibson wrote:
> The usual use model for the libqos PCI functions is to map a specific PCI
> BAR using qpci_iomap() then pass the returned token into IO accessor
> functions.  This, and the fact that iomap() returns a (void *) which
> actually contains a PCI space address, kind of suggests that the return
> value from iomap is supposed to be an opaque token.
> 
> ..except that the callers expect to be able to add offsets to it.  Which
> also assumes the compiler will support pointer arithmetic on a (void *),
> and treat it as working with byte offsets.
> 
> To clarify this situation change iomap() and the IO accessors to take
> a definitely opaque BAR handle (enforced with a wrapper struct) along with
> an offset within the BAR.  This changes both the functions and all the
> callers.
> 
> A few notes:
>     * Asserts that iomap() returns non-NULL are removed in some places;
> iomap() already asserts if it can't map the BAR
>     * In ide-test.c we change explicit outb() etc. calls to matching
> qpci_io_writeb() calls.  That makes the test more portable, and removes
> assumptions that the test case shouldn't be making about how iomap()'s
> return value is formatted internally.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> 
> # Conflicts:
> #	tests/libqos/virtio-pci.c

A sequel of a cherry-pick?

> ---
>  tests/ahci-test.c         |   4 +-
>  tests/e1000e-test.c       |   7 ++-
>  tests/ide-test.c          |  23 +++++----
>  tests/ivshmem-test.c      |  28 +++++------
>  tests/libqos/ahci.c       |   3 +-
>  tests/libqos/ahci.h       |   6 +--
>  tests/libqos/pci.c        | 125 +++++++++++++++++++++-------------------------
>  tests/libqos/pci.h        |  39 +++++++++------
>  tests/libqos/usb.c        |   6 +--
>  tests/libqos/usb.h        |   2 +-
>  tests/libqos/virtio-pci.c | 113 +++++++++++++++++++++--------------------
>  tests/libqos/virtio-pci.h |   2 +-
>  tests/rtl8139-test.c      |  10 ++--
>  tests/usb-hcd-ehci-test.c |   5 +-

Perhaps you can move tco-test update in this series?

>  14 files changed, 186 insertions(+), 187 deletions(-)
> 
> diff --git a/tests/ahci-test.c b/tests/ahci-test.c
> index 9c0adce..4358631 100644
> --- a/tests/ahci-test.c
> +++ b/tests/ahci-test.c
> @@ -90,12 +90,12 @@ static void verify_state(AHCIQState *ahci)
>      g_assert_cmphex(ahci_fingerprint, ==, ahci->fingerprint);
>  
>      /* If we haven't initialized, this is as much as can be validated. */
> -    if (!ahci->hba_base) {
> +    if (!ahci->hba_bar.addr) {
>          return;
>      }
>  
>      hba_base = (uint64_t)qpci_config_readl(ahci->dev, PCI_BASE_ADDRESS_5);
> -    hba_stored = (uint64_t)(uintptr_t)ahci->hba_base;
> +    hba_stored = ahci->hba_bar.addr;
>      g_assert_cmphex(hba_base, ==, hba_stored);
>  
>      g_assert_cmphex(ahci_rreg(ahci, AHCI_CAP), ==, ahci->cap);
> diff --git a/tests/e1000e-test.c b/tests/e1000e-test.c
> index 3979b20..8c42ca9 100644
> --- a/tests/e1000e-test.c
> +++ b/tests/e1000e-test.c
> @@ -87,7 +87,7 @@
>  
>  typedef struct e1000e_device {
>      QPCIDevice *pci_dev;
> -    void *mac_regs;
> +    QPCIBar mac_regs;
>  
>      uint64_t tx_ring;
>      uint64_t rx_ring;
> @@ -119,12 +119,12 @@ static QPCIDevice *e1000e_device_find(QPCIBus *bus)
>  
>  static void e1000e_macreg_write(e1000e_device *d, uint32_t reg, uint32_t val)
>  {
> -    qpci_io_writel(d->pci_dev, d->mac_regs + reg, val);
> +    qpci_io_writel(d->pci_dev, d->mac_regs, reg, val);
>  }
>  
>  static uint32_t e1000e_macreg_read(e1000e_device *d, uint32_t reg)
>  {
> -    return qpci_io_readl(d->pci_dev, d->mac_regs + reg);
> +    return qpci_io_readl(d->pci_dev, d->mac_regs, reg);
>  }
>  
>  static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
> @@ -138,7 +138,6 @@ static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
>  
>      /* Map BAR0 (mac registers) */
>      d->mac_regs = qpci_iomap(d->pci_dev, 0, NULL);
> -    g_assert_nonnull(d->mac_regs);
>  
>      /* Reset the device */
>      val = e1000e_macreg_read(d, E1000E_CTRL);
> diff --git a/tests/ide-test.c b/tests/ide-test.c
> index a8a4081..dc08536 100644
> --- a/tests/ide-test.c
> +++ b/tests/ide-test.c
> @@ -137,7 +137,7 @@ static void ide_test_quit(void)
>      qtest_end();
>  }
>  
> -static QPCIDevice *get_pci_device(uint16_t *bmdma_base)
> +static QPCIDevice *get_pci_device(QPCIBar *bmdma_bar)
>  {
>      QPCIDevice *dev;
>      uint16_t vendor_id, device_id;
> @@ -156,7 +156,7 @@ static QPCIDevice *get_pci_device(uint16_t *bmdma_base)
>      g_assert(device_id == PCI_DEVICE_ID_INTEL_82371SB_1);
>  
>      /* Map bmdma BAR */
> -    *bmdma_base = (uint16_t)(uintptr_t) qpci_iomap(dev, 4, NULL);
> +    *bmdma_bar = qpci_iomap(dev, 4, NULL);
>  
>      qpci_device_enable(dev);
>  
> @@ -182,14 +182,14 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
>                              void(*post_exec)(uint64_t sector, int nb_sectors))
>  {
>      QPCIDevice *dev;
> -    uint16_t bmdma_base;
> +    QPCIBar bmdma_bar;
>      uintptr_t guest_prdt;
>      size_t len;
>      bool from_dev;
>      uint8_t status;
>      int flags;
>  
> -    dev = get_pci_device(&bmdma_base);
> +    dev = get_pci_device(&bmdma_bar);
>  
>      flags = cmd & ~0xff;
>      cmd &= 0xff;
> @@ -217,14 +217,14 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
>      outb(IDE_BASE + reg_device, 0 | LBA);
>  
>      /* Stop any running transfer, clear any pending interrupt */
> -    outb(bmdma_base + bmreg_cmd, 0);
> -    outb(bmdma_base + bmreg_status, BM_STS_INTR);
> +    qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
> +    qpci_io_writeb(dev, bmdma_bar, bmreg_status, BM_STS_INTR);
>  
>      /* Setup PRDT */
>      len = sizeof(*prdt) * prdt_entries;
>      guest_prdt = guest_alloc(guest_malloc, len);
>      memwrite(guest_prdt, prdt, len);
> -    outl(bmdma_base + bmreg_prdt, guest_prdt);
> +    qpci_io_writel(dev, bmdma_bar, bmreg_prdt, guest_prdt);
>  
>      /* ATA DMA command */
>      if (cmd == CMD_PACKET) {
> @@ -244,15 +244,16 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
>      }
>  
>      /* Start DMA transfer */
> -    outb(bmdma_base + bmreg_cmd, BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));
> +    qpci_io_writeb(dev, bmdma_bar, bmreg_cmd,
> +                   BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));
>  
>      if (flags & CMDF_ABORT) {
> -        outb(bmdma_base + bmreg_cmd, 0);
> +        qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
>      }
>  
>      /* Wait for the DMA transfer to complete */
>      do {
> -        status = inb(bmdma_base + bmreg_status);
> +        status = qpci_io_readb(dev, bmdma_bar, bmreg_status);
>      } while ((status & (BM_STS_ACTIVE | BM_STS_INTR)) == BM_STS_ACTIVE);
>  
>      g_assert_cmpint(get_irq(IDE_PRIMARY_IRQ), ==, !!(status & BM_STS_INTR));
> @@ -266,7 +267,7 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
>  
>      /* Stop DMA transfer if still active */
>      if (status & BM_STS_ACTIVE) {
> -        outb(bmdma_base + bmreg_cmd, 0);
> +        qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
>      }
>  
>      free_pci_device(dev);
> diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c
> index 97a887e..f7c5bf4 100644
> --- a/tests/ivshmem-test.c
> +++ b/tests/ivshmem-test.c
> @@ -41,7 +41,7 @@ static QPCIDevice *get_device(QPCIBus *pcibus)
>  
>  typedef struct _IVState {
>      QTestState *qtest;
> -    void *reg_base, *mem_base;
> +    QPCIBar reg_bar, mem_bar;
>      QPCIBus *pcibus;
>      QPCIDevice *dev;
>  } IVState;
> @@ -75,7 +75,7 @@ static inline unsigned in_reg(IVState *s, enum Reg reg)
>      unsigned res;
>  
>      global_qtest = s->qtest;
> -    res = qpci_io_readl(s->dev, s->reg_base + reg);
> +    res = qpci_io_readl(s->dev, s->reg_bar, reg);
>      g_test_message("*%s -> %x\n", name, res);
>      global_qtest = qtest;
>  
> @@ -89,7 +89,7 @@ static inline void out_reg(IVState *s, enum Reg reg, unsigned v)
>  
>      global_qtest = s->qtest;
>      g_test_message("%x -> *%s\n", v, name);
> -    qpci_io_writel(s->dev, s->reg_base + reg, v);
> +    qpci_io_writel(s->dev, s->reg_bar, reg, v);
>      global_qtest = qtest;
>  }
>  
> @@ -108,16 +108,14 @@ static void setup_vm_cmd(IVState *s, const char *cmd, bool msix)
>      s->pcibus = qpci_init_pc(NULL);
>      s->dev = get_device(s->pcibus);
>  
> -    s->reg_base = qpci_iomap(s->dev, 0, &barsize);
> -    g_assert_nonnull(s->reg_base);
> +    s->reg_bar = qpci_iomap(s->dev, 0, &barsize);
>      g_assert_cmpuint(barsize, ==, 256);
>  
>      if (msix) {
>          qpci_msix_enable(s->dev);
>      }
>  
> -    s->mem_base = qpci_iomap(s->dev, 2, &barsize);
> -    g_assert_nonnull(s->mem_base);
> +    s->mem_bar = qpci_iomap(s->dev, 2, &barsize);
>      g_assert_cmpuint(barsize, ==, TMPSHMSIZE);
>  
>      qpci_device_enable(s->dev);
> @@ -169,7 +167,7 @@ static void test_ivshmem_single(void)
>      for (i = 0; i < G_N_ELEMENTS(data); i++) {
>          data[i] = i;
>      }
> -    qpci_memwrite(s->dev, s->mem_base, data, sizeof(data));
> +    qpci_memwrite(s->dev, s->mem_bar, 0, data, sizeof(data));
>  
>      /* verify write */
>      for (i = 0; i < G_N_ELEMENTS(data); i++) {
> @@ -178,7 +176,7 @@ static void test_ivshmem_single(void)
>  
>      /* read it back and verify read */
>      memset(data, 0, sizeof(data));
> -    qpci_memread(s->dev, s->mem_base, data, sizeof(data));
> +    qpci_memread(s->dev, s->mem_bar, 0, data, sizeof(data));
>      for (i = 0; i < G_N_ELEMENTS(data); i++) {
>          g_assert_cmpuint(data[i], ==, i);
>      }
> @@ -201,29 +199,29 @@ static void test_ivshmem_pair(void)
>  
>      /* host write, guest 1 & 2 read */
>      memset(tmpshmem, 0x42, TMPSHMSIZE);
> -    qpci_memread(s1->dev, s1->mem_base, data, TMPSHMSIZE);
> +    qpci_memread(s1->dev, s1->mem_bar, 0, data, TMPSHMSIZE);
>      for (i = 0; i < TMPSHMSIZE; i++) {
>          g_assert_cmpuint(data[i], ==, 0x42);
>      }
> -    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
> +    qpci_memread(s2->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
>      for (i = 0; i < TMPSHMSIZE; i++) {
>          g_assert_cmpuint(data[i], ==, 0x42);
>      }
>  
>      /* guest 1 write, guest 2 read */
>      memset(data, 0x43, TMPSHMSIZE);
> -    qpci_memwrite(s1->dev, s1->mem_base, data, TMPSHMSIZE);
> +    qpci_memwrite(s1->dev, s1->mem_bar, 0, data, TMPSHMSIZE);
>      memset(data, 0, TMPSHMSIZE);
> -    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
> +    qpci_memread(s2->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
>      for (i = 0; i < TMPSHMSIZE; i++) {
>          g_assert_cmpuint(data[i], ==, 0x43);
>      }
>  
>      /* guest 2 write, guest 1 read */
>      memset(data, 0x44, TMPSHMSIZE);
> -    qpci_memwrite(s2->dev, s2->mem_base, data, TMPSHMSIZE);
> +    qpci_memwrite(s2->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
>      memset(data, 0, TMPSHMSIZE);
> -    qpci_memread(s1->dev, s2->mem_base, data, TMPSHMSIZE);
> +    qpci_memread(s1->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
>      for (i = 0; i < TMPSHMSIZE; i++) {
>          g_assert_cmpuint(data[i], ==, 0x44);
>      }
> diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c
> index 716ab79..43b6695 100644
> --- a/tests/libqos/ahci.c
> +++ b/tests/libqos/ahci.c
> @@ -210,8 +210,7 @@ void ahci_pci_enable(AHCIQState *ahci)
>  void start_ahci_device(AHCIQState *ahci)
>  {
>      /* Map AHCI's ABAR (BAR5) */
> -    ahci->hba_base = qpci_iomap(ahci->dev, 5, &ahci->barsize);
> -    g_assert(ahci->hba_base);
> +    ahci->hba_bar = qpci_iomap(ahci->dev, 5, &ahci->barsize);
>  
>      /* turns on pci.cmd.iose, pci.cmd.mse and pci.cmd.bme */
>      qpci_device_enable(ahci->dev);
> diff --git a/tests/libqos/ahci.h b/tests/libqos/ahci.h
> index c69fb5a..6c4abf6 100644
> --- a/tests/libqos/ahci.h
> +++ b/tests/libqos/ahci.h
> @@ -321,7 +321,7 @@ typedef struct AHCIPortQState {
>  typedef struct AHCIQState {
>      QOSState *parent;
>      QPCIDevice *dev;
> -    void *hba_base;
> +    QPCIBar hba_bar;
>      uint64_t barsize;
>      uint32_t fingerprint;
>      uint32_t cap;
> @@ -488,12 +488,12 @@ typedef struct AHCIOpts {
>  
>  static inline uint32_t ahci_mread(AHCIQState *ahci, size_t offset)
>  {
> -    return qpci_io_readl(ahci->dev, ahci->hba_base + offset);
> +    return qpci_io_readl(ahci->dev, ahci->hba_bar, offset);
>  }
>  
>  static inline void ahci_mwrite(AHCIQState *ahci, size_t offset, uint32_t value)
>  {
> -    qpci_io_writel(ahci->dev, ahci->hba_base + offset, value);
> +    qpci_io_writel(ahci->dev, ahci->hba_bar, offset, value);
>  }
>  
>  static inline uint32_t ahci_rreg(AHCIQState *ahci, uint32_t reg_num)
> diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
> index bbacbcf..875c517 100644
> --- a/tests/libqos/pci.c
> +++ b/tests/libqos/pci.c
> @@ -104,7 +104,6 @@ void qpci_msix_enable(QPCIDevice *dev)
>      uint32_t table;
>      uint8_t bir_table;
>      uint8_t bir_pba;
> -    void *offset;
>  
>      addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
>      g_assert_cmphex(addr, !=, 0);
> @@ -114,18 +113,16 @@ void qpci_msix_enable(QPCIDevice *dev)
>  
>      table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE);
>      bir_table = table & PCI_MSIX_FLAGS_BIRMASK;
> -    offset = qpci_iomap(dev, bir_table, NULL);
> -    dev->msix_table = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK);
> +    dev->msix_table_bar = qpci_iomap(dev, bir_table, NULL);
> +    dev->msix_table_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
>  
>      table = qpci_config_readl(dev, addr + PCI_MSIX_PBA);
>      bir_pba = table & PCI_MSIX_FLAGS_BIRMASK;
>      if (bir_pba != bir_table) {
> -        offset = qpci_iomap(dev, bir_pba, NULL);
> +        dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL);
>      }
> -    dev->msix_pba = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK);
> +    dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
>  
> -    g_assert(dev->msix_table != NULL);
> -    g_assert(dev->msix_pba != NULL);
>      dev->msix_enabled = true;
>  }
>  
> @@ -141,22 +138,25 @@ void qpci_msix_disable(QPCIDevice *dev)
>      qpci_config_writew(dev, addr + PCI_MSIX_FLAGS,
>                                                  val & ~PCI_MSIX_FLAGS_ENABLE);
>  
> -    qpci_iounmap(dev, dev->msix_table);
> -    qpci_iounmap(dev, dev->msix_pba);
> +    qpci_iounmap(dev, dev->msix_table_bar);
> +    qpci_iounmap(dev, dev->msix_pba_bar);
>      dev->msix_enabled = 0;
> -    dev->msix_table = NULL;
> -    dev->msix_pba = NULL;
> +    memset(&dev->msix_table_bar, 0, sizeof(dev->msix_table_bar));
> +    memset(&dev->msix_pba_bar, 0, sizeof(dev->msix_pba_bar));
> +    dev->msix_table_off = 0;
> +    dev->msix_pba_off = 0;
>  }
>  
>  bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry)
>  {
>      uint32_t pba_entry;
>      uint8_t bit_n = entry % 32;
> -    void *addr = dev->msix_pba + (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
> +    uint64_t  off = (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
>  
>      g_assert(dev->msix_enabled);
> -    pba_entry = qpci_io_readl(dev, addr);
> -    qpci_io_writel(dev, addr, pba_entry & ~(1 << bit_n));
> +    pba_entry = qpci_io_readl(dev, dev->msix_pba_bar, dev->msix_pba_off + off);
> +    qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off,
> +                   pba_entry & ~(1 << bit_n));
>      return (pba_entry & (1 << bit_n)) != 0;
>  }
>  
> @@ -164,7 +164,7 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
>  {
>      uint8_t addr;
>      uint16_t val;
> -    void *vector_addr = dev->msix_table + (entry * PCI_MSIX_ENTRY_SIZE);
> +    uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE;
>  
>      g_assert(dev->msix_enabled);
>      addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
> @@ -174,8 +174,9 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
>      if (val & PCI_MSIX_FLAGS_MASKALL) {
>          return true;
>      } else {
> -        return (qpci_io_readl(dev, vector_addr + PCI_MSIX_ENTRY_VECTOR_CTRL)
> -                                            & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
> +        return (qpci_io_readl(dev, dev->msix_table_bar,
> +                              vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL)
> +                & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
>      }
>  }
>  
> @@ -222,104 +223,93 @@ void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
>      dev->bus->config_writel(dev->bus, dev->devfn, offset, value);
>  }
>  
> -
> -uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
> +uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off)
>  {
> -    uintptr_t addr = (uintptr_t)data;
> -
> -    if (addr < QPCI_PIO_LIMIT) {
> -        return dev->bus->pio_readb(dev->bus, addr);
> +    if (token.addr < QPCI_PIO_LIMIT) {
> +        return dev->bus->pio_readb(dev->bus, token.addr + off);
>      } else {
>          uint8_t val;
> -        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
> +        dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
>          return val;
>      }
>  }
>  
> -uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
> +uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
>  {
> -    uintptr_t addr = (uintptr_t)data;
> -
> -    if (addr < QPCI_PIO_LIMIT) {
> -        return dev->bus->pio_readw(dev->bus, addr);
> +    if (token.addr < QPCI_PIO_LIMIT) {
> +        return dev->bus->pio_readw(dev->bus, token.addr + off);
>      } else {
>          uint16_t val;
> -        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
> +        dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
>          return le16_to_cpu(val);
>      }
>  }
>  
> -uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
> +uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
>  {
> -    uintptr_t addr = (uintptr_t)data;
> -
> -    if (addr < QPCI_PIO_LIMIT) {
> -        return dev->bus->pio_readl(dev->bus, addr);
> +    if (token.addr < QPCI_PIO_LIMIT) {
> +        return dev->bus->pio_readl(dev->bus, token.addr + off);
>      } else {
>          uint32_t val;
> -        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
> +        dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
>          return le32_to_cpu(val);
>      }
>  }
>  
> -void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
> +void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
> +                    uint8_t value)
>  {
> -    uintptr_t addr = (uintptr_t)data;
> -
> -    if (addr < QPCI_PIO_LIMIT) {
> -        dev->bus->pio_writeb(dev->bus, addr, value);
> +    if (token.addr < QPCI_PIO_LIMIT) {
> +        dev->bus->pio_writeb(dev->bus, token.addr + off, value);
>      } else {
> -        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
> +        dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
>      }
>  }
>  
> -void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
> +void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
> +                    uint16_t value)
>  {
> -    uintptr_t addr = (uintptr_t)data;
> -
> -    if (addr < QPCI_PIO_LIMIT) {
> -        dev->bus->pio_writew(dev->bus, addr, value);
> +    if (token.addr < QPCI_PIO_LIMIT) {
> +        dev->bus->pio_writew(dev->bus, token.addr + off, value);
>      } else {
>          value = cpu_to_le16(value);
> -        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
> +        dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
>      }
>  }
>  
> -void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
> +void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
> +                    uint32_t value)
>  {
> -    uintptr_t addr = (uintptr_t)data;
> -
> -    if (addr < QPCI_PIO_LIMIT) {
> -        dev->bus->pio_writel(dev->bus, addr, value);
> +    if (token.addr < QPCI_PIO_LIMIT) {
> +        dev->bus->pio_writel(dev->bus, token.addr + off, value);
>      } else {
>          value = cpu_to_le32(value);
> -        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
> +        dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
>      }
>  }
>  
> -void qpci_memread(QPCIDevice *dev, void *data, void *buf, size_t len)
> +void qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off,
> +                  void *buf, size_t len)
>  {
> -    uintptr_t addr = (uintptr_t)data;
> -
> -    g_assert(addr >= QPCI_PIO_LIMIT);
> -    dev->bus->memread(dev->bus, addr, buf, len);
> +    g_assert(token.addr >= QPCI_PIO_LIMIT);
> +    dev->bus->memread(dev->bus, token.addr + off, buf, len);
>  }
>  
> -void qpci_memwrite(QPCIDevice *dev, void *data, const void *buf, size_t len)
> +void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
> +                   const void *buf, size_t len)
>  {
> -    uintptr_t addr = (uintptr_t)data;
> -
> -    g_assert(addr >= QPCI_PIO_LIMIT);
> -    dev->bus->memwrite(dev->bus, addr, buf, len);
> +    g_assert(token.addr >= QPCI_PIO_LIMIT);
> +    dev->bus->memwrite(dev->bus, token.addr + off, buf, len);
>  }
>  
> -void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
> +QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
>  {
>      QPCIBus *bus = dev->bus;
>      static const int bar_reg_map[] = {
>          PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
>          PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
>      };
> +    QPCIBar bar;
>      int bar_reg;
>      uint32_t addr, size;
>      uint32_t io_type;
> @@ -366,10 +356,11 @@ void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
>          qpci_config_writel(dev, bar_reg, loc);
>      }
>  
> -    return (void *)(uintptr_t)loc;
> +    bar.addr = loc;
> +    return bar;
>  }
>  
> -void qpci_iounmap(QPCIDevice *dev, void *data)
> +void qpci_iounmap(QPCIDevice *dev, QPCIBar bar)
>  {
>      /* FIXME */
>  }
> diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
> index 59fa3da..40b277c 100644
> --- a/tests/libqos/pci.h
> +++ b/tests/libqos/pci.h
> @@ -21,6 +21,7 @@
>  
>  typedef struct QPCIDevice QPCIDevice;
>  typedef struct QPCIBus QPCIBus;
> +typedef struct QPCIBar QPCIBar;
>  
>  struct QPCIBus {
>      uint8_t (*pio_readb)(QPCIBus *bus, uint32_t addr);
> @@ -49,13 +50,17 @@ struct QPCIBus {
>      uint64_t mmio_alloc_ptr, mmio_limit;
>  };
>  
> +struct QPCIBar {
> +    uint64_t addr;
> +};
> +
>  struct QPCIDevice
>  {
>      QPCIBus *bus;
>      int devfn;
>      bool msix_enabled;
> -    void *msix_table;
> -    void *msix_pba;
> +    QPCIBar msix_table_bar, msix_pba_bar;
> +    uint64_t msix_table_off, msix_pba_off;
>  };
>  
>  void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
> @@ -79,19 +84,23 @@ void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value);
>  void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value);
>  void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value);
>  
> -uint8_t qpci_io_readb(QPCIDevice *dev, void *data);
> -uint16_t qpci_io_readw(QPCIDevice *dev, void *data);
> -uint32_t qpci_io_readl(QPCIDevice *dev, void *data);
> -
> -void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value);
> -void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value);
> -void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value);
> -
> -void qpci_memread(QPCIDevice *bus, void *data, void *buf, size_t len);
> -void qpci_memwrite(QPCIDevice *bus, void *data, const void *buf, size_t len);
> -
> -void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
> -void qpci_iounmap(QPCIDevice *dev, void *data);
> +uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off);
> +uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off);
> +uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off);
> +
> +void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
> +                    uint8_t value);
> +void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
> +                    uint16_t value);
> +void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
> +                    uint32_t value);
> +
> +void qpci_memread(QPCIDevice *bus, QPCIBar token, uint64_t off,
> +                  void *buf, size_t len);
> +void qpci_memwrite(QPCIDevice *bus, QPCIBar token, uint64_t off,
> +                   const void *buf, size_t len);
> +QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
> +void qpci_iounmap(QPCIDevice *dev, QPCIBar addr);
>  
>  void qpci_plug_device_test(const char *driver, const char *id,
>                             uint8_t slot, const char *opts);
> diff --git a/tests/libqos/usb.c b/tests/libqos/usb.c
> index f794d92..72d7a96 100644
> --- a/tests/libqos/usb.c
> +++ b/tests/libqos/usb.c
> @@ -21,14 +21,12 @@ void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc, uint32_t devfn, int bar)
>      hc->dev = qpci_device_find(pcibus, devfn);
>      g_assert(hc->dev != NULL);
>      qpci_device_enable(hc->dev);
> -    hc->base = qpci_iomap(hc->dev, bar, NULL);
> -    g_assert(hc->base != NULL);
> +    hc->bar = qpci_iomap(hc->dev, bar, NULL);
>  }
>  
>  void uhci_port_test(struct qhc *hc, int port, uint16_t expect)
>  {
> -    void *addr = hc->base + 0x10 + 2 * port;
> -    uint16_t value = qpci_io_readw(hc->dev, addr);
> +    uint16_t value = qpci_io_readw(hc->dev, hc->bar, 0x10 + 2 * port);
>      uint16_t mask = ~(UHCI_PORT_WRITE_CLEAR | UHCI_PORT_RSVD1);
>  
>      g_assert((value & mask) == (expect & mask));
> diff --git a/tests/libqos/usb.h b/tests/libqos/usb.h
> index 8fe5687..423dcfd 100644
> --- a/tests/libqos/usb.h
> +++ b/tests/libqos/usb.h
> @@ -5,7 +5,7 @@
>  
>  struct qhc {
>      QPCIDevice *dev;
> -    void *base;
> +    QPCIBar bar;
>  };
>  
>  void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc,
> diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
> index 8037724..5b78d30 100644
> --- a/tests/libqos/virtio-pci.c
> +++ b/tests/libqos/virtio-pci.c
> @@ -65,22 +65,22 @@ static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data)
>  static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> -    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> -    return qpci_io_readb(dev->pdev, base + off);
> +    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> +    return qpci_io_readb(dev->pdev, dev->bar, base + off);
>  }
>  
>  static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> -    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> -    return qpci_io_readw(dev->pdev, base + off);
> +    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> +    return qpci_io_readw(dev->pdev, dev->bar, base + off);
>  }
>  
>  static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t off)
>  {
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> -    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> -    return qpci_io_readl(dev->pdev, base + off);
> +    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> +    return qpci_io_readl(dev->pdev, dev->bar, base + off);
>  }
>  
>  static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
> @@ -88,17 +88,17 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
>      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
>      int i;
>      uint64_t u64 = 0;
> -    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> +    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled) + off;
>  
>      if (target_big_endian()) {
>          for (i = 0; i < 8; ++i) {
> -            u64 |= (uint64_t)qpci_io_readb(dev->pdev,
> -                                           base + off + i) << (7 - i) * 8;
> +            u64 |= (uint64_t)qpci_io_readb(dev->pdev, dev->bar,
> +                                           base + i) << (7 - i) * 8;
>          }
>      } else {
>          for (i = 0; i < 8; ++i) {
> -            u64 |= (uint64_t)qpci_io_readb(dev->pdev,
> -                                           base + off + i) << i * 8;
> +            u64 |= (uint64_t)qpci_io_readb(dev->pdev, dev->bar,
> +                                           base + i) << i * 8;
>          }

You should update this part with qpci_memread() + bswap64()

Thanks,
Laurent

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling
  2016-10-18 11:56 ` [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling Laurent Vivier
@ 2016-10-19  1:11   ` David Gibson
  0 siblings, 0 replies; 28+ messages in thread
From: David Gibson @ 2016-10-19  1:11 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: pbonzini, qemu-devel, qemu-ppc, agraf, stefanha, mst, aik,
	mdroth, groug, thuth

[-- Attachment #1: Type: text/plain, Size: 2710 bytes --]

On Tue, Oct 18, 2016 at 01:56:53PM +0200, Laurent Vivier wrote:
> 
> 
> On 18/10/2016 12:52, David Gibson wrote:
> > This series contains a number of cleanups to the libqos code for
> > accessing PCI devices, and to tests which use it.
> > 
> > The general aim is to improve the consistency of semantics across
> > functions, and reduce the amount of intimate knowledge of the libqos
> > PCI layer needed by tests.
> > 
> > This should make it easier to write PCI tests which will be portable
> > to different guest machines with different PCI host bridge
> > arrangements.
> > 
> > David Gibson (8):
> >   libqos: Give qvirtio_config_read*() consistent semantics
> >   libqos: Handle PCI IO de-multiplexing in common code
> >   libqos: Move BAR assignment to common code
> >   tests: Better handle legacy IO addresses in tco-test
> >   libqos: Add streaming accessors for PCI MMIO
> >   libqos: Implement mmio accessors in terms of mem{read,write}
> >   tests: Use qpci_mem{read,write} in ivshmem-test
> >   libqos: Change PCI accessors to take opaque BAR handle
> > 
> >  tests/ahci-test.c          |   4 +-
> >  tests/e1000e-test.c        |   7 +-
> >  tests/ide-test.c           |  23 +++---
> >  tests/ivshmem-test.c       |  28 ++++----
> >  tests/libqos/ahci.c        |   3 +-
> >  tests/libqos/ahci.h        |   6 +-
> >  tests/libqos/pci-pc.c      | 170 +++++++++-----------------------------------
> >  tests/libqos/pci-spapr.c   | 172 ++++++++++-----------------------------------
> >  tests/libqos/pci.c         | 168 ++++++++++++++++++++++++++++++++++---------
> >  tests/libqos/pci.h         |  60 ++++++++++------
> >  tests/libqos/usb.c         |   6 +-
> >  tests/libqos/usb.h         |   2 +-
> >  tests/libqos/virtio-mmio.c |  16 ++---
> >  tests/libqos/virtio-pci.c  | 117 ++++++++++++++++--------------
> >  tests/libqos/virtio-pci.h  |   2 +-
> >  tests/rtl8139-test.c       |  10 ++-
> >  tests/tco-test.c           |  87 +++++++++++------------
> >  tests/usb-hcd-ehci-test.c  |   5 +-
> >  tests/virtio-9p-test.c     |   9 +--
> >  tests/virtio-blk-test.c    |  51 +++-----------
> >  tests/virtio-scsi-test.c   |   5 +-
> >  21 files changed, 418 insertions(+), 533 deletions(-)
> > 
> 
> This series conflicts with series "tests: enable virtio tests on SPAPR".
> 
> Which one will you apply first?

Oops, didn't think that through.  I'll rebase my next spin on
ppc-for-2.8, which already includes your virtio test enabling patches.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 1/8] libqos: Give qvirtio_config_read*() consistent semantics
  2016-10-18 13:27   ` Greg Kurz
@ 2016-10-19  2:41     ` David Gibson
  0 siblings, 0 replies; 28+ messages in thread
From: David Gibson @ 2016-10-19  2:41 UTC (permalink / raw)
  To: Greg Kurz
  Cc: pbonzini, qemu-devel, qemu-ppc, lvivier, agraf, stefanha, mst,
	aik, mdroth, thuth

[-- Attachment #1: Type: text/plain, Size: 16234 bytes --]

On Tue, Oct 18, 2016 at 03:27:09PM +0200, Greg Kurz wrote:
> On Tue, 18 Oct 2016 21:52:06 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > The 'addr' parameter to qvirtio_config_read*() doesn't have a consistent
> > meaning: when using the virtio-pci versions, it's a full PCI space address,
> > but for virtio-mmio, it's an offset from the device's base mmio address.
> > 
> > This means that the callers need to do different things to calculate the
> > addresses in the two cases, which rather defeats the purpose of function
> > pointer backends.
> > 
> > All the current users of these functions are using them to retrieve
> > variables from the device specific portion of the virtio config space.
> > So, this patch alters the semantics to always be an offset into that
> > device specific config area.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> >  tests/libqos/virtio-mmio.c | 16 +++++++--------
> >  tests/libqos/virtio-pci.c  | 22 ++++++++++++--------
> >  tests/virtio-9p-test.c     |  9 ++------
> >  tests/virtio-blk-test.c    | 51 ++++++++++------------------------------------
> >  tests/virtio-scsi-test.c   |  5 +----
> >  5 files changed, 35 insertions(+), 68 deletions(-)
> > 
> > diff --git a/tests/libqos/virtio-mmio.c b/tests/libqos/virtio-mmio.c
> > index 0cab38f..b0b74dc 100644
> > --- a/tests/libqos/virtio-mmio.c
> > +++ b/tests/libqos/virtio-mmio.c
> > @@ -15,28 +15,28 @@
> >  #include "libqos/malloc-generic.h"
> >  #include "standard-headers/linux/virtio_ring.h"
> >  
> > -static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t addr)
> > +static uint8_t qvirtio_mmio_config_readb(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> > -    return readb(dev->addr + addr);
> > +    return readb(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
> >  }
> >  
> > -static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t addr)
> > +static uint16_t qvirtio_mmio_config_readw(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> > -    return readw(dev->addr + addr);
> > +    return readw(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
> >  }
> >  
> > -static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t addr)
> > +static uint32_t qvirtio_mmio_config_readl(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> > -    return readl(dev->addr + addr);
> > +    return readl(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
> >  }
> >  
> > -static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t addr)
> > +static uint64_t qvirtio_mmio_config_readq(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d;
> > -    return readq(dev->addr + addr);
> > +    return readq(dev->addr + QVIRTIO_MMIO_DEVICE_SPECIFIC + off);
> >  }
> >  
> >  static uint32_t qvirtio_mmio_get_features(QVirtioDevice *d)
> > diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
> > index 6e005c1..8037724 100644
> > --- a/tests/libqos/virtio-pci.c
> > +++ b/tests/libqos/virtio-pci.c
> > @@ -62,39 +62,43 @@ static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data)
> >      *vpcidev = (QVirtioPCIDevice *)d;
> >  }
> >  
> > -static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t addr)
> > +static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> > -    return qpci_io_readb(dev->pdev, (void *)(uintptr_t)addr);
> > +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> 
> $ git grep VIRTIO_PCI_CONFIG_OFF tests
> tests/libqos/virtio-pci.c:    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> tests/libqos/virtio-pci.c:    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> tests/libqos/virtio-pci.c:    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> tests/libqos/virtio-pci.c:    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> 
> Maybe this could be consolidated into a helper ?

Good idea, I'll add a macro.

> 
> Either way works for me since it is a definite improvement over what we currently have:
> 
> Reviewed-by: Greg Kurz <groug@kaod.org>
> 
> > +    return qpci_io_readb(dev->pdev, base + off);
> >  }
> >  
> > -static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t addr)
> > +static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> > -    return qpci_io_readw(dev->pdev, (void *)(uintptr_t)addr);
> > +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> > +    return qpci_io_readw(dev->pdev, base + off);
> >  }
> >  
> > -static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t addr)
> > +static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> > -    return qpci_io_readl(dev->pdev, (void *)(uintptr_t)addr);
> > +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> > +    return qpci_io_readl(dev->pdev, base + off);
> >  }
> >  
> > -static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t addr)
> > +static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> >      int i;
> >      uint64_t u64 = 0;
> > +    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> >  
> >      if (target_big_endian()) {
> >          for (i = 0; i < 8; ++i) {
> >              u64 |= (uint64_t)qpci_io_readb(dev->pdev,
> > -                                (void *)(uintptr_t)addr + i) << (7 - i) * 8;
> > +                                           base + off + i) << (7 - i) * 8;
> >          }
> >      } else {
> >          for (i = 0; i < 8; ++i) {
> >              u64 |= (uint64_t)qpci_io_readb(dev->pdev,
> > -                                (void *)(uintptr_t)addr + i) << i * 8;
> > +                                           base + off + i) << i * 8;
> >          }
> >      }
> >  
> > diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
> > index e8b2196..620e523 100644
> > --- a/tests/virtio-9p-test.c
> > +++ b/tests/virtio-9p-test.c
> > @@ -92,7 +92,6 @@ static void qvirtio_9p_pci_free(QVirtIO9P *v9p)
> >  static void pci_basic_config(void)
> >  {
> >      QVirtIO9P *v9p;
> > -    void *addr;
> >      size_t tag_len;
> >      char *tag;
> >      int i;
> > @@ -100,16 +99,12 @@ static void pci_basic_config(void)
> >      qvirtio_9p_start();
> >      v9p = qvirtio_9p_pci_init();
> >  
> > -    addr = ((QVirtioPCIDevice *) v9p->dev)->addr + VIRTIO_PCI_CONFIG_OFF(false);
> > -    tag_len = qvirtio_config_readw(&qvirtio_pci, v9p->dev,
> > -                                   (uint64_t)(uintptr_t)addr);
> > +    tag_len = qvirtio_config_readw(&qvirtio_pci, v9p->dev, 0);
> >      g_assert_cmpint(tag_len, ==, strlen(mount_tag));
> > -    addr += sizeof(uint16_t);
> >  
> >      tag = g_malloc(tag_len);
> >      for (i = 0; i < tag_len; i++) {
> > -        tag[i] = qvirtio_config_readb(&qvirtio_pci, v9p->dev,
> > -                                      (uint64_t)(uintptr_t)addr + i);
> > +        tag[i] = qvirtio_config_readb(&qvirtio_pci, v9p->dev, i + 2);
> >      }
> >      g_assert_cmpmem(tag, tag_len, mount_tag, tag_len);
> >      g_free(tag);
> > diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
> > index 0506917..9162a5d 100644
> > --- a/tests/virtio-blk-test.c
> > +++ b/tests/virtio-blk-test.c
> > @@ -151,7 +151,7 @@ static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioBlkReq *req,
> >  }
> >  
> >  static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
> > -            QGuestAllocator *alloc, QVirtQueue *vq, uint64_t device_specific)
> > +                       QGuestAllocator *alloc, QVirtQueue *vq)
> >  {
> >      QVirtioBlkReq req;
> >      uint64_t req_addr;
> > @@ -161,7 +161,7 @@ static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
> >      uint8_t status;
> >      char *data;
> >  
> > -    capacity = qvirtio_config_readq(bus, dev, device_specific);
> > +    capacity = qvirtio_config_readq(bus, dev, 0);
> >  
> >      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
> >  
> > @@ -282,7 +282,6 @@ static void pci_basic(void)
> >      QPCIBus *bus;
> >      QVirtQueuePCI *vqpci;
> >      QGuestAllocator *alloc;
> > -    void *addr;
> >  
> >      bus = pci_test_start();
> >      dev = virtio_blk_pci_init(bus, PCI_SLOT);
> > @@ -291,11 +290,7 @@ static void pci_basic(void)
> >      vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
> >                                                                      alloc, 0);
> >  
> > -    /* MSI-X is not enabled */
> > -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> > -
> > -    test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq,
> > -                                                    (uint64_t)(uintptr_t)addr);
> > +    test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq);
> >  
> >      /* End test */
> >      qvirtqueue_cleanup(&qvirtio_pci, &vqpci->vq, alloc);
> > @@ -314,7 +309,6 @@ static void pci_indirect(void)
> >      QGuestAllocator *alloc;
> >      QVirtioBlkReq req;
> >      QVRingIndirectDesc *indirect;
> > -    void *addr;
> >      uint64_t req_addr;
> >      uint64_t capacity;
> >      uint32_t features;
> > @@ -326,11 +320,7 @@ static void pci_indirect(void)
> >  
> >      dev = virtio_blk_pci_init(bus, PCI_SLOT);
> >  
> > -    /* MSI-X is not enabled */
> > -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> > -
> > -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> > -                                                    (uint64_t)(uintptr_t)addr);
> > +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
> >      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
> >  
> >      features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
> > @@ -414,18 +404,13 @@ static void pci_config(void)
> >      QVirtioPCIDevice *dev;
> >      QPCIBus *bus;
> >      int n_size = TEST_IMAGE_SIZE / 2;
> > -    void *addr;
> >      uint64_t capacity;
> >  
> >      bus = pci_test_start();
> >  
> >      dev = virtio_blk_pci_init(bus, PCI_SLOT);
> >  
> > -    /* MSI-X is not enabled */
> > -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> > -
> > -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> > -                                                    (uint64_t)(uintptr_t)addr);
> > +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
> >      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
> >  
> >      qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
> > @@ -434,8 +419,7 @@ static void pci_config(void)
> >                                                      " 'size': %d } }", n_size);
> >      qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
> >  
> > -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> > -                                                    (uint64_t)(uintptr_t)addr);
> > +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
> >      g_assert_cmpint(capacity, ==, n_size / 512);
> >  
> >      qvirtio_pci_device_disable(dev);
> > @@ -452,7 +436,6 @@ static void pci_msix(void)
> >      QGuestAllocator *alloc;
> >      QVirtioBlkReq req;
> >      int n_size = TEST_IMAGE_SIZE / 2;
> > -    void *addr;
> >      uint64_t req_addr;
> >      uint64_t capacity;
> >      uint32_t features;
> > @@ -468,11 +451,7 @@ static void pci_msix(void)
> >  
> >      qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
> >  
> > -    /* MSI-X is enabled */
> > -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
> > -
> > -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> > -                                                    (uint64_t)(uintptr_t)addr);
> > +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
> >      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
> >  
> >      features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
> > @@ -493,8 +472,7 @@ static void pci_msix(void)
> >  
> >      qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
> >  
> > -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> > -                                                    (uint64_t)(uintptr_t)addr);
> > +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
> >      g_assert_cmpint(capacity, ==, n_size / 512);
> >  
> >      /* Write request */
> > @@ -568,7 +546,6 @@ static void pci_idx(void)
> >      QVirtQueuePCI *vqpci;
> >      QGuestAllocator *alloc;
> >      QVirtioBlkReq req;
> > -    void *addr;
> >      uint64_t req_addr;
> >      uint64_t capacity;
> >      uint32_t features;
> > @@ -584,11 +561,7 @@ static void pci_idx(void)
> >  
> >      qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
> >  
> > -    /* MSI-X is enabled */
> > -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
> > -
> > -    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
> > -                                                    (uint64_t)(uintptr_t)addr);
> > +    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev, 0);
> >      g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
> >  
> >      features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
> > @@ -731,8 +704,7 @@ static void mmio_basic(void)
> >      alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
> >      vq = qvirtqueue_setup(&qvirtio_mmio, &dev->vdev, alloc, 0);
> >  
> > -    test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq,
> > -                            QVIRTIO_MMIO_DEVICE_SPECIFIC);
> > +    test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq);
> >  
> >      qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
> >                                                      " 'size': %d } }", n_size);
> > @@ -740,8 +712,7 @@ static void mmio_basic(void)
> >      qvirtio_wait_queue_isr(&qvirtio_mmio, &dev->vdev, vq,
> >                             QVIRTIO_BLK_TIMEOUT_US);
> >  
> > -    capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev,
> > -                                                QVIRTIO_MMIO_DEVICE_SPECIFIC);
> > +    capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev, 0);
> >      g_assert_cmpint(capacity, ==, n_size / 512);
> >  
> >      /* End test */
> > diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
> > index 79088bb..2df8f9a 100644
> > --- a/tests/virtio-scsi-test.c
> > +++ b/tests/virtio-scsi-test.c
> > @@ -141,7 +141,6 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
> >      QVirtIOSCSI *vs;
> >      QVirtioPCIDevice *dev;
> >      struct virtio_scsi_cmd_resp resp;
> > -    void *addr;
> >      int i;
> >  
> >      vs = g_new0(QVirtIOSCSI, 1);
> > @@ -158,9 +157,7 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
> >      qvirtio_set_acknowledge(&qvirtio_pci, vs->dev);
> >      qvirtio_set_driver(&qvirtio_pci, vs->dev);
> >  
> > -    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
> > -    vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev,
> > -                                          (uint64_t)(uintptr_t)addr);
> > +    vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev, 0);
> >  
> >      g_assert_cmpint(vs->num_queues, <, MAX_NUM_QUEUES);
> >  
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 2/8] libqos: Handle PCI IO de-multiplexing in common code
  2016-10-18 13:28   ` Laurent Vivier
@ 2016-10-19  2:59     ` David Gibson
  0 siblings, 0 replies; 28+ messages in thread
From: David Gibson @ 2016-10-19  2:59 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: pbonzini, qemu-devel, qemu-ppc, agraf, stefanha, mst, aik,
	mdroth, groug, thuth

[-- Attachment #1: Type: text/plain, Size: 18266 bytes --]

On Tue, Oct 18, 2016 at 03:28:17PM +0200, Laurent Vivier wrote:
> 
> 
> On 18/10/2016 12:52, David Gibson wrote:
> > The PCI IO space (aka PIO, aka legacy IO) and PCI memory space (aka MMIO)
> > are distinct address spaces by the PCI spec (although parts of one might be
> > aliased to parts of the other in some cases).
> > 
> > However, qpci_io_read*() and qpci_io_write*() can perform accesses to
> > either space depending on parameter.  That's convenient for test case
> > drivers, since there are a fair few devices which can be controlled via
> > either a PIO or MMIO BAR but with an otherwise identical driver.
> > 
> > This is implemented by having addresses below 64kiB treated as PIO, and
> > those above treated as MMIO.  This works because low addresses in memory
> > space are generally reserved for DMA rather than MMIO.
> > 
> > At the moment, this demultiplexing must be handled by each PCI backend
> > (pc and spapr, so far).  There's no real reason for this - the current
> > encoding is likely to work for all platforms, and even if it doesn't we
> > can still use a more complex common encoding since the value returned from
> > iomap are semi-opaque.
> > 
> > This patch moves the demultiplexing into the common part of the libqos PCI
> > code, with the backends having simpler, separate accessors for PIO and
> > MMIO space.  This also means we have a way of explicitly accessing either
> > space if it's necessary for some special case.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> >  tests/libqos/pci-pc.c    | 107 ++++++++++++++++++++----------------------
> >  tests/libqos/pci-spapr.c | 118 +++++++++++++++++++++++++----------------------
> >  tests/libqos/pci.c       |  49 +++++++++++++++++---
> >  tests/libqos/pci.h       |  22 ++++++---
> >  4 files changed, 170 insertions(+), 126 deletions(-)
> > 
> > diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
> > index 9600ed6..51dff8a 100644
> > --- a/tests/libqos/pci-pc.c
> > +++ b/tests/libqos/pci-pc.c
> > @@ -36,79 +36,64 @@ typedef struct QPCIBusPC
> >      uint16_t pci_iohole_alloc;
> >  } QPCIBusPC;
> >  
> > -static uint8_t qpci_pc_io_readb(QPCIBus *bus, void *addr)
> > +static uint8_t qpci_pc_pio_readb(QPCIBus *bus, uint32_t addr)
> >  {
> > -    uintptr_t port = (uintptr_t)addr;
> > -    uint8_t value;
> > -
> > -    if (port < 0x10000) {
> > -        value = inb(port);
> > -    } else {
> > -        value = readb(port);
> > -    }
> > -
> > -    return value;
> > +    return inb(addr);
> >  }
> >  
> > -static uint16_t qpci_pc_io_readw(QPCIBus *bus, void *addr)
> > +static uint8_t qpci_pc_mmio_readb(QPCIBus *bus, uint32_t addr)
> >  {
> > -    uintptr_t port = (uintptr_t)addr;
> > -    uint16_t value;
> > -
> > -    if (port < 0x10000) {
> > -        value = inw(port);
> > -    } else {
> > -        value = readw(port);
> > -    }
> > +    return readb(addr);
> > +}
> >  
> > -    return value;
> > +static void qpci_pc_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
> > +{
> > +    outb(addr, val);
> >  }
> >  
> > -static uint32_t qpci_pc_io_readl(QPCIBus *bus, void *addr)
> > +static void qpci_pc_mmio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
> >  {
> > -    uintptr_t port = (uintptr_t)addr;
> > -    uint32_t value;
> > +    writeb(addr, val);
> > +}
> >  
> > -    if (port < 0x10000) {
> > -        value = inl(port);
> > -    } else {
> > -        value = readl(port);
> > -    }
> > +static uint16_t qpci_pc_pio_readw(QPCIBus *bus, uint32_t addr)
> > +{
> > +    return inw(addr);
> > +}
> >  
> > -    return value;
> > +static uint16_t qpci_pc_mmio_readw(QPCIBus *bus, uint32_t addr)
> > +{
> > +    return readw(addr);
> >  }
> >  
> > -static void qpci_pc_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
> > +static void qpci_pc_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
> >  {
> > -    uintptr_t port = (uintptr_t)addr;
> > +    outw(addr, val);
> > +}
> >  
> > -    if (port < 0x10000) {
> > -        outb(port, value);
> > -    } else {
> > -        writeb(port, value);
> > -    }
> > +static void qpci_pc_mmio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
> > +{
> > +    writew(addr, val);
> >  }
> >  
> > -static void qpci_pc_io_writew(QPCIBus *bus, void *addr, uint16_t value)
> > +static uint32_t qpci_pc_pio_readl(QPCIBus *bus, uint32_t addr)
> >  {
> > -    uintptr_t port = (uintptr_t)addr;
> > +    return inl(addr);
> > +}
> >  
> > -    if (port < 0x10000) {
> > -        outw(port, value);
> > -    } else {
> > -        writew(port, value);
> > -    }
> > +static uint32_t qpci_pc_mmio_readl(QPCIBus *bus, uint32_t addr)
> > +{
> > +    return readl(addr);
> >  }
> >  
> > -static void qpci_pc_io_writel(QPCIBus *bus, void *addr, uint32_t value)
> > +static void qpci_pc_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
> >  {
> > -    uintptr_t port = (uintptr_t)addr;
> > +    outl(addr, val);
> > +}
> >  
> > -    if (port < 0x10000) {
> > -        outl(port, value);
> > -    } else {
> > -        writel(port, value);
> > -    }
> > +static void qpci_pc_mmio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
> > +{
> > +    writel(addr, val);
> >  }
> >  
> >  static uint8_t qpci_pc_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
> > @@ -218,13 +203,21 @@ QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
> >  
> >      ret = g_malloc(sizeof(*ret));
> >  
> > -    ret->bus.io_readb = qpci_pc_io_readb;
> > -    ret->bus.io_readw = qpci_pc_io_readw;
> > -    ret->bus.io_readl = qpci_pc_io_readl;
> > +    ret->bus.pio_readb = qpci_pc_pio_readb;
> > +    ret->bus.pio_readw = qpci_pc_pio_readw;
> > +    ret->bus.pio_readl = qpci_pc_pio_readl;
> > +
> > +    ret->bus.pio_writeb = qpci_pc_pio_writeb;
> > +    ret->bus.pio_writew = qpci_pc_pio_writew;
> > +    ret->bus.pio_writel = qpci_pc_pio_writel;
> > +
> > +    ret->bus.mmio_readb = qpci_pc_mmio_readb;
> > +    ret->bus.mmio_readw = qpci_pc_mmio_readw;
> > +    ret->bus.mmio_readl = qpci_pc_mmio_readl;
> >  
> > -    ret->bus.io_writeb = qpci_pc_io_writeb;
> > -    ret->bus.io_writew = qpci_pc_io_writew;
> > -    ret->bus.io_writel = qpci_pc_io_writel;
> > +    ret->bus.mmio_writeb = qpci_pc_mmio_writeb;
> > +    ret->bus.mmio_writew = qpci_pc_mmio_writew;
> > +    ret->bus.mmio_writel = qpci_pc_mmio_writel;
> >  
> >      ret->bus.config_readb = qpci_pc_config_readb;
> >      ret->bus.config_readw = qpci_pc_config_readw;
> > diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
> > index 2eaaf91..2d26a94 100644
> > --- a/tests/libqos/pci-spapr.c
> > +++ b/tests/libqos/pci-spapr.c
> > @@ -50,78 +50,76 @@ typedef struct QPCIBusSPAPR {
> >   * so PCI accessors need to swap data endianness
> >   */
> >  
> > -static uint8_t qpci_spapr_io_readb(QPCIBus *bus, void *addr)
> > +static uint8_t qpci_spapr_pio_readb(QPCIBus *bus, uint32_t addr)
> >  {
> >      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > -    uint64_t port = (uintptr_t)addr;
> > -    uint8_t v;
> > -    if (port < s->pio.size) {
> > -        v = readb(s->pio_cpu_base + port);
> > -    } else {
> > -        v = readb(s->mmio32_cpu_base + port);
> > -    }
> > -    return v;
> > +    return readb(s->pio_cpu_base + addr);
> >  }
> >  
> > -static uint16_t qpci_spapr_io_readw(QPCIBus *bus, void *addr)
> > +static uint8_t qpci_spapr_mmio32_readb(QPCIBus *bus, uint32_t addr)
> >  {
> >      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > -    uint64_t port = (uintptr_t)addr;
> > -    uint16_t v;
> > -    if (port < s->pio.size) {
> > -        v = readw(s->pio_cpu_base + port);
> > -    } else {
> > -        v = readw(s->mmio32_cpu_base + port);
> > -    }
> > -    return bswap16(v);
> > +    return readb(s->mmio32_cpu_base + addr);
> >  }
> >  
> > -static uint32_t qpci_spapr_io_readl(QPCIBus *bus, void *addr)
> > +static void qpci_spapr_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
> >  {
> >      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > -    uint64_t port = (uintptr_t)addr;
> > -    uint32_t v;
> > -    if (port < s->pio.size) {
> > -        v = readl(s->pio_cpu_base + port);
> > -    } else {
> > -        v = readl(s->mmio32_cpu_base + port);
> > -    }
> > -    return bswap32(v);
> > +    writeb(s->pio_cpu_base + addr, val);
> >  }
> >  
> > -static void qpci_spapr_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
> > +static void qpci_spapr_mmio32_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
> >  {
> >      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > -    uint64_t port = (uintptr_t)addr;
> > -    if (port < s->pio.size) {
> > -        writeb(s->pio_cpu_base + port, value);
> > -    } else {
> > -        writeb(s->mmio32_cpu_base + port, value);
> > -    }
> > +    writeb(s->mmio32_cpu_base + addr, val);
> >  }
> >  
> > -static void qpci_spapr_io_writew(QPCIBus *bus, void *addr, uint16_t value)
> > +static uint16_t qpci_spapr_pio_readw(QPCIBus *bus, uint32_t addr)
> >  {
> >      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > -    uint64_t port = (uintptr_t)addr;
> > -    value = bswap16(value);
> > -    if (port < s->pio.size) {
> > -        writew(s->pio_cpu_base + port, value);
> > -    } else {
> > -        writew(s->mmio32_cpu_base + port, value);
> > -    }
> > +    return bswap16(readw(s->pio_cpu_base + addr));
> >  }
> >  
> > -static void qpci_spapr_io_writel(QPCIBus *bus, void *addr, uint32_t value)
> > +static uint16_t qpci_spapr_mmio32_readw(QPCIBus *bus, uint32_t addr)
> >  {
> >      QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > -    uint64_t port = (uintptr_t)addr;
> > -    value = bswap32(value);
> > -    if (port < s->pio.size) {
> > -        writel(s->pio_cpu_base + port, value);
> > -    } else {
> > -        writel(s->mmio32_cpu_base + port, value);
> > -    }
> > +    return bswap16(readw(s->mmio32_cpu_base + addr));
> > +}
> > +
> > +static void qpci_spapr_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
> > +{
> > +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > +    writew(s->pio_cpu_base + addr, bswap16(val));
> > +}
> > +
> > +static void qpci_spapr_mmio32_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
> > +{
> > +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > +    writew(s->mmio32_cpu_base + addr, bswap16(val));
> > +}
> > +
> > +static uint32_t qpci_spapr_pio_readl(QPCIBus *bus, uint32_t addr)
> > +{
> > +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > +    return bswap32(readl(s->pio_cpu_base + addr));
> > +}
> > +
> > +static uint32_t qpci_spapr_mmio32_readl(QPCIBus *bus, uint32_t addr)
> > +{
> > +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > +    return bswap32(readl(s->mmio32_cpu_base + addr));
> > +}
> > +
> > +static void qpci_spapr_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
> > +{
> > +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > +    writel(s->pio_cpu_base + addr, bswap32(val));
> > +}
> > +
> > +static void qpci_spapr_mmio32_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
> > +{
> > +    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > +    writel(s->mmio32_cpu_base + addr, bswap32(val));
> >  }
> >  
> >  static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
> > @@ -248,13 +246,21 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
> >  
> >      ret->alloc = alloc;
> >  
> > -    ret->bus.io_readb = qpci_spapr_io_readb;
> > -    ret->bus.io_readw = qpci_spapr_io_readw;
> > -    ret->bus.io_readl = qpci_spapr_io_readl;
> > +    ret->bus.pio_readb = qpci_spapr_pio_readb;
> > +    ret->bus.pio_readw = qpci_spapr_pio_readw;
> > +    ret->bus.pio_readl = qpci_spapr_pio_readl;
> > +
> > +    ret->bus.pio_writeb = qpci_spapr_pio_writeb;
> > +    ret->bus.pio_writew = qpci_spapr_pio_writew;
> > +    ret->bus.pio_writel = qpci_spapr_pio_writel;
> > +
> > +    ret->bus.mmio_readb = qpci_spapr_mmio32_readb;
> > +    ret->bus.mmio_readw = qpci_spapr_mmio32_readw;
> > +    ret->bus.mmio_readl = qpci_spapr_mmio32_readl;
> >  
> > -    ret->bus.io_writeb = qpci_spapr_io_writeb;
> > -    ret->bus.io_writew = qpci_spapr_io_writew;
> > -    ret->bus.io_writel = qpci_spapr_io_writel;
> > +    ret->bus.mmio_writeb = qpci_spapr_mmio32_writeb;
> > +    ret->bus.mmio_writew = qpci_spapr_mmio32_writew;
> > +    ret->bus.mmio_writel = qpci_spapr_mmio32_writel;
> >  
> >      ret->bus.config_readb = qpci_spapr_config_readb;
> >      ret->bus.config_readw = qpci_spapr_config_readw;
> > diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
> > index c3f3382..55b01df 100644
> > --- a/tests/libqos/pci.c
> > +++ b/tests/libqos/pci.c
> > @@ -224,33 +224,68 @@ void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
> >  
> >  uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
> >  {
> > -    return dev->bus->io_readb(dev->bus, data);
> > +    uintptr_t addr = (uintptr_t)data;
> > +
> > +    if (addr < QPCI_PIO_LIMIT) {
> > +        return dev->bus->pio_readb(dev->bus, addr);
> > +    } else {
> > +        return dev->bus->mmio_readb(dev->bus, addr);
> > +    }
> >  }
> >  
> >  uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
> >  {
> > -    return dev->bus->io_readw(dev->bus, data);
> > +    uintptr_t addr = (uintptr_t)data;
> > +
> > +    if (addr < QPCI_PIO_LIMIT) {
> > +        return dev->bus->pio_readw(dev->bus, addr);
> > +    } else {
> > +        return dev->bus->mmio_readw(dev->bus, addr);
> > +    }
> >  }
> >  
> >  uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
> >  {
> > -    return dev->bus->io_readl(dev->bus, data);
> > -}
> > +    uintptr_t addr = (uintptr_t)data;
> >  
> > +    if (addr < QPCI_PIO_LIMIT) {
> > +        return dev->bus->pio_readl(dev->bus, addr);
> > +    } else {
> > +        return dev->bus->mmio_readl(dev->bus, addr);
> > +    }
> > +}
> >  
> >  void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
> >  {
> > -    dev->bus->io_writeb(dev->bus, data, value);
> > +    uintptr_t addr = (uintptr_t)data;
> > +
> > +    if (addr < QPCI_PIO_LIMIT) {
> > +        dev->bus->pio_writeb(dev->bus, addr, value);
> > +    } else {
> > +        dev->bus->mmio_writeb(dev->bus, addr, value);
> > +    }
> >  }
> >  
> >  void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
> >  {
> > -    dev->bus->io_writew(dev->bus, data, value);
> > +    uintptr_t addr = (uintptr_t)data;
> > +
> > +    if (addr < QPCI_PIO_LIMIT) {
> > +        dev->bus->pio_writew(dev->bus, addr, value);
> > +    } else {
> > +        dev->bus->mmio_writew(dev->bus, addr, value);
> > +    }
> >  }
> >  
> >  void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
> >  {
> > -    dev->bus->io_writel(dev->bus, data, value);
> > +    uintptr_t addr = (uintptr_t)data;
> > +
> > +    if (addr < QPCI_PIO_LIMIT) {
> > +        dev->bus->pio_writel(dev->bus, addr, value);
> > +    } else {
> > +        dev->bus->mmio_writel(dev->bus, addr, value);
> > +    }
> >  }
> >  
> >  void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
> > diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
> > index c06add8..72a2245 100644
> > --- a/tests/libqos/pci.h
> > +++ b/tests/libqos/pci.h
> > @@ -15,6 +15,8 @@
> >  
> >  #include "libqtest.h"
> >  
> > +#define QPCI_PIO_LIMIT    0x10000
> 
> Perhaps you can remove the definition of SPAPR_PCI_IO_WIN_SIZE and use
> QPCI_PIO_LIMIT instead in pci-spapr.c?
> or add a QEMU_BUILD_BUG_ON(SPAPR_PCI_IO_WIN_SIZE != QPCI_PIO_LIMIT)?

I don't think that's really right.  They'll match in practice because
PIO space is basically always 64kiB, but they don't actually have to,
technically.  QPCI_PIO_LIMIT describes how the multiplexed address
space for BAR "pointers" is divided.  SPAPR_PCI_IO_WIN_SIZE describes
how much IO space the hardware can really map.  If they don't match
you might not be able to access all the hardware's PIO space.  But
that's already true for MMIO space, so I don't think it's a
fundamental problem.

> > +
> >  #define QPCI_DEVFN(dev, fn) (((dev) << 3) | (fn))
> >  
> >  typedef struct QPCIDevice QPCIDevice;
> > @@ -22,13 +24,21 @@ typedef struct QPCIBus QPCIBus;
> >  
> >  struct QPCIBus
> >  {
> > -    uint8_t (*io_readb)(QPCIBus *bus, void *addr);
> > -    uint16_t (*io_readw)(QPCIBus *bus, void *addr);
> > -    uint32_t (*io_readl)(QPCIBus *bus, void *addr);
> > +    uint8_t (*pio_readb)(QPCIBus *bus, uint32_t addr);
> > +    uint16_t (*pio_readw)(QPCIBus *bus, uint32_t addr);
> > +    uint32_t (*pio_readl)(QPCIBus *bus, uint32_t addr);
> > +
> > +    uint8_t (*mmio_readb)(QPCIBus *bus, uint32_t addr);
> > +    uint16_t (*mmio_readw)(QPCIBus *bus, uint32_t addr);
> > +    uint32_t (*mmio_readl)(QPCIBus *bus, uint32_t addr);
> > +
> > +    void (*pio_writeb)(QPCIBus *bus, uint32_t addr, uint8_t value);
> > +    void (*pio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
> > +    void (*pio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
> >  
> > -    void (*io_writeb)(QPCIBus *bus, void *addr, uint8_t value);
> > -    void (*io_writew)(QPCIBus *bus, void *addr, uint16_t value);
> > -    void (*io_writel)(QPCIBus *bus, void *addr, uint32_t value);
> > +    void (*mmio_writeb)(QPCIBus *bus, uint32_t addr, uint8_t value);
> > +    void (*mmio_writew)(QPCIBus *bus, uint32_t addr, uint16_t value);
> > +    void (*mmio_writel)(QPCIBus *bus, uint32_t addr, uint32_t value);
> >  
> >      uint8_t (*config_readb)(QPCIBus *bus, int devfn, uint8_t offset);
> >      uint16_t (*config_readw)(QPCIBus *bus, int devfn, uint8_t offset);
> > 
> 
> Thanks,
> Laurent
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 3/8] libqos: Move BAR assignment to common code
  2016-10-18 15:00   ` Laurent Vivier
@ 2016-10-19  3:07     ` David Gibson
  0 siblings, 0 replies; 28+ messages in thread
From: David Gibson @ 2016-10-19  3:07 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: pbonzini, qemu-devel, qemu-ppc, agraf, stefanha, mst, aik,
	mdroth, groug, thuth

[-- Attachment #1: Type: text/plain, Size: 9487 bytes --]

On Tue, Oct 18, 2016 at 05:00:08PM +0200, Laurent Vivier wrote:
> 
> 
> On 18/10/2016 12:52, David Gibson wrote:
> > The PCI backends in libqos each supply an iomap() and iounmap() function
> > which is used to set up a specified PCI BAR.  But PCI BAR allocation takes
> > place entirely within PCI space, so doesn't really need per-backend
> > versions.  For example, Linux includes generic BAR allocation code used on
> > platforms where that isn't done by firmware.
> > 
> > This patch merges the BAR allocation from the two existing backends into a
> > single simplified copy.  The back ends just need to set up some parameters
> > describing the window of PCI IO and PCI memory addresses which are
> > available for allocation.  Like both the existing versions the new one uses
> > a simple bump allocator.
> > 
> > Note that (again like the existing versions) this doesn't really handle
> > 64-bit memory BARs properly.  It is actually used for such a BAR by the
> > ivshmem test, and apparently the 32-bit MMIO BAR logic is close enough to
> > work, as long as the BAR isn't too big.  Fixing that to properly handle
> > 64-bit BAR allocation is a problem for another time.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> >  tests/libqos/pci-pc.c    | 79 ++--------------------------------------------
> >  tests/libqos/pci-spapr.c | 81 ++----------------------------------------------
> >  tests/libqos/pci.c       | 56 +++++++++++++++++++++++++++++++--
> >  tests/libqos/pci.h       |  7 ++---
> >  4 files changed, 63 insertions(+), 160 deletions(-)
> > 
> > diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
> > index 51dff8a..b087d13 100644
> > --- a/tests/libqos/pci-pc.c
> > +++ b/tests/libqos/pci-pc.c
> > @@ -17,7 +17,6 @@
> >  #include "hw/pci/pci_regs.h"
> >  
> >  #include "qemu-common.h"
> > -#include "qemu/host-utils.h"
> >  
> >  
> >  #define ACPI_PCIHP_ADDR         0xae00
> > @@ -132,71 +131,6 @@ static void qpci_pc_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint3
> >      outl(0xcfc, value);
> >  }
> >  
> > -static void *qpci_pc_iomap(QPCIBus *bus, QPCIDevice *dev, int barno, uint64_t *sizeptr)
> > -{
> > -    QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
> > -    static const int bar_reg_map[] = {
> > -        PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
> > -        PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
> > -    };
> > -    int bar_reg;
> > -    uint32_t addr;
> > -    uint64_t size;
> > -    uint32_t io_type;
> > -
> > -    g_assert(barno >= 0 && barno <= 5);
> > -    bar_reg = bar_reg_map[barno];
> > -
> > -    qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
> > -    addr = qpci_config_readl(dev, bar_reg);
> > -
> > -    io_type = addr & PCI_BASE_ADDRESS_SPACE;
> > -    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
> > -        addr &= PCI_BASE_ADDRESS_IO_MASK;
> > -    } else {
> > -        addr &= PCI_BASE_ADDRESS_MEM_MASK;
> > -    }
> > -
> > -    size = (1ULL << ctzl(addr));
> > -    if (size == 0) {
> > -        return NULL;
> > -    }
> > -    if (sizeptr) {
> > -        *sizeptr = size;
> > -    }
> > -
> > -    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
> > -        uint16_t loc;
> > -
> > -        g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
> > -                 <= s->pci_iohole_size);
> > -        s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
> > -        loc = s->pci_iohole_start + s->pci_iohole_alloc;
> > -        s->pci_iohole_alloc += size;
> > -
> > -        qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
> > -
> > -        return (void *)(intptr_t)loc;
> > -    } else {
> > -        uint64_t loc;
> > -
> > -        g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
> > -                 <= s->pci_hole_size);
> > -        s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
> > -        loc = s->pci_hole_start + s->pci_hole_alloc;
> > -        s->pci_hole_alloc += size;
> > -
> > -        qpci_config_writel(dev, bar_reg, loc);
> > -
> > -        return (void *)(intptr_t)loc;
> > -    }
> > -}
> > -
> > -static void qpci_pc_iounmap(QPCIBus *bus, void *data)
> > -{
> > -    /* FIXME */
> > -}
> > -
> >  QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
> >  {
> >      QPCIBusPC *ret;
> > @@ -227,16 +161,9 @@ QPCIBus *qpci_init_pc(QGuestAllocator *alloc)
> >      ret->bus.config_writew = qpci_pc_config_writew;
> >      ret->bus.config_writel = qpci_pc_config_writel;
> >  
> > -    ret->bus.iomap = qpci_pc_iomap;
> > -    ret->bus.iounmap = qpci_pc_iounmap;
> > -
> > -    ret->pci_hole_start = 0xE0000000;
> > -    ret->pci_hole_size = 0x20000000;
> > -    ret->pci_hole_alloc = 0;
> > -
> > -    ret->pci_iohole_start = 0xc000;
> > -    ret->pci_iohole_size = 0x4000;
> > -    ret->pci_iohole_alloc = 0;
> 
> I think you can remove all these fields (pci_hole_.., pci_iohole_...)
> from QPCIBusPC.
> 
> > +    ret->bus.pio_alloc_ptr = 0xc000;
> > +    ret->bus.mmio_alloc_ptr = 0xE0000000;
> > +    ret->bus.mmio_limit = 0x100000000ULL;
> >  
> >      return &ret->bus;
> >  }
> > diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
> > index 2d26a94..9a18d8a 100644
> > --- a/tests/libqos/pci-spapr.c
> > +++ b/tests/libqos/pci-spapr.c
> > @@ -167,72 +167,6 @@ static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset,
> >      qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 4, value);
> >  }
> >  
> > -static void *qpci_spapr_iomap(QPCIBus *bus, QPCIDevice *dev, int barno,
> > -                              uint64_t *sizeptr)
> > -{
> > -    QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> > -    static const int bar_reg_map[] = {
> > -        PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
> > -        PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
> > -    };
> > -    int bar_reg;
> > -    uint32_t addr;
> > -    uint64_t size;
> > -    uint32_t io_type;
> > -
> > -    g_assert(barno >= 0 && barno <= 5);
> > -    bar_reg = bar_reg_map[barno];
> > -
> > -    qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
> > -    addr = qpci_config_readl(dev, bar_reg);
> > -
> > -    io_type = addr & PCI_BASE_ADDRESS_SPACE;
> > -    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
> > -        addr &= PCI_BASE_ADDRESS_IO_MASK;
> > -    } else {
> > -        addr &= PCI_BASE_ADDRESS_MEM_MASK;
> > -    }
> > -
> > -    size = (1ULL << ctzl(addr));
> > -    if (size == 0) {
> > -        return NULL;
> > -    }
> > -    if (sizeptr) {
> > -        *sizeptr = size;
> > -    }
> > -
> > -    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
> > -        uint16_t loc;
> > -
> > -        g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
> > -                 <= s->pci_iohole_size);
> > -        s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
> > -        loc = s->pci_iohole_start + s->pci_iohole_alloc;
> > -        s->pci_iohole_alloc += size;
> > -
> > -        qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
> > -
> > -        return (void *)(unsigned long)loc;
> > -    } else {
> > -        uint64_t loc;
> > -
> > -        g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
> > -                 <= s->pci_hole_size);
> > -        s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
> > -        loc = s->pci_hole_start + s->pci_hole_alloc;
> > -        s->pci_hole_alloc += size;
> > -
> > -        qpci_config_writel(dev, bar_reg, loc);
> > -
> > -        return (void *)(unsigned long)loc;
> > -    }
> > -}
> > -
> > -static void qpci_spapr_iounmap(QPCIBus *bus, void *data)
> > -{
> > -    /* FIXME */
> > -}
> > -
> >  #define SPAPR_PCI_BASE               (1ULL << 45)
> >  
> >  #define SPAPR_PCI_MMIO32_WIN_SIZE    0x80000000 /* 2 GiB */
> > @@ -270,9 +204,6 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
> >      ret->bus.config_writew = qpci_spapr_config_writew;
> >      ret->bus.config_writel = qpci_spapr_config_writel;
> >  
> > -    ret->bus.iomap = qpci_spapr_iomap;
> > -    ret->bus.iounmap = qpci_spapr_iounmap;
> > -
> >      /* FIXME: We assume the default location of the PHB for now.
> >       * Ideally we'd parse the device tree deposited in the guest to
> >       * get the window locations */
> > @@ -287,15 +218,9 @@ QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
> >      ret->mmio32.pci_base = 0x80000000; /* 2 GiB */
> >      ret->mmio32.size = SPAPR_PCI_MMIO32_WIN_SIZE;
> >  
> > -    ret->pci_hole_start = 0xC0000000;
> > -    ret->pci_hole_size =
> > -        ret->mmio32.pci_base + ret->mmio32.size - ret->pci_hole_start;
> > -    ret->pci_hole_alloc = 0;
> > -
> > -    ret->pci_iohole_start = 0xc000;
> > -    ret->pci_iohole_size =
> > -        ret->pio.pci_base + ret->pio.size - ret->pci_iohole_start;
> > -    ret->pci_iohole_alloc = 0;
> 
> I think you can remove all these fields (pci_hole_.., pci_iohole_...)
> from QPCIBusSPAPR.

Ah, yes, meant to remove them from both PC and spapr, but forgot.
Done for the next spin.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 4/8] tests: Better handle legacy IO addresses in tco-test
  2016-10-18 15:14   ` Laurent Vivier
  2016-10-18 16:28     ` Laurent Vivier
@ 2016-10-19  3:09     ` David Gibson
  1 sibling, 0 replies; 28+ messages in thread
From: David Gibson @ 2016-10-19  3:09 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: pbonzini, qemu-devel, qemu-ppc, agraf, stefanha, mst, aik,
	mdroth, groug, thuth

[-- Attachment #1: Type: text/plain, Size: 3253 bytes --]

On Tue, Oct 18, 2016 at 05:14:04PM +0200, Laurent Vivier wrote:
> 
> 
> On 18/10/2016 12:52, David Gibson wrote:
> > tco_test uses the libqos PCI code to access the device.  This makes perfect
> > sense for the PCI config space accesses.  However for IO, rather than the
> > usual PCI approach of mapping a PCI BAR, then accessing that, it instead
> > uses the legacy approach of fixed, known addresses in PCI IO space.
> > 
> > That doesn't work very well with the qpci_io_{read,write} functions because
> > we never use qpci_iomap() and so have to make assumptions about the
> > internal encoding of the address tokens iomap() returns.
> > 
> > This patch avoids that, by directly using the bus's pio_{read,write}
> > callbacks, which are defined to take addresses within the PCI IO space.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> >  tests/tco-test.c | 87 ++++++++++++++++++++++++++++----------------------------
> >  1 file changed, 44 insertions(+), 43 deletions(-)
> > 
> > diff --git a/tests/tco-test.c b/tests/tco-test.c
> > index 0d201b1..e668630 100644
> > --- a/tests/tco-test.c
> > +++ b/tests/tco-test.c
> > @@ -40,13 +40,13 @@ enum {
> >  typedef struct {
> >      const char *args;
> >      bool noreboot;
> > +    QPCIBus *bus;
> >      QPCIDevice *dev;
> > -    void *tco_io_base;
> > +    uint16_t tco_io_base;
> >  } TestData;
> >  
> >  static void test_init(TestData *d)
> >  {
> > -    QPCIBus *bus;
> >      QTestState *qs;
> >      char *s;
> >  
> > @@ -57,8 +57,8 @@ static void test_init(TestData *d)
> >      qtest_irq_intercept_in(qs, "ioapic");
> >      g_free(s);
> >  
> > -    bus = qpci_init_pc(NULL);
> > -    d->dev = qpci_device_find(bus, QPCI_DEVFN(0x1f, 0x00));
> > +    d->bus = qpci_init_pc(NULL);
> 
> You can use qtest_pc_boot() now.

I could, but that's not really in scope for this patch.

> > +    d->dev = qpci_device_find(d->bus, QPCI_DEVFN(0x1f, 0x00));
> >      g_assert(d->dev != NULL);
> >  
> >      qpci_device_enable(d->dev);
> > @@ -70,42 +70,42 @@ static void test_init(TestData *d)
> >      /* set Root Complex BAR */
> >      qpci_config_writel(d->dev, ICH9_LPC_RCBA, RCBA_BASE_ADDR | 0x1);
> >  
> > -    d->tco_io_base = (void *)((uintptr_t)PM_IO_BASE_ADDR + 0x60);
> > +    d->tco_io_base = PM_IO_BASE_ADDR + 0x60;
> 
> Why don't you use QPCIBar in TestData to store the address?
> And you can call qpci_io_XXX() with it.

As noted in your later patch, QPCIBar hasn't been introduced at this
stage of the series.  Further, storing the address in there would
require the testcase to understand the QPCIBar's internal structure,
which is exactly what I'm trying to avoid.

Now, it's quite likely that the ICH9 device here has the same
registers aliased in a PIO bar, which we could map in the normal way.
However, if we did that, we wouldn't be testing quite the same thing -
we'd be testing availability of the registers via the BAR address,
rather than via the fixed legacy address.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 4/8] tests: Better handle legacy IO addresses in tco-test
  2016-10-18 16:28     ` Laurent Vivier
@ 2016-10-19  3:19       ` David Gibson
  0 siblings, 0 replies; 28+ messages in thread
From: David Gibson @ 2016-10-19  3:19 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: pbonzini, qemu-devel, qemu-ppc, agraf, stefanha, mst, aik,
	mdroth, groug, thuth

[-- Attachment #1: Type: text/plain, Size: 3575 bytes --]

On Tue, Oct 18, 2016 at 06:28:26PM +0200, Laurent Vivier wrote:
> 
> 
> On 18/10/2016 17:14, Laurent Vivier wrote:
> > 
> > 
> > On 18/10/2016 12:52, David Gibson wrote:
> >> tco_test uses the libqos PCI code to access the device.  This makes perfect
> >> sense for the PCI config space accesses.  However for IO, rather than the
> >> usual PCI approach of mapping a PCI BAR, then accessing that, it instead
> >> uses the legacy approach of fixed, known addresses in PCI IO space.
> >>
> >> That doesn't work very well with the qpci_io_{read,write} functions because
> >> we never use qpci_iomap() and so have to make assumptions about the
> >> internal encoding of the address tokens iomap() returns.
> >>
> >> This patch avoids that, by directly using the bus's pio_{read,write}
> >> callbacks, which are defined to take addresses within the PCI IO space.
> >>
> >> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> >> ---
> >>  tests/tco-test.c | 87 ++++++++++++++++++++++++++++----------------------------
> >>  1 file changed, 44 insertions(+), 43 deletions(-)
> >>
> >> diff --git a/tests/tco-test.c b/tests/tco-test.c
> >> index 0d201b1..e668630 100644
> >> --- a/tests/tco-test.c
> >> +++ b/tests/tco-test.c
> >> @@ -40,13 +40,13 @@ enum {
> >>  typedef struct {
> >>      const char *args;
> >>      bool noreboot;
> >> +    QPCIBus *bus;
> >>      QPCIDevice *dev;
> >> -    void *tco_io_base;
> >> +    uint16_t tco_io_base;
> >>  } TestData;
> >>  
> >>  static void test_init(TestData *d)
> >>  {
> >> -    QPCIBus *bus;
> >>      QTestState *qs;
> >>      char *s;
> >>  
> >> @@ -57,8 +57,8 @@ static void test_init(TestData *d)
> >>      qtest_irq_intercept_in(qs, "ioapic");
> >>      g_free(s);
> >>  
> >> -    bus = qpci_init_pc(NULL);
> >> -    d->dev = qpci_device_find(bus, QPCI_DEVFN(0x1f, 0x00));
> >> +    d->bus = qpci_init_pc(NULL);
> > 
> > You can use qtest_pc_boot() now.
> > 
> >> +    d->dev = qpci_device_find(d->bus, QPCI_DEVFN(0x1f, 0x00));
> >>      g_assert(d->dev != NULL);
> >>  
> >>      qpci_device_enable(d->dev);
> >> @@ -70,42 +70,42 @@ static void test_init(TestData *d)
> >>      /* set Root Complex BAR */
> >>      qpci_config_writel(d->dev, ICH9_LPC_RCBA, RCBA_BASE_ADDR | 0x1);
> >>  
> >> -    d->tco_io_base = (void *)((uintptr_t)PM_IO_BASE_ADDR + 0x60);
> >> +    d->tco_io_base = PM_IO_BASE_ADDR + 0x60;
> > 
> > Why don't you use QPCIBar in TestData to store the address?
> > And you can call qpci_io_XXX() with it.
> 
> OK, I was watching the state of qpci_io_XXX() after the series, so you
> can't do that here, but perhaps this patch should be moved to PATCH 8/8?

No, this is quite deliberately before 8/8.  The point of 8/8 is that
QPCIBar is supposed to be opaque to the tests/drivers.  Using the
legacy addresses requires that the test/driver work directly with the
actual IO address.  Mixing the two - having the test case construct
the base pointer makes the conversion to an opaque token more awkward.

However.. another approach just occurred to me.  I could define a
special QPCIBar constant - exported as a global by libqos, or returned
by a function - which references the legacy PIO space instead of a
particular bar.  The qpci_io_*() functions could be used with that.

I'll look into that, and see how it works.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 8/8] libqos: Change PCI accessors to take opaque BAR handle
  2016-10-18 16:48   ` Laurent Vivier
@ 2016-10-19  4:06     ` David Gibson
  0 siblings, 0 replies; 28+ messages in thread
From: David Gibson @ 2016-10-19  4:06 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: pbonzini, qemu-devel, qemu-ppc, agraf, stefanha, mst, aik,
	mdroth, groug, thuth

[-- Attachment #1: Type: text/plain, Size: 31215 bytes --]

On Tue, Oct 18, 2016 at 06:48:16PM +0200, Laurent Vivier wrote:
> 
> 
> On 18/10/2016 12:52, David Gibson wrote:
> > The usual use model for the libqos PCI functions is to map a specific PCI
> > BAR using qpci_iomap() then pass the returned token into IO accessor
> > functions.  This, and the fact that iomap() returns a (void *) which
> > actually contains a PCI space address, kind of suggests that the return
> > value from iomap is supposed to be an opaque token.
> > 
> > ..except that the callers expect to be able to add offsets to it.  Which
> > also assumes the compiler will support pointer arithmetic on a (void *),
> > and treat it as working with byte offsets.
> > 
> > To clarify this situation change iomap() and the IO accessors to take
> > a definitely opaque BAR handle (enforced with a wrapper struct) along with
> > an offset within the BAR.  This changes both the functions and all the
> > callers.
> > 
> > A few notes:
> >     * Asserts that iomap() returns non-NULL are removed in some places;
> > iomap() already asserts if it can't map the BAR
> >     * In ide-test.c we change explicit outb() etc. calls to matching
> > qpci_io_writeb() calls.  That makes the test more portable, and removes
> > assumptions that the test case shouldn't be making about how iomap()'s
> > return value is formatted internally.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > 
> > # Conflicts:
> > #	tests/libqos/virtio-pci.c
> 
> A sequel of a cherry-pick?
> 
> > ---
> >  tests/ahci-test.c         |   4 +-
> >  tests/e1000e-test.c       |   7 ++-
> >  tests/ide-test.c          |  23 +++++----
> >  tests/ivshmem-test.c      |  28 +++++------
> >  tests/libqos/ahci.c       |   3 +-
> >  tests/libqos/ahci.h       |   6 +--
> >  tests/libqos/pci.c        | 125 +++++++++++++++++++++-------------------------
> >  tests/libqos/pci.h        |  39 +++++++++------
> >  tests/libqos/usb.c        |   6 +--
> >  tests/libqos/usb.h        |   2 +-
> >  tests/libqos/virtio-pci.c | 113 +++++++++++++++++++++--------------------
> >  tests/libqos/virtio-pci.h |   2 +-
> >  tests/rtl8139-test.c      |  10 ++--
> >  tests/usb-hcd-ehci-test.c |   5 +-
> 
> Perhaps you can move tco-test update in this series?
> 
> >  14 files changed, 186 insertions(+), 187 deletions(-)
> > 
> > diff --git a/tests/ahci-test.c b/tests/ahci-test.c
> > index 9c0adce..4358631 100644
> > --- a/tests/ahci-test.c
> > +++ b/tests/ahci-test.c
> > @@ -90,12 +90,12 @@ static void verify_state(AHCIQState *ahci)
> >      g_assert_cmphex(ahci_fingerprint, ==, ahci->fingerprint);
> >  
> >      /* If we haven't initialized, this is as much as can be validated. */
> > -    if (!ahci->hba_base) {
> > +    if (!ahci->hba_bar.addr) {
> >          return;
> >      }
> >  
> >      hba_base = (uint64_t)qpci_config_readl(ahci->dev, PCI_BASE_ADDRESS_5);
> > -    hba_stored = (uint64_t)(uintptr_t)ahci->hba_base;
> > +    hba_stored = ahci->hba_bar.addr;
> >      g_assert_cmphex(hba_base, ==, hba_stored);
> >  
> >      g_assert_cmphex(ahci_rreg(ahci, AHCI_CAP), ==, ahci->cap);
> > diff --git a/tests/e1000e-test.c b/tests/e1000e-test.c
> > index 3979b20..8c42ca9 100644
> > --- a/tests/e1000e-test.c
> > +++ b/tests/e1000e-test.c
> > @@ -87,7 +87,7 @@
> >  
> >  typedef struct e1000e_device {
> >      QPCIDevice *pci_dev;
> > -    void *mac_regs;
> > +    QPCIBar mac_regs;
> >  
> >      uint64_t tx_ring;
> >      uint64_t rx_ring;
> > @@ -119,12 +119,12 @@ static QPCIDevice *e1000e_device_find(QPCIBus *bus)
> >  
> >  static void e1000e_macreg_write(e1000e_device *d, uint32_t reg, uint32_t val)
> >  {
> > -    qpci_io_writel(d->pci_dev, d->mac_regs + reg, val);
> > +    qpci_io_writel(d->pci_dev, d->mac_regs, reg, val);
> >  }
> >  
> >  static uint32_t e1000e_macreg_read(e1000e_device *d, uint32_t reg)
> >  {
> > -    return qpci_io_readl(d->pci_dev, d->mac_regs + reg);
> > +    return qpci_io_readl(d->pci_dev, d->mac_regs, reg);
> >  }
> >  
> >  static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
> > @@ -138,7 +138,6 @@ static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
> >  
> >      /* Map BAR0 (mac registers) */
> >      d->mac_regs = qpci_iomap(d->pci_dev, 0, NULL);
> > -    g_assert_nonnull(d->mac_regs);
> >  
> >      /* Reset the device */
> >      val = e1000e_macreg_read(d, E1000E_CTRL);
> > diff --git a/tests/ide-test.c b/tests/ide-test.c
> > index a8a4081..dc08536 100644
> > --- a/tests/ide-test.c
> > +++ b/tests/ide-test.c
> > @@ -137,7 +137,7 @@ static void ide_test_quit(void)
> >      qtest_end();
> >  }
> >  
> > -static QPCIDevice *get_pci_device(uint16_t *bmdma_base)
> > +static QPCIDevice *get_pci_device(QPCIBar *bmdma_bar)
> >  {
> >      QPCIDevice *dev;
> >      uint16_t vendor_id, device_id;
> > @@ -156,7 +156,7 @@ static QPCIDevice *get_pci_device(uint16_t *bmdma_base)
> >      g_assert(device_id == PCI_DEVICE_ID_INTEL_82371SB_1);
> >  
> >      /* Map bmdma BAR */
> > -    *bmdma_base = (uint16_t)(uintptr_t) qpci_iomap(dev, 4, NULL);
> > +    *bmdma_bar = qpci_iomap(dev, 4, NULL);
> >  
> >      qpci_device_enable(dev);
> >  
> > @@ -182,14 +182,14 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
> >                              void(*post_exec)(uint64_t sector, int nb_sectors))
> >  {
> >      QPCIDevice *dev;
> > -    uint16_t bmdma_base;
> > +    QPCIBar bmdma_bar;
> >      uintptr_t guest_prdt;
> >      size_t len;
> >      bool from_dev;
> >      uint8_t status;
> >      int flags;
> >  
> > -    dev = get_pci_device(&bmdma_base);
> > +    dev = get_pci_device(&bmdma_bar);
> >  
> >      flags = cmd & ~0xff;
> >      cmd &= 0xff;
> > @@ -217,14 +217,14 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
> >      outb(IDE_BASE + reg_device, 0 | LBA);
> >  
> >      /* Stop any running transfer, clear any pending interrupt */
> > -    outb(bmdma_base + bmreg_cmd, 0);
> > -    outb(bmdma_base + bmreg_status, BM_STS_INTR);
> > +    qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
> > +    qpci_io_writeb(dev, bmdma_bar, bmreg_status, BM_STS_INTR);
> >  
> >      /* Setup PRDT */
> >      len = sizeof(*prdt) * prdt_entries;
> >      guest_prdt = guest_alloc(guest_malloc, len);
> >      memwrite(guest_prdt, prdt, len);
> > -    outl(bmdma_base + bmreg_prdt, guest_prdt);
> > +    qpci_io_writel(dev, bmdma_bar, bmreg_prdt, guest_prdt);
> >  
> >      /* ATA DMA command */
> >      if (cmd == CMD_PACKET) {
> > @@ -244,15 +244,16 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
> >      }
> >  
> >      /* Start DMA transfer */
> > -    outb(bmdma_base + bmreg_cmd, BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));
> > +    qpci_io_writeb(dev, bmdma_bar, bmreg_cmd,
> > +                   BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));
> >  
> >      if (flags & CMDF_ABORT) {
> > -        outb(bmdma_base + bmreg_cmd, 0);
> > +        qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
> >      }
> >  
> >      /* Wait for the DMA transfer to complete */
> >      do {
> > -        status = inb(bmdma_base + bmreg_status);
> > +        status = qpci_io_readb(dev, bmdma_bar, bmreg_status);
> >      } while ((status & (BM_STS_ACTIVE | BM_STS_INTR)) == BM_STS_ACTIVE);
> >  
> >      g_assert_cmpint(get_irq(IDE_PRIMARY_IRQ), ==, !!(status & BM_STS_INTR));
> > @@ -266,7 +267,7 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
> >  
> >      /* Stop DMA transfer if still active */
> >      if (status & BM_STS_ACTIVE) {
> > -        outb(bmdma_base + bmreg_cmd, 0);
> > +        qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
> >      }
> >  
> >      free_pci_device(dev);
> > diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c
> > index 97a887e..f7c5bf4 100644
> > --- a/tests/ivshmem-test.c
> > +++ b/tests/ivshmem-test.c
> > @@ -41,7 +41,7 @@ static QPCIDevice *get_device(QPCIBus *pcibus)
> >  
> >  typedef struct _IVState {
> >      QTestState *qtest;
> > -    void *reg_base, *mem_base;
> > +    QPCIBar reg_bar, mem_bar;
> >      QPCIBus *pcibus;
> >      QPCIDevice *dev;
> >  } IVState;
> > @@ -75,7 +75,7 @@ static inline unsigned in_reg(IVState *s, enum Reg reg)
> >      unsigned res;
> >  
> >      global_qtest = s->qtest;
> > -    res = qpci_io_readl(s->dev, s->reg_base + reg);
> > +    res = qpci_io_readl(s->dev, s->reg_bar, reg);
> >      g_test_message("*%s -> %x\n", name, res);
> >      global_qtest = qtest;
> >  
> > @@ -89,7 +89,7 @@ static inline void out_reg(IVState *s, enum Reg reg, unsigned v)
> >  
> >      global_qtest = s->qtest;
> >      g_test_message("%x -> *%s\n", v, name);
> > -    qpci_io_writel(s->dev, s->reg_base + reg, v);
> > +    qpci_io_writel(s->dev, s->reg_bar, reg, v);
> >      global_qtest = qtest;
> >  }
> >  
> > @@ -108,16 +108,14 @@ static void setup_vm_cmd(IVState *s, const char *cmd, bool msix)
> >      s->pcibus = qpci_init_pc(NULL);
> >      s->dev = get_device(s->pcibus);
> >  
> > -    s->reg_base = qpci_iomap(s->dev, 0, &barsize);
> > -    g_assert_nonnull(s->reg_base);
> > +    s->reg_bar = qpci_iomap(s->dev, 0, &barsize);
> >      g_assert_cmpuint(barsize, ==, 256);
> >  
> >      if (msix) {
> >          qpci_msix_enable(s->dev);
> >      }
> >  
> > -    s->mem_base = qpci_iomap(s->dev, 2, &barsize);
> > -    g_assert_nonnull(s->mem_base);
> > +    s->mem_bar = qpci_iomap(s->dev, 2, &barsize);
> >      g_assert_cmpuint(barsize, ==, TMPSHMSIZE);
> >  
> >      qpci_device_enable(s->dev);
> > @@ -169,7 +167,7 @@ static void test_ivshmem_single(void)
> >      for (i = 0; i < G_N_ELEMENTS(data); i++) {
> >          data[i] = i;
> >      }
> > -    qpci_memwrite(s->dev, s->mem_base, data, sizeof(data));
> > +    qpci_memwrite(s->dev, s->mem_bar, 0, data, sizeof(data));
> >  
> >      /* verify write */
> >      for (i = 0; i < G_N_ELEMENTS(data); i++) {
> > @@ -178,7 +176,7 @@ static void test_ivshmem_single(void)
> >  
> >      /* read it back and verify read */
> >      memset(data, 0, sizeof(data));
> > -    qpci_memread(s->dev, s->mem_base, data, sizeof(data));
> > +    qpci_memread(s->dev, s->mem_bar, 0, data, sizeof(data));
> >      for (i = 0; i < G_N_ELEMENTS(data); i++) {
> >          g_assert_cmpuint(data[i], ==, i);
> >      }
> > @@ -201,29 +199,29 @@ static void test_ivshmem_pair(void)
> >  
> >      /* host write, guest 1 & 2 read */
> >      memset(tmpshmem, 0x42, TMPSHMSIZE);
> > -    qpci_memread(s1->dev, s1->mem_base, data, TMPSHMSIZE);
> > +    qpci_memread(s1->dev, s1->mem_bar, 0, data, TMPSHMSIZE);
> >      for (i = 0; i < TMPSHMSIZE; i++) {
> >          g_assert_cmpuint(data[i], ==, 0x42);
> >      }
> > -    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
> > +    qpci_memread(s2->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
> >      for (i = 0; i < TMPSHMSIZE; i++) {
> >          g_assert_cmpuint(data[i], ==, 0x42);
> >      }
> >  
> >      /* guest 1 write, guest 2 read */
> >      memset(data, 0x43, TMPSHMSIZE);
> > -    qpci_memwrite(s1->dev, s1->mem_base, data, TMPSHMSIZE);
> > +    qpci_memwrite(s1->dev, s1->mem_bar, 0, data, TMPSHMSIZE);
> >      memset(data, 0, TMPSHMSIZE);
> > -    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
> > +    qpci_memread(s2->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
> >      for (i = 0; i < TMPSHMSIZE; i++) {
> >          g_assert_cmpuint(data[i], ==, 0x43);
> >      }
> >  
> >      /* guest 2 write, guest 1 read */
> >      memset(data, 0x44, TMPSHMSIZE);
> > -    qpci_memwrite(s2->dev, s2->mem_base, data, TMPSHMSIZE);
> > +    qpci_memwrite(s2->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
> >      memset(data, 0, TMPSHMSIZE);
> > -    qpci_memread(s1->dev, s2->mem_base, data, TMPSHMSIZE);
> > +    qpci_memread(s1->dev, s2->mem_bar, 0, data, TMPSHMSIZE);
> >      for (i = 0; i < TMPSHMSIZE; i++) {
> >          g_assert_cmpuint(data[i], ==, 0x44);
> >      }
> > diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c
> > index 716ab79..43b6695 100644
> > --- a/tests/libqos/ahci.c
> > +++ b/tests/libqos/ahci.c
> > @@ -210,8 +210,7 @@ void ahci_pci_enable(AHCIQState *ahci)
> >  void start_ahci_device(AHCIQState *ahci)
> >  {
> >      /* Map AHCI's ABAR (BAR5) */
> > -    ahci->hba_base = qpci_iomap(ahci->dev, 5, &ahci->barsize);
> > -    g_assert(ahci->hba_base);
> > +    ahci->hba_bar = qpci_iomap(ahci->dev, 5, &ahci->barsize);
> >  
> >      /* turns on pci.cmd.iose, pci.cmd.mse and pci.cmd.bme */
> >      qpci_device_enable(ahci->dev);
> > diff --git a/tests/libqos/ahci.h b/tests/libqos/ahci.h
> > index c69fb5a..6c4abf6 100644
> > --- a/tests/libqos/ahci.h
> > +++ b/tests/libqos/ahci.h
> > @@ -321,7 +321,7 @@ typedef struct AHCIPortQState {
> >  typedef struct AHCIQState {
> >      QOSState *parent;
> >      QPCIDevice *dev;
> > -    void *hba_base;
> > +    QPCIBar hba_bar;
> >      uint64_t barsize;
> >      uint32_t fingerprint;
> >      uint32_t cap;
> > @@ -488,12 +488,12 @@ typedef struct AHCIOpts {
> >  
> >  static inline uint32_t ahci_mread(AHCIQState *ahci, size_t offset)
> >  {
> > -    return qpci_io_readl(ahci->dev, ahci->hba_base + offset);
> > +    return qpci_io_readl(ahci->dev, ahci->hba_bar, offset);
> >  }
> >  
> >  static inline void ahci_mwrite(AHCIQState *ahci, size_t offset, uint32_t value)
> >  {
> > -    qpci_io_writel(ahci->dev, ahci->hba_base + offset, value);
> > +    qpci_io_writel(ahci->dev, ahci->hba_bar, offset, value);
> >  }
> >  
> >  static inline uint32_t ahci_rreg(AHCIQState *ahci, uint32_t reg_num)
> > diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
> > index bbacbcf..875c517 100644
> > --- a/tests/libqos/pci.c
> > +++ b/tests/libqos/pci.c
> > @@ -104,7 +104,6 @@ void qpci_msix_enable(QPCIDevice *dev)
> >      uint32_t table;
> >      uint8_t bir_table;
> >      uint8_t bir_pba;
> > -    void *offset;
> >  
> >      addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
> >      g_assert_cmphex(addr, !=, 0);
> > @@ -114,18 +113,16 @@ void qpci_msix_enable(QPCIDevice *dev)
> >  
> >      table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE);
> >      bir_table = table & PCI_MSIX_FLAGS_BIRMASK;
> > -    offset = qpci_iomap(dev, bir_table, NULL);
> > -    dev->msix_table = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK);
> > +    dev->msix_table_bar = qpci_iomap(dev, bir_table, NULL);
> > +    dev->msix_table_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
> >  
> >      table = qpci_config_readl(dev, addr + PCI_MSIX_PBA);
> >      bir_pba = table & PCI_MSIX_FLAGS_BIRMASK;
> >      if (bir_pba != bir_table) {
> > -        offset = qpci_iomap(dev, bir_pba, NULL);
> > +        dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL);
> >      }
> > -    dev->msix_pba = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK);
> > +    dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
> >  
> > -    g_assert(dev->msix_table != NULL);
> > -    g_assert(dev->msix_pba != NULL);
> >      dev->msix_enabled = true;
> >  }
> >  
> > @@ -141,22 +138,25 @@ void qpci_msix_disable(QPCIDevice *dev)
> >      qpci_config_writew(dev, addr + PCI_MSIX_FLAGS,
> >                                                  val & ~PCI_MSIX_FLAGS_ENABLE);
> >  
> > -    qpci_iounmap(dev, dev->msix_table);
> > -    qpci_iounmap(dev, dev->msix_pba);
> > +    qpci_iounmap(dev, dev->msix_table_bar);
> > +    qpci_iounmap(dev, dev->msix_pba_bar);
> >      dev->msix_enabled = 0;
> > -    dev->msix_table = NULL;
> > -    dev->msix_pba = NULL;
> > +    memset(&dev->msix_table_bar, 0, sizeof(dev->msix_table_bar));
> > +    memset(&dev->msix_pba_bar, 0, sizeof(dev->msix_pba_bar));
> > +    dev->msix_table_off = 0;
> > +    dev->msix_pba_off = 0;
> >  }
> >  
> >  bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry)
> >  {
> >      uint32_t pba_entry;
> >      uint8_t bit_n = entry % 32;
> > -    void *addr = dev->msix_pba + (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
> > +    uint64_t  off = (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
> >  
> >      g_assert(dev->msix_enabled);
> > -    pba_entry = qpci_io_readl(dev, addr);
> > -    qpci_io_writel(dev, addr, pba_entry & ~(1 << bit_n));
> > +    pba_entry = qpci_io_readl(dev, dev->msix_pba_bar, dev->msix_pba_off + off);
> > +    qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off,
> > +                   pba_entry & ~(1 << bit_n));
> >      return (pba_entry & (1 << bit_n)) != 0;
> >  }
> >  
> > @@ -164,7 +164,7 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
> >  {
> >      uint8_t addr;
> >      uint16_t val;
> > -    void *vector_addr = dev->msix_table + (entry * PCI_MSIX_ENTRY_SIZE);
> > +    uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE;
> >  
> >      g_assert(dev->msix_enabled);
> >      addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
> > @@ -174,8 +174,9 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
> >      if (val & PCI_MSIX_FLAGS_MASKALL) {
> >          return true;
> >      } else {
> > -        return (qpci_io_readl(dev, vector_addr + PCI_MSIX_ENTRY_VECTOR_CTRL)
> > -                                            & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
> > +        return (qpci_io_readl(dev, dev->msix_table_bar,
> > +                              vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL)
> > +                & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
> >      }
> >  }
> >  
> > @@ -222,104 +223,93 @@ void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
> >      dev->bus->config_writel(dev->bus, dev->devfn, offset, value);
> >  }
> >  
> > -
> > -uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
> > +uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off)
> >  {
> > -    uintptr_t addr = (uintptr_t)data;
> > -
> > -    if (addr < QPCI_PIO_LIMIT) {
> > -        return dev->bus->pio_readb(dev->bus, addr);
> > +    if (token.addr < QPCI_PIO_LIMIT) {
> > +        return dev->bus->pio_readb(dev->bus, token.addr + off);
> >      } else {
> >          uint8_t val;
> > -        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
> > +        dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
> >          return val;
> >      }
> >  }
> >  
> > -uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
> > +uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
> >  {
> > -    uintptr_t addr = (uintptr_t)data;
> > -
> > -    if (addr < QPCI_PIO_LIMIT) {
> > -        return dev->bus->pio_readw(dev->bus, addr);
> > +    if (token.addr < QPCI_PIO_LIMIT) {
> > +        return dev->bus->pio_readw(dev->bus, token.addr + off);
> >      } else {
> >          uint16_t val;
> > -        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
> > +        dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
> >          return le16_to_cpu(val);
> >      }
> >  }
> >  
> > -uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
> > +uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
> >  {
> > -    uintptr_t addr = (uintptr_t)data;
> > -
> > -    if (addr < QPCI_PIO_LIMIT) {
> > -        return dev->bus->pio_readl(dev->bus, addr);
> > +    if (token.addr < QPCI_PIO_LIMIT) {
> > +        return dev->bus->pio_readl(dev->bus, token.addr + off);
> >      } else {
> >          uint32_t val;
> > -        dev->bus->memread(dev->bus, addr, &val, sizeof(val));
> > +        dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
> >          return le32_to_cpu(val);
> >      }
> >  }
> >  
> > -void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
> > +void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
> > +                    uint8_t value)
> >  {
> > -    uintptr_t addr = (uintptr_t)data;
> > -
> > -    if (addr < QPCI_PIO_LIMIT) {
> > -        dev->bus->pio_writeb(dev->bus, addr, value);
> > +    if (token.addr < QPCI_PIO_LIMIT) {
> > +        dev->bus->pio_writeb(dev->bus, token.addr + off, value);
> >      } else {
> > -        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
> > +        dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
> >      }
> >  }
> >  
> > -void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
> > +void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
> > +                    uint16_t value)
> >  {
> > -    uintptr_t addr = (uintptr_t)data;
> > -
> > -    if (addr < QPCI_PIO_LIMIT) {
> > -        dev->bus->pio_writew(dev->bus, addr, value);
> > +    if (token.addr < QPCI_PIO_LIMIT) {
> > +        dev->bus->pio_writew(dev->bus, token.addr + off, value);
> >      } else {
> >          value = cpu_to_le16(value);
> > -        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
> > +        dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
> >      }
> >  }
> >  
> > -void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
> > +void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
> > +                    uint32_t value)
> >  {
> > -    uintptr_t addr = (uintptr_t)data;
> > -
> > -    if (addr < QPCI_PIO_LIMIT) {
> > -        dev->bus->pio_writel(dev->bus, addr, value);
> > +    if (token.addr < QPCI_PIO_LIMIT) {
> > +        dev->bus->pio_writel(dev->bus, token.addr + off, value);
> >      } else {
> >          value = cpu_to_le32(value);
> > -        dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
> > +        dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
> >      }
> >  }
> >  
> > -void qpci_memread(QPCIDevice *dev, void *data, void *buf, size_t len)
> > +void qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off,
> > +                  void *buf, size_t len)
> >  {
> > -    uintptr_t addr = (uintptr_t)data;
> > -
> > -    g_assert(addr >= QPCI_PIO_LIMIT);
> > -    dev->bus->memread(dev->bus, addr, buf, len);
> > +    g_assert(token.addr >= QPCI_PIO_LIMIT);
> > +    dev->bus->memread(dev->bus, token.addr + off, buf, len);
> >  }
> >  
> > -void qpci_memwrite(QPCIDevice *dev, void *data, const void *buf, size_t len)
> > +void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
> > +                   const void *buf, size_t len)
> >  {
> > -    uintptr_t addr = (uintptr_t)data;
> > -
> > -    g_assert(addr >= QPCI_PIO_LIMIT);
> > -    dev->bus->memwrite(dev->bus, addr, buf, len);
> > +    g_assert(token.addr >= QPCI_PIO_LIMIT);
> > +    dev->bus->memwrite(dev->bus, token.addr + off, buf, len);
> >  }
> >  
> > -void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
> > +QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
> >  {
> >      QPCIBus *bus = dev->bus;
> >      static const int bar_reg_map[] = {
> >          PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
> >          PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
> >      };
> > +    QPCIBar bar;
> >      int bar_reg;
> >      uint32_t addr, size;
> >      uint32_t io_type;
> > @@ -366,10 +356,11 @@ void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
> >          qpci_config_writel(dev, bar_reg, loc);
> >      }
> >  
> > -    return (void *)(uintptr_t)loc;
> > +    bar.addr = loc;
> > +    return bar;
> >  }
> >  
> > -void qpci_iounmap(QPCIDevice *dev, void *data)
> > +void qpci_iounmap(QPCIDevice *dev, QPCIBar bar)
> >  {
> >      /* FIXME */
> >  }
> > diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
> > index 59fa3da..40b277c 100644
> > --- a/tests/libqos/pci.h
> > +++ b/tests/libqos/pci.h
> > @@ -21,6 +21,7 @@
> >  
> >  typedef struct QPCIDevice QPCIDevice;
> >  typedef struct QPCIBus QPCIBus;
> > +typedef struct QPCIBar QPCIBar;
> >  
> >  struct QPCIBus {
> >      uint8_t (*pio_readb)(QPCIBus *bus, uint32_t addr);
> > @@ -49,13 +50,17 @@ struct QPCIBus {
> >      uint64_t mmio_alloc_ptr, mmio_limit;
> >  };
> >  
> > +struct QPCIBar {
> > +    uint64_t addr;
> > +};
> > +
> >  struct QPCIDevice
> >  {
> >      QPCIBus *bus;
> >      int devfn;
> >      bool msix_enabled;
> > -    void *msix_table;
> > -    void *msix_pba;
> > +    QPCIBar msix_table_bar, msix_pba_bar;
> > +    uint64_t msix_table_off, msix_pba_off;
> >  };
> >  
> >  void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
> > @@ -79,19 +84,23 @@ void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value);
> >  void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value);
> >  void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value);
> >  
> > -uint8_t qpci_io_readb(QPCIDevice *dev, void *data);
> > -uint16_t qpci_io_readw(QPCIDevice *dev, void *data);
> > -uint32_t qpci_io_readl(QPCIDevice *dev, void *data);
> > -
> > -void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value);
> > -void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value);
> > -void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value);
> > -
> > -void qpci_memread(QPCIDevice *bus, void *data, void *buf, size_t len);
> > -void qpci_memwrite(QPCIDevice *bus, void *data, const void *buf, size_t len);
> > -
> > -void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
> > -void qpci_iounmap(QPCIDevice *dev, void *data);
> > +uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off);
> > +uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off);
> > +uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off);
> > +
> > +void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
> > +                    uint8_t value);
> > +void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
> > +                    uint16_t value);
> > +void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
> > +                    uint32_t value);
> > +
> > +void qpci_memread(QPCIDevice *bus, QPCIBar token, uint64_t off,
> > +                  void *buf, size_t len);
> > +void qpci_memwrite(QPCIDevice *bus, QPCIBar token, uint64_t off,
> > +                   const void *buf, size_t len);
> > +QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
> > +void qpci_iounmap(QPCIDevice *dev, QPCIBar addr);
> >  
> >  void qpci_plug_device_test(const char *driver, const char *id,
> >                             uint8_t slot, const char *opts);
> > diff --git a/tests/libqos/usb.c b/tests/libqos/usb.c
> > index f794d92..72d7a96 100644
> > --- a/tests/libqos/usb.c
> > +++ b/tests/libqos/usb.c
> > @@ -21,14 +21,12 @@ void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc, uint32_t devfn, int bar)
> >      hc->dev = qpci_device_find(pcibus, devfn);
> >      g_assert(hc->dev != NULL);
> >      qpci_device_enable(hc->dev);
> > -    hc->base = qpci_iomap(hc->dev, bar, NULL);
> > -    g_assert(hc->base != NULL);
> > +    hc->bar = qpci_iomap(hc->dev, bar, NULL);
> >  }
> >  
> >  void uhci_port_test(struct qhc *hc, int port, uint16_t expect)
> >  {
> > -    void *addr = hc->base + 0x10 + 2 * port;
> > -    uint16_t value = qpci_io_readw(hc->dev, addr);
> > +    uint16_t value = qpci_io_readw(hc->dev, hc->bar, 0x10 + 2 * port);
> >      uint16_t mask = ~(UHCI_PORT_WRITE_CLEAR | UHCI_PORT_RSVD1);
> >  
> >      g_assert((value & mask) == (expect & mask));
> > diff --git a/tests/libqos/usb.h b/tests/libqos/usb.h
> > index 8fe5687..423dcfd 100644
> > --- a/tests/libqos/usb.h
> > +++ b/tests/libqos/usb.h
> > @@ -5,7 +5,7 @@
> >  
> >  struct qhc {
> >      QPCIDevice *dev;
> > -    void *base;
> > +    QPCIBar bar;
> >  };
> >  
> >  void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc,
> > diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
> > index 8037724..5b78d30 100644
> > --- a/tests/libqos/virtio-pci.c
> > +++ b/tests/libqos/virtio-pci.c
> > @@ -65,22 +65,22 @@ static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data)
> >  static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> > -    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> > -    return qpci_io_readb(dev->pdev, base + off);
> > +    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> > +    return qpci_io_readb(dev->pdev, dev->bar, base + off);
> >  }
> >  
> >  static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> > -    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> > -    return qpci_io_readw(dev->pdev, base + off);
> > +    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> > +    return qpci_io_readw(dev->pdev, dev->bar, base + off);
> >  }
> >  
> >  static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t off)
> >  {
> >      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> > -    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> > -    return qpci_io_readl(dev->pdev, base + off);
> > +    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> > +    return qpci_io_readl(dev->pdev, dev->bar, base + off);
> >  }
> >  
> >  static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
> > @@ -88,17 +88,17 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
> >      QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
> >      int i;
> >      uint64_t u64 = 0;
> > -    void *base = dev->addr + VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled);
> > +    uint64_t base = VIRTIO_PCI_CONFIG_OFF(dev->pdev->msix_enabled) + off;
> >  
> >      if (target_big_endian()) {
> >          for (i = 0; i < 8; ++i) {
> > -            u64 |= (uint64_t)qpci_io_readb(dev->pdev,
> > -                                           base + off + i) << (7 - i) * 8;
> > +            u64 |= (uint64_t)qpci_io_readb(dev->pdev, dev->bar,
> > +                                           base + i) << (7 - i) * 8;
> >          }
> >      } else {
> >          for (i = 0; i < 8; ++i) {
> > -            u64 |= (uint64_t)qpci_io_readb(dev->pdev,
> > -                                           base + off + i) << i * 8;
> > +            u64 |= (uint64_t)qpci_io_readb(dev->pdev, dev->bar,
> > +                                           base + i) << i * 8;
> >          }
> 
> You should update this part with qpci_memread() + bswap64()

Good idea.  Well, actually, I thinl I'll add 64-bit PCI accessors.
I'm sure we'll want them in other places soon enough.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 7/8] tests: Use qpci_mem{read, write} in ivshmem-test
  2016-10-18 16:14   ` Laurent Vivier
@ 2016-10-19  4:13     ` David Gibson
  0 siblings, 0 replies; 28+ messages in thread
From: David Gibson @ 2016-10-19  4:13 UTC (permalink / raw)
  To: Laurent Vivier
  Cc: pbonzini, qemu-devel, qemu-ppc, agraf, stefanha, mst, aik,
	mdroth, groug, thuth

[-- Attachment #1: Type: text/plain, Size: 4102 bytes --]

On Tue, Oct 18, 2016 at 06:14:09PM +0200, Laurent Vivier wrote:
> 
> 
> On 18/10/2016 12:52, David Gibson wrote:
> > ivshmem implements a block of shared memory in a PCI BAR.  Currently our
> > test case accesses this using qtest_mem{read,write}.  However, deducing
> > the correct addresses for these requires making assumptions about the
> > internel format returned by qpci_iomap(), along with some ugly casts.
> > 
> > This patch changes the test to use the new qpci_mem{read,write} interfaces
> > which is neater.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> 
> I think your changes break this test.
> 
> There is two guest, so we need to access them through two sockets,
> defined in s1->qtest and s2->qtest.
> 
> But qpci_memXXX() always use memread(...) and thus
> qtest_memread(global_qtest, ...) , so always test the last guest started.
> 
> You must swap global_qtest as it is done in in_reg()/out_reg() before
> your qpci_memXXX() in test_ivshmem_pair().

Ah.. good point.  I'll fix that in the next spin.

> 
> Laurent
> 
> > ---
> >  tests/ivshmem-test.c | 16 ++++++++--------
> >  1 file changed, 8 insertions(+), 8 deletions(-)
> > 
> > diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c
> > index f36bfe7..97a887e 100644
> > --- a/tests/ivshmem-test.c
> > +++ b/tests/ivshmem-test.c
> > @@ -169,7 +169,7 @@ static void test_ivshmem_single(void)
> >      for (i = 0; i < G_N_ELEMENTS(data); i++) {
> >          data[i] = i;
> >      }
> > -    qtest_memwrite(s->qtest, (uintptr_t)s->mem_base, data, sizeof(data));
> > +    qpci_memwrite(s->dev, s->mem_base, data, sizeof(data));
> >  
> >      /* verify write */
> >      for (i = 0; i < G_N_ELEMENTS(data); i++) {
> > @@ -178,7 +178,7 @@ static void test_ivshmem_single(void)
> >  
> >      /* read it back and verify read */
> >      memset(data, 0, sizeof(data));
> > -    qtest_memread(s->qtest, (uintptr_t)s->mem_base, data, sizeof(data));
> > +    qpci_memread(s->dev, s->mem_base, data, sizeof(data));
> >      for (i = 0; i < G_N_ELEMENTS(data); i++) {
> >          g_assert_cmpuint(data[i], ==, i);
> >      }
> > @@ -201,29 +201,29 @@ static void test_ivshmem_pair(void)
> >  
> >      /* host write, guest 1 & 2 read */
> >      memset(tmpshmem, 0x42, TMPSHMSIZE);
> > -    qtest_memread(s1->qtest, (uintptr_t)s1->mem_base, data, TMPSHMSIZE);
> > +    qpci_memread(s1->dev, s1->mem_base, data, TMPSHMSIZE);
> >      for (i = 0; i < TMPSHMSIZE; i++) {
> >          g_assert_cmpuint(data[i], ==, 0x42);
> >      }
> > -    qtest_memread(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
> > +    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
> >      for (i = 0; i < TMPSHMSIZE; i++) {
> >          g_assert_cmpuint(data[i], ==, 0x42);
> >      }
> >  
> >      /* guest 1 write, guest 2 read */
> >      memset(data, 0x43, TMPSHMSIZE);
> > -    qtest_memwrite(s1->qtest, (uintptr_t)s1->mem_base, data, TMPSHMSIZE);
> > +    qpci_memwrite(s1->dev, s1->mem_base, data, TMPSHMSIZE);
> >      memset(data, 0, TMPSHMSIZE);
> > -    qtest_memread(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
> > +    qpci_memread(s2->dev, s2->mem_base, data, TMPSHMSIZE);
> >      for (i = 0; i < TMPSHMSIZE; i++) {
> >          g_assert_cmpuint(data[i], ==, 0x43);
> >      }
> >  
> >      /* guest 2 write, guest 1 read */
> >      memset(data, 0x44, TMPSHMSIZE);
> > -    qtest_memwrite(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
> > +    qpci_memwrite(s2->dev, s2->mem_base, data, TMPSHMSIZE);
> >      memset(data, 0, TMPSHMSIZE);
> > -    qtest_memread(s1->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
> > +    qpci_memread(s1->dev, s2->mem_base, data, TMPSHMSIZE);
> >      for (i = 0; i < TMPSHMSIZE; i++) {
> >          g_assert_cmpuint(data[i], ==, 0x44);
> >      }
> > 
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2016-10-19  4:49 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-18 10:52 [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling David Gibson
2016-10-18 10:52 ` [Qemu-devel] [PATCH 1/8] libqos: Give qvirtio_config_read*() consistent semantics David Gibson
2016-10-18 12:41   ` Laurent Vivier
2016-10-18 13:27   ` Greg Kurz
2016-10-19  2:41     ` David Gibson
2016-10-18 10:52 ` [Qemu-devel] [PATCH 2/8] libqos: Handle PCI IO de-multiplexing in common code David Gibson
2016-10-18 13:28   ` Laurent Vivier
2016-10-19  2:59     ` David Gibson
2016-10-18 10:52 ` [Qemu-devel] [PATCH 3/8] libqos: Move BAR assignment to " David Gibson
2016-10-18 15:00   ` Laurent Vivier
2016-10-19  3:07     ` David Gibson
2016-10-18 10:52 ` [Qemu-devel] [PATCH 4/8] tests: Better handle legacy IO addresses in tco-test David Gibson
2016-10-18 15:14   ` Laurent Vivier
2016-10-18 16:28     ` Laurent Vivier
2016-10-19  3:19       ` David Gibson
2016-10-19  3:09     ` David Gibson
2016-10-18 10:52 ` [Qemu-devel] [PATCH 5/8] libqos: Add streaming accessors for PCI MMIO David Gibson
2016-10-18 15:17   ` Laurent Vivier
2016-10-18 10:52 ` [Qemu-devel] [PATCH 6/8] libqos: Implement mmio accessors in terms of mem{read, write} David Gibson
2016-10-18 16:04   ` Laurent Vivier
2016-10-18 10:52 ` [Qemu-devel] [PATCH 7/8] tests: Use qpci_mem{read, write} in ivshmem-test David Gibson
2016-10-18 16:14   ` Laurent Vivier
2016-10-19  4:13     ` David Gibson
2016-10-18 10:52 ` [Qemu-devel] [PATCH 8/8] libqos: Change PCI accessors to take opaque BAR handle David Gibson
2016-10-18 16:48   ` Laurent Vivier
2016-10-19  4:06     ` David Gibson
2016-10-18 11:56 ` [Qemu-devel] [PATCH 0/8] Cleanups to qtest PCI handling Laurent Vivier
2016-10-19  1:11   ` David Gibson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.