From 2a61b8af7e694460b8615d449f2e6a8e09085280 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 18 Oct 2007 10:24:50 +0100 Subject: [PATCH] x86, vt-d: Fail PCI device assignment if device already assigned. Signed-off-by: Weidong Han --- xen/arch/x86/domctl.c | 8 ++++++-- xen/arch/x86/hvm/vmx/vtd/intel-iommu.c | 15 +++++++++++++++ xen/include/asm-x86/iommu.h | 1 + 3 files changed, 22 insertions(+), 2 deletions(-) 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); -- 2.30.2