summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrstone <rstone@FreeBSD.org>2014-04-01 14:54:43 +0000
committerrstone <rstone@FreeBSD.org>2014-04-01 14:54:43 +0000
commit4df708593361cce38ba4fb0065b4244dfa8e5b2c (patch)
treed47c0e7c317776a8dd77f701b69b1ccd1df0ac3e
parenteabfe8df7a0fc73c404f7673f0a79c09ef6e81bf (diff)
downloadFreeBSD-src-4df708593361cce38ba4fb0065b4244dfa8e5b2c.zip
FreeBSD-src-4df708593361cce38ba4fb0065b4244dfa8e5b2c.tar.gz
Re-write bhyve's I/O MMU handling in terms of PCI RIDs
Reviewed by: neel Sponsored by: Sandvine Inc
-rw-r--r--sys/amd64/vmm/amd/amdv.c4
-rw-r--r--sys/amd64/vmm/intel/vtd.c28
-rw-r--r--sys/amd64/vmm/io/iommu.c19
-rw-r--r--sys/amd64/vmm/io/iommu.h8
-rw-r--r--sys/amd64/vmm/io/ppt.c4
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);
}
OpenPOWER on IntegriCloud