Changeset View
Changeset View
Standalone View
Standalone View
head/sys/amd64/vmm/io/iommu.c
Show All 32 Lines | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <dev/pci/pcivar.h> | #include <dev/pci/pcivar.h> | ||||
#include <dev/pci/pcireg.h> | #include <dev/pci/pcireg.h> | ||||
#include <machine/cpu.h> | |||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include "vmm_util.h" | #include "vmm_util.h" | ||||
#include "vmm_mem.h" | #include "vmm_mem.h" | ||||
#include "iommu.h" | #include "iommu.h" | ||||
SYSCTL_DECL(_hw_vmm); | SYSCTL_DECL(_hw_vmm); | ||||
SYSCTL_NODE(_hw_vmm, OID_AUTO, iommu, CTLFLAG_RW, 0, "bhyve iommu parameters"); | SYSCTL_NODE(_hw_vmm, OID_AUTO, iommu, CTLFLAG_RW, 0, "bhyve iommu parameters"); | ||||
static int iommu_avail; | static int iommu_avail; | ||||
SYSCTL_INT(_hw_vmm_iommu, OID_AUTO, initialized, CTLFLAG_RD, &iommu_avail, | SYSCTL_INT(_hw_vmm_iommu, OID_AUTO, initialized, CTLFLAG_RD, &iommu_avail, | ||||
0, "bhyve iommu initialized?"); | 0, "bhyve iommu initialized?"); | ||||
static int iommu_enable = 1; | |||||
SYSCTL_INT(_hw_vmm_iommu, OID_AUTO, enable, CTLFLAG_RDTUN, &iommu_enable, 0, | |||||
"Enable use of I/O MMU (required for PCI passthrough)."); | |||||
static struct iommu_ops *ops; | static struct iommu_ops *ops; | ||||
static void *host_domain; | static void *host_domain; | ||||
static __inline int | static __inline int | ||||
IOMMU_INIT(void) | IOMMU_INIT(void) | ||||
{ | { | ||||
if (ops != NULL) | if (ops != NULL) | ||||
return ((*ops->init)()); | return ((*ops->init)()); | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | |||||
static __inline void | static __inline void | ||||
IOMMU_DISABLE(void) | IOMMU_DISABLE(void) | ||||
{ | { | ||||
if (ops != NULL && iommu_avail) | if (ops != NULL && iommu_avail) | ||||
(*ops->disable)(); | (*ops->disable)(); | ||||
} | } | ||||
void | static void | ||||
iommu_init(void) | iommu_init(void) | ||||
{ | { | ||||
int error, bus, slot, func; | int error, bus, slot, func; | ||||
vm_paddr_t maxaddr; | vm_paddr_t maxaddr; | ||||
const char *name; | const char *name; | ||||
device_t dev; | device_t dev; | ||||
if (!iommu_enable) | |||||
return; | |||||
if (vmm_is_intel()) | if (vmm_is_intel()) | ||||
ops = &iommu_ops_intel; | ops = &iommu_ops_intel; | ||||
else if (vmm_is_amd()) | else if (vmm_is_amd()) | ||||
ops = &iommu_ops_amd; | ops = &iommu_ops_amd; | ||||
else | else | ||||
ops = NULL; | ops = NULL; | ||||
error = IOMMU_INIT(); | error = IOMMU_INIT(); | ||||
if (error) | if (error) | ||||
return; | return; | ||||
iommu_avail = 1; | iommu_avail = 1; | ||||
/* | /* | ||||
* Create a domain for the devices owned by the host | * Create a domain for the devices owned by the host | ||||
*/ | */ | ||||
maxaddr = vmm_mem_maxaddr(); | maxaddr = vmm_mem_maxaddr(); | ||||
host_domain = IOMMU_CREATE_DOMAIN(maxaddr); | host_domain = IOMMU_CREATE_DOMAIN(maxaddr); | ||||
if (host_domain == NULL) | if (host_domain == NULL) { | ||||
panic("iommu_init: unable to create a host domain"); | printf("iommu_init: unable to create a host domain"); | ||||
IOMMU_CLEANUP(); | |||||
ops = NULL; | |||||
iommu_avail = 0; | |||||
return; | |||||
} | |||||
/* | /* | ||||
* Create 1:1 mappings from '0' to 'maxaddr' for devices assigned to | * Create 1:1 mappings from '0' to 'maxaddr' for devices assigned to | ||||
* the host | * the host | ||||
*/ | */ | ||||
iommu_create_mapping(host_domain, 0, 0, maxaddr); | iommu_create_mapping(host_domain, 0, 0, maxaddr); | ||||
for (bus = 0; bus <= PCI_BUSMAX; bus++) { | for (bus = 0; bus <= PCI_BUSMAX; bus++) { | ||||
Show All 24 Lines | iommu_cleanup(void) | ||||
IOMMU_DISABLE(); | IOMMU_DISABLE(); | ||||
IOMMU_DESTROY_DOMAIN(host_domain); | IOMMU_DESTROY_DOMAIN(host_domain); | ||||
IOMMU_CLEANUP(); | IOMMU_CLEANUP(); | ||||
} | } | ||||
void * | void * | ||||
iommu_create_domain(vm_paddr_t maxaddr) | iommu_create_domain(vm_paddr_t maxaddr) | ||||
{ | { | ||||
static volatile int iommu_initted; | |||||
if (iommu_initted < 2) { | |||||
if (atomic_cmpset_int(&iommu_initted, 0, 1)) { | |||||
iommu_init(); | |||||
atomic_store_rel_int(&iommu_initted, 2); | |||||
} else | |||||
while (iommu_initted == 1) | |||||
cpu_spinwait(); | |||||
} | |||||
return (IOMMU_CREATE_DOMAIN(maxaddr)); | return (IOMMU_CREATE_DOMAIN(maxaddr)); | ||||
} | } | ||||
void | void | ||||
iommu_destroy_domain(void *dom) | iommu_destroy_domain(void *dom) | ||||
{ | { | ||||
IOMMU_DESTROY_DOMAIN(dom); | IOMMU_DESTROY_DOMAIN(dom); | ||||
▲ Show 20 Lines • Show All 58 Lines • Show Last 20 Lines |