* small cleanups for pc-bios/optionrom Makefiles

* checkpatch: fix g_malloc check
 * fix mremap() and RDMA detection
 * confine igd-passthrough-isa-bridge to Xen-enabled builds
 * cover PCI in arm-virt machine qtests
 * add -M boot and -M mem compound properties
 * bump SLIRP submodule
 * support CFI with system libslirp (>= 4.7)
 * clean up CoQueue wakeup functions
 * fix vhost-vsock regression
 * fix --disable-vnc compilation
 * other minor bugfixes
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmJ8/KMUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroNTTAf9Et1C8iZn+OlZi99wMEeMy8a4mIE5
 CpkBpFphhkBvt3AH7XNsCyL4Gea4QgsI7nOIEVUwvW7gPf85PiBUX8mjrIVg3x1k
 bmMEwMKSTYPmDieAnYBP9zCqZQXNYP8L8WxVs2jFY2GXZ2ZogODYFbvCY4yEEB72
 UR6uIvQRdpiB6BEj8UZ+5i+sDtb0zxqrjzUz8T/PJC9/2JSNgi+sAWWQoQT3PPU7
 R7z2nmEa1VeVLPP6mUHvJKhBltVXF+LyIjQHvo+Tp9tSqp9JwXfFBNQ5W/MFes2D
 skF47N7PdgKRH9Dp4r0j+MqBwoAq86+ao+MKsbQ1Gb91HhoCWt/MrVrVyg==
 =1E6P
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* small cleanups for pc-bios/optionrom Makefiles
* checkpatch: fix g_malloc check
* fix mremap() and RDMA detection
* confine igd-passthrough-isa-bridge to Xen-enabled builds
* cover PCI in arm-virt machine qtests
* add -M boot and -M mem compound properties
* bump SLIRP submodule
* support CFI with system libslirp (>= 4.7)
* clean up CoQueue wakeup functions
* fix vhost-vsock regression
* fix --disable-vnc compilation
* other minor bugfixes

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmJ8/KMUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroNTTAf9Et1C8iZn+OlZi99wMEeMy8a4mIE5
# CpkBpFphhkBvt3AH7XNsCyL4Gea4QgsI7nOIEVUwvW7gPf85PiBUX8mjrIVg3x1k
# bmMEwMKSTYPmDieAnYBP9zCqZQXNYP8L8WxVs2jFY2GXZ2ZogODYFbvCY4yEEB72
# UR6uIvQRdpiB6BEj8UZ+5i+sDtb0zxqrjzUz8T/PJC9/2JSNgi+sAWWQoQT3PPU7
# R7z2nmEa1VeVLPP6mUHvJKhBltVXF+LyIjQHvo+Tp9tSqp9JwXfFBNQ5W/MFes2D
# skF47N7PdgKRH9Dp4r0j+MqBwoAq86+ao+MKsbQ1Gb91HhoCWt/MrVrVyg==
# =1E6P
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 12 May 2022 05:25:07 AM PDT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [undefined]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (27 commits)
  vmxcap: add tertiary execution controls
  vl: make machine type deprecation a warning
  meson: link libpng independent of vnc
  vhost-backend: do not depend on CONFIG_VHOST_VSOCK
  coroutine-lock: qemu_co_queue_restart_all is a coroutine-only qemu_co_enter_all
  coroutine-lock: introduce qemu_co_queue_enter_all
  coroutine-lock: qemu_co_queue_next is a coroutine-only qemu_co_enter_next
  net: slirp: allow CFI with libslirp >= 4.7
  net: slirp: add support for CFI-friendly timer API
  net: slirp: switch to slirp_new
  net: slirp: introduce a wrapper struct for QemuTimer
  slirp: bump submodule past 4.7 release
  machine: move more memory validation to Machine object
  machine: make memory-backend a link property
  machine: add mem compound property
  machine: add boot compound property
  machine: use QAPI struct for boot configuration
  tests/qtest/libqos: Add generic pci host bridge in arm-virt machine
  tests/qtest/libqos: Skip hotplug tests if pci root bus is not hotpluggable
  tests/qtest/libqos/pci: Introduce pio_limit
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-05-12 10:52:15 -07:00
commit 9de5f2b408
51 changed files with 1072 additions and 498 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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',

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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,14 +49,16 @@ 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 */
bool not_hotpluggable; /* TRUE if devices cannot be hotplugged */
};
struct QPCIBar {
uint64_t addr;
bool is_io;
};
struct QPCIDevice

View file

@ -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

View file

@ -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'}",

View file

@ -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));

View file

@ -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",