iommu/vt-d, trivial: refine support of 64bit guest address
[deliverable/linux.git] / drivers / iommu / intel-iommu.c
index 43b9bfea48fa4d7351e22134601338426b57c6cf..7bddb9b32da8dfd9403686145a06367f05607d57 100644 (file)
@@ -63,6 +63,7 @@
 #define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
 
 #define MAX_AGAW_WIDTH 64
+#define MAX_AGAW_PFN_WIDTH     (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT)
 
 #define __DOMAIN_MAX_PFN(gaw)  ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
 #define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
@@ -106,12 +107,12 @@ static inline int agaw_to_level(int agaw)
 
 static inline int agaw_to_width(int agaw)
 {
-       return 30 + agaw * LEVEL_STRIDE;
+       return min_t(int, 30 + agaw * LEVEL_STRIDE, MAX_AGAW_WIDTH);
 }
 
 static inline int width_to_agaw(int width)
 {
-       return (width - 30) / LEVEL_STRIDE;
+       return DIV_ROUND_UP(width - 30, LEVEL_STRIDE);
 }
 
 static inline unsigned int level_to_offset_bits(int level)
@@ -141,7 +142,7 @@ static inline unsigned long align_to_level(unsigned long pfn, int level)
 
 static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
 {
-       return  1 << ((lvl - 1) * LEVEL_STRIDE);
+       return  1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
 }
 
 /* VT-d pages must always be _smaller_ than MM pages. Otherwise things
@@ -865,7 +866,6 @@ static int dma_pte_clear_range(struct dmar_domain *domain,
        int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
        unsigned int large_page = 1;
        struct dma_pte *first_pte, *pte;
-       int order;
 
        BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
        BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
@@ -890,8 +890,7 @@ static int dma_pte_clear_range(struct dmar_domain *domain,
 
        } while (start_pfn && start_pfn <= last_pfn);
 
-       order = (large_page - 1) * 9;
-       return order;
+       return min_t(int, (large_page - 1) * 9, MAX_AGAW_PFN_WIDTH);
 }
 
 static void dma_pte_free_level(struct dmar_domain *domain, int level,
@@ -1255,8 +1254,8 @@ static int iommu_init_domains(struct intel_iommu *iommu)
        unsigned long nlongs;
 
        ndomains = cap_ndoms(iommu->cap);
-       pr_debug("IOMMU %d: Number of Domains supported <%ld>\n", iommu->seq_id,
-                       ndomains);
+       pr_debug("IOMMU%d: Number of Domains supported <%ld>\n",
+                iommu->seq_id, ndomains);
        nlongs = BITS_TO_LONGS(ndomains);
 
        spin_lock_init(&iommu->lock);
@@ -1266,13 +1265,17 @@ static int iommu_init_domains(struct intel_iommu *iommu)
         */
        iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
        if (!iommu->domain_ids) {
-               printk(KERN_ERR "Allocating domain id array failed\n");
+               pr_err("IOMMU%d: allocating domain id array failed\n",
+                      iommu->seq_id);
                return -ENOMEM;
        }
        iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *),
                        GFP_KERNEL);
        if (!iommu->domains) {
-               printk(KERN_ERR "Allocating domain array failed\n");
+               pr_err("IOMMU%d: allocating domain array failed\n",
+                      iommu->seq_id);
+               kfree(iommu->domain_ids);
+               iommu->domain_ids = NULL;
                return -ENOMEM;
        }
 
@@ -2758,7 +2761,7 @@ static int iommu_no_mapping(struct device *dev)
        struct pci_dev *pdev;
        int found;
 
-       if (unlikely(dev->bus != &pci_bus_type))
+       if (unlikely(!dev_is_pci(dev)))
                return 1;
 
        pdev = to_pci_dev(dev);
@@ -3877,7 +3880,7 @@ 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 atomic_t vm_domid = ATOMIC_INIT(0);
 
 static struct dmar_domain *iommu_alloc_vm_domain(void)
 {
@@ -3887,7 +3890,7 @@ static struct dmar_domain *iommu_alloc_vm_domain(void)
        if (!domain)
                return NULL;
 
-       domain->id = vm_domid++;
+       domain->id = atomic_inc_return(&vm_domid);
        domain->nid = -1;
        memset(domain->iommu_bmp, 0, sizeof(domain->iommu_bmp));
        domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
This page took 0.02538 seconds and 5 git commands to generate.