* [PATCH v6 1/3] tests/qtest/libqos/pci: Introduce pio_limit
2022-05-04 15:20 [PATCH v6 0/3] qtests/libqos: Allow PCI tests to be run with virt-machine Eric Auger
@ 2022-05-04 15:20 ` Eric Auger
2022-05-04 15:20 ` [PATCH v6 2/3] tests/qtest/libqos: Skip hotplug tests if pci root bus is not hotpluggable Eric Auger
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Eric Auger @ 2022-05-04 15:20 UTC (permalink / raw)
To: eric.auger.pro, eric.auger, pbonzini, qemu-arm, qemu-devel, mst,
david, clg, eesposit, Coiby.Xu, stefanha
Cc: jean-philippe
At the moment the IO space limit is hardcoded to
QPCI_PIO_LIMIT = 0x10000. When accesses are performed to a bar,
the base address of this latter is compared against the limit
to decide whether we perform an IO or a memory access.
On ARM, we cannot keep this PIO limit as the arm-virt machine
uses [0x3eff0000, 0x3f000000 ] for the IO space map and we
are mandated to allocate at 0x0.
Add a new flag in QPCIBar indicating whether it is an IO bar
or a memory bar. This flag is set on QPCIBar allocation and
provisionned based on the BAR configuration. Then the new flag
is used in access functions and in iomap() function.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
tests/qtest/libqos/pci-pc.c | 1 +
tests/qtest/libqos/pci-spapr.c | 1 +
tests/qtest/libqos/pci.c | 78 ++++++++++++++++++++++------------
tests/qtest/libqos/pci.h | 5 +--
4 files changed, 54 insertions(+), 31 deletions(-)
diff --git a/tests/qtest/libqos/pci-pc.c b/tests/qtest/libqos/pci-pc.c
index e9dd5a57ec..81c2c055ca 100644
--- a/tests/qtest/libqos/pci-pc.c
+++ b/tests/qtest/libqos/pci-pc.c
@@ -150,6 +150,7 @@ void qpci_init_pc(QPCIBusPC *qpci, QTestState *qts, QGuestAllocator *alloc)
qpci->bus.qts = qts;
qpci->bus.pio_alloc_ptr = 0xc000;
+ qpci->bus.pio_limit = 0x10000;
qpci->bus.mmio_alloc_ptr = 0xE0000000;
qpci->bus.mmio_limit = 0x100000000ULL;
diff --git a/tests/qtest/libqos/pci-spapr.c b/tests/qtest/libqos/pci-spapr.c
index 76bf9a855d..0f1023e4a7 100644
--- a/tests/qtest/libqos/pci-spapr.c
+++ b/tests/qtest/libqos/pci-spapr.c
@@ -197,6 +197,7 @@ void qpci_init_spapr(QPCIBusSPAPR *qpci, QTestState *qts,
qpci->bus.qts = qts;
qpci->bus.pio_alloc_ptr = 0xc000;
+ qpci->bus.pio_limit = 0x10000;
qpci->bus.mmio_alloc_ptr = qpci->mmio32.pci_base;
qpci->bus.mmio_limit = qpci->mmio32.pci_base + qpci->mmio32.size;
diff --git a/tests/qtest/libqos/pci.c b/tests/qtest/libqos/pci.c
index 3a9076ae58..b23d72346b 100644
--- a/tests/qtest/libqos/pci.c
+++ b/tests/qtest/libqos/pci.c
@@ -398,44 +398,56 @@ void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off)
{
- if (token.addr < QPCI_PIO_LIMIT) {
- return dev->bus->pio_readb(dev->bus, token.addr + off);
+ QPCIBus *bus = dev->bus;
+
+ if (token.is_io) {
+ return bus->pio_readb(bus, token.addr + off);
} else {
uint8_t val;
- dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
+
+ bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
return val;
}
}
uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
{
- if (token.addr < QPCI_PIO_LIMIT) {
- return dev->bus->pio_readw(dev->bus, token.addr + off);
+ QPCIBus *bus = dev->bus;
+
+ if (token.is_io) {
+ return bus->pio_readw(bus, token.addr + off);
} else {
uint16_t val;
- dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
+
+ bus->memread(bus, token.addr + off, &val, sizeof(val));
return le16_to_cpu(val);
}
}
uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
{
- if (token.addr < QPCI_PIO_LIMIT) {
- return dev->bus->pio_readl(dev->bus, token.addr + off);
+ QPCIBus *bus = dev->bus;
+
+ if (token.is_io) {
+ return bus->pio_readl(bus, token.addr + off);
} else {
uint32_t val;
- dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
+
+ bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
return le32_to_cpu(val);
}
}
uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off)
{
- if (token.addr < QPCI_PIO_LIMIT) {
- return dev->bus->pio_readq(dev->bus, token.addr + off);
+ QPCIBus *bus = dev->bus;
+
+ if (token.is_io) {
+ return bus->pio_readq(bus, token.addr + off);
} else {
uint64_t val;
- dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
+
+ bus->memread(bus, token.addr + off, &val, sizeof(val));
return le64_to_cpu(val);
}
}
@@ -443,57 +455,65 @@ uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off)
void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
uint8_t value)
{
- if (token.addr < QPCI_PIO_LIMIT) {
- dev->bus->pio_writeb(dev->bus, token.addr + off, value);
+ QPCIBus *bus = dev->bus;
+
+ if (token.is_io) {
+ bus->pio_writeb(bus, token.addr + off, value);
} else {
- dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
+ bus->memwrite(bus, token.addr + off, &value, sizeof(value));
}
}
void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
uint16_t value)
{
- if (token.addr < QPCI_PIO_LIMIT) {
- dev->bus->pio_writew(dev->bus, token.addr + off, value);
+ QPCIBus *bus = dev->bus;
+
+ if (token.is_io) {
+ bus->pio_writew(bus, token.addr + off, value);
} else {
value = cpu_to_le16(value);
- dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
+ bus->memwrite(bus, token.addr + off, &value, sizeof(value));
}
}
void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
uint32_t value)
{
- if (token.addr < QPCI_PIO_LIMIT) {
- dev->bus->pio_writel(dev->bus, token.addr + off, value);
+ QPCIBus *bus = dev->bus;
+
+ if (token.is_io) {
+ bus->pio_writel(bus, token.addr + off, value);
} else {
value = cpu_to_le32(value);
- dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
+ bus->memwrite(bus, token.addr + off, &value, sizeof(value));
}
}
void qpci_io_writeq(QPCIDevice *dev, QPCIBar token, uint64_t off,
uint64_t value)
{
- if (token.addr < QPCI_PIO_LIMIT) {
- dev->bus->pio_writeq(dev->bus, token.addr + off, value);
+ QPCIBus *bus = dev->bus;
+
+ if (token.is_io) {
+ bus->pio_writeq(bus, token.addr + off, value);
} else {
value = cpu_to_le64(value);
- dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
+ bus->memwrite(bus, token.addr + off, &value, sizeof(value));
}
}
void qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off,
void *buf, size_t len)
{
- g_assert(token.addr >= QPCI_PIO_LIMIT);
+ g_assert(!token.is_io);
dev->bus->memread(dev->bus, token.addr + off, buf, len);
}
void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
const void *buf, size_t len)
{
- g_assert(token.addr >= QPCI_PIO_LIMIT);
+ g_assert(!token.is_io);
dev->bus->memwrite(dev->bus, token.addr + off, buf, len);
}
@@ -534,9 +554,10 @@ QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
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 */
+ g_assert(loc + size <= bus->pio_limit);
bus->pio_alloc_ptr = loc + size;
+ bar.is_io = true;
qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
} else {
@@ -547,6 +568,7 @@ QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
g_assert(loc + size <= bus->mmio_limit);
bus->mmio_alloc_ptr = loc + size;
+ bar.is_io = false;
qpci_config_writel(dev, bar_reg, loc);
}
@@ -562,7 +584,7 @@ void qpci_iounmap(QPCIDevice *dev, QPCIBar bar)
QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
{
- QPCIBar bar = { .addr = addr };
+ QPCIBar bar = { .addr = addr, .is_io = true };
return bar;
}
diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h
index e705e06598..a3c657d962 100644
--- a/tests/qtest/libqos/pci.h
+++ b/tests/qtest/libqos/pci.h
@@ -16,8 +16,6 @@
#include "../libqtest.h"
#include "qgraph.h"
-#define QPCI_PIO_LIMIT 0x10000
-
#define QPCI_DEVFN(dev, fn) (((dev) << 3) | (fn))
typedef struct QPCIDevice QPCIDevice;
@@ -51,7 +49,7 @@ struct QPCIBus {
uint8_t offset, uint32_t value);
QTestState *qts;
- uint16_t pio_alloc_ptr;
+ uint64_t pio_alloc_ptr, pio_limit;
uint64_t mmio_alloc_ptr, mmio_limit;
bool has_buggy_msi; /* TRUE for spapr, FALSE for pci */
@@ -59,6 +57,7 @@ struct QPCIBus {
struct QPCIBar {
uint64_t addr;
+ bool is_io;
};
struct QPCIDevice
--
2.35.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v6 2/3] tests/qtest/libqos: Skip hotplug tests if pci root bus is not hotpluggable
2022-05-04 15:20 [PATCH v6 0/3] qtests/libqos: Allow PCI tests to be run with virt-machine Eric Auger
2022-05-04 15:20 ` [PATCH v6 1/3] tests/qtest/libqos/pci: Introduce pio_limit Eric Auger
@ 2022-05-04 15:20 ` Eric Auger
2022-05-04 15:20 ` [PATCH v6 3/3] tests/qtest/libqos: Add generic pci host bridge in arm-virt machine Eric Auger
2022-05-09 8:18 ` [PATCH v6 0/3] qtests/libqos: Allow PCI tests to be run with virt-machine Eric Auger
3 siblings, 0 replies; 7+ messages in thread
From: Eric Auger @ 2022-05-04 15:20 UTC (permalink / raw)
To: eric.auger.pro, eric.auger, pbonzini, qemu-arm, qemu-devel, mst,
david, clg, eesposit, Coiby.Xu, stefanha
Cc: jean-philippe
ARM does not not support hotplug on pcie.0. Add a flag on the bus
which tells if devices can be hotplugged and skip hotplug tests
if the bus cannot be hotplugged. This is a temporary solution to
enable the other pci tests on aarch64.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
v1 ->v2:
- reword g_test_skip msg into "pci bus does not support hotplug"
---
tests/qtest/e1000e-test.c | 6 ++++++
tests/qtest/libqos/pci.h | 1 +
tests/qtest/vhost-user-blk-test.c | 10 ++++++++++
tests/qtest/virtio-blk-test.c | 5 +++++
tests/qtest/virtio-net-test.c | 5 +++++
tests/qtest/virtio-rng-test.c | 5 +++++
6 files changed, 32 insertions(+)
diff --git a/tests/qtest/e1000e-test.c b/tests/qtest/e1000e-test.c
index ddd6983ede..c98779c7c0 100644
--- a/tests/qtest/e1000e-test.c
+++ b/tests/qtest/e1000e-test.c
@@ -233,6 +233,12 @@ static void test_e1000e_multiple_transfers(void *obj, void *data,
static void test_e1000e_hotplug(void *obj, void *data, QGuestAllocator * alloc)
{
QTestState *qts = global_qtest; /* TODO: get rid of global_qtest here */
+ QE1000E_PCI *dev = obj;
+
+ if (dev->pci_dev.bus->not_hotpluggable) {
+ g_test_skip("pci bus does not support hotplug");
+ return;
+ }
qtest_qmp_device_add(qts, "e1000e", "e1000e_net", "{'addr': '0x06'}");
qpci_unplug_acpi_device_test(qts, "e1000e_net", 0x06);
diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h
index a3c657d962..8389614523 100644
--- a/tests/qtest/libqos/pci.h
+++ b/tests/qtest/libqos/pci.h
@@ -52,6 +52,7 @@ struct QPCIBus {
uint64_t pio_alloc_ptr, pio_limit;
uint64_t mmio_alloc_ptr, mmio_limit;
bool has_buggy_msi; /* TRUE for spapr, FALSE for pci */
+ bool not_hotpluggable; /* TRUE if devices cannot be hotplugged */
};
diff --git a/tests/qtest/vhost-user-blk-test.c b/tests/qtest/vhost-user-blk-test.c
index 659b5050d8..a81c2a2715 100644
--- a/tests/qtest/vhost-user-blk-test.c
+++ b/tests/qtest/vhost-user-blk-test.c
@@ -676,6 +676,11 @@ static void pci_hotplug(void *obj, void *data, QGuestAllocator *t_alloc)
QVirtioPCIDevice *dev;
QTestState *qts = dev1->pdev->bus->qts;
+ if (dev1->pdev->bus->not_hotpluggable) {
+ g_test_skip("pci bus does not support hotplug");
+ return;
+ }
+
/* plug secondary disk */
qtest_qmp_device_add(qts, "vhost-user-blk-pci", "drv1",
"{'addr': %s, 'chardev': 'char2'}",
@@ -703,6 +708,11 @@ static void multiqueue(void *obj, void *data, QGuestAllocator *t_alloc)
uint64_t features;
uint16_t num_queues;
+ if (pdev1->pdev->bus->not_hotpluggable) {
+ g_test_skip("bus pci.0 does not support hotplug");
+ return;
+ }
+
/*
* The primary device has 1 queue and VIRTIO_BLK_F_MQ is not enabled. The
* VIRTIO specification allows VIRTIO_BLK_F_MQ to be enabled when there is
diff --git a/tests/qtest/virtio-blk-test.c b/tests/qtest/virtio-blk-test.c
index f22594a1a8..dc5eed31c8 100644
--- a/tests/qtest/virtio-blk-test.c
+++ b/tests/qtest/virtio-blk-test.c
@@ -701,6 +701,11 @@ static void pci_hotplug(void *obj, void *data, QGuestAllocator *t_alloc)
QVirtioPCIDevice *dev;
QTestState *qts = dev1->pdev->bus->qts;
+ if (dev1->pdev->bus->not_hotpluggable) {
+ g_test_skip("pci bus does not support hotplug");
+ return;
+ }
+
/* plug secondary disk */
qtest_qmp_device_add(qts, "virtio-blk-pci", "drv1",
"{'addr': %s, 'drive': 'drive1'}",
diff --git a/tests/qtest/virtio-net-test.c b/tests/qtest/virtio-net-test.c
index fc9f2b9498..6ded252901 100644
--- a/tests/qtest/virtio-net-test.c
+++ b/tests/qtest/virtio-net-test.c
@@ -173,6 +173,11 @@ static void hotplug(void *obj, void *data, QGuestAllocator *t_alloc)
QTestState *qts = dev->pdev->bus->qts;
const char *arch = qtest_get_arch();
+ if (dev->pdev->bus->not_hotpluggable) {
+ g_test_skip("pci bus does not support hotplug");
+ return;
+ }
+
qtest_qmp_device_add(qts, "virtio-net-pci", "net1",
"{'addr': %s}", stringify(PCI_SLOT_HP));
diff --git a/tests/qtest/virtio-rng-test.c b/tests/qtest/virtio-rng-test.c
index 092ba13068..64e131cd8c 100644
--- a/tests/qtest/virtio-rng-test.c
+++ b/tests/qtest/virtio-rng-test.c
@@ -20,6 +20,11 @@ static void rng_hotplug(void *obj, void *data, QGuestAllocator *alloc)
QVirtioPCIDevice *dev = obj;
QTestState *qts = dev->pdev->bus->qts;
+ if (dev->pdev->bus->not_hotpluggable) {
+ g_test_skip("pci bus does not support hotplug");
+ return;
+ }
+
const char *arch = qtest_get_arch();
qtest_qmp_device_add(qts, "virtio-rng-pci", "rng1",
--
2.35.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v6 3/3] tests/qtest/libqos: Add generic pci host bridge in arm-virt machine
2022-05-04 15:20 [PATCH v6 0/3] qtests/libqos: Allow PCI tests to be run with virt-machine Eric Auger
2022-05-04 15:20 ` [PATCH v6 1/3] tests/qtest/libqos/pci: Introduce pio_limit Eric Auger
2022-05-04 15:20 ` [PATCH v6 2/3] tests/qtest/libqos: Skip hotplug tests if pci root bus is not hotpluggable Eric Auger
@ 2022-05-04 15:20 ` Eric Auger
2022-05-09 13:59 ` Alex Bennée
2022-05-09 8:18 ` [PATCH v6 0/3] qtests/libqos: Allow PCI tests to be run with virt-machine Eric Auger
3 siblings, 1 reply; 7+ messages in thread
From: Eric Auger @ 2022-05-04 15:20 UTC (permalink / raw)
To: eric.auger.pro, eric.auger, pbonzini, qemu-arm, qemu-devel, mst,
david, clg, eesposit, Coiby.Xu, stefanha
Cc: jean-philippe
Up to now the virt-machine node contains a virtio-mmio node.
However no driver produces any PCI interface node. Hence, PCI
tests cannot be run with aarch64 binary.
Add a GPEX driver node that produces a pci interface node. This latter
then can be consumed by all the pci tests. One of the first motivation
was to be able to run the virtio-iommu-pci tests.
We still face an issue with pci hotplug tests as hotplug cannot happen
on the pcie root bus and require a generic root port. This will be
addressed later on.
We force cpu=max along with aarch64/virt machine as some PCI tests
require high MMIO regions to be available.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v5 -> v6:
- change header path: #include "../libqtest.h"
v3 -> v4:
- properly handle le/cpu conversions on config access
v2 -> v3:
- force cpu=max with aarch64/virt
v1 -> v2:
- copyright updated to 2022
- QPCIBusARM renamed into QGenericPCIBus
- QGenericPCIHost declarations and definitions moved in the same
place as the generic pci implementation
- rename pci-arm.c/h in generic-pcihost.c/h and remove any ref to
ARM there
- remove qos_node_produces_opts, qpci_new_arm, qpci_free_arm
- ecam_alloc_ptr now is a field of QGenericPCIBus and not QPCIBus
- new libqos_init to create generic-pcihost driver that contains
pci-bus-generic
- QGenericPCIHost moved in the same place as the generic pci
bindings
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
tests/qtest/libqos/arm-virt-machine.c | 19 ++-
tests/qtest/libqos/generic-pcihost.c | 231 ++++++++++++++++++++++++++
tests/qtest/libqos/generic-pcihost.h | 54 ++++++
tests/qtest/libqos/meson.build | 1 +
4 files changed, 301 insertions(+), 4 deletions(-)
create mode 100644 tests/qtest/libqos/generic-pcihost.c
create mode 100644 tests/qtest/libqos/generic-pcihost.h
diff --git a/tests/qtest/libqos/arm-virt-machine.c b/tests/qtest/libqos/arm-virt-machine.c
index 2e0beaefb8..139eaba142 100644
--- a/tests/qtest/libqos/arm-virt-machine.c
+++ b/tests/qtest/libqos/arm-virt-machine.c
@@ -22,6 +22,8 @@
#include "malloc.h"
#include "qgraph.h"
#include "virtio-mmio.h"
+#include "generic-pcihost.h"
+#include "hw/pci/pci_regs.h"
#define ARM_PAGE_SIZE 4096
#define VIRTIO_MMIO_BASE_ADDR 0x0A003E00
@@ -35,6 +37,7 @@ struct QVirtMachine {
QOSGraphObject obj;
QGuestAllocator alloc;
QVirtioMMIODevice virtio_mmio;
+ QGenericPCIHost bridge;
};
static void virt_destructor(QOSGraphObject *obj)
@@ -57,11 +60,13 @@ static void *virt_get_driver(void *object, const char *interface)
static QOSGraphObject *virt_get_device(void *obj, const char *device)
{
QVirtMachine *machine = obj;
- if (!g_strcmp0(device, "virtio-mmio")) {
+ if (!g_strcmp0(device, "generic-pcihost")) {
+ return &machine->bridge.obj;
+ } else if (!g_strcmp0(device, "virtio-mmio")) {
return &machine->virtio_mmio.obj;
}
- fprintf(stderr, "%s not present in arm/virtio\n", device);
+ fprintf(stderr, "%s not present in arm/virt\n", device);
g_assert_not_reached();
}
@@ -76,16 +81,22 @@ static void *qos_create_machine_arm_virt(QTestState *qts)
qvirtio_mmio_init_device(&machine->virtio_mmio, qts, VIRTIO_MMIO_BASE_ADDR,
VIRTIO_MMIO_SIZE);
+ qos_create_generic_pcihost(&machine->bridge, qts, &machine->alloc);
+
machine->obj.get_device = virt_get_device;
machine->obj.get_driver = virt_get_driver;
machine->obj.destructor = virt_destructor;
return machine;
}
-static void virtio_mmio_register_nodes(void)
+static void virt_machine_register_nodes(void)
{
qos_node_create_machine("arm/virt", qos_create_machine_arm_virt);
qos_node_contains("arm/virt", "virtio-mmio", NULL);
+
+ qos_node_create_machine_args("aarch64/virt", qos_create_machine_arm_virt,
+ " -cpu max");
+ qos_node_contains("aarch64/virt", "generic-pcihost", NULL);
}
-libqos_init(virtio_mmio_register_nodes);
+libqos_init(virt_machine_register_nodes);
diff --git a/tests/qtest/libqos/generic-pcihost.c b/tests/qtest/libqos/generic-pcihost.c
new file mode 100644
index 0000000000..3124b0e46b
--- /dev/null
+++ b/tests/qtest/libqos/generic-pcihost.c
@@ -0,0 +1,231 @@
+/*
+ * libqos PCI bindings for generic PCI
+ *
+ * Copyright Red Hat Inc., 2022
+ *
+ * Authors:
+ * Eric Auger <eric.auger@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "../libqtest.h"
+#include "generic-pcihost.h"
+#include "qapi/qmp/qdict.h"
+#include "hw/pci/pci_regs.h"
+#include "qemu/host-utils.h"
+
+#include "qemu/module.h"
+
+/* QGenericPCIHost */
+
+QOSGraphObject *generic_pcihost_get_device(void *obj, const char *device)
+{
+ QGenericPCIHost *host = obj;
+ if (!g_strcmp0(device, "pci-bus-generic")) {
+ return &host->pci.obj;
+ }
+ fprintf(stderr, "%s not present in generic-pcihost\n", device);
+ g_assert_not_reached();
+}
+
+void qos_create_generic_pcihost(QGenericPCIHost *host,
+ QTestState *qts,
+ QGuestAllocator *alloc)
+{
+ host->obj.get_device = generic_pcihost_get_device;
+ qpci_init_generic(&host->pci, qts, alloc, false);
+}
+
+static uint8_t qpci_generic_pio_readb(QPCIBus *bus, uint32_t addr)
+{
+ QGenericPCIBus *s = container_of(bus, QGenericPCIBus, bus);
+
+ return qtest_readb(bus->qts, s->gpex_pio_base + addr);
+}
+
+static void qpci_generic_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
+{
+ QGenericPCIBus *s = container_of(bus, QGenericPCIBus, bus);
+
+ qtest_writeb(bus->qts, s->gpex_pio_base + addr, val);
+}
+
+static uint16_t qpci_generic_pio_readw(QPCIBus *bus, uint32_t addr)
+{
+ QGenericPCIBus *s = container_of(bus, QGenericPCIBus, bus);
+
+ return qtest_readw(bus->qts, s->gpex_pio_base + addr);
+}
+
+static void qpci_generic_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
+{
+ QGenericPCIBus *s = container_of(bus, QGenericPCIBus, bus);
+
+ qtest_writew(bus->qts, s->gpex_pio_base + addr, val);
+}
+
+static uint32_t qpci_generic_pio_readl(QPCIBus *bus, uint32_t addr)
+{
+ QGenericPCIBus *s = container_of(bus, QGenericPCIBus, bus);
+
+ return qtest_readl(bus->qts, s->gpex_pio_base + addr);
+}
+
+static void qpci_generic_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
+{
+ QGenericPCIBus *s = container_of(bus, QGenericPCIBus, bus);
+
+ qtest_writel(bus->qts, s->gpex_pio_base + addr, val);
+}
+
+static uint64_t qpci_generic_pio_readq(QPCIBus *bus, uint32_t addr)
+{
+ QGenericPCIBus *s = container_of(bus, QGenericPCIBus, bus);
+
+ return qtest_readq(bus->qts, s->gpex_pio_base + addr);
+}
+
+static void qpci_generic_pio_writeq(QPCIBus *bus, uint32_t addr, uint64_t val)
+{
+ QGenericPCIBus *s = container_of(bus, QGenericPCIBus, bus);
+
+ qtest_writeq(bus->qts, s->gpex_pio_base + addr, val);
+}
+
+static void qpci_generic_memread(QPCIBus *bus, uint32_t addr, void *buf, size_t len)
+{
+ qtest_memread(bus->qts, addr, buf, len);
+}
+
+static void qpci_generic_memwrite(QPCIBus *bus, uint32_t addr,
+ const void *buf, size_t len)
+{
+ qtest_memwrite(bus->qts, addr, buf, len);
+}
+
+static uint8_t qpci_generic_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
+{
+ QGenericPCIBus *gbus = container_of(bus, QGenericPCIBus, bus);
+ uint64_t addr = gbus->ecam_alloc_ptr + ((0 << 20) | (devfn << 12) | offset);
+ uint8_t val;
+
+ qtest_memread(bus->qts, addr, &val, 1);
+ return val;
+}
+
+static uint16_t qpci_generic_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
+{
+ QGenericPCIBus *gbus = container_of(bus, QGenericPCIBus, bus);
+ uint64_t addr = gbus->ecam_alloc_ptr + ((0 << 20) | (devfn << 12) | offset);
+ uint16_t val;
+
+ qtest_memread(bus->qts, addr, &val, 2);
+ return le16_to_cpu(val);
+}
+
+static uint32_t qpci_generic_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
+{
+ QGenericPCIBus *gbus = container_of(bus, QGenericPCIBus, bus);
+ uint64_t addr = gbus->ecam_alloc_ptr + ((0 << 20) | (devfn << 12) | offset);
+ uint32_t val;
+
+ qtest_memread(bus->qts, addr, &val, 4);
+ return le32_to_cpu(val);
+}
+
+static void
+qpci_generic_config_writeb(QPCIBus *bus, int devfn, uint8_t offset, uint8_t value)
+{
+ QGenericPCIBus *gbus = container_of(bus, QGenericPCIBus, bus);
+ uint64_t addr = gbus->ecam_alloc_ptr + ((0 << 20) | (devfn << 12) | offset);
+
+ qtest_memwrite(bus->qts, addr, &value, 1);
+}
+
+static void
+qpci_generic_config_writew(QPCIBus *bus, int devfn, uint8_t offset, uint16_t value)
+{
+ QGenericPCIBus *gbus = container_of(bus, QGenericPCIBus, bus);
+ uint64_t addr = gbus->ecam_alloc_ptr + ((0 << 20) | (devfn << 12) | offset);
+ uint16_t val = cpu_to_le16(value);
+
+ qtest_memwrite(bus->qts, addr, &val, 2);
+}
+
+static void
+qpci_generic_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint32_t value)
+{
+ QGenericPCIBus *gbus = container_of(bus, QGenericPCIBus, bus);
+ uint64_t addr = gbus->ecam_alloc_ptr + ((0 << 20) | (devfn << 12) | offset);
+ uint32_t val = cpu_to_le32(value);
+
+ qtest_memwrite(bus->qts, addr, &val, 4);
+}
+
+static void *qpci_generic_get_driver(void *obj, const char *interface)
+{
+ QGenericPCIBus *qpci = obj;
+ if (!g_strcmp0(interface, "pci-bus")) {
+ return &qpci->bus;
+ }
+ fprintf(stderr, "%s not present in pci-bus-generic\n", interface);
+ g_assert_not_reached();
+}
+
+void qpci_init_generic(QGenericPCIBus *qpci, QTestState *qts,
+ QGuestAllocator *alloc, bool hotpluggable)
+{
+ assert(qts);
+
+ qpci->gpex_pio_base = 0x3eff0000;
+ qpci->bus.not_hotpluggable = !hotpluggable;
+ qpci->bus.has_buggy_msi = false;
+
+ qpci->bus.pio_readb = qpci_generic_pio_readb;
+ qpci->bus.pio_readw = qpci_generic_pio_readw;
+ qpci->bus.pio_readl = qpci_generic_pio_readl;
+ qpci->bus.pio_readq = qpci_generic_pio_readq;
+
+ qpci->bus.pio_writeb = qpci_generic_pio_writeb;
+ qpci->bus.pio_writew = qpci_generic_pio_writew;
+ qpci->bus.pio_writel = qpci_generic_pio_writel;
+ qpci->bus.pio_writeq = qpci_generic_pio_writeq;
+
+ qpci->bus.memread = qpci_generic_memread;
+ qpci->bus.memwrite = qpci_generic_memwrite;
+
+ qpci->bus.config_readb = qpci_generic_config_readb;
+ qpci->bus.config_readw = qpci_generic_config_readw;
+ qpci->bus.config_readl = qpci_generic_config_readl;
+
+ qpci->bus.config_writeb = qpci_generic_config_writeb;
+ qpci->bus.config_writew = qpci_generic_config_writew;
+ qpci->bus.config_writel = qpci_generic_config_writel;
+
+ qpci->bus.qts = qts;
+ qpci->bus.pio_alloc_ptr = 0x0000;
+ qpci->bus.pio_limit = 0x10000;
+ qpci->bus.mmio_alloc_ptr = 0x10000000;
+ qpci->bus.mmio_limit = 0x2eff0000;
+ qpci->ecam_alloc_ptr = 0x4010000000;
+
+ qpci->obj.get_driver = qpci_generic_get_driver;
+}
+
+static void qpci_generic_register_nodes(void)
+{
+ qos_node_create_driver("pci-bus-generic", NULL);
+ qos_node_produces("pci-bus-generic", "pci-bus");
+}
+
+static void qpci_generic_pci_register_nodes(void)
+{
+ qos_node_create_driver("generic-pcihost", NULL);
+ qos_node_contains("generic-pcihost", "pci-bus-generic", NULL);
+}
+
+libqos_init(qpci_generic_register_nodes);
+libqos_init(qpci_generic_pci_register_nodes);
diff --git a/tests/qtest/libqos/generic-pcihost.h b/tests/qtest/libqos/generic-pcihost.h
new file mode 100644
index 0000000000..c693c769df
--- /dev/null
+++ b/tests/qtest/libqos/generic-pcihost.h
@@ -0,0 +1,54 @@
+/*
+ * libqos Generic PCI bindings and generic pci host bridge
+ *
+ * Copyright Red Hat Inc., 2022
+ *
+ * Authors:
+ * Eric Auger <eric.auger@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_GENERIC_PCIHOST_H
+#define LIBQOS_GENERIC_PCIHOST_H
+
+#include "pci.h"
+#include "malloc.h"
+#include "qgraph.h"
+
+typedef struct QGenericPCIBus {
+ QOSGraphObject obj;
+ QPCIBus bus;
+ uint64_t gpex_pio_base;
+ uint64_t ecam_alloc_ptr;
+} QGenericPCIBus;
+
+/*
+ * qpci_init_generic():
+ * @ret: A valid QGenericPCIBus * pointer
+ * @qts: The %QTestState
+ * @alloc: A previously initialized @alloc providing memory for @qts
+ * @bool: devices can be hotplugged on this bus
+ *
+ * This function initializes an already allocated
+ * QGenericPCIBus object.
+ */
+void qpci_init_generic(QGenericPCIBus *ret, QTestState *qts,
+ QGuestAllocator *alloc, bool hotpluggable);
+
+/* QGenericPCIHost */
+
+typedef struct QGenericPCIHost QGenericPCIHost;
+
+struct QGenericPCIHost {
+ QOSGraphObject obj;
+ QGenericPCIBus pci;
+};
+
+QOSGraphObject *generic_pcihost_get_device(void *obj, const char *device);
+void qos_create_generic_pcihost(QGenericPCIHost *host,
+ QTestState *qts,
+ QGuestAllocator *alloc);
+
+#endif
diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build
index 9f292339f9..fd5d6e5ae1 100644
--- a/tests/qtest/libqos/meson.build
+++ b/tests/qtest/libqos/meson.build
@@ -45,6 +45,7 @@ libqos_srcs = files(
'virtio-scsi.c',
'virtio-serial.c',
'virtio-iommu.c',
+ 'generic-pcihost.c',
# qgraph machines:
'aarch64-xlnx-zcu102-machine.c',
--
2.35.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v6 3/3] tests/qtest/libqos: Add generic pci host bridge in arm-virt machine
2022-05-04 15:20 ` [PATCH v6 3/3] tests/qtest/libqos: Add generic pci host bridge in arm-virt machine Eric Auger
@ 2022-05-09 13:59 ` Alex Bennée
2022-05-09 14:33 ` Eric Auger
0 siblings, 1 reply; 7+ messages in thread
From: Alex Bennée @ 2022-05-09 13:59 UTC (permalink / raw)
To: Eric Auger
Cc: eric.auger.pro, pbonzini, qemu-arm, qemu-devel, mst, david, clg,
eesposit, Coiby.Xu, stefanha, jean-philippe
Eric Auger <eric.auger@redhat.com> writes:
> Up to now the virt-machine node contains a virtio-mmio node.
> However no driver produces any PCI interface node. Hence, PCI
> tests cannot be run with aarch64 binary.
>
> Add a GPEX driver node that produces a pci interface node. This latter
> then can be consumed by all the pci tests. One of the first motivation
> was to be able to run the virtio-iommu-pci tests.
>
> We still face an issue with pci hotplug tests as hotplug cannot happen
> on the pcie root bus and require a generic root port. This will be
> addressed later on.
>
> We force cpu=max along with aarch64/virt machine as some PCI tests
> require high MMIO regions to be available.
Where would I be able to force disable-legacy=off for the PCI device
from? Building on this for GPIO I run into the following:
subprocess_run_one_test: /aarch64/virt/generic-pcihost/pci-bus-generic/pci-bus/vhost-user-gpio-pci/vhost-user-gpio/vhost-user-gpio-tests/read-guest-mem/memfile/subprocess
vhost_user_test_setup: -M virt, -cpu max -device vhost-user-gpio-pci,id=gpio0,addr=04.0,chardev=chr-vhost-user-test
vu_gpio_get_protocol_features: 0x202
qemu-system-aarch64: -device vhost-user-gpio-pci,id=gpio0,addr=04.0,chardev=chr-vhost-user-test: Device doesn't support modern mode, and legacy mode is disabled
Set disable-legacy to off
Broken pipe
and I think this needs to be applied to the root bus device?
Anyway otherwise it looks OK to me:
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
--
Alex Bennée
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6 3/3] tests/qtest/libqos: Add generic pci host bridge in arm-virt machine
2022-05-09 13:59 ` Alex Bennée
@ 2022-05-09 14:33 ` Eric Auger
0 siblings, 0 replies; 7+ messages in thread
From: Eric Auger @ 2022-05-09 14:33 UTC (permalink / raw)
To: Alex Bennée
Cc: eric.auger.pro, pbonzini, qemu-arm, qemu-devel, mst, david, clg,
eesposit, Coiby.Xu, stefanha, jean-philippe
Hi Alex,
On 5/9/22 15:59, Alex Bennée wrote:
> Eric Auger <eric.auger@redhat.com> writes:
>
>> Up to now the virt-machine node contains a virtio-mmio node.
>> However no driver produces any PCI interface node. Hence, PCI
>> tests cannot be run with aarch64 binary.
>>
>> Add a GPEX driver node that produces a pci interface node. This latter
>> then can be consumed by all the pci tests. One of the first motivation
>> was to be able to run the virtio-iommu-pci tests.
>>
>> We still face an issue with pci hotplug tests as hotplug cannot happen
>> on the pcie root bus and require a generic root port. This will be
>> addressed later on.
>>
>> We force cpu=max along with aarch64/virt machine as some PCI tests
>> require high MMIO regions to be available.
> Where would I be able to force disable-legacy=off for the PCI device
in libqos/vhost-user-gpio-pci.c qos_node_consumes("vhost-user-blk-pci",
"pci-bus", &opts);
I think you can use opts to force disable-legacy to off.
see vhost-user-blk.c.
> from? Building on this for GPIO I run into the following:
>
> subprocess_run_one_test: /aarch64/virt/generic-pcihost/pci-bus-generic/pci-bus/vhost-user-gpio-pci/vhost-user-gpio/vhost-user-gpio-tests/read-guest-mem/memfile/subprocess
> vhost_user_test_setup: -M virt, -cpu max -device vhost-user-gpio-pci,id=gpio0,addr=04.0,chardev=chr-vhost-user-test
> vu_gpio_get_protocol_features: 0x202
> qemu-system-aarch64: -device vhost-user-gpio-pci,id=gpio0,addr=04.0,chardev=chr-vhost-user-test: Device doesn't support modern mode, and legacy mode is disabled
> Set disable-legacy to off
> Broken pipe
>
> and I think this needs to be applied to the root bus device?
you mean the disable-legacy? I guess it should be applied to your device?
Eric
>
> Anyway otherwise it looks OK to me:
>
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6 0/3] qtests/libqos: Allow PCI tests to be run with virt-machine
2022-05-04 15:20 [PATCH v6 0/3] qtests/libqos: Allow PCI tests to be run with virt-machine Eric Auger
` (2 preceding siblings ...)
2022-05-04 15:20 ` [PATCH v6 3/3] tests/qtest/libqos: Add generic pci host bridge in arm-virt machine Eric Auger
@ 2022-05-09 8:18 ` Eric Auger
3 siblings, 0 replies; 7+ messages in thread
From: Eric Auger @ 2022-05-09 8:18 UTC (permalink / raw)
To: eric.auger.pro, pbonzini, qemu-arm, qemu-devel, mst, david, clg,
eesposit, Coiby.Xu, stefanha
Cc: jean-philippe
Hi,
On 5/4/22 17:20, Eric Auger wrote:
> Up to now the virt-machine node only contains a virtio-mmio
> driver node but no driver that eventually produces any pci-bus
> interface.
>
> Hence, PCI libqos tests cannot be run with aarch64 binary.
>
> This series brings the pieces needed to be able to run PCI tests
> with the aarch64 binary: a generic-pcihost driver node gets
> instantiated by the machine. This later contains a pci-bus-generic
> driver which produces a pci-bus interface. Then all tests
> consuming the pci-bus interface can be run with the libqos arm
> virt machine.
>
> One of the first goal was to be able to run the virtio-iommu-pci
> tests as the virtio-iommu was initially targetting ARM and it
> was awkard to run the tests with the pc machine. This is now
> possible.
>
> Only the tests doing hotplug cannot be run yet as hotplug is
> not possible on the root bus. This will be dealt with separately
> by adding a root port to the object tree.
>
> Best Regards
>
> Eric
>
> This series can be found at:
> https://github.com/eauger/qemu/tree/libqos-pci-arm-v6
A gentle ping on this series.
Now 5b4f72f5e86 ("tests/qtest: properly initialise the vring used idx")
has landed and the all the enabled tests pass, Could someone please consider
pulling it. I have rebased it on
907b5105f1b ("tests: move libqtest.h back under qtest")
so now I hope everything is OK
Thank you in advance
Eric
>
> History
>
> v5 -> v6:
> - change the libqtest.h header path after pull of
> "tests: move libqtest.h back under qtest/"
>
> v4 -> v5:
> - Added Alex' R-b
> - Removed [PATCH v3 4/5] tests/qtest/vhost-user-blk-test:
> Temporary hack to get tests passing on aarch64
> following Alex' fix
>
> v3 -> v4:
> - handle endianess when accessing the cfg space (fix PPC64
> BE failure). Tested on such machine.
>
> v2 -> v3:
> - force -cpu=max along with aarch64/virt
> - reduced the vhost-user-block-pci issue workaround to a
> single guest_alloc() instead of enabling MSIs. Call for
> help on this specific issue. The 2 tests which fail are:
> test_basic and indirect.
>
> v1 -> v2:
> - copyright updated to 2022
> - QPCIBusARM renamed into QGenericPCIBus
> - QGenericPCIHost declarations and definitions moved in the same
> place as the generic pci implementation
> - rename pci-arm.c/h in generic-pcihost.c/h and remove any ref to
> ARM there
> - remove qos_node_produces_opts, qpci_new_arm, qpci_free_arm
> - ecam_alloc_ptr now is a field of QGenericPCIBus and not QPCIBus
> - new libqos_init to create generic-pcihost driver that contains
> pci-bus-generic
> - QGenericPCIHost moved in the same place as the generic pci
> bindings
> - collected Thomas A-b/R-b
>
> Eric Auger (3):
> tests/qtest/libqos/pci: Introduce pio_limit
> tests/qtest/libqos: Skip hotplug tests if pci root bus is not
> hotpluggable
> tests/qtest/libqos: Add generic pci host bridge in arm-virt machine
>
> tests/qtest/e1000e-test.c | 6 +
> tests/qtest/libqos/arm-virt-machine.c | 19 ++-
> tests/qtest/libqos/generic-pcihost.c | 231 ++++++++++++++++++++++++++
> tests/qtest/libqos/generic-pcihost.h | 54 ++++++
> tests/qtest/libqos/meson.build | 1 +
> tests/qtest/libqos/pci-pc.c | 1 +
> tests/qtest/libqos/pci-spapr.c | 1 +
> tests/qtest/libqos/pci.c | 78 +++++----
> tests/qtest/libqos/pci.h | 6 +-
> tests/qtest/vhost-user-blk-test.c | 10 ++
> tests/qtest/virtio-blk-test.c | 5 +
> tests/qtest/virtio-net-test.c | 5 +
> tests/qtest/virtio-rng-test.c | 5 +
> 13 files changed, 387 insertions(+), 35 deletions(-)
> create mode 100644 tests/qtest/libqos/generic-pcihost.c
> create mode 100644 tests/qtest/libqos/generic-pcihost.h
>
^ permalink raw reply [flat|nested] 7+ messages in thread