Page MenuHomeFreeBSD

D54641.1775049587.diff
No OneTemporary

Size
8 KB
Referenced Files
None
Subscribers
None

D54641.1775049587.diff

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

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)

Event Timeline