From: Keir Fraser Date: Thu, 18 Oct 2007 09:24:50 +0000 (+0100) Subject: x86, vt-d: Fail PCI device assignment if device already assigned. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14847^2~25 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=2a61b8af7e694460b8615d449f2e6a8e09085280;p=xen.git x86, vt-d: Fail PCI device assignment if device already assigned. Signed-off-by: Weidong Han --- diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 7a1547c949..a222944c9b 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -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)); diff --git a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c index b63b0217d0..a6676a439f 100644 --- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c +++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c @@ -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); diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h index 914145c503..ebda8fb794 100644 --- a/xen/include/asm-x86/iommu.h +++ b/xen/include/asm-x86/iommu.h @@ -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);