mirror of https://github.com/xemu-project/xemu.git
tests/qtest/libqos/pci: Introduce pio_limit
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> Message-Id: <20220504152025.1785704-2-eric.auger@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
76acef2b73
commit
3df72d1c55
|
@ -150,6 +150,7 @@ void qpci_init_pc(QPCIBusPC *qpci, QTestState *qts, QGuestAllocator *alloc)
|
||||||
|
|
||||||
qpci->bus.qts = qts;
|
qpci->bus.qts = qts;
|
||||||
qpci->bus.pio_alloc_ptr = 0xc000;
|
qpci->bus.pio_alloc_ptr = 0xc000;
|
||||||
|
qpci->bus.pio_limit = 0x10000;
|
||||||
qpci->bus.mmio_alloc_ptr = 0xE0000000;
|
qpci->bus.mmio_alloc_ptr = 0xE0000000;
|
||||||
qpci->bus.mmio_limit = 0x100000000ULL;
|
qpci->bus.mmio_limit = 0x100000000ULL;
|
||||||
|
|
||||||
|
|
|
@ -197,6 +197,7 @@ void qpci_init_spapr(QPCIBusSPAPR *qpci, QTestState *qts,
|
||||||
|
|
||||||
qpci->bus.qts = qts;
|
qpci->bus.qts = qts;
|
||||||
qpci->bus.pio_alloc_ptr = 0xc000;
|
qpci->bus.pio_alloc_ptr = 0xc000;
|
||||||
|
qpci->bus.pio_limit = 0x10000;
|
||||||
qpci->bus.mmio_alloc_ptr = qpci->mmio32.pci_base;
|
qpci->bus.mmio_alloc_ptr = qpci->mmio32.pci_base;
|
||||||
qpci->bus.mmio_limit = qpci->mmio32.pci_base + qpci->mmio32.size;
|
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)
|
uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
||||||
{
|
{
|
||||||
if (token.addr < QPCI_PIO_LIMIT) {
|
QPCIBus *bus = dev->bus;
|
||||||
return dev->bus->pio_readb(dev->bus, token.addr + off);
|
|
||||||
|
if (token.is_io) {
|
||||||
|
return bus->pio_readb(bus, token.addr + off);
|
||||||
} else {
|
} else {
|
||||||
uint8_t val;
|
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;
|
return val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
||||||
{
|
{
|
||||||
if (token.addr < QPCI_PIO_LIMIT) {
|
QPCIBus *bus = dev->bus;
|
||||||
return dev->bus->pio_readw(dev->bus, token.addr + off);
|
|
||||||
|
if (token.is_io) {
|
||||||
|
return bus->pio_readw(bus, token.addr + off);
|
||||||
} else {
|
} else {
|
||||||
uint16_t val;
|
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);
|
return le16_to_cpu(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
||||||
{
|
{
|
||||||
if (token.addr < QPCI_PIO_LIMIT) {
|
QPCIBus *bus = dev->bus;
|
||||||
return dev->bus->pio_readl(dev->bus, token.addr + off);
|
|
||||||
|
if (token.is_io) {
|
||||||
|
return bus->pio_readl(bus, token.addr + off);
|
||||||
} else {
|
} else {
|
||||||
uint32_t val;
|
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);
|
return le32_to_cpu(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
||||||
{
|
{
|
||||||
if (token.addr < QPCI_PIO_LIMIT) {
|
QPCIBus *bus = dev->bus;
|
||||||
return dev->bus->pio_readq(dev->bus, token.addr + off);
|
|
||||||
|
if (token.is_io) {
|
||||||
|
return bus->pio_readq(bus, token.addr + off);
|
||||||
} else {
|
} else {
|
||||||
uint64_t val;
|
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);
|
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,
|
void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||||
uint8_t value)
|
uint8_t value)
|
||||||
{
|
{
|
||||||
if (token.addr < QPCI_PIO_LIMIT) {
|
QPCIBus *bus = dev->bus;
|
||||||
dev->bus->pio_writeb(dev->bus, token.addr + off, value);
|
|
||||||
|
if (token.is_io) {
|
||||||
|
bus->pio_writeb(bus, token.addr + off, value);
|
||||||
} else {
|
} 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,
|
void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||||
uint16_t value)
|
uint16_t value)
|
||||||
{
|
{
|
||||||
if (token.addr < QPCI_PIO_LIMIT) {
|
QPCIBus *bus = dev->bus;
|
||||||
dev->bus->pio_writew(dev->bus, token.addr + off, value);
|
|
||||||
|
if (token.is_io) {
|
||||||
|
bus->pio_writew(bus, token.addr + off, value);
|
||||||
} else {
|
} else {
|
||||||
value = cpu_to_le16(value);
|
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,
|
void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||||
uint32_t value)
|
uint32_t value)
|
||||||
{
|
{
|
||||||
if (token.addr < QPCI_PIO_LIMIT) {
|
QPCIBus *bus = dev->bus;
|
||||||
dev->bus->pio_writel(dev->bus, token.addr + off, value);
|
|
||||||
|
if (token.is_io) {
|
||||||
|
bus->pio_writel(bus, token.addr + off, value);
|
||||||
} else {
|
} else {
|
||||||
value = cpu_to_le32(value);
|
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,
|
void qpci_io_writeq(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||||
uint64_t value)
|
uint64_t value)
|
||||||
{
|
{
|
||||||
if (token.addr < QPCI_PIO_LIMIT) {
|
QPCIBus *bus = dev->bus;
|
||||||
dev->bus->pio_writeq(dev->bus, token.addr + off, value);
|
|
||||||
|
if (token.is_io) {
|
||||||
|
bus->pio_writeq(bus, token.addr + off, value);
|
||||||
} else {
|
} else {
|
||||||
value = cpu_to_le64(value);
|
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 qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||||
void *buf, size_t len)
|
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);
|
dev->bus->memread(dev->bus, token.addr + off, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||||
const void *buf, size_t len)
|
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);
|
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);
|
loc = QEMU_ALIGN_UP(bus->pio_alloc_ptr, size);
|
||||||
|
|
||||||
g_assert(loc >= bus->pio_alloc_ptr);
|
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;
|
bus->pio_alloc_ptr = loc + size;
|
||||||
|
bar.is_io = true;
|
||||||
|
|
||||||
qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
|
qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
|
||||||
} else {
|
} else {
|
||||||
|
@ -547,6 +568,7 @@ QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
|
||||||
g_assert(loc + size <= bus->mmio_limit);
|
g_assert(loc + size <= bus->mmio_limit);
|
||||||
|
|
||||||
bus->mmio_alloc_ptr = loc + size;
|
bus->mmio_alloc_ptr = loc + size;
|
||||||
|
bar.is_io = false;
|
||||||
|
|
||||||
qpci_config_writel(dev, bar_reg, loc);
|
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 qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
|
||||||
{
|
{
|
||||||
QPCIBar bar = { .addr = addr };
|
QPCIBar bar = { .addr = addr, .is_io = true };
|
||||||
return bar;
|
return bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
#include "../libqtest.h"
|
#include "../libqtest.h"
|
||||||
#include "qgraph.h"
|
#include "qgraph.h"
|
||||||
|
|
||||||
#define QPCI_PIO_LIMIT 0x10000
|
|
||||||
|
|
||||||
#define QPCI_DEVFN(dev, fn) (((dev) << 3) | (fn))
|
#define QPCI_DEVFN(dev, fn) (((dev) << 3) | (fn))
|
||||||
|
|
||||||
typedef struct QPCIDevice QPCIDevice;
|
typedef struct QPCIDevice QPCIDevice;
|
||||||
|
@ -51,7 +49,7 @@ struct QPCIBus {
|
||||||
uint8_t offset, uint32_t value);
|
uint8_t offset, uint32_t value);
|
||||||
|
|
||||||
QTestState *qts;
|
QTestState *qts;
|
||||||
uint16_t pio_alloc_ptr;
|
uint64_t pio_alloc_ptr, pio_limit;
|
||||||
uint64_t mmio_alloc_ptr, mmio_limit;
|
uint64_t mmio_alloc_ptr, mmio_limit;
|
||||||
bool has_buggy_msi; /* TRUE for spapr, FALSE for pci */
|
bool has_buggy_msi; /* TRUE for spapr, FALSE for pci */
|
||||||
|
|
||||||
|
@ -59,6 +57,7 @@ struct QPCIBus {
|
||||||
|
|
||||||
struct QPCIBar {
|
struct QPCIBar {
|
||||||
uint64_t addr;
|
uint64_t addr;
|
||||||
|
bool is_io;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QPCIDevice
|
struct QPCIDevice
|
||||||
|
|
Loading…
Reference in New Issue