mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 07:13:54 -06:00
libqos: Move BAR assignment to common code
The PCI backends in libqos each supply an iomap() and iounmap() function which is used to set up a specified PCI BAR. But PCI BAR allocation takes place entirely within PCI space, so doesn't really need per-backend versions. For example, Linux includes generic BAR allocation code used on platforms where that isn't done by firmware. This patch merges the BAR allocation from the two existing backends into a single simplified copy. The back ends just need to set up some parameters describing the window of PCI IO and PCI memory addresses which are available for allocation. Like both the existing versions the new one uses a simple bump allocator. Note that (again like the existing versions) this doesn't really handle 64-bit memory BARs properly. It is actually used for such a BAR by the ivshmem test, and apparently the 32-bit MMIO BAR logic is close enough to work, as long as the BAR isn't too big. Fixing that to properly handle 64-bit BAR allocation is a problem for another time. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Laurent Vivier <lvivier@redhat.com> Reviewed-by: Greg Kurz <groug@kaod.org>
This commit is contained in:
parent
a795fc08f2
commit
b8cc4d0231
4 changed files with 63 additions and 176 deletions
|
@ -14,6 +14,7 @@
|
|||
#include "libqos/pci.h"
|
||||
|
||||
#include "hw/pci/pci_regs.h"
|
||||
#include "qemu/host-utils.h"
|
||||
|
||||
void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
|
||||
void (*func)(QPCIDevice *dev, int devfn, void *data),
|
||||
|
@ -290,12 +291,63 @@ void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
|
|||
|
||||
void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
|
||||
{
|
||||
return dev->bus->iomap(dev->bus, dev, barno, sizeptr);
|
||||
QPCIBus *bus = dev->bus;
|
||||
static const int bar_reg_map[] = {
|
||||
PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
|
||||
PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
|
||||
};
|
||||
int bar_reg;
|
||||
uint32_t addr, size;
|
||||
uint32_t io_type;
|
||||
uint64_t loc;
|
||||
|
||||
g_assert(barno >= 0 && barno <= 5);
|
||||
bar_reg = bar_reg_map[barno];
|
||||
|
||||
qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
|
||||
addr = qpci_config_readl(dev, bar_reg);
|
||||
|
||||
io_type = addr & PCI_BASE_ADDRESS_SPACE;
|
||||
if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
|
||||
addr &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
} else {
|
||||
addr &= PCI_BASE_ADDRESS_MEM_MASK;
|
||||
}
|
||||
|
||||
g_assert(addr); /* Must have *some* size bits */
|
||||
|
||||
size = 1U << ctz32(addr);
|
||||
if (sizeptr) {
|
||||
*sizeptr = size;
|
||||
}
|
||||
|
||||
if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
|
||||
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 */
|
||||
|
||||
bus->pio_alloc_ptr = loc + size;
|
||||
|
||||
qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
|
||||
} else {
|
||||
loc = QEMU_ALIGN_UP(bus->mmio_alloc_ptr, size);
|
||||
|
||||
/* Check for space */
|
||||
g_assert(loc >= bus->mmio_alloc_ptr);
|
||||
g_assert(loc + size <= bus->mmio_limit);
|
||||
|
||||
bus->mmio_alloc_ptr = loc + size;
|
||||
|
||||
qpci_config_writel(dev, bar_reg, loc);
|
||||
}
|
||||
|
||||
return (void *)(uintptr_t)loc;
|
||||
}
|
||||
|
||||
void qpci_iounmap(QPCIDevice *dev, void *data)
|
||||
{
|
||||
dev->bus->iounmap(dev->bus, data);
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
void qpci_plug_device_test(const char *driver, const char *id,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue