mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 17:53:56 -06:00
* 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:
commit
9de5f2b408
51 changed files with 1072 additions and 498 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
231
tests/qtest/libqos/generic-pcihost.c
Normal file
231
tests/qtest/libqos/generic-pcihost.c
Normal 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);
|
54
tests/qtest/libqos/generic-pcihost.h
Normal file
54
tests/qtest/libqos/generic-pcihost.h
Normal 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
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'}",
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue