From 0c558c4ce7f5464467b0fd033079e50123723687 Mon Sep 17 00:00:00 2001 From: Tom Lyon Date: Mon, 17 May 2010 08:20:45 +0100 Subject: [PATCH] --- yaml --- r: 197887 b: refs/heads/master c: a99c47a228c194aa75bffdcb82806c5f33c7c63b h: refs/heads/master i: 197885: 506e2b6bef6b3629158a7fd2c945bee9a0a3d0bd 197883: eec6a52a69331199b6e67a719bf01a636718ee26 197879: 6e9eb17b20eb8ce68e142a1e9b8e466b8263484f 197871: 98aca2de5adaf4bdaa191ce3631fb6bd5d690a01 197855: 253131d33f1f3744def39fc060c9c3566bac290c 197823: 8dd322c581b9c8883dad94500b4077db63d0d8f1 197759: 3b4ec2f06b8ed26c5fd6cd2ef7783b17744e4fe5 197631: 25ce0b3385453dfd886b175dd38f1829ad7835f2 v: v3 --- [refs] | 2 +- trunk/drivers/pci/intel-iommu.c | 40 +++++++++++++++++---------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/[refs] b/[refs] index 85317802813a..814770dce38a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4f506e07e0a3dff34427cece255a8f390a78d5a0 +refs/heads/master: a99c47a228c194aa75bffdcb82806c5f33c7c63b diff --git a/trunk/drivers/pci/intel-iommu.c b/trunk/drivers/pci/intel-iommu.c index da40f0789739..57be89e6f484 100644 --- a/trunk/drivers/pci/intel-iommu.c +++ b/trunk/drivers/pci/intel-iommu.c @@ -3433,19 +3433,6 @@ static void vm_domain_remove_all_dev_info(struct dmar_domain *domain) /* domain id for virtual machine, it won't be set in context */ static unsigned long vm_domid; -static int vm_domain_min_agaw(struct dmar_domain *domain) -{ - int i; - int min_agaw = domain->agaw; - - for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) { - if (min_agaw > g_iommus[i]->agaw) - min_agaw = g_iommus[i]->agaw; - } - - return min_agaw; -} - static struct dmar_domain *iommu_alloc_vm_domain(void) { struct dmar_domain *domain; @@ -3574,7 +3561,6 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, struct pci_dev *pdev = to_pci_dev(dev); struct intel_iommu *iommu; int addr_width; - u64 end; /* normally pdev is not mapped */ if (unlikely(domain_context_mapped(pdev))) { @@ -3597,14 +3583,30 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, /* check if this iommu agaw is sufficient for max mapped address */ addr_width = agaw_to_width(iommu->agaw); - end = DOMAIN_MAX_ADDR(addr_width); - end = end & VTD_PAGE_MASK; - if (end < dmar_domain->max_addr) { - printk(KERN_ERR "%s: iommu agaw (%d) is not " + if (addr_width > cap_mgaw(iommu->cap)) + addr_width = cap_mgaw(iommu->cap); + + if (dmar_domain->max_addr > (1LL << addr_width)) { + printk(KERN_ERR "%s: iommu width (%d) is not " "sufficient for the mapped address (%llx)\n", - __func__, iommu->agaw, dmar_domain->max_addr); + __func__, addr_width, dmar_domain->max_addr); return -EFAULT; } + dmar_domain->gaw = addr_width; + + /* + * Knock out extra levels of page tables if necessary + */ + while (iommu->agaw < dmar_domain->agaw) { + struct dma_pte *pte; + + pte = dmar_domain->pgd; + if (dma_pte_present(pte)) { + free_pgtable_page(dmar_domain->pgd); + dmar_domain->pgd = (struct dma_pte *)dma_pte_addr(pte); + } + dmar_domain->agaw--; + } return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL); }