Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177466318
D54641.1794491459.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
7 KB
Referenced Files
None
Subscribers
None
D54641.1794491459.diff
View Options
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -29,6 +29,8 @@
#include <sys/param.h>
#include <sys/linker_set.h>
#include <sys/mman.h>
+#include <sys/nv.h>
+#include <sys/vmem.h>
#include <ctype.h>
#include <err.h>
@@ -95,6 +97,7 @@
uint32_t membase32, memlimit32; /* mmio window below 4GB */
uint64_t membase64, memlimit64; /* mmio window above 4GB */
struct slotinfo slotinfo[MAXSLOTS];
+ vmem_t *resources[PCIBAR_MAX];
};
static struct businfo *pci_businfo[MAXBUSES];
@@ -610,25 +613,6 @@
return (0);
}
-
-static int
-pci_emul_alloc_resource(uint64_t *baseptr, uint64_t limit, uint64_t size,
- uint64_t *addr)
-{
- uint64_t base;
-
- assert((size & (size - 1)) == 0); /* must be a power of 2 */
-
- base = roundup2(*baseptr, size);
-
- if (base + size <= limit) {
- *addr = base;
- *baseptr = base + size;
- return (0);
- } else
- return (-1);
-}
-
/*
* Register (or unregister) the MMIO or I/O region associated with the BAR
* register 'idx' of an emulated pci device.
@@ -762,7 +746,11 @@
static void
update_bar_address(struct pci_devinst *pi, uint64_t addr, int idx, int type)
{
- int decode;
+ vmem_t *arena;
+ struct pcibar *bp;
+ struct businfo *bi;
+ uint64_t mask, old_addr;
+ int decode, alloc, error;
if (pi->pi_bar[idx].type == PCIBAR_IO)
decode = porten(pi);
@@ -772,23 +760,45 @@
if (decode)
unregister_bar(pi, idx);
+ bi = pci_businfo[pi->pi_bus];
+ bp = &pi->pi_bar[idx];
+ old_addr = pi->pi_bar[idx].addr;
+ mask = ~(pi->pi_bar[idx].size - 1);
switch (type) {
case PCIBAR_IO:
+ bp->addr = addr;
+ alloc = addr != ((uint16_t)-1 & mask);
+ break;
case PCIBAR_MEM32:
- pi->pi_bar[idx].addr = addr;
+ bp->addr = addr;
+ alloc = addr != ((uint32_t)-1 & mask);
break;
case PCIBAR_MEM64:
- pi->pi_bar[idx].addr &= ~0xffffffffUL;
- pi->pi_bar[idx].addr |= addr;
+ bp->addr &= ~0xffffffffUL;
+ bp->addr |= addr;
+ alloc = addr != ((uint64_t)-1 & mask);
break;
case PCIBAR_MEMHI64:
- pi->pi_bar[idx].addr &= 0xffffffff;
- pi->pi_bar[idx].addr |= addr;
+ bp->addr &= 0xffffffff;
+ bp->addr |= addr;
break;
default:
assert(0);
}
+ arena = bi->resources[type];
+ if (arena != NULL) {
+ if (!alloc)
+ vmem_free(arena, old_addr, bp->size);
+ else {
+ error = vmem_xalloc(arena, bp->size, bp->size, 0, 0,
+ bp->addr, bp->addr + bp->size, M_BESTFIT | M_NOWAIT,
+ &bp->addr);
+ assert(error == 0);
+ assert(bp->addr == addr);
+ }
+ }
+
if (decode)
register_bar(pi, idx);
}
@@ -892,17 +902,14 @@
pci_emul_assign_bar(struct pci_devinst *const pdi, const int idx,
const enum pcibar_type type, const uint64_t size)
{
- int error;
- uint64_t *baseptr, limit, addr, mask, lobits, bar;
+ uint64_t addr, mask, lobits, bar;
+ vmem_t *arena;
switch (type) {
case PCIBAR_NONE:
- baseptr = NULL;
addr = mask = lobits = 0;
- break;
+ return (0);
case PCIBAR_IO:
- baseptr = &pci_emul_iobase;
- limit = PCI_EMUL_IOLIMIT;
mask = PCIM_BAR_IO_BASE;
lobits = PCIM_BAR_IO_SPACE;
break;
@@ -915,43 +922,36 @@
* number (128MB currently).
*/
if (size > 128 * 1024 * 1024) {
- baseptr = &pci_emul_membase64;
- limit = pci_emul_memlim64;
mask = PCIM_BAR_MEM_BASE;
lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 |
PCIM_BAR_MEM_PREFETCH;
} else {
- baseptr = &pci_emul_membase32;
- limit = PCI_EMUL_MEMLIMIT32;
mask = PCIM_BAR_MEM_BASE;
lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64;
}
break;
case PCIBAR_MEM32:
- baseptr = &pci_emul_membase32;
- limit = PCI_EMUL_MEMLIMIT32;
mask = PCIM_BAR_MEM_BASE;
lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32;
break;
case PCIBAR_ROM:
+ /* XXX: how should this behave when the VM is running? */
/* do not claim memory for ROM. OVMF will do it for us. */
- baseptr = NULL;
- limit = 0;
+ addr = 0;
mask = PCIM_BIOS_ADDR_MASK;
lobits = 0;
break;
default:
- printf("pci_emul_alloc_base: invalid bar type %d\n", type);
- assert(0);
+ printf("%s: invalid bar type %d\n", __func__, type);
+ return (-1);
}
- if (baseptr != NULL) {
- error = pci_emul_alloc_resource(baseptr, limit, size, &addr);
- if (error != 0)
- return (error);
- } else {
- addr = 0;
- }
+ assert((size & (size - 1)) == 0); /* must be a power of 2 */
+ arena = pci_businfo[pdi->pi_bus]->resources[type];
+ if (arena != NULL &&
+ (vmem_xalloc(arena, size, size, 0, 0, 0, ~0, M_BESTFIT | M_NOWAIT,
+ &addr) != 0))
+ return (-1);
pdi->pi_bar[idx].type = type;
pdi->pi_bar[idx].addr = addr;
@@ -1526,11 +1526,21 @@
const char *emul;
size_t lowmem;
int bus, slot, func;
- int error;
+ int error, nbuses;
+ size_t io_quantum, mem32_quantum, mem64_quantum;
if (vm_get_lowmem_limit(ctx) > PCI_EMUL_MEMBASE32)
errx(EX_OSERR, "Invalid lowmem limit");
+ nbuses = 0;
+ for (bus = 0; bus < MAXBUSES; bus++) {
+ snprintf(node_name, sizeof(node_name), "pci.%d", bus);
+ nvl = find_config_node(node_name);
+ if (nvl == NULL)
+ continue;
+ nbuses++;
+ }
+
pci_emul_iobase = PCI_EMUL_IOBASE;
pci_emul_membase32 = PCI_EMUL_MEMBASE32;
@@ -1539,6 +1549,10 @@
pci_emul_membase64 = roundup2(pci_emul_membase64, PCI_EMUL_MEMSIZE64);
pci_emul_memlim64 = pci_emul_membase64 + PCI_EMUL_MEMSIZE64;
+ io_quantum = (PCI_EMUL_IOLIMIT - pci_emul_iobase) / nbuses;
+ mem32_quantum = (PCI_EMUL_MEMLIMIT32 - pci_emul_membase32) / nbuses;
+ mem64_quantum = (pci_emul_memlim64 - pci_emul_membase64) / nbuses;
+
TAILQ_INIT(&boot_devices);
for (bus = 0; bus < MAXBUSES; bus++) {
@@ -1557,6 +1571,24 @@
bi->membase32 = pci_emul_membase32;
bi->membase64 = pci_emul_membase64;
+ pci_emul_iobase += io_quantum;
+ pci_emul_membase32 += mem32_quantum;
+ pci_emul_membase64 += mem64_quantum;
+
+ bi->iolimit = pci_emul_iobase - 1;
+ bi->memlimit32 = pci_emul_membase32 - 1;
+ bi->memlimit64 = pci_emul_membase64 - 1;
+
+ bi->resources[PCIBAR_IO] = vmem_create("io", bi->iobase,
+ io_quantum, 0, 0, 0);
+ assert(bi->resources[PCIBAR_IO] != NULL);
+ bi->resources[PCIBAR_MEM32] = vmem_create("mem32",
+ bi->membase32, mem32_quantum, 0, 0, 0);
+ assert(bi->resources[PCIBAR_MEM32] != NULL);
+ bi->resources[PCIBAR_MEM64] = vmem_create("mem64",
+ bi->membase64, mem64_quantum, 0, 0, 0);
+ assert(bi->resources[PCIBAR_MEM64] != NULL);
+
/* first run: init devices */
for (slot = 0; slot < MAXSLOTS; slot++) {
si = &bi->slotinfo[slot];
@@ -1606,25 +1638,6 @@
free(bar);
}
TAILQ_INIT(&pci_bars);
-
- /*
- * Add some slop to the I/O and memory resources decoded by
- * this bus to give a guest some flexibility if it wants to
- * reprogram the BARs.
- */
- pci_emul_iobase += BUSIO_ROUNDUP;
- pci_emul_iobase = roundup2(pci_emul_iobase, BUSIO_ROUNDUP);
- bi->iolimit = pci_emul_iobase;
-
- pci_emul_membase32 += BUSMEM32_ROUNDUP;
- pci_emul_membase32 = roundup2(pci_emul_membase32,
- BUSMEM32_ROUNDUP);
- bi->memlimit32 = pci_emul_membase32;
-
- pci_emul_membase64 += BUSMEM64_ROUNDUP;
- pci_emul_membase64 = roundup2(pci_emul_membase64,
- BUSMEM64_ROUNDUP);
- bi->memlimit64 = pci_emul_membase64;
}
/*
@@ -1785,6 +1798,9 @@
#ifdef __amd64__
if (bus == 0) {
+ int error;
+ vmem_t *arena;
+
dsdt_indent(3);
dsdt_fixed_ioport(0xCF8, 8);
dsdt_unindent(3);
@@ -1813,6 +1829,13 @@
dsdt_line(" })");
goto done;
}
+
+ /*
+ * Register the bus's IO BAR address range.
+ */
+ arena = bi->resources[PCIBAR_IO];
+ error = vmem_add(arena, 0x0D00, PCI_EMUL_IOBASE - 0x0D00, 0);
+ assert(error == 0);
}
#endif
assert(bi != NULL);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Nov 12, 1:50 PM (22 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41677122
Default Alt Text
D54641.1794491459.diff (7 KB)
Attached To
Mode
D54641: bhyve/pci_emul: Use vmem to track BAR allocations
Attached
Detach File
Event Timeline