tests/libqos: pci-pc driver and interface nodes
Add pci-bus-pc node, move QPCIBusPC struct declaration in its header (since it will be needed by other drivers) and introduce a setter method for drivers that do not need to allocate but have to initialize QPCIBusPC. Signed-off-by: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
fc281c8020
commit
85af0057e7
@ -749,11 +749,15 @@ libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o
|
||||
libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o
|
||||
libqos-virtio-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o
|
||||
|
||||
# Devices
|
||||
qos-test-obj-y = tests/qos-test.o $(libqgraph-obj-y)
|
||||
qos-test-obj-y += $(libqos-pc-obj-y)
|
||||
|
||||
check-unit-y += tests/test-qgraph$(EXESUF)
|
||||
tests/test-qgraph$(EXESUF): tests/test-qgraph.o $(libqgraph-obj-y)
|
||||
|
||||
check-qtest-generic-y += tests/qos-test$(EXESUF)
|
||||
tests/qos-test$(EXESUF): tests/qos-test.o $(libqgraph-obj-y)
|
||||
tests/qos-test$(EXESUF): $(qos-test-obj-y)
|
||||
|
||||
tests/qmp-test$(EXESUF): tests/qmp-test.o
|
||||
tests/qmp-cmd-test$(EXESUF): tests/qmp-cmd-test.o
|
||||
|
@ -18,15 +18,9 @@
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
|
||||
#define ACPI_PCIHP_ADDR 0xae00
|
||||
#define PCI_EJ_BASE 0x0008
|
||||
|
||||
typedef struct QPCIBusPC
|
||||
{
|
||||
QPCIBus bus;
|
||||
} QPCIBusPC;
|
||||
|
||||
static uint8_t qpci_pc_pio_readb(QPCIBus *bus, uint32_t addr)
|
||||
{
|
||||
return qtest_inb(bus->qts, addr);
|
||||
@ -116,44 +110,65 @@ static void qpci_pc_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint3
|
||||
qtest_outl(bus->qts, 0xcfc, value);
|
||||
}
|
||||
|
||||
QPCIBus *qpci_new_pc(QTestState *qts, QGuestAllocator *alloc)
|
||||
static void *qpci_pc_get_driver(void *obj, const char *interface)
|
||||
{
|
||||
QPCIBusPC *ret = g_new0(QPCIBusPC, 1);
|
||||
QPCIBusPC *qpci = obj;
|
||||
if (!g_strcmp0(interface, "pci-bus")) {
|
||||
return &qpci->bus;
|
||||
}
|
||||
fprintf(stderr, "%s not present in pci-bus-pc\n", interface);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
void qpci_init_pc(QPCIBusPC *qpci, QTestState *qts, QGuestAllocator *alloc)
|
||||
{
|
||||
assert(qts);
|
||||
|
||||
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_readq = qpci_pc_pio_readq;
|
||||
qpci->bus.pio_readb = qpci_pc_pio_readb;
|
||||
qpci->bus.pio_readw = qpci_pc_pio_readw;
|
||||
qpci->bus.pio_readl = qpci_pc_pio_readl;
|
||||
qpci->bus.pio_readq = qpci_pc_pio_readq;
|
||||
|
||||
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.pio_writeq = qpci_pc_pio_writeq;
|
||||
qpci->bus.pio_writeb = qpci_pc_pio_writeb;
|
||||
qpci->bus.pio_writew = qpci_pc_pio_writew;
|
||||
qpci->bus.pio_writel = qpci_pc_pio_writel;
|
||||
qpci->bus.pio_writeq = qpci_pc_pio_writeq;
|
||||
|
||||
ret->bus.memread = qpci_pc_memread;
|
||||
ret->bus.memwrite = qpci_pc_memwrite;
|
||||
qpci->bus.memread = qpci_pc_memread;
|
||||
qpci->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;
|
||||
qpci->bus.config_readb = qpci_pc_config_readb;
|
||||
qpci->bus.config_readw = qpci_pc_config_readw;
|
||||
qpci->bus.config_readl = qpci_pc_config_readl;
|
||||
|
||||
ret->bus.config_writeb = qpci_pc_config_writeb;
|
||||
ret->bus.config_writew = qpci_pc_config_writew;
|
||||
ret->bus.config_writel = qpci_pc_config_writel;
|
||||
qpci->bus.config_writeb = qpci_pc_config_writeb;
|
||||
qpci->bus.config_writew = qpci_pc_config_writew;
|
||||
qpci->bus.config_writel = qpci_pc_config_writel;
|
||||
|
||||
ret->bus.qts = qts;
|
||||
ret->bus.pio_alloc_ptr = 0xc000;
|
||||
ret->bus.mmio_alloc_ptr = 0xE0000000;
|
||||
ret->bus.mmio_limit = 0x100000000ULL;
|
||||
qpci->bus.qts = qts;
|
||||
qpci->bus.pio_alloc_ptr = 0xc000;
|
||||
qpci->bus.mmio_alloc_ptr = 0xE0000000;
|
||||
qpci->bus.mmio_limit = 0x100000000ULL;
|
||||
|
||||
return &ret->bus;
|
||||
qpci->obj.get_driver = qpci_pc_get_driver;
|
||||
}
|
||||
|
||||
QPCIBus *qpci_new_pc(QTestState *qts, QGuestAllocator *alloc)
|
||||
{
|
||||
QPCIBusPC *qpci = g_new0(QPCIBusPC, 1);
|
||||
qpci_init_pc(qpci, qts, alloc);
|
||||
|
||||
return &qpci->bus;
|
||||
}
|
||||
|
||||
void qpci_free_pc(QPCIBus *bus)
|
||||
{
|
||||
QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
|
||||
QPCIBusPC *s;
|
||||
|
||||
if (!bus) {
|
||||
return;
|
||||
}
|
||||
s = container_of(bus, QPCIBusPC, bus);
|
||||
|
||||
g_free(s);
|
||||
}
|
||||
@ -172,3 +187,11 @@ void qpci_unplug_acpi_device_test(const char *id, uint8_t slot)
|
||||
|
||||
qmp_eventwait("DEVICE_DELETED");
|
||||
}
|
||||
|
||||
static void qpci_pc_register_nodes(void)
|
||||
{
|
||||
qos_node_create_driver("pci-bus-pc", NULL);
|
||||
qos_node_produces("pci-bus-pc", "pci-bus");
|
||||
}
|
||||
|
||||
libqos_init(qpci_pc_register_nodes);
|
||||
|
@ -15,6 +15,22 @@
|
||||
|
||||
#include "libqos/pci.h"
|
||||
#include "libqos/malloc.h"
|
||||
#include "libqos/qgraph.h"
|
||||
|
||||
typedef struct QPCIBusPC {
|
||||
QOSGraphObject obj;
|
||||
QPCIBus bus;
|
||||
} QPCIBusPC;
|
||||
|
||||
/* qpci_init_pc():
|
||||
* @ret: A valid QPCIBusPC * pointer
|
||||
* @qts: The %QTestState for this PC machine
|
||||
* @alloc: A previously initialized @alloc providing memory for @qts
|
||||
*
|
||||
* This function initializes an already allocated
|
||||
* QPCIBusPC object.
|
||||
*/
|
||||
void qpci_init_pc(QPCIBusPC *ret, QTestState *qts, QGuestAllocator *alloc);
|
||||
|
||||
/* qpci_pc_new():
|
||||
* @qts: The %QTestState for this PC machine
|
||||
@ -23,7 +39,8 @@
|
||||
* This function creates a new QPCIBusPC object,
|
||||
* and properly initialize its fields.
|
||||
*
|
||||
* Returns a newly allocated QPCIBus.
|
||||
* Returns the QPCIBus *bus field of a newly
|
||||
* allocated QPCIBusPC.
|
||||
*/
|
||||
QPCIBus *qpci_new_pc(QTestState *qts, QGuestAllocator *alloc);
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "hw/pci/pci_regs.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "libqos/qgraph.h"
|
||||
|
||||
void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
|
||||
void (*func)(QPCIDevice *dev, int devfn, void *data),
|
||||
@ -50,13 +51,20 @@ void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
|
||||
}
|
||||
}
|
||||
|
||||
static void qpci_device_set(QPCIDevice *dev, QPCIBus *bus, int devfn)
|
||||
{
|
||||
g_assert(dev);
|
||||
|
||||
dev->bus = bus;
|
||||
dev->devfn = devfn;
|
||||
}
|
||||
|
||||
QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
|
||||
dev = g_malloc0(sizeof(*dev));
|
||||
dev->bus = bus;
|
||||
dev->devfn = devfn;
|
||||
qpci_device_set(dev, bus, devfn);
|
||||
|
||||
if (qpci_config_readw(dev, PCI_VENDOR_ID) == 0xFFFF) {
|
||||
g_free(dev);
|
||||
@ -66,6 +74,17 @@ QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn)
|
||||
return dev;
|
||||
}
|
||||
|
||||
void qpci_device_init(QPCIDevice *dev, QPCIBus *bus, QPCIAddress *addr)
|
||||
{
|
||||
uint16_t vendor_id, device_id;
|
||||
|
||||
qpci_device_set(dev, bus, addr->devfn);
|
||||
vendor_id = qpci_config_readw(dev, PCI_VENDOR_ID);
|
||||
device_id = qpci_config_readw(dev, PCI_DEVICE_ID);
|
||||
g_assert(!addr->vendor_id || vendor_id == addr->vendor_id);
|
||||
g_assert(!addr->device_id || device_id == addr->device_id);
|
||||
}
|
||||
|
||||
void qpci_device_enable(QPCIDevice *dev)
|
||||
{
|
||||
uint16_t cmd;
|
||||
@ -395,3 +414,12 @@ QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
|
||||
QPCIBar bar = { .addr = addr };
|
||||
return bar;
|
||||
}
|
||||
|
||||
void add_qpci_address(QOSGraphEdgeOptions *opts, QPCIAddress *addr)
|
||||
{
|
||||
g_assert(addr);
|
||||
g_assert(opts);
|
||||
|
||||
opts->arg = addr;
|
||||
opts->size_arg = sizeof(QPCIAddress);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define LIBQOS_PCI_H
|
||||
|
||||
#include "libqtest.h"
|
||||
#include "libqos/qgraph.h"
|
||||
|
||||
#define QPCI_PIO_LIMIT 0x10000
|
||||
|
||||
@ -22,6 +23,7 @@
|
||||
typedef struct QPCIDevice QPCIDevice;
|
||||
typedef struct QPCIBus QPCIBus;
|
||||
typedef struct QPCIBar QPCIBar;
|
||||
typedef struct QPCIAddress QPCIAddress;
|
||||
|
||||
struct QPCIBus {
|
||||
uint8_t (*pio_readb)(QPCIBus *bus, uint32_t addr);
|
||||
@ -51,6 +53,7 @@ struct QPCIBus {
|
||||
QTestState *qts;
|
||||
uint16_t pio_alloc_ptr;
|
||||
uint64_t mmio_alloc_ptr, mmio_limit;
|
||||
|
||||
};
|
||||
|
||||
struct QPCIBar {
|
||||
@ -66,10 +69,17 @@ struct QPCIDevice
|
||||
uint64_t msix_table_off, msix_pba_off;
|
||||
};
|
||||
|
||||
struct QPCIAddress {
|
||||
uint32_t devfn;
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
};
|
||||
|
||||
void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
|
||||
void (*func)(QPCIDevice *dev, int devfn, void *data),
|
||||
void *data);
|
||||
QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn);
|
||||
void qpci_device_init(QPCIDevice *dev, QPCIBus *bus, QPCIAddress *addr);
|
||||
|
||||
void qpci_device_enable(QPCIDevice *dev);
|
||||
uint8_t qpci_find_capability(QPCIDevice *dev, uint8_t id);
|
||||
@ -110,4 +120,6 @@ void qpci_iounmap(QPCIDevice *dev, QPCIBar addr);
|
||||
QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr);
|
||||
|
||||
void qpci_unplug_acpi_device_test(const char *id, uint8_t slot);
|
||||
|
||||
void add_qpci_address(QOSGraphEdgeOptions *opts, QPCIAddress *addr);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user