Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144501759
D54641.1775049587.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D54641.1775049587.diff
View Options
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
--- a/usr.sbin/bhyve/pci_emul.h
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -92,6 +92,7 @@
PCIBAR_MEM64,
PCIBAR_MEMHI64,
PCIBAR_ROM,
+ PCIBAR_MAX
};
struct pcibar {
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,19 +97,16 @@
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];
SET_DECLARE(pci_devemu_set, struct pci_devemu);
-static uint64_t pci_emul_iobase;
static uint8_t *pci_emul_rombase;
static uint64_t pci_emul_romoffset;
static uint8_t *pci_emul_romlim;
-static uint64_t pci_emul_membase32;
-static uint64_t pci_emul_membase64;
-static uint64_t pci_emul_memlim64;
struct pci_bar_allocation {
TAILQ_ENTRY(pci_bar_allocation) chain;
@@ -610,25 +609,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 +742,12 @@
static void
update_bar_address(struct pci_devinst *pi, uint64_t addr, int idx, int type)
{
- int decode;
+ bool alloc;
+ vmem_t *arena;
+ int decode, error;
+ struct pcibar *bp;
+ struct businfo *bi;
+ uint64_t mask, old_addr;
if (pi->pi_bar[idx].type == PCIBAR_IO)
decode = porten(pi);
@@ -772,23 +757,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,
+ &bp->addr);
+ assert(error == 0);
+ assert(bp->addr == addr);
+ }
+ }
+
if (decode)
register_bar(pi, idx);
}
@@ -892,17 +899,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 +919,34 @@
* 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:
/* 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, ~0ul, M_BESTFIT, &addr) != 0))
+ return (-1);
pdi->pi_bar[idx].type = type;
pdi->pi_bar[idx].addr = addr;
@@ -1516,6 +1511,9 @@
int
init_pci(struct vmctx *ctx)
{
+ size_t io_range_size, mem32_range_size, mem64_range_size;
+ uint64_t pci_emul_membase32, pci_emul_membase64;
+ uint64_t pci_emul_iobase, pci_emul_memlim64;
char node_name[sizeof("pci.XXX.XX.X")];
struct mem_range mr;
struct pci_devemu *pde;
@@ -1526,11 +1524,20 @@
const char *emul;
size_t lowmem;
int bus, slot, func;
- int error;
+ int error, nbuses;
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 +1546,10 @@
pci_emul_membase64 = roundup2(pci_emul_membase64, PCI_EMUL_MEMSIZE64);
pci_emul_memlim64 = pci_emul_membase64 + PCI_EMUL_MEMSIZE64;
+ io_range_size = (PCI_EMUL_IOLIMIT - pci_emul_iobase) / nbuses;
+ mem32_range_size = (PCI_EMUL_MEMLIMIT32 - pci_emul_membase32) / nbuses;
+ mem64_range_size = (pci_emul_memlim64 - pci_emul_membase64) / nbuses;
+
TAILQ_INIT(&boot_devices);
for (bus = 0; bus < MAXBUSES; bus++) {
@@ -1557,6 +1568,24 @@
bi->membase32 = pci_emul_membase32;
bi->membase64 = pci_emul_membase64;
+ pci_emul_iobase += io_range_size;
+ pci_emul_membase32 += mem32_range_size;
+ pci_emul_membase64 += mem64_range_size;
+
+ 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_range_size, 0, 0, 0);
+ assert(bi->resources[PCIBAR_IO] != NULL);
+ bi->resources[PCIBAR_MEM32] = vmem_create("mem32",
+ bi->membase32, mem32_range_size, 0, 0, 0);
+ assert(bi->resources[PCIBAR_MEM32] != NULL);
+ bi->resources[PCIBAR_MEM64] = vmem_create("mem64",
+ bi->membase64, mem64_range_size, 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 +1635,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 +1795,9 @@
#ifdef __amd64__
if (bus == 0) {
+ int error;
+ vmem_t *arena;
+
dsdt_indent(3);
dsdt_fixed_ioport(0xCF8, 8);
dsdt_unindent(3);
@@ -1813,6 +1826,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
Wed, Apr 1, 1:19 PM (19 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27744523
Default Alt Text
D54641.1775049587.diff (8 KB)
Attached To
Mode
D54641: bhyve/pci_emul: Use vmem to track BAR allocations
Attached
Detach File
Event Timeline
Log In to Comment