From 04d95acf63c5abd13d0d7c9015e5499627d6bf02 Mon Sep 17 00:00:00 2001 From: Ryan Stone Date: Sun, 16 Mar 2014 22:04:51 -0400 Subject: [PATCH 3/5] Re-write bhyve's I/O MMU handling in terms of PCI RIDs --- sys/amd64/vmm/amd/amdv.c | 4 ++-- sys/amd64/vmm/intel/vtd.c | 28 ++++++++++++---------------- sys/amd64/vmm/io/iommu.c | 19 ++++++++++--------- sys/amd64/vmm/io/iommu.h | 8 ++++---- sys/amd64/vmm/io/ppt.c | 4 ++-- 5 files changed, 30 insertions(+), 33 deletions(-) diff --git a/sys/amd64/vmm/amd/amdv.c b/sys/amd64/vmm/amd/amdv.c index 4c88d12..ca639df 100644 --- a/sys/amd64/vmm/amd/amdv.c +++ b/sys/amd64/vmm/amd/amdv.c @@ -242,14 +242,14 @@ amd_iommu_remove_mapping(void *domain, vm_paddr_t gpa, uint64_t len) } static void -amd_iommu_add_device(void *domain, int bus, int slot, int func) +amd_iommu_add_device(void *domain, uint16_t rid) { printf("amd_iommu_add_device: not implemented\n"); } static void -amd_iommu_remove_device(void *domain, int bus, int slot, int func) +amd_iommu_remove_device(void *domain, uint16_t rid) { printf("amd_iommu_remove_device: not implemented\n"); diff --git a/sys/amd64/vmm/intel/vtd.c b/sys/amd64/vmm/intel/vtd.c index ca76ea8..afd7155 100644 --- a/sys/amd64/vmm/intel/vtd.c +++ b/sys/amd64/vmm/intel/vtd.c @@ -99,6 +99,8 @@ struct vtdmap { #define VTD_PTE_SUPERPAGE (1UL << 7) #define VTD_PTE_ADDR_M (0x000FFFFFFFFFF000UL) +#define VTD_RID2IDX(rid) (((rid) & 0xff) * 2) + struct domain { uint64_t *ptp; /* first level page table page */ int pt_levels; /* number of page table levels */ @@ -360,27 +362,24 @@ vtd_disable(void) } static void -vtd_add_device(void *arg, int bus, int slot, int func) +vtd_add_device(void *arg, uint16_t rid) { int idx; uint64_t *ctxp; struct domain *dom = arg; vm_paddr_t pt_paddr; struct vtdmap *vtdmap; - - if (bus < 0 || bus > PCI_BUSMAX || - slot < 0 || slot > PCI_SLOTMAX || - func < 0 || func > PCI_FUNCMAX) - panic("vtd_add_device: invalid bsf %d/%d/%d", bus, slot, func); + uint8_t bus; vtdmap = vtdmaps[0]; + bus = PCI_RID2BUS(rid); ctxp = ctx_tables[bus]; pt_paddr = vtophys(dom->ptp); - idx = (slot << 3 | func) * 2; + idx = VTD_RID2IDX(rid); if (ctxp[idx] & VTD_CTX_PRESENT) { - panic("vtd_add_device: device %d/%d/%d is already owned by " - "domain %d", bus, slot, func, + panic("vtd_add_device: device %x is already owned by " + "domain %d", rid, (uint16_t)(ctxp[idx + 1] >> 8)); } @@ -404,19 +403,16 @@ vtd_add_device(void *arg, int bus, int slot, int func) } static void -vtd_remove_device(void *arg, int bus, int slot, int func) +vtd_remove_device(void *arg, uint16_t rid) { int i, idx; uint64_t *ctxp; struct vtdmap *vtdmap; + uint8_t bus; - if (bus < 0 || bus > PCI_BUSMAX || - slot < 0 || slot > PCI_SLOTMAX || - func < 0 || func > PCI_FUNCMAX) - panic("vtd_add_device: invalid bsf %d/%d/%d", bus, slot, func); - + bus = PCI_RID2BUS(rid); ctxp = ctx_tables[bus]; - idx = (slot << 3 | func) * 2; + idx = VTD_RID2IDX(rid); /* * Order is important. The 'present' bit is must be cleared first. diff --git a/sys/amd64/vmm/io/iommu.c b/sys/amd64/vmm/io/iommu.c index c491232..9cfc4c2 100644 --- a/sys/amd64/vmm/io/iommu.c +++ b/sys/amd64/vmm/io/iommu.c @@ -109,19 +109,19 @@ IOMMU_REMOVE_MAPPING(void *domain, vm_paddr_t gpa, uint64_t len) } static __inline void -IOMMU_ADD_DEVICE(void *domain, int bus, int slot, int func) +IOMMU_ADD_DEVICE(void *domain, uint16_t rid) { if (ops != NULL && iommu_avail) - (*ops->add_device)(domain, bus, slot, func); + (*ops->add_device)(domain, rid); } static __inline void -IOMMU_REMOVE_DEVICE(void *domain, int bus, int slot, int func) +IOMMU_REMOVE_DEVICE(void *domain, uint16_t rid) { if (ops != NULL && iommu_avail) - (*ops->remove_device)(domain, bus, slot, func); + (*ops->remove_device)(domain, rid); } static __inline void @@ -196,7 +196,8 @@ iommu_init(void) continue; /* everything else belongs to the host domain */ - iommu_add_device(host_domain, bus, slot, func); + iommu_add_device(host_domain, + pci_get_rid(dev)); } } } @@ -263,17 +264,17 @@ iommu_host_domain(void) } void -iommu_add_device(void *dom, int bus, int slot, int func) +iommu_add_device(void *dom, uint16_t rid) { - IOMMU_ADD_DEVICE(dom, bus, slot, func); + IOMMU_ADD_DEVICE(dom, rid); } void -iommu_remove_device(void *dom, int bus, int slot, int func) +iommu_remove_device(void *dom, uint16_t rid) { - IOMMU_REMOVE_DEVICE(dom, bus, slot, func); + IOMMU_REMOVE_DEVICE(dom, rid); } void diff --git a/sys/amd64/vmm/io/iommu.h b/sys/amd64/vmm/io/iommu.h index d5c1d6e..36b44fa 100644 --- a/sys/amd64/vmm/io/iommu.h +++ b/sys/amd64/vmm/io/iommu.h @@ -39,8 +39,8 @@ typedef uint64_t (*iommu_create_mapping_t)(void *domain, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len); typedef uint64_t (*iommu_remove_mapping_t)(void *domain, vm_paddr_t gpa, uint64_t len); -typedef void (*iommu_add_device_t)(void *domain, int bus, int slot, int func); -typedef void (*iommu_remove_device_t)(void *dom, int bus, int slot, int func); +typedef void (*iommu_add_device_t)(void *domain, uint16_t rid); +typedef void (*iommu_remove_device_t)(void *dom, uint16_t rid); typedef void (*iommu_invalidate_tlb_t)(void *dom); struct iommu_ops { @@ -69,7 +69,7 @@ void iommu_destroy_domain(void *dom); void iommu_create_mapping(void *dom, vm_paddr_t gpa, vm_paddr_t hpa, size_t len); void iommu_remove_mapping(void *dom, vm_paddr_t gpa, size_t len); -void iommu_add_device(void *dom, int bus, int slot, int func); -void iommu_remove_device(void *dom, int bus, int slot, int func); +void iommu_add_device(void *dom, uint16_t rid); +void iommu_remove_device(void *dom, uint16_t rid); void iommu_invalidate_tlb(void *domain); #endif diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c index a7ea091..fa7083e 100644 --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -346,7 +346,7 @@ ppt_assign_device(struct vm *vm, int bus, int slot, int func) return (EBUSY); ppt->vm = vm; - iommu_add_device(vm_iommu_domain(vm), bus, slot, func); + iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); return (0); } return (ENOENT); @@ -367,7 +367,7 @@ ppt_unassign_device(struct vm *vm, int bus, int slot, int func) ppt_unmap_mmio(vm, ppt); ppt_teardown_msi(ppt); ppt_teardown_msix(ppt); - iommu_remove_device(vm_iommu_domain(vm), bus, slot, func); + iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); ppt->vm = NULL; return (0); } -- 1.8.5.2