x86, vt-d: Fail PCI device assignment if device already assigned.
authorKeir Fraser <keir@xensource.com>
Thu, 18 Oct 2007 09:24:50 +0000 (10:24 +0100)
committerKeir Fraser <keir@xensource.com>
Thu, 18 Oct 2007 09:24:50 +0000 (10:24 +0100)
Signed-off-by: Weidong Han <weidong.han@intel.com>
xen/arch/x86/domctl.c
xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
xen/include/asm-x86/iommu.h

index 7a1547c9498b78b2fd8b4b8d07e5872159cbe407..a222944c9ba05f490041571b9700402c5a711fa9 100644 (file)
@@ -531,10 +531,10 @@ long arch_do_domctl(
         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"); 
@@ -543,6 +543,10 @@ long arch_do_domctl(
         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));
index b63b0217d0584201bb7122e8947cf102c0236457..a6676a439f4be78b1f76e948c75c138cb061f480 100644 (file)
@@ -1813,6 +1813,21 @@ int iommu_setup(void)
     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);
index 914145c503a4cd5c9b6911555e49b2ea4f941408..ebda8fb794c4d011a6ac204c8a5734ee5933d921 100644 (file)
@@ -69,6 +69,7 @@ struct iommu {
 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);