Loading drivers/iommu/intel-iommu.c +87 −36 Original line number Diff line number Diff line Loading @@ -1833,6 +1833,63 @@ static inline int guestwidth_to_adjustwidth(int gaw) return agaw; } static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu, int guest_width) { int adjust_width, agaw; unsigned long sagaw; int err; init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN); err = init_iova_flush_queue(&domain->iovad, iommu_flush_iova, iova_entry_free); if (err) return err; domain_reserve_special_ranges(domain); /* calculate AGAW */ if (guest_width > cap_mgaw(iommu->cap)) guest_width = cap_mgaw(iommu->cap); domain->gaw = guest_width; adjust_width = guestwidth_to_adjustwidth(guest_width); agaw = width_to_agaw(adjust_width); sagaw = cap_sagaw(iommu->cap); if (!test_bit(agaw, &sagaw)) { /* hardware doesn't support it, choose a bigger one */ pr_debug("Hardware doesn't support agaw %d\n", agaw); agaw = find_next_bit(&sagaw, 5, agaw); if (agaw >= 5) return -ENODEV; } domain->agaw = agaw; if (ecap_coherent(iommu->ecap)) domain->iommu_coherency = 1; else domain->iommu_coherency = 0; if (ecap_sc_support(iommu->ecap)) domain->iommu_snooping = 1; else domain->iommu_snooping = 0; if (intel_iommu_superpage) domain->iommu_superpage = fls(cap_super_page_val(iommu->cap)); else domain->iommu_superpage = 0; domain->nid = iommu->node; /* always allocate the top pgd */ domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid); if (!domain->pgd) return -ENOMEM; __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE); return 0; } static void domain_exit(struct dmar_domain *domain) { struct page *freelist; Loading Loading @@ -2513,31 +2570,6 @@ static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque) return 0; } static int domain_init(struct dmar_domain *domain, int guest_width) { int adjust_width; init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN); domain_reserve_special_ranges(domain); /* calculate AGAW */ domain->gaw = guest_width; adjust_width = guestwidth_to_adjustwidth(guest_width); domain->agaw = width_to_agaw(adjust_width); domain->iommu_coherency = 0; domain->iommu_snooping = 0; domain->iommu_superpage = 0; domain->max_addr = 0; /* always allocate the top pgd */ domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid); if (!domain->pgd) return -ENOMEM; domain_flush_cache(domain, domain->pgd, PAGE_SIZE); return 0; } static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw) { struct device_domain_info *info; Loading Loading @@ -2575,19 +2607,11 @@ static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw) domain = alloc_domain(0); if (!domain) return NULL; if (domain_init(domain, gaw)) { if (domain_init(domain, iommu, gaw)) { domain_exit(domain); return NULL; } if (init_iova_flush_queue(&domain->iovad, iommu_flush_iova, iova_entry_free)) { pr_warn("iova flush queue initialization failed\n"); intel_iommu_strict = 1; } out: return domain; } Loading Loading @@ -2692,6 +2716,8 @@ static int domain_prepare_identity_map(struct device *dev, return iommu_domain_identity_map(domain, start, end); } static int md_domain_init(struct dmar_domain *domain, int guest_width); static int __init si_domain_init(int hw) { struct dmar_rmrr_unit *rmrr; Loading @@ -2702,7 +2728,7 @@ static int __init si_domain_init(int hw) if (!si_domain) return -EFAULT; if (domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { domain_exit(si_domain); return -EFAULT; } Loading Loading @@ -4829,6 +4855,31 @@ static void dmar_remove_one_dev_info(struct device *dev) spin_unlock_irqrestore(&device_domain_lock, flags); } static int md_domain_init(struct dmar_domain *domain, int guest_width) { int adjust_width; init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN); domain_reserve_special_ranges(domain); /* calculate AGAW */ domain->gaw = guest_width; adjust_width = guestwidth_to_adjustwidth(guest_width); domain->agaw = width_to_agaw(adjust_width); domain->iommu_coherency = 0; domain->iommu_snooping = 0; domain->iommu_superpage = 0; domain->max_addr = 0; /* always allocate the top pgd */ domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid); if (!domain->pgd) return -ENOMEM; domain_flush_cache(domain, domain->pgd, PAGE_SIZE); return 0; } static struct iommu_domain *intel_iommu_domain_alloc(unsigned type) { struct dmar_domain *dmar_domain; Loading @@ -4843,7 +4894,7 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type) pr_err("Can't allocate dmar_domain\n"); return NULL; } if (domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { pr_err("Domain initialization failed\n"); domain_exit(dmar_domain); return NULL; Loading Loading
drivers/iommu/intel-iommu.c +87 −36 Original line number Diff line number Diff line Loading @@ -1833,6 +1833,63 @@ static inline int guestwidth_to_adjustwidth(int gaw) return agaw; } static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu, int guest_width) { int adjust_width, agaw; unsigned long sagaw; int err; init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN); err = init_iova_flush_queue(&domain->iovad, iommu_flush_iova, iova_entry_free); if (err) return err; domain_reserve_special_ranges(domain); /* calculate AGAW */ if (guest_width > cap_mgaw(iommu->cap)) guest_width = cap_mgaw(iommu->cap); domain->gaw = guest_width; adjust_width = guestwidth_to_adjustwidth(guest_width); agaw = width_to_agaw(adjust_width); sagaw = cap_sagaw(iommu->cap); if (!test_bit(agaw, &sagaw)) { /* hardware doesn't support it, choose a bigger one */ pr_debug("Hardware doesn't support agaw %d\n", agaw); agaw = find_next_bit(&sagaw, 5, agaw); if (agaw >= 5) return -ENODEV; } domain->agaw = agaw; if (ecap_coherent(iommu->ecap)) domain->iommu_coherency = 1; else domain->iommu_coherency = 0; if (ecap_sc_support(iommu->ecap)) domain->iommu_snooping = 1; else domain->iommu_snooping = 0; if (intel_iommu_superpage) domain->iommu_superpage = fls(cap_super_page_val(iommu->cap)); else domain->iommu_superpage = 0; domain->nid = iommu->node; /* always allocate the top pgd */ domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid); if (!domain->pgd) return -ENOMEM; __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE); return 0; } static void domain_exit(struct dmar_domain *domain) { struct page *freelist; Loading Loading @@ -2513,31 +2570,6 @@ static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque) return 0; } static int domain_init(struct dmar_domain *domain, int guest_width) { int adjust_width; init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN); domain_reserve_special_ranges(domain); /* calculate AGAW */ domain->gaw = guest_width; adjust_width = guestwidth_to_adjustwidth(guest_width); domain->agaw = width_to_agaw(adjust_width); domain->iommu_coherency = 0; domain->iommu_snooping = 0; domain->iommu_superpage = 0; domain->max_addr = 0; /* always allocate the top pgd */ domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid); if (!domain->pgd) return -ENOMEM; domain_flush_cache(domain, domain->pgd, PAGE_SIZE); return 0; } static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw) { struct device_domain_info *info; Loading Loading @@ -2575,19 +2607,11 @@ static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw) domain = alloc_domain(0); if (!domain) return NULL; if (domain_init(domain, gaw)) { if (domain_init(domain, iommu, gaw)) { domain_exit(domain); return NULL; } if (init_iova_flush_queue(&domain->iovad, iommu_flush_iova, iova_entry_free)) { pr_warn("iova flush queue initialization failed\n"); intel_iommu_strict = 1; } out: return domain; } Loading Loading @@ -2692,6 +2716,8 @@ static int domain_prepare_identity_map(struct device *dev, return iommu_domain_identity_map(domain, start, end); } static int md_domain_init(struct dmar_domain *domain, int guest_width); static int __init si_domain_init(int hw) { struct dmar_rmrr_unit *rmrr; Loading @@ -2702,7 +2728,7 @@ static int __init si_domain_init(int hw) if (!si_domain) return -EFAULT; if (domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { domain_exit(si_domain); return -EFAULT; } Loading Loading @@ -4829,6 +4855,31 @@ static void dmar_remove_one_dev_info(struct device *dev) spin_unlock_irqrestore(&device_domain_lock, flags); } static int md_domain_init(struct dmar_domain *domain, int guest_width) { int adjust_width; init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN); domain_reserve_special_ranges(domain); /* calculate AGAW */ domain->gaw = guest_width; adjust_width = guestwidth_to_adjustwidth(guest_width); domain->agaw = width_to_agaw(adjust_width); domain->iommu_coherency = 0; domain->iommu_snooping = 0; domain->iommu_superpage = 0; domain->max_addr = 0; /* always allocate the top pgd */ domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid); if (!domain->pgd) return -ENOMEM; domain_flush_cache(domain, domain->pgd, PAGE_SIZE); return 0; } static struct iommu_domain *intel_iommu_domain_alloc(unsigned type) { struct dmar_domain *dmar_domain; Loading @@ -4843,7 +4894,7 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type) pr_err("Can't allocate dmar_domain\n"); return NULL; } if (domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { pr_err("Domain initialization failed\n"); domain_exit(dmar_domain); return NULL; Loading