Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F156850903
D26506.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
35 KB
Referenced Files
None
Subscribers
None
D26506.id.diff
View Options
Index: lib/libvmmapi/vmmapi.h
===================================================================
--- lib/libvmmapi/vmmapi.h
+++ lib/libvmmapi/vmmapi.h
@@ -41,7 +41,7 @@
* API version for out-of-tree consumers like grub-bhyve for making compile
* time decisions.
*/
-#define VMMAPI_VERSION 0103 /* 2 digit major followed by 2 digit minor */
+#define VMMAPI_VERSION 0104 /* 2 digit major followed by 2 digit minor */
struct iovec;
struct vmctx;
@@ -73,6 +73,8 @@
VM_SYSMEM,
VM_BOOTROM,
VM_FRAMEBUFFER,
+ VM_VIDEOBIOS,
+ VM_NOTHING /* Last entry */
};
/*
@@ -111,6 +113,12 @@
int vm_mmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, int segid,
vm_ooffset_t segoff, size_t len, int prot);
+/*
+ * Unmap a memory segment previously mapped with the given parameters.
+ */
+int vm_munmap_memseg(struct vmctx *ctx, vm_paddr_t gpa,
+ int segid, vm_ooffset_t segoff);
+
int vm_create(const char *name);
int vm_get_device_fd(struct vmctx *ctx);
struct vmctx *vm_open(const char *name);
@@ -176,6 +184,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_get_vbios(struct vmctx *ctx, int bus, int slot, int func,
+ uint16_t vendor, uint16_t dev_id, void *bios, uint64_t *size);
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
@@ -61,9 +61,13 @@
#include "vmmapi.h"
+#define KB (1024UL)
#define MB (1024 * 1024UL)
#define GB (1024 * 1024 * 1024UL)
+#define VGAMEM_START (640*KB)
+#define VGAMEM_END (VGAMEM_START + 128*KB)
+
/*
* Size of the guard region before and after the virtual address space
* mapping the guest physical memory. This must be a multiple of the
@@ -87,6 +91,10 @@
#define CREATE(x) sysctlbyname("hw.vmm.create", NULL, NULL, (x), strlen((x)))
#define DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), strlen((x)))
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
static int
vm_device_open(const char *name)
{
@@ -227,8 +235,10 @@
*/
error = vm_mmap_getnext(ctx, &gpa, &segid, &off, &len, &prot, &flags);
if (error == 0 && gpa == memmap.gpa) {
- if (segid != memmap.segid || off != memmap.segoff ||
- prot != memmap.prot || flags != memmap.flags) {
+ /* Allow other segments to align with SYSMEM borders */
+ if ((segid != VM_SYSMEM || memmap.segid == VM_SYSMEM) &&
+ (segid != memmap.segid || off != memmap.segoff ||
+ prot != memmap.prot || flags != memmap.flags)) {
errno = EEXIST;
return (-1);
} else {
@@ -251,6 +261,24 @@
return (0);
}
+int
+vm_munmap_memseg(struct vmctx *ctx, vm_paddr_t gpa,
+ int segid, vm_ooffset_t segoff)
+{
+ struct vm_memmap memmap;
+ int error;
+
+ memmap.gpa = gpa;
+ memmap.segid = segid;
+ memmap.segoff = segoff;
+ memmap.len = 0;
+ memmap.prot = 0;
+ memmap.flags = 0;
+
+ error = ioctl(ctx->fd, VM_MMAP_MEMSEG, &memmap);
+ 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)
@@ -420,9 +448,23 @@
return (error);
}
+ /*
+ * Leave a memory hole for VGA memory.
+ */
+ if (ctx->lowmem > VGAMEM_END) {
+ gpa = VGAMEM_END;
+ len = ctx->lowmem - VGAMEM_END;
+ error = setup_memory_segment(ctx, gpa, len, baseaddr);
+ if (error)
+ return (error);
+ }
+
+ /*
+ * Add up to 640 KB of base memory.
+ */
if (ctx->lowmem > 0) {
gpa = 0;
- len = ctx->lowmem;
+ len = min(ctx->lowmem, VGAMEM_START);
error = setup_memory_segment(ctx, gpa, len, baseaddr);
if (error)
return (error);
@@ -446,7 +488,13 @@
if (ctx->lowmem > 0) {
if (gaddr < ctx->lowmem && len <= ctx->lowmem &&
- gaddr + len <= ctx->lowmem)
+ gaddr + len <= VGAMEM_START)
+ return (ctx->baseaddr + gaddr);
+ }
+
+ if (ctx->lowmem > VGAMEM_END) {
+ if (gaddr >= VGAMEM_END && gaddr < ctx->lowmem &&
+ len <= ctx->lowmem && gaddr + len <= ctx->lowmem)
return (ctx->baseaddr + gaddr);
}
@@ -980,6 +1028,33 @@
return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
}
+int
+vm_get_vbios(struct vmctx *ctx, int bus, int slot, int func,
+ uint16_t vendor, uint16_t dev_id, void *bios, uint64_t *size)
+{
+ int error;
+ struct vm_vbios vbios;
+
+ bzero(&vbios, sizeof(vbios));
+ vbios.bus = bus;
+ vbios.slot = slot;
+ vbios.func = func;
+ vbios.vendor = vendor;
+ vbios.dev_id = dev_id;
+ vbios.bios = bios;
+ if (size != NULL)
+ vbios.size = *size;
+ else
+ vbios.size = 0;
+
+ error = ioctl(ctx->fd, VM_GET_VBIOS, &vbios);
+
+ if (size)
+ *size = vbios.size;
+
+ return (error);
+}
+
int
vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
uint64_t addr, uint64_t msg, int numvec)
@@ -1311,10 +1386,6 @@
return (error);
}
-#ifndef min
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
int
vm_copy_setup(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
uint64_t gla, size_t len, int prot, struct iovec *iov, int iovcnt,
@@ -1641,8 +1712,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_GET_VBIOS, 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_dev.h
===================================================================
--- sys/amd64/include/vmm_dev.h
+++ sys/amd64/include/vmm_dev.h
@@ -141,6 +141,16 @@
size_t len;
};
+struct vm_vbios {
+ int bus;
+ int slot;
+ int func;
+ uint16_t vendor;
+ uint16_t dev_id;
+ void *bios;
+ uint64_t size;
+};
+
struct vm_pptdev_msi {
int vcpu;
int bus;
@@ -301,6 +311,7 @@
IOCNUM_MAP_PPTDEV_MMIO = 42,
IOCNUM_PPTDEV_MSI = 43,
IOCNUM_PPTDEV_MSIX = 44,
+ IOCNUM_GET_VBIOS = 46,
/* statistics */
IOCNUM_VM_STATS = 50,
@@ -413,6 +424,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_GET_VBIOS \
+ _IOWR('v', IOCNUM_GET_VBIOS, struct vm_vbios)
#define VM_INJECT_NMI \
_IOW('v', IOCNUM_INJECT_NMI, struct vm_nmi)
#define VM_STATS \
Index: sys/amd64/vmm/amd/amdgpu.h
===================================================================
--- /dev/null
+++ sys/amd64/vmm/amd/amdgpu.h
@@ -0,0 +1,10 @@
+
+#ifndef _AMD_AMDGPU_H_
+#define _AMD_AMDGPU_H_
+
+#include <machine/vmm_dev.h>
+
+int vm_amdgpu_get_vbios(struct vm *vm, int bus, int slot, int func,
+ uint16_t vendor, uint16_t dev_id, void *bios, uint64_t *size);
+
+#endif /* !_AMD_AMDGPU_H_ */
Index: sys/amd64/vmm/amd/amdgpu.c
===================================================================
--- /dev/null
+++ sys/amd64/vmm/amd/amdgpu.c
@@ -0,0 +1,270 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+
+
+#include <sys/param.h>
+#include <sys/bitstring.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/rangeset.h>
+#include <sys/rwlock.h>
+#include <sys/sbuf.h>
+#include <sys/sx.h>
+#include <sys/turnstile.h>
+#include <sys/vmem.h>
+#include <sys/vmmeter.h>
+#include <sys/sched.h>
+#include <sys/sysctl.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_pager.h>
+#include <vm/vm_phys.h>
+#include <vm/vm_radix.h>
+#include <vm/vm_reserv.h>
+#include <vm/uma.h>
+
+#include <machine/pmap.h>
+#include <machine/vmm.h>
+#include <machine/vmparam.h>
+
+#include "amd/amdgpu.h"
+#include "contrib/dev/acpica/include/acpi.h"
+#include "contrib/dev/acpica/include/acpixf.h"
+
+#define GFP_NATIVE_MASK (M_NOWAIT | M_WAITOK | M_USE_RESERVE | M_ZERO)
+#define GFP_KERNEL M_WAITOK
+
+//MALLOC_DECLARE(M_KMALLOC);
+MALLOC_DECLARE(M_VMMDEV);
+
+typedef unsigned gfp_t;
+
+static inline gfp_t
+linux_check_m_flags(gfp_t flags)
+{
+ const gfp_t m = M_NOWAIT | M_WAITOK;
+
+ /* make sure either M_NOWAIT or M_WAITOK is set */
+ if ((flags & m) == 0)
+ flags |= M_NOWAIT;
+ else if ((flags & m) == m)
+ flags &= ~M_WAITOK;
+
+ /* mask away LinuxKPI specific flags */
+ return (flags & GFP_NATIVE_MASK);
+}
+
+static inline void *
+kmalloc(size_t size, gfp_t flags)
+{
+ return (malloc(size, M_VMMDEV, linux_check_m_flags(flags)));
+}
+
+static inline void
+kfree(const void *ptr)
+{
+ free(__DECONST(void *, ptr), M_VMMDEV);
+}
+
+static inline void *
+kmemdup(const void *src, size_t len, gfp_t gfp)
+{
+ void *dst;
+
+ dst = kmalloc(len, gfp);
+ if (dst != NULL) {
+ memcpy(dst, src, len);
+ }
+ return (dst);
+}
+
+#define AMD_VBIOS_SIGNATURE " 761295520"
+#define AMD_VBIOS_SIGNATURE_OFFSET 0x30
+#define AMD_VBIOS_SIGNATURE_SIZE sizeof(AMD_VBIOS_SIGNATURE)
+#define AMD_VBIOS_SIGNATURE_END (AMD_VBIOS_SIGNATURE_OFFSET + AMD_VBIOS_SIGNATURE_SIZE)
+#define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA)
+#define AMD_VBIOS_LENGTH(p) ((p)[2] << 9)
+
+#define acpi_get_table AcpiGetTable
+
+typedef struct {
+ uint32_t Signature;
+ uint32_t TableLength; //Length
+ uint8_t Revision;
+ uint8_t Checksum;
+ uint8_t OemId[6];
+ uint8_t OemTableId[8]; //UINT64 OemTableId;
+ uint32_t OemRevision;
+ uint32_t CreatorId;
+ uint32_t CreatorRevision;
+} AMD_ACPI_DESCRIPTION_HEADER;
+
+typedef struct {
+ AMD_ACPI_DESCRIPTION_HEADER SHeader;
+ uint8_t TableUUID[16]; //0x24
+ uint32_t VBIOSImageOffset; //0x34. Offset to the first GOP_VBIOS_CONTENT block from the beginning of the stucture.
+ uint32_t Lib1ImageOffset; //0x38. Offset to the first GOP_LIB1_CONTENT block from the beginning of the stucture.
+ uint32_t Reserved[4]; //0x3C
+}UEFI_ACPI_VFCT;
+
+typedef struct {
+ uint32_t PCIBus; //0x4C
+ uint32_t PCIDevice; //0x50
+ uint32_t PCIFunction; //0x54
+ uint16_t VendorID; //0x58
+ uint16_t DeviceID; //0x5A
+ uint16_t SSVID; //0x5C
+ uint16_t SSID; //0x5E
+ uint32_t Revision; //0x60
+ uint32_t ImageLength; //0x64
+}VFCT_IMAGE_HEADER;
+
+
+typedef struct {
+ VFCT_IMAGE_HEADER VbiosHeader;
+ uint8_t VbiosContent[1];
+}GOP_VBIOS_CONTENT;
+
+/* Check if current bios is an ATOM BIOS.
+ * Return true if it is ATOM BIOS. Otherwise, return false.
+ */
+static bool check_atom_bios(uint8_t *bios, size_t size)
+{
+ uint16_t tmp, bios_header_start;
+
+ if (!bios || size < 0x49) {
+ // vbios mem is null or mem size is wrong
+ return false;
+ }
+
+ if (!AMD_IS_VALID_VBIOS(bios)) {
+ // BIOS signature incorrect
+ return false;
+ }
+
+ bios_header_start = bios[0x48] | (bios[0x49] << 8);
+ if (!bios_header_start) {
+ // Can't locate bios header
+ return false;
+ }
+
+ tmp = bios_header_start + 4;
+ if (size < tmp) {
+ // BIOS header is broken
+ return false;
+ }
+
+ if (!memcmp(bios + tmp, "ATOM", 4) ||
+ !memcmp(bios + tmp, "MOTA", 4)) {
+ // ATOMBIOS detected
+ return true;
+ }
+
+ return false;
+}
+
+static int
+amdgpu_get_vbios_vfct(struct vm *vm, int bus, int slot, int func,
+ uint16_t vendor, uint16_t dev_id, void **bios, uint64_t *size)
+{
+ if (vm == NULL || bios == NULL || size == NULL)
+ return EINVAL;
+
+ struct acpi_table_header *hdr;
+ uint32_t tbl_size;
+ UEFI_ACPI_VFCT *vfct;
+ unsigned offset;
+
+ if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
+ return ENOENT;
+
+ tbl_size = hdr->Length;
+
+ if (tbl_size < sizeof(UEFI_ACPI_VFCT))
+ return ENODEV;
+
+ vfct = (UEFI_ACPI_VFCT *)hdr;
+ offset = vfct->VBIOSImageOffset;
+
+ while (offset < tbl_size) {
+ GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);
+ VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;
+
+ offset += sizeof(VFCT_IMAGE_HEADER);
+ if (offset > tbl_size)
+ return ENODEV;
+
+ offset += vhdr->ImageLength;
+ if (offset > tbl_size)
+ return ENODEV;
+
+ if (vhdr->ImageLength &&
+ vhdr->PCIBus == bus &&
+ vhdr->PCIDevice == slot &&
+ vhdr->PCIFunction == func &&
+ vhdr->VendorID == vendor &&
+ vhdr->DeviceID == dev_id) {
+ *bios = kmemdup(&vbios->VbiosContent,
+ vhdr->ImageLength,
+ GFP_KERNEL);
+
+ if (!check_atom_bios((uint8_t *)*bios, vhdr->ImageLength)) {
+ kfree(*bios);
+ return ENODEV;
+ }
+ *size = vhdr->ImageLength;
+ return 0;
+ }
+ }
+
+ return ENOENT;
+}
+
+int
+vm_amdgpu_get_vbios(struct vm *vm, int bus, int slot, int func,
+ uint16_t vendor, uint16_t dev_id, void *bios, uint64_t *size)
+{
+ int error;
+ void *bios_base;
+ uint64_t bios_size;
+
+ error = 0;
+
+ if (amdgpu_get_vbios_vfct(vm, bus, slot, func, vendor, dev_id, &bios_base, &bios_size) == 0)
+ goto done;
+
+ return ENOENT;
+
+done:
+
+ if (bios) {
+ *size = min(bios_size, *size);
+ error = copyout(bios_base, bios, *size);
+ } else {
+ *size = bios_size;
+ }
+
+ kfree(bios_base);
+
+ return (error);
+}
Index: sys/amd64/vmm/vmm.c
===================================================================
--- sys/amd64/vmm/vmm.c
+++ sys/amd64/vmm/vmm.c
@@ -133,7 +133,7 @@
bool sysmem;
struct vm_object *object;
};
-#define VM_MAX_MEMSEGS 3
+#define VM_MAX_MEMSEGS 4
struct mem_map {
vm_paddr_t gpa;
@@ -256,6 +256,8 @@
static void vm_free_memmap(struct vm *vm, int ident);
static bool sysmem_mapping(struct vm *vm, struct mem_map *mm);
static void vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr);
+static int vm_munmap_memseg(struct vm *vm, vm_paddr_t gpa,
+ int segid, vm_ooffset_t segoff);
#ifdef KTR
static const char *
@@ -729,7 +731,7 @@
vm_ooffset_t last;
int i, error;
- if (prot == 0 || (prot & ~(VM_PROT_ALL)) != 0)
+ if ((len != 0 && prot == 0) || (prot & ~(VM_PROT_ALL)) != 0)
return (EINVAL);
if (flags & ~VM_MEMMAP_F_WIRED)
@@ -743,12 +745,16 @@
return (EINVAL);
last = first + len;
- if (first < 0 || first >= last || last > seg->len)
+ if (first < 0 || first > last || last > seg->len)
return (EINVAL);
if ((gpa | first | last) & PAGE_MASK)
return (EINVAL);
+ /* The same thing at the same place but with zero length means unmap */
+ if (len == 0)
+ return vm_munmap_memseg(vm, gpa, segid, first);
+
map = NULL;
for (i = 0; i < VM_MAX_MEMMAPS; i++) {
m = &vm->mem_maps[i];
@@ -787,6 +793,26 @@
return (0);
}
+static int
+vm_munmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t segoff)
+{
+ struct mem_map *m;
+ int i;
+
+ for (i = 0; i < VM_MAX_MEMMAPS; i++) {
+ m = &vm->mem_maps[i];
+ if (m->gpa == gpa && m->segid == segid && m->segoff == segoff)
+ break;
+ }
+
+ if (i >= VM_MAX_MEMMAPS)
+ return (ENOENT);
+
+ vm_free_memmap(vm, i);
+
+ return (0);
+}
+
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
@@ -60,6 +60,7 @@
#include <machine/vmm_snapshot.h>
#include <x86/apicreg.h>
+#include "amd/amdgpu.h"
#include "vmm_lapic.h"
#include "vmm_stat.h"
#include "vmm_mem.h"
@@ -366,6 +367,7 @@
struct vm_capability *vmcap;
struct vm_pptdev *pptdev;
struct vm_pptdev_mmio *pptmmio;
+ struct vm_vbios *vbios;
struct vm_pptdev_msi *pptmsi;
struct vm_pptdev_msix *pptmsix;
struct vm_nmi *vmnmi;
@@ -435,6 +437,7 @@
break;
case VM_MAP_PPTDEV_MMIO:
+ case VM_GET_VBIOS:
case VM_BIND_PPTDEV:
case VM_UNBIND_PPTDEV:
#ifdef COMPAT_FREEBSD12
@@ -520,6 +523,12 @@
pptmmio->func, pptmmio->gpa, pptmmio->len,
pptmmio->hpa);
break;
+ case VM_GET_VBIOS:
+ vbios = (struct vm_vbios *)data;
+ // currently only amd cpus are supported
+ error = vm_amdgpu_get_vbios(sc->vm, vbios->bus, vbios->slot, vbios->func,
+ vbios->vendor, vbios->dev_id, vbios->bios, &vbios->size);
+ break;
case VM_BIND_PPTDEV:
pptdev = (struct vm_pptdev *)data;
error = vm_assign_pptdev(sc->vm, pptdev->bus, pptdev->slot,
Index: sys/modules/vmm/Makefile
===================================================================
--- sys/modules/vmm/Makefile
+++ sys/modules/vmm/Makefile
@@ -56,7 +56,8 @@
npt.c \
ivrs_drv.c \
amdvi_hw.c \
- svm_msr.c
+ svm_msr.c \
+ amdgpu.c
.if ${KERN_OPTS:MBHYVE_SNAPSHOT} != ""
SRCS+= vmm_snapshot.c
Index: usr.sbin/bhyve/Makefile
===================================================================
--- usr.sbin/bhyve/Makefile
+++ usr.sbin/bhyve/Makefile
@@ -9,6 +9,8 @@
PROG= bhyve
PACKAGE= bhyve
+# DEBUG_FLAGS= -g -O0 --coverage -DWITHOUT_CAPSICUM
+
MAN= bhyve.8
BHYVE_SYSDIR?=${SRCTOP}
@@ -38,6 +40,7 @@
net_backends.c \
net_utils.c \
pci_ahci.c \
+ pci_apu-d.c \
pci_e82545.c \
pci_emul.c \
pci_hda.c \
@@ -103,6 +106,7 @@
LIBADD+= crypto
.endif
+CFLAGS+= -no-integrated-as
CFLAGS+= -I${BHYVE_SYSDIR}/sys/dev/e1000
CFLAGS+= -I${BHYVE_SYSDIR}/sys/dev/mii
CFLAGS+= -I${BHYVE_SYSDIR}/sys/dev/usb/controller
Index: usr.sbin/bhyve/pci_apu-d.c
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/pci_apu-d.c
@@ -0,0 +1,282 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Beckhoff Automation GmbH & Co. KG
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR OR CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <dev/io/iodev.h>
+#include <dev/pci/pcireg.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <machine/iodev.h>
+#include <machine/vmm.h>
+
+#include "inout.h"
+#include "pci_passthru.h"
+#include "vga.h"
+
+#define KB (1024UL)
+#define MB (1024 * 1024UL)
+#define GB (1024 * 1024 * 1024UL)
+
+#define VBIOS_ADDR 0xC0000
+
+#ifndef _PATH_DEVIO
+#define _PATH_DEVIO "/dev/io"
+#endif
+
+static int iofd = -1;
+
+uint32_t rom_space = 0;
+
+static int
+passthru_port_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, uint32_t *eax, void *arg)
+{
+ int error;
+ struct iodev_pio_req pio;
+ pio.access = in ? IODEV_PIO_READ : IODEV_PIO_WRITE;
+ pio.port = port;
+ pio.width = bytes;
+ pio.val = in ? 0 : *eax;
+
+ error = ioctl(iofd, IODEV_PIO, &pio);
+
+ if (in)
+ *eax = pio.val;
+
+ return error;
+}
+
+static int
+apu_d_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ int error;
+ struct passthru_softc *sc;
+
+ error = 0;
+
+ /*
+ * That's a little hack to allow shadowing of ROM
+ * EFI copies the ROM to MMIO space
+ * Alloc 16 MB of MMIO space for nothing. So, EFI can use this space
+ */
+ if (rom_space == 0) {
+ rom_space = pci_emul_alloc_mmio(PCIBAR_MEM32, 16*MB, 16*MB-1);
+ pci_parse_slot("0:3:0,apu-d-dummy");
+ }
+
+ if ((error = passthru_init(ctx, pi, opts)) != 0)
+ goto done;
+
+ sc = pi->pi_arg;
+
+ // enable mem and io
+ int16_t cmd;
+ cmd = pci_get_cfgdata16(pi, PCIR_COMMAND);
+ cmd |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
+ pci_set_cfgdata16(pi, PCIR_COMMAND, cmd);
+ cmd = read_config(&sc->psc_sel, PCIR_COMMAND, 0x02);
+ cmd |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
+ write_config(&sc->psc_sel, PCIR_COMMAND, 0x02, cmd);
+
+ /* passthrough VGA ports */
+ if (iofd < 0) {
+ iofd = open(_PATH_DEVIO, O_RDWR, 0);
+ if (iofd < 0) {
+ warn("failed to open %s", _PATH_DEVIO);
+ }
+ }
+ struct inout_port iop;
+ bzero(&iop, sizeof(iop));
+ iop.name = "VGA";
+ for (int port = VGA_IOPORT_START; port <= VGA_IOPORT_END; port++) {
+ iop.port = port;
+ iop.size = 1;
+ iop.flags = IOPORT_F_INOUT;
+ iop.handler = passthru_port_handler;
+ iop.arg = NULL;
+
+ error = register_inout(&iop);
+ assert(error == 0);
+ }
+
+ /* passthrough VGA memory */
+ if ((error = vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, sc->psc_sel.pc_func, 640*KB, 128*KB, 640*KB)) != 0) {
+ warnx("vm_map_pptdev_mmio (%d): %d", error, errno);
+ error = 0;
+ }
+
+ uint16_t vendor, dev_id;
+ uint64_t bios_size;
+ vendor = read_config(&sc->psc_sel, PCIR_VENDOR, 0x02);
+ dev_id = read_config(&sc->psc_sel, PCIR_DEVICE, 0x02);
+
+ vm_get_vbios(ctx, sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, sc->psc_sel.pc_func, vendor, dev_id, NULL, &bios_size);
+
+ // round up size to a power of two
+ // check in descendig order to avoid endless loop
+ pi->pi_vbios.len = 1ULL << 63;
+ while (pi->pi_vbios.len > bios_size) {
+ pi->pi_vbios.len >>= 1;
+ }
+ pi->pi_vbios.len <<= 1;
+ pi->pi_vbios.gpa = VBIOS_ADDR;
+ pi->pi_vbios.hpa = (uint64_t)vm_create_devmem(ctx, VM_VIDEOBIOS, "videobios", pi->pi_vbios.len);
+ if ((void *)pi->pi_vbios.hpa == MAP_FAILED) {
+ warnx("vm_create_devmem: %x", errno);
+ error = -1;
+ goto done;
+ }
+
+ vm_get_vbios(ctx, sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, sc->psc_sel.pc_func, vendor, dev_id, (void *)pi->pi_vbios.hpa, &bios_size);
+
+ if ((error = pci_emul_alloc_rom(pi, VM_VIDEOBIOS, pi->pi_vbios.gpa, pi->pi_vbios.len)) != 0) {
+ warnx("pci_emul_alloc_rom: %x", error);
+ goto done;
+ }
+
+done:
+ return (error);
+}
+
+static int
+apu_d_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int coff, int bytes, uint32_t val)
+{
+ /* ROM is emulated */
+ if (coff >= PCIR_BIOS && coff < PCIR_BIOS + 4) {
+ return (-1);
+ } else {
+ return passthru_cfgwrite(ctx, vcpu, pi, coff, bytes, val);
+ }
+}
+
+static int
+apu_d_cfgread(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int coff, int bytes, uint32_t *rv)
+{
+ /* ROM is emulated */
+ if (coff >= PCIR_BIOS && coff < PCIR_BIOS + 4) {
+ return (-1);
+ } else {
+ return passthru_cfgread(ctx, vcpu, pi, coff, bytes, rv);
+ }
+}
+
+static void
+apu_d_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size, uint64_t value)
+{
+ passthru_write(ctx, vcpu, pi, baridx, offset, size, value);
+}
+
+static uint64_t
+apu_d_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size)
+{
+ return passthru_read(ctx, vcpu, pi, baridx, offset, size);
+}
+
+struct pci_devemu apu_d = {
+ .pe_emu = "apu-d",
+ .pe_init = apu_d_init,
+ .pe_cfgwrite = apu_d_cfgwrite,
+ .pe_cfgread = apu_d_cfgread,
+ .pe_barwrite = apu_d_write,
+ .pe_barread = apu_d_read,
+};
+PCI_EMUL_SET(apu_d);
+
+/*
+ * This device signals EFI the rom_space
+ */
+static int
+apu_d_dummy_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ pci_set_cfgdata16(pi, PCIR_COMMAND, PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);
+
+ return (0);
+}
+
+static int
+apu_d_dummy_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int coff, int bytes, uint32_t val)
+{
+ /* BAR is emulated */
+ if (coff >= PCIR_BAR(0) && coff < PCIR_BAR(0) + 4) {
+ switch (bytes) {
+ case 1:
+ pci_set_cfgdata8(pi, coff, val);
+ break;
+ case 2:
+ pci_set_cfgdata16(pi, coff, val);
+ break;
+ case 4:
+ pci_set_cfgdata32(pi, coff, val);
+ break;
+ }
+ return (0);
+ } else {
+ return (-1);
+ }
+}
+
+static int
+apu_d_dummy_cfgread(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int coff, int bytes, uint32_t *rv)
+{
+ /* BAR is emulated */
+ if (coff >= PCIR_BAR(0) && coff < PCIR_BAR(0) + 4) {
+ uint32_t bar = pci_get_cfgdata32(pi, PCIR_BAR(0));
+ if (bar == 0xFFFFFFFF) {
+ *rv = (uint32_t)~(16*MB - 1);
+ } else {
+ *rv = rom_space | PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32;
+ }
+ *rv >>= 8 * (coff & 0x03);
+ return (0);
+ } else {
+ return (-1);
+ }
+}
+
+struct pci_devemu apu_d_dummy = {
+ .pe_emu = "apu-d-dummy",
+ .pe_init = apu_d_dummy_init,
+ .pe_cfgwrite = apu_d_dummy_cfgwrite,
+ .pe_cfgread = apu_d_dummy_cfgread,
+};
+PCI_EMUL_SET(apu_d_dummy);
Index: usr.sbin/bhyve/pci_emul.h
===================================================================
--- usr.sbin/bhyve/pci_emul.h
+++ usr.sbin/bhyve/pci_emul.h
@@ -85,7 +85,8 @@
PCIBAR_IO,
PCIBAR_MEM32,
PCIBAR_MEM64,
- PCIBAR_MEMHI64
+ PCIBAR_MEMHI64,
+ PCIBAR_ROM,
};
struct pcibar {
@@ -116,6 +117,12 @@
PENDING
};
+struct pci_vbiosemu {
+ uint64_t hpa;
+ uint64_t len;
+ uint64_t gpa;
+};
+
struct pci_devinst {
struct pci_devemu *pi_d;
struct vmctx *pi_vmctx;
@@ -158,6 +165,11 @@
u_char pi_cfgdata[PCI_REGMAX + 1];
struct pcibar pi_bar[PCI_BARMAX + 1];
+ struct pcibar pi_rom_bar;
+ int pi_rom_segment;
+ int pi_rom_enabled;
+
+ struct pci_vbiosemu pi_vbios;
};
struct msicap {
@@ -223,6 +235,9 @@
enum pcibar_type type, uint64_t size);
int pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx,
uint64_t hostbase, enum pcibar_type type, uint64_t size);
+int pci_emul_alloc_rom(struct pci_devinst *pdi, int segid,
+ uint32_t addr, uint32_t size);
+uint64_t pci_emul_alloc_mmio(enum pcibar_type type, uint64_t size, uint64_t mask);
int pci_emul_add_msicap(struct pci_devinst *pi, int msgnum);
int pci_emul_add_pciecap(struct pci_devinst *pi, int pcie_device_type);
void pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes,
Index: usr.sbin/bhyve/pci_emul.c
===================================================================
--- usr.sbin/bhyve/pci_emul.c
+++ usr.sbin/bhyve/pci_emul.c
@@ -33,6 +33,7 @@
#include <sys/param.h>
#include <sys/linker_set.h>
+#include <sys/mman.h>
#include <ctype.h>
#include <errno.h>
@@ -582,6 +583,76 @@
register_bar(pi, idx);
}
+int
+pci_emul_alloc_rom(struct pci_devinst *pdi, int segid,
+ uint32_t addr, uint32_t size)
+{
+ /* The segment ID must be valid */
+ if (segid <= VM_SYSMEM || segid >= VM_NOTHING)
+ return (-1);
+
+ /* The size must be a power of two >= 4 KiB */
+ if ((size & (size - 1)) != 0 || size < 4096)
+ return (-2);
+
+ /* The address must be at a multiple of size */
+ if ((addr & (size - 1)) != 0)
+ return (-3);
+
+ pdi->pi_rom_segment = segid;
+ pdi->pi_rom_bar.type = PCIBAR_ROM;
+ pdi->pi_rom_bar.addr = addr;
+ pdi->pi_rom_bar.size = size;
+ pdi->pi_rom_enabled = 0;
+
+ pci_set_cfgdata32(pdi, PCIR_BIOS, addr);
+
+ return (0);
+}
+
+static int
+update_rom_address(struct pci_devinst *pdi)
+{
+ uint32_t bar, addr;
+ int enable;
+
+ /* Grab info directly from the config data */
+ bar = pci_get_cfgdata32(pdi, PCIR_BIOS);
+ enable = (bar & PCIM_BIOS_ENABLE)? 1 : 0;
+ addr = bar & PCIM_BIOS_ADDR_MASK;
+
+ /* Ignore the mapping if we don't have a ROM segment to map */
+ if (!pdi->pi_rom_segment) {
+ pdi->pi_rom_bar.addr = addr;
+ return (0);
+ }
+
+ /* Something has changed; unmap the segment if it's mapped */
+ if (pdi->pi_rom_enabled) {
+ vm_munmap_memseg(pdi->pi_vmctx, pdi->pi_rom_bar.addr,
+ pdi->pi_rom_segment, 0);
+ }
+
+ pdi->pi_rom_enabled = enable && memen(pdi);
+ pdi->pi_rom_bar.addr = addr;
+
+ /* Map the segment only if both ROM and global Memory Space are on */
+ if (pdi->pi_rom_enabled) {
+ int error;
+
+ error = vm_mmap_memseg(pdi->pi_vmctx, pdi->pi_rom_bar.addr,
+ pdi->pi_rom_segment, 0, pdi->pi_rom_bar.size,
+ PROT_READ | PROT_EXEC);
+
+ if (error) {
+ perror("ROM mapping failed");
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
int
pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase,
enum pcibar_type type, uint64_t size)
@@ -684,6 +755,44 @@
return (0);
}
+// mask should be a power of 2 minus 1 (e.g. 0x000FFFFF)
+uint64_t
+pci_emul_alloc_mmio(enum pcibar_type type, uint64_t size, uint64_t mask)
+{
+ int error;
+
+ error = 1;
+
+ uint64_t *baseptr, limit, base;
+
+ switch (type) {
+ case PCIBAR_IO:
+ baseptr = &pci_emul_iobase;
+ limit = PCI_EMUL_IOLIMIT;
+ break;
+ case PCIBAR_MEM32:
+ baseptr = &pci_emul_membase32;
+ limit = PCI_EMUL_MEMLIMIT32;
+ break;
+ case PCIBAR_MEM64:
+ baseptr = &pci_emul_membase64;
+ limit = PCI_EMUL_MEMLIMIT64;
+ break;
+ default:
+ return 0;
+ }
+
+ // align base
+ base = (*baseptr + mask) & ~mask;
+
+ if (base + size > limit)
+ return 0;
+
+ *baseptr = base + size;
+
+ return base;
+}
+
#define CAP_START_OFFSET 0x40
static int
pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen)
@@ -1736,6 +1845,9 @@
}
}
+ if ((changed & PCIM_CMD_MEMEN))
+ update_rom_address(pi);
+
/*
* If INTx has been unmasked and is pending, assert the
* interrupt.
@@ -1899,6 +2011,25 @@
}
pci_set_cfgdata32(pi, coff, bar);
+ /*
+ * The BAR register for an Expansion ROM is slightly different.
+ */
+ } else if (coff >= PCIR_BIOS && coff < PCIR_BIOS + 4) {
+
+ /* Well, it's ignored for ordinary BAR registers... */
+ if (bytes != 4 || (coff & 0x3) != 0)
+ return;
+
+ /* Refuse to enable unless we have a BIOS */
+ mask = ~(pi->pi_rom_bar.size - 1);
+ if (pi->pi_rom_bar.size > 0)
+ mask |= PCIM_BIOS_ENABLE;
+
+ /* Make the change and update ROM location */
+ bar = *eax & mask;
+ pci_set_cfgdata32(pi, coff, bar);
+ update_rom_address(pi);
+
} else if (pci_emul_iscap(pi, coff)) {
pci_emul_capwrite(pi, coff, bytes, *eax, 0, 0);
} else if (coff >= PCIR_COMMAND && coff < PCIR_REVID) {
Index: usr.sbin/bhyve/pci_passthru.h
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/pci_passthru.h
@@ -0,0 +1,63 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Beckhoff Automation GmbH & Co. KG
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR OR CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __PCI_PASSTHRU_H__
+#define __PCI_PASSTHRU_H__
+
+#include <sys/pciio.h>
+
+#include <vmmapi.h>
+
+#include "pci_emul.h"
+
+struct passthru_softc {
+ struct pci_devinst *psc_pi;
+ struct pcibar psc_bar[PCI_BARMAX + 1];
+ struct {
+ int capoff;
+ int msgctrl;
+ int emulated;
+ } psc_msi;
+ struct {
+ int capoff;
+ } psc_msix;
+ struct pcisel psc_sel;
+};
+
+uint32_t read_config(const struct pcisel *sel, long reg, int width);
+void write_config(const struct pcisel *sel, long reg, int width, uint32_t data);
+int bar_access(int coff);
+int passthru_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts);
+int passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int coff, int bytes, uint32_t val);
+int passthru_cfgread(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int coff, int bytes, uint32_t *rv);
+void passthru_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size, uint64_t value);
+uint64_t passthru_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size);
+
+#endif
Index: usr.sbin/bhyve/pci_passthru.c
===================================================================
--- usr.sbin/bhyve/pci_passthru.c
+++ usr.sbin/bhyve/pci_passthru.c
@@ -61,6 +61,7 @@
#include <vmmapi.h>
#include "pci_emul.h"
#include "mem.h"
+#include "pci_passthru.h"
#ifndef _PATH_DEVPCI
#define _PATH_DEVPCI "/dev/pci"
@@ -83,20 +84,6 @@
static int iofd = -1;
static int memfd = -1;
-struct passthru_softc {
- struct pci_devinst *psc_pi;
- struct pcibar psc_bar[PCI_BARMAX + 1];
- struct {
- int capoff;
- int msgctrl;
- int emulated;
- } psc_msi;
- struct {
- int capoff;
- } psc_msix;
- struct pcisel psc_sel;
-};
-
static int
msi_caplen(int msgctrl)
{
@@ -119,7 +106,7 @@
return (len);
}
-static uint32_t
+uint32_t
read_config(const struct pcisel *sel, long reg, int width)
{
struct pci_io pi;
@@ -135,7 +122,7 @@
return (pi.pi_data);
}
-static void
+void
write_config(const struct pcisel *sel, long reg, int width, uint32_t data)
{
struct pci_io pi;
@@ -647,7 +634,7 @@
return (error);
}
-static int
+int
passthru_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
{
int bus, slot, func, error, memflags;
@@ -743,7 +730,7 @@
return (error);
}
-static int
+int
bar_access(int coff)
{
if (coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1))
@@ -778,7 +765,7 @@
coff < sc->psc_msix.capoff + MSIX_CAPLEN);
}
-static int
+int
passthru_cfgread(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
int coff, int bytes, uint32_t *rv)
{
@@ -822,7 +809,7 @@
return (0);
}
-static int
+int
passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
int coff, int bytes, uint32_t val)
{
@@ -898,7 +885,7 @@
return (0);
}
-static void
+void
passthru_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
uint64_t offset, int size, uint64_t value)
{
@@ -921,7 +908,7 @@
}
}
-static uint64_t
+uint64_t
passthru_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
uint64_t offset, int size)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, May 17, 9:55 PM (18 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33211941
Default Alt Text
D26506.id.diff (35 KB)
Attached To
Mode
D26506: [WIP] bhyve: GPU Passthrough for AMD Ryzen V1000
Attached
Detach File
Event Timeline
Log In to Comment