struct hvm_iommu *hd;
u8 bus, devfn;
- if (!vtd_enabled)
+ ret = -EINVAL;
+ if ( !vtd_enabled )
break;
- ret = -EINVAL;
if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) ) {
gdprintk(XENLOG_ERR,
"XEN_DOMCTL_assign_device: get_domain_by_id() failed\n");
hd = domain_hvm_iommu(d);
bus = (domctl->u.assign_device.machine_bdf >> 16) & 0xff;
devfn = (domctl->u.assign_device.machine_bdf >> 8) & 0xff;
+
+ if ( device_assigned(bus, devfn) )
+ break;
+
ret = assign_device(d, bus, devfn);
gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: bdf = %x:%x:%x\n",
bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
return -EIO;
}
+/*
+ * If the device isn't owned by dom0, it means it already
+ * has been assigned to other domain, or it's not exist.
+ */
+int device_assigned(u8 bus, u8 devfn)
+{
+ struct pci_dev *pdev;
+
+ for_each_pdev( dom0, pdev )
+ if ( (pdev->bus == bus ) && (pdev->devfn == devfn) )
+ return 0;
+
+ return 1;
+}
+
int assign_device(struct domain *d, u8 bus, u8 devfn)
{
struct hvm_iommu *hd = domain_hvm_iommu(d);
int iommu_setup(void);
int iommu_domain_init(struct domain *d);
void iommu_domain_destroy(struct domain *d);
+int device_assigned(u8 bus, u8 devfn);
int assign_device(struct domain *d, u8 bus, u8 devfn);
int iommu_map_page(struct domain *d, dma_addr_t gfn, dma_addr_t mfn);
int iommu_unmap_page(struct domain *d, dma_addr_t gfn);