Page MenuHomeFreeBSD

D24066.id70138.diff
No OneTemporary

D24066.id70138.diff

Index: lib/libvmmapi/vmmapi.h
===================================================================
--- lib/libvmmapi/vmmapi.h
+++ lib/libvmmapi/vmmapi.h
@@ -103,6 +103,8 @@
int vm_mmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, int segid,
vm_ooffset_t segoff, size_t len, int prot);
+int vm_munmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, size_t len);
+
int vm_create(const char *name);
int vm_get_device_fd(struct vmctx *ctx);
struct vmctx *vm_open(const char *name);
@@ -163,6 +165,8 @@
int vm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func);
int vm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
+int vm_unmap_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
+ vm_paddr_t gpa, size_t len);
int vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot,
int func, uint64_t addr, uint64_t msg, int numvec);
int vm_setup_pptdev_msix(struct vmctx *ctx, int vcpu, int bus, int slot,
Index: lib/libvmmapi/vmmapi.c
===================================================================
--- lib/libvmmapi/vmmapi.c
+++ lib/libvmmapi/vmmapi.c
@@ -237,6 +237,19 @@
return (error);
}
+int
+vm_munmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, size_t len)
+{
+ struct vm_munmap munmap;
+ int error;
+
+ munmap.gpa = gpa;
+ munmap.len = len;
+
+ error = ioctl(ctx->fd, VM_MUNMAP_MEMSEG, &munmap);
+ return (error);
+}
+
int
vm_mmap_getnext(struct vmctx *ctx, vm_paddr_t *gpa, int *segid,
vm_ooffset_t *segoff, size_t *len, int *prot, int *flags)
@@ -926,6 +939,22 @@
return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
}
+int
+vm_unmap_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
+ vm_paddr_t gpa, size_t len)
+{
+ struct vm_pptdev_mmio pptmmio;
+
+ bzero(&pptmmio, sizeof(pptmmio));
+ pptmmio.bus = bus;
+ pptmmio.slot = slot;
+ pptmmio.func = func;
+ pptmmio.gpa = gpa;
+ pptmmio.len = len;
+
+ return (ioctl(ctx->fd, VM_UNMAP_PPTDEV_MMIO, &pptmmio));
+}
+
int
vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
uint64_t addr, uint64_t msg, int numvec)
@@ -1554,7 +1583,7 @@
/* keep in sync with machine/vmm_dev.h */
static const cap_ioctl_t vm_ioctl_cmds[] = { VM_RUN, VM_SUSPEND, VM_REINIT,
VM_ALLOC_MEMSEG, VM_GET_MEMSEG, VM_MMAP_MEMSEG, VM_MMAP_MEMSEG,
- VM_MMAP_GETNEXT, VM_SET_REGISTER, VM_GET_REGISTER,
+ VM_MMAP_GETNEXT, VM_MUNMAP_MEMSEG, VM_SET_REGISTER, VM_GET_REGISTER,
VM_SET_SEGMENT_DESCRIPTOR, VM_GET_SEGMENT_DESCRIPTOR,
VM_SET_REGISTER_SET, VM_GET_REGISTER_SET,
VM_INJECT_EXCEPTION, VM_LAPIC_IRQ, VM_LAPIC_LOCAL_IRQ,
@@ -1563,8 +1592,8 @@
VM_ISA_DEASSERT_IRQ, VM_ISA_PULSE_IRQ, VM_ISA_SET_IRQ_TRIGGER,
VM_SET_CAPABILITY, VM_GET_CAPABILITY, VM_BIND_PPTDEV,
VM_UNBIND_PPTDEV, VM_MAP_PPTDEV_MMIO, VM_PPTDEV_MSI,
- VM_PPTDEV_MSIX, VM_INJECT_NMI, VM_STATS, VM_STAT_DESC,
- VM_SET_X2APIC_STATE, VM_GET_X2APIC_STATE,
+ VM_PPTDEV_MSIX, VM_UNMAP_PPTDEV_MMIO, VM_INJECT_NMI, VM_STATS,
+ VM_STAT_DESC, VM_SET_X2APIC_STATE, VM_GET_X2APIC_STATE,
VM_GET_HPET_CAPABILITIES, VM_GET_GPA_PMAP, VM_GLA2GPA,
VM_GLA2GPA_NOFAULT,
VM_ACTIVATE_CPU, VM_GET_CPUS, VM_SUSPEND_CPU, VM_RESUME_CPU,
Index: sys/amd64/include/vmm.h
===================================================================
--- sys/amd64/include/vmm.h
+++ sys/amd64/include/vmm.h
@@ -219,6 +219,7 @@
*/
int vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t off,
size_t len, int prot, int flags);
+int vm_munmap_memseg(struct vm *vm, vm_paddr_t gpa, size_t len);
int vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem);
void vm_free_memseg(struct vm *vm, int ident);
int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
Index: sys/amd64/include/vmm_dev.h
===================================================================
--- sys/amd64/include/vmm_dev.h
+++ sys/amd64/include/vmm_dev.h
@@ -47,6 +47,11 @@
#define VM_MEMMAP_F_WIRED 0x01
#define VM_MEMMAP_F_IOMMU 0x02
+struct vm_munmap {
+ vm_paddr_t gpa;
+ size_t len;
+};
+
#define VM_MEMSEG_NAME(m) ((m)->name[0] != '\0' ? (m)->name : NULL)
struct vm_memseg {
int segid;
@@ -252,6 +257,7 @@
IOCNUM_MMAP_MEMSEG = 16,
IOCNUM_MMAP_GETNEXT = 17,
IOCNUM_GLA2GPA_NOFAULT = 18,
+ IOCNUM_MUNMAP_MEMSEG = 19,
/* register/state accessors */
IOCNUM_SET_REGISTER = 20,
@@ -281,6 +287,7 @@
IOCNUM_MAP_PPTDEV_MMIO = 42,
IOCNUM_PPTDEV_MSI = 43,
IOCNUM_PPTDEV_MSIX = 44,
+ IOCNUM_UNMAP_PPTDEV_MMIO = 45,
/* statistics */
IOCNUM_VM_STATS = 50,
@@ -328,6 +335,8 @@
_IOW('v', IOCNUM_MMAP_MEMSEG, struct vm_memmap)
#define VM_MMAP_GETNEXT \
_IOWR('v', IOCNUM_MMAP_GETNEXT, struct vm_memmap)
+#define VM_MUNMAP_MEMSEG \
+ _IOW('v', IOCNUM_MUNMAP_MEMSEG, struct vm_munmap)
#define VM_SET_REGISTER \
_IOW('v', IOCNUM_SET_REGISTER, struct vm_register)
#define VM_GET_REGISTER \
@@ -378,6 +387,8 @@
_IOW('v', IOCNUM_PPTDEV_MSI, struct vm_pptdev_msi)
#define VM_PPTDEV_MSIX \
_IOW('v', IOCNUM_PPTDEV_MSIX, struct vm_pptdev_msix)
+#define VM_UNMAP_PPTDEV_MMIO \
+ _IOW('v', IOCNUM_UNMAP_PPTDEV_MMIO, struct vm_pptdev_mmio)
#define VM_INJECT_NMI \
_IOW('v', IOCNUM_INJECT_NMI, struct vm_nmi)
#define VM_STATS \
Index: sys/amd64/vmm/io/ppt.h
===================================================================
--- sys/amd64/vmm/io/ppt.h
+++ sys/amd64/vmm/io/ppt.h
@@ -34,6 +34,8 @@
int ppt_unassign_all(struct vm *vm);
int ppt_map_mmio(struct vm *vm, int bus, int slot, int func,
vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
+int ppt_unmap_mmio(struct vm *vm, int bus, int slot, int func,
+ vm_paddr_t gpa, size_t len);
int ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func,
uint64_t addr, uint64_t msg, int numvec);
int ppt_setup_msix(struct vm *vm, int vcpu, int bus, int slot, int func,
Index: sys/amd64/vmm/io/ppt.c
===================================================================
--- sys/amd64/vmm/io/ppt.c
+++ sys/amd64/vmm/io/ppt.c
@@ -218,7 +218,7 @@
}
static void
-ppt_unmap_mmio(struct vm *vm, struct pptdev *ppt)
+ppt_unmap_all_mmio(struct vm *vm, struct pptdev *ppt)
{
int i;
struct pptseg *seg;
@@ -414,7 +414,7 @@
pci_save_state(ppt->dev);
ppt_pci_reset(ppt->dev);
pci_restore_state(ppt->dev);
- ppt_unmap_mmio(vm, ppt);
+ ppt_unmap_all_mmio(vm, ppt);
ppt_teardown_msi(ppt);
ppt_teardown_msix(ppt);
iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev));
@@ -473,6 +473,35 @@
return (ENOENT);
}
+int
+ppt_unmap_mmio(struct vm *vm, int bus, int slot, int func,
+ vm_paddr_t gpa, size_t len)
+{
+ int i, error;
+ struct pptseg *seg;
+ struct pptdev *ppt;
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt != NULL) {
+ if (ppt->vm != vm)
+ return (EBUSY);
+
+ for (i = 0; i < MAX_MMIOSEGS; i++) {
+ seg = &ppt->mmio[i];
+ if (seg->gpa == gpa && seg->len == len) {
+ error = vm_unmap_mmio(vm, seg->gpa, seg->len);
+ if (error == 0) {
+ seg->gpa = 0;
+ seg->len = 0;
+ }
+ return (error);
+ }
+ }
+ return (ENOENT);
+ }
+ return (ENOENT);
+}
+
static int
pptintr(void *arg)
{
Index: sys/amd64/vmm/vmm.c
===================================================================
--- sys/amd64/vmm/vmm.c
+++ sys/amd64/vmm/vmm.c
@@ -769,6 +769,24 @@
return (0);
}
+int
+vm_munmap_memseg(struct vm *vm, vm_paddr_t gpa, size_t len)
+{
+ struct mem_map *m;
+ int i;
+
+ for (i = 0; i < VM_MAX_MEMMAPS; i++) {
+ m = &vm->mem_maps[i];
+ if (m->gpa == gpa && m->len == len &&
+ (m->flags & VM_MEMMAP_F_IOMMU) == 0) {
+ vm_free_memmap(vm, i);
+ return (0);
+ }
+ }
+
+ return (EINVAL);
+}
+
int
vm_mmap_getnext(struct vm *vm, vm_paddr_t *gpa, int *segid,
vm_ooffset_t *segoff, size_t *len, int *prot, int *flags)
Index: sys/amd64/vmm/vmm_dev.c
===================================================================
--- sys/amd64/vmm/vmm_dev.c
+++ sys/amd64/vmm/vmm_dev.c
@@ -378,6 +378,7 @@
struct vm_rtc_time *rtctime;
struct vm_rtc_data *rtcdata;
struct vm_memmap *mm;
+ struct vm_munmap *mu;
struct vm_cpu_topology *topology;
uint64_t *regvals;
int *regnums;
@@ -428,10 +429,12 @@
break;
case VM_MAP_PPTDEV_MMIO:
+ case VM_UNMAP_PPTDEV_MMIO:
case VM_BIND_PPTDEV:
case VM_UNBIND_PPTDEV:
case VM_ALLOC_MEMSEG:
case VM_MMAP_MEMSEG:
+ case VM_MUNMAP_MEMSEG:
case VM_REINIT:
/*
* ioctls that operate on the entire virtual machine must
@@ -507,6 +510,11 @@
pptmmio->func, pptmmio->gpa, pptmmio->len,
pptmmio->hpa);
break;
+ case VM_UNMAP_PPTDEV_MMIO:
+ pptmmio = (struct vm_pptdev_mmio *)data;
+ error = ppt_unmap_mmio(sc->vm, pptmmio->bus, pptmmio->slot,
+ pptmmio->func, pptmmio->gpa, pptmmio->len);
+ break;
case VM_BIND_PPTDEV:
pptdev = (struct vm_pptdev *)data;
error = vm_assign_pptdev(sc->vm, pptdev->bus, pptdev->slot,
@@ -590,6 +598,10 @@
error = vm_mmap_memseg(sc->vm, mm->gpa, mm->segid, mm->segoff,
mm->len, mm->prot, mm->flags);
break;
+ case VM_MUNMAP_MEMSEG:
+ mu = (struct vm_munmap *)data;
+ error = vm_munmap_memseg(sc->vm, mu->gpa, mu->len);
+ break;
case VM_ALLOC_MEMSEG:
error = alloc_memseg(sc, (struct vm_memseg *)data);
break;
Index: usr.sbin/bhyve/pci_emul.h
===================================================================
--- usr.sbin/bhyve/pci_emul.h
+++ usr.sbin/bhyve/pci_emul.h
@@ -71,6 +71,9 @@
uint64_t (*pe_barread)(struct vmctx *ctx, int vcpu,
struct pci_devinst *pi, int baridx,
uint64_t offset, int size);
+
+ void (*pe_baraddr)(struct vmctx *ctx, struct pci_devinst *pi,
+ int baridx, int enabled, uint64_t address);
};
#define PCI_EMUL_SET(x) DATA_SET(pci_devemu_set, x);
Index: usr.sbin/bhyve/pci_emul.c
===================================================================
--- usr.sbin/bhyve/pci_emul.c
+++ usr.sbin/bhyve/pci_emul.c
@@ -465,10 +465,12 @@
static void
modify_bar_registration(struct pci_devinst *pi, int idx, int registration)
{
+ struct pci_devemu *pe;
int error;
struct inout_port iop;
struct mem_range mr;
+ pe = pi->pi_d;
switch (pi->pi_bar[idx].type) {
case PCIBAR_IO:
bzero(&iop, sizeof(struct inout_port));
@@ -482,6 +484,9 @@
error = register_inout(&iop);
} else
error = unregister_inout(&iop);
+ if (pe->pe_baraddr != NULL)
+ (*pe->pe_baraddr)(pi->pi_vmctx, pi, idx, registration,
+ pi->pi_bar[idx].addr);
break;
case PCIBAR_MEM32:
case PCIBAR_MEM64:
@@ -497,6 +502,9 @@
error = register_mem(&mr);
} else
error = unregister_mem(&mr);
+ if (pe->pe_baraddr != NULL)
+ (*pe->pe_baraddr)(pi->pi_vmctx, pi, idx, registration,
+ pi->pi_bar[idx].addr);
break;
default:
error = EINVAL;
Index: usr.sbin/bhyve/pci_fbuf.c
===================================================================
--- usr.sbin/bhyve/pci_fbuf.c
+++ usr.sbin/bhyve/pci_fbuf.c
@@ -223,6 +223,30 @@
return (value);
}
+static void
+pci_fbuf_baraddr(struct vmctx *ctx, struct pci_devinst *pi, int baridx,
+ int enabled, uint64_t address)
+{
+ struct pci_fbuf_softc *sc;
+ int prot;
+
+ if (baridx != 1)
+ return;
+
+ sc = pi->pi_arg;
+ if (!enabled && sc->fbaddr != 0) {
+ if (vm_munmap_memseg(ctx, sc->fbaddr, FB_SIZE) != 0)
+ EPRINTLN("pci_fbuf: munmap_memseg failed");
+ sc->fbaddr = 0;
+ } else if (sc->fb_base != NULL && sc->fbaddr == 0) {
+ prot = PROT_READ | PROT_WRITE;
+ if (vm_mmap_memseg(ctx, address, VM_FRAMEBUFFER, 0, FB_SIZE, prot) != 0)
+ EPRINTLN("pci_fbuf: mmap_memseg failed");
+ sc->fbaddr = address;
+ }
+}
+
+
static int
pci_fbuf_parse_opts(struct pci_fbuf_softc *sc, char *opts)
{
@@ -444,6 +468,7 @@
.pe_emu = "fbuf",
.pe_init = pci_fbuf_init,
.pe_barwrite = pci_fbuf_write,
- .pe_barread = pci_fbuf_read
+ .pe_barread = pci_fbuf_read,
+ .pe_baraddr = pci_fbuf_baraddr,
};
PCI_EMUL_SET(pci_fbuf);
Index: usr.sbin/bhyve/pci_passthru.c
===================================================================
--- usr.sbin/bhyve/pci_passthru.c
+++ usr.sbin/bhyve/pci_passthru.c
@@ -438,8 +438,8 @@
init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base)
{
int b, s, f;
- int error, idx;
- size_t len, remaining;
+ int idx;
+ size_t remaining;
uint32_t table_size, table_offset;
uint32_t pba_size, pba_offset;
vm_paddr_t start;
@@ -501,31 +501,6 @@
}
}
- /* Map everything before the MSI-X table */
- if (table_offset > 0) {
- len = table_offset;
- error = vm_map_pptdev_mmio(ctx, b, s, f, start, len, base);
- if (error)
- return (error);
-
- base += len;
- start += len;
- remaining -= len;
- }
-
- /* Skip the MSI-X table */
- base += table_size;
- start += table_size;
- remaining -= table_size;
-
- /* Map everything beyond the end of the MSI-X table */
- if (remaining > 0) {
- len = remaining;
- error = vm_map_pptdev_mmio(ctx, b, s, f, start, len, base);
- if (error)
- return (error);
- }
-
return (0);
}
@@ -592,13 +567,6 @@
error = init_msix_table(ctx, sc, base);
if (error)
return (-1);
- } else if (bartype != PCIBAR_IO) {
- /* Map the physical BAR in the guest MMIO space */
- error = vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
- sc->psc_sel.pc_dev, sc->psc_sel.pc_func,
- pi->pi_bar[i].addr, pi->pi_bar[i].size, base);
- if (error)
- return (-1);
}
/*
@@ -948,6 +916,92 @@
return (val);
}
+static void
+passthru_msix_addr(struct vmctx *ctx, struct pci_devinst *pi, int baridx,
+ int enabled, uint64_t address)
+{
+ struct passthru_softc *sc;
+ size_t remaining;
+ uint32_t table_size, table_offset;
+
+ sc = pi->pi_arg;
+ table_offset = rounddown2(pi->pi_msix.table_offset, 4096);
+ if (table_offset > 0) {
+ if (!enabled) {
+ if (vm_unmap_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
+ sc->psc_sel.pc_dev,
+ sc->psc_sel.pc_func, address,
+ table_offset) != 0)
+ warnx("pci_passthru: unmap_pptdev_mmio failed");
+ } else {
+ if (vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
+ sc->psc_sel.pc_dev,
+ sc->psc_sel.pc_func, address,
+ table_offset,
+ sc->psc_bar[baridx].addr) != 0)
+ warnx("pci_passthru: map_pptdev_mmio failed");
+ }
+ }
+ table_size = pi->pi_msix.table_offset - table_offset;
+ table_size += pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
+ table_size = roundup2(table_size, 4096);
+ remaining = pi->pi_bar[baridx].size - table_offset - table_size;
+ if (remaining > 0) {
+ address += table_offset + table_size;
+ if (!enabled) {
+ if (vm_unmap_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
+ sc->psc_sel.pc_dev,
+ sc->psc_sel.pc_func, address,
+ remaining) != 0)
+ warnx("pci_passthru: unmap_pptdev_mmio failed");
+ } else {
+ if (vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
+ sc->psc_sel.pc_dev,
+ sc->psc_sel.pc_func, address,
+ remaining,
+ sc->psc_bar[baridx].addr +
+ table_offset + table_size) != 0)
+ warnx("pci_passthru: map_pptdev_mmio failed");
+ }
+ }
+}
+
+static void
+passthru_mmio_addr(struct vmctx *ctx, struct pci_devinst *pi, int baridx,
+ int enabled, uint64_t address)
+{
+ struct passthru_softc *sc;
+
+ sc = pi->pi_arg;
+ if (!enabled) {
+ if (vm_unmap_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
+ sc->psc_sel.pc_dev,
+ sc->psc_sel.pc_func, address,
+ sc->psc_bar[baridx].size) != 0)
+ warnx("pci_passthru: unmap_pptdev_mmio failed");
+ } else {
+ if (vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
+ sc->psc_sel.pc_dev,
+ sc->psc_sel.pc_func, address,
+ sc->psc_bar[baridx].size,
+ sc->psc_bar[baridx].addr) != 0)
+ warnx("pci_passthru: map_pptdev_mmio failed");
+ }
+}
+
+static void
+passthru_addr(struct vmctx *ctx, struct pci_devinst *pi, int baridx,
+ int enabled, uint64_t address)
+{
+
+ if (pi->pi_bar[baridx].type == PCIBAR_IO)
+ return;
+ if (baridx == pci_msix_table_bar(pi))
+ passthru_msix_addr(ctx, pi, baridx, enabled, address);
+ else
+ passthru_mmio_addr(ctx, pi, baridx, enabled, address);
+}
+
struct pci_devemu passthru = {
.pe_emu = "passthru",
.pe_init = passthru_init,
@@ -955,5 +1009,6 @@
.pe_cfgread = passthru_cfgread,
.pe_barwrite = passthru_write,
.pe_barread = passthru_read,
+ .pe_baraddr = passthru_addr,
};
PCI_EMUL_SET(passthru);

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 11, 7:06 PM (19 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15756928
Default Alt Text
D24066.id70138.diff (15 KB)

Event Timeline