Loading drivers/iommu/intel-iommu.c +38 −159 Original line number Diff line number Diff line Loading @@ -458,31 +458,6 @@ static LIST_HEAD(dmar_rmrr_units); #define for_each_rmrr_units(rmrr) \ list_for_each_entry(rmrr, &dmar_rmrr_units, list) static void flush_unmaps_timeout(unsigned long data); struct deferred_flush_entry { unsigned long iova_pfn; unsigned long nrpages; struct dmar_domain *domain; struct page *freelist; }; #define HIGH_WATER_MARK 250 struct deferred_flush_table { int next; struct deferred_flush_entry entries[HIGH_WATER_MARK]; }; struct deferred_flush_data { spinlock_t lock; int timer_on; struct timer_list timer; long size; struct deferred_flush_table *tables; }; static DEFINE_PER_CPU(struct deferred_flush_data, deferred_flush); /* bitmap for indexing intel_iommus */ static int g_num_of_iommus; Loading Loading @@ -1309,6 +1284,13 @@ static void dma_free_pagelist(struct page *freelist) } } static void iova_entry_free(unsigned long data) { struct page *freelist = (struct page *)data; dma_free_pagelist(freelist); } /* iommu handling */ static int iommu_alloc_root_entry(struct intel_iommu *iommu) { Loading Loading @@ -1622,6 +1604,25 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, addr, mask); } static void iommu_flush_iova(struct iova_domain *iovad) { struct dmar_domain *domain; int idx; domain = container_of(iovad, struct dmar_domain, iovad); for_each_domain_iommu(idx, domain) { struct intel_iommu *iommu = g_iommus[idx]; u16 did = domain->iommu_did[iommu->seq_id]; iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH); if (!cap_caching_mode(iommu->cap)) iommu_flush_dev_iotlb(get_iommu_domain(iommu, did), 0, MAX_AGAW_PFN_WIDTH); } } static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu) { u32 pmen; Loading Loading @@ -1932,9 +1933,16 @@ static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu, { int adjust_width, agaw; unsigned long sagaw; int err; init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN, DMA_32BIT_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 */ Loading Loading @@ -1986,14 +1994,6 @@ static void domain_exit(struct dmar_domain *domain) if (!domain) return; /* Flush any lazy unmaps that may reference this domain */ if (!intel_iommu_strict) { int cpu; for_each_possible_cpu(cpu) flush_unmaps_timeout(cpu); } /* Remove associated devices and clear attached or cached domains */ rcu_read_lock(); domain_remove_dev_info(domain); Loading Loading @@ -3206,7 +3206,7 @@ static int __init init_dmars(void) bool copied_tables = false; struct device *dev; struct intel_iommu *iommu; int i, ret, cpu; int i, ret; /* * for each drhd Loading Loading @@ -3239,22 +3239,6 @@ static int __init init_dmars(void) goto error; } for_each_possible_cpu(cpu) { struct deferred_flush_data *dfd = per_cpu_ptr(&deferred_flush, cpu); dfd->tables = kzalloc(g_num_of_iommus * sizeof(struct deferred_flush_table), GFP_KERNEL); if (!dfd->tables) { ret = -ENOMEM; goto free_g_iommus; } spin_lock_init(&dfd->lock); setup_timer(&dfd->timer, flush_unmaps_timeout, cpu); } for_each_active_iommu(iommu, drhd) { g_iommus[iommu->seq_id] = iommu; Loading Loading @@ -3437,10 +3421,9 @@ static int __init init_dmars(void) disable_dmar_iommu(iommu); free_dmar_iommu(iommu); } free_g_iommus: for_each_possible_cpu(cpu) kfree(per_cpu_ptr(&deferred_flush, cpu)->tables); kfree(g_iommus); error: return ret; } Loading Loading @@ -3645,110 +3628,6 @@ static dma_addr_t intel_map_page(struct device *dev, struct page *page, dir, *dev->dma_mask); } static void flush_unmaps(struct deferred_flush_data *flush_data) { int i, j; flush_data->timer_on = 0; /* just flush them all */ for (i = 0; i < g_num_of_iommus; i++) { struct intel_iommu *iommu = g_iommus[i]; struct deferred_flush_table *flush_table = &flush_data->tables[i]; if (!iommu) continue; if (!flush_table->next) continue; /* In caching mode, global flushes turn emulation expensive */ if (!cap_caching_mode(iommu->cap)) iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH); for (j = 0; j < flush_table->next; j++) { unsigned long mask; struct deferred_flush_entry *entry = &flush_table->entries[j]; unsigned long iova_pfn = entry->iova_pfn; unsigned long nrpages = entry->nrpages; struct dmar_domain *domain = entry->domain; struct page *freelist = entry->freelist; /* On real hardware multiple invalidations are expensive */ if (cap_caching_mode(iommu->cap)) iommu_flush_iotlb_psi(iommu, domain, mm_to_dma_pfn(iova_pfn), nrpages, !freelist, 0); else { mask = ilog2(nrpages); iommu_flush_dev_iotlb(domain, (uint64_t)iova_pfn << PAGE_SHIFT, mask); } free_iova_fast(&domain->iovad, iova_pfn, nrpages); if (freelist) dma_free_pagelist(freelist); } flush_table->next = 0; } flush_data->size = 0; } static void flush_unmaps_timeout(unsigned long cpuid) { struct deferred_flush_data *flush_data = per_cpu_ptr(&deferred_flush, cpuid); unsigned long flags; spin_lock_irqsave(&flush_data->lock, flags); flush_unmaps(flush_data); spin_unlock_irqrestore(&flush_data->lock, flags); } static void add_unmap(struct dmar_domain *dom, unsigned long iova_pfn, unsigned long nrpages, struct page *freelist) { unsigned long flags; int entry_id, iommu_id; struct intel_iommu *iommu; struct deferred_flush_entry *entry; struct deferred_flush_data *flush_data; flush_data = raw_cpu_ptr(&deferred_flush); /* Flush all CPUs' entries to avoid deferring too much. If * this becomes a bottleneck, can just flush us, and rely on * flush timer for the rest. */ if (flush_data->size == HIGH_WATER_MARK) { int cpu; for_each_online_cpu(cpu) flush_unmaps_timeout(cpu); } spin_lock_irqsave(&flush_data->lock, flags); iommu = domain_get_iommu(dom); iommu_id = iommu->seq_id; entry_id = flush_data->tables[iommu_id].next; ++(flush_data->tables[iommu_id].next); entry = &flush_data->tables[iommu_id].entries[entry_id]; entry->domain = dom; entry->iova_pfn = iova_pfn; entry->nrpages = nrpages; entry->freelist = freelist; if (!flush_data->timer_on) { mod_timer(&flush_data->timer, jiffies + msecs_to_jiffies(10)); flush_data->timer_on = 1; } flush_data->size++; spin_unlock_irqrestore(&flush_data->lock, flags); } static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) { struct dmar_domain *domain; Loading Loading @@ -3784,7 +3663,8 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages)); dma_free_pagelist(freelist); } else { add_unmap(domain, iova_pfn, nrpages, freelist); queue_iova(&domain->iovad, iova_pfn, nrpages, (unsigned long)freelist); /* * queue up the release of the unmap to save the 1/6th of the * cpu used up by the iotlb flush operation... Loading Loading @@ -4721,7 +4601,6 @@ static void free_all_cpu_cached_iovas(unsigned int cpu) static int intel_iommu_cpu_dead(unsigned int cpu) { free_all_cpu_cached_iovas(cpu); flush_unmaps_timeout(cpu); return 0; } Loading Loading
drivers/iommu/intel-iommu.c +38 −159 Original line number Diff line number Diff line Loading @@ -458,31 +458,6 @@ static LIST_HEAD(dmar_rmrr_units); #define for_each_rmrr_units(rmrr) \ list_for_each_entry(rmrr, &dmar_rmrr_units, list) static void flush_unmaps_timeout(unsigned long data); struct deferred_flush_entry { unsigned long iova_pfn; unsigned long nrpages; struct dmar_domain *domain; struct page *freelist; }; #define HIGH_WATER_MARK 250 struct deferred_flush_table { int next; struct deferred_flush_entry entries[HIGH_WATER_MARK]; }; struct deferred_flush_data { spinlock_t lock; int timer_on; struct timer_list timer; long size; struct deferred_flush_table *tables; }; static DEFINE_PER_CPU(struct deferred_flush_data, deferred_flush); /* bitmap for indexing intel_iommus */ static int g_num_of_iommus; Loading Loading @@ -1309,6 +1284,13 @@ static void dma_free_pagelist(struct page *freelist) } } static void iova_entry_free(unsigned long data) { struct page *freelist = (struct page *)data; dma_free_pagelist(freelist); } /* iommu handling */ static int iommu_alloc_root_entry(struct intel_iommu *iommu) { Loading Loading @@ -1622,6 +1604,25 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, addr, mask); } static void iommu_flush_iova(struct iova_domain *iovad) { struct dmar_domain *domain; int idx; domain = container_of(iovad, struct dmar_domain, iovad); for_each_domain_iommu(idx, domain) { struct intel_iommu *iommu = g_iommus[idx]; u16 did = domain->iommu_did[iommu->seq_id]; iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH); if (!cap_caching_mode(iommu->cap)) iommu_flush_dev_iotlb(get_iommu_domain(iommu, did), 0, MAX_AGAW_PFN_WIDTH); } } static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu) { u32 pmen; Loading Loading @@ -1932,9 +1933,16 @@ static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu, { int adjust_width, agaw; unsigned long sagaw; int err; init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN, DMA_32BIT_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 */ Loading Loading @@ -1986,14 +1994,6 @@ static void domain_exit(struct dmar_domain *domain) if (!domain) return; /* Flush any lazy unmaps that may reference this domain */ if (!intel_iommu_strict) { int cpu; for_each_possible_cpu(cpu) flush_unmaps_timeout(cpu); } /* Remove associated devices and clear attached or cached domains */ rcu_read_lock(); domain_remove_dev_info(domain); Loading Loading @@ -3206,7 +3206,7 @@ static int __init init_dmars(void) bool copied_tables = false; struct device *dev; struct intel_iommu *iommu; int i, ret, cpu; int i, ret; /* * for each drhd Loading Loading @@ -3239,22 +3239,6 @@ static int __init init_dmars(void) goto error; } for_each_possible_cpu(cpu) { struct deferred_flush_data *dfd = per_cpu_ptr(&deferred_flush, cpu); dfd->tables = kzalloc(g_num_of_iommus * sizeof(struct deferred_flush_table), GFP_KERNEL); if (!dfd->tables) { ret = -ENOMEM; goto free_g_iommus; } spin_lock_init(&dfd->lock); setup_timer(&dfd->timer, flush_unmaps_timeout, cpu); } for_each_active_iommu(iommu, drhd) { g_iommus[iommu->seq_id] = iommu; Loading Loading @@ -3437,10 +3421,9 @@ static int __init init_dmars(void) disable_dmar_iommu(iommu); free_dmar_iommu(iommu); } free_g_iommus: for_each_possible_cpu(cpu) kfree(per_cpu_ptr(&deferred_flush, cpu)->tables); kfree(g_iommus); error: return ret; } Loading Loading @@ -3645,110 +3628,6 @@ static dma_addr_t intel_map_page(struct device *dev, struct page *page, dir, *dev->dma_mask); } static void flush_unmaps(struct deferred_flush_data *flush_data) { int i, j; flush_data->timer_on = 0; /* just flush them all */ for (i = 0; i < g_num_of_iommus; i++) { struct intel_iommu *iommu = g_iommus[i]; struct deferred_flush_table *flush_table = &flush_data->tables[i]; if (!iommu) continue; if (!flush_table->next) continue; /* In caching mode, global flushes turn emulation expensive */ if (!cap_caching_mode(iommu->cap)) iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH); for (j = 0; j < flush_table->next; j++) { unsigned long mask; struct deferred_flush_entry *entry = &flush_table->entries[j]; unsigned long iova_pfn = entry->iova_pfn; unsigned long nrpages = entry->nrpages; struct dmar_domain *domain = entry->domain; struct page *freelist = entry->freelist; /* On real hardware multiple invalidations are expensive */ if (cap_caching_mode(iommu->cap)) iommu_flush_iotlb_psi(iommu, domain, mm_to_dma_pfn(iova_pfn), nrpages, !freelist, 0); else { mask = ilog2(nrpages); iommu_flush_dev_iotlb(domain, (uint64_t)iova_pfn << PAGE_SHIFT, mask); } free_iova_fast(&domain->iovad, iova_pfn, nrpages); if (freelist) dma_free_pagelist(freelist); } flush_table->next = 0; } flush_data->size = 0; } static void flush_unmaps_timeout(unsigned long cpuid) { struct deferred_flush_data *flush_data = per_cpu_ptr(&deferred_flush, cpuid); unsigned long flags; spin_lock_irqsave(&flush_data->lock, flags); flush_unmaps(flush_data); spin_unlock_irqrestore(&flush_data->lock, flags); } static void add_unmap(struct dmar_domain *dom, unsigned long iova_pfn, unsigned long nrpages, struct page *freelist) { unsigned long flags; int entry_id, iommu_id; struct intel_iommu *iommu; struct deferred_flush_entry *entry; struct deferred_flush_data *flush_data; flush_data = raw_cpu_ptr(&deferred_flush); /* Flush all CPUs' entries to avoid deferring too much. If * this becomes a bottleneck, can just flush us, and rely on * flush timer for the rest. */ if (flush_data->size == HIGH_WATER_MARK) { int cpu; for_each_online_cpu(cpu) flush_unmaps_timeout(cpu); } spin_lock_irqsave(&flush_data->lock, flags); iommu = domain_get_iommu(dom); iommu_id = iommu->seq_id; entry_id = flush_data->tables[iommu_id].next; ++(flush_data->tables[iommu_id].next); entry = &flush_data->tables[iommu_id].entries[entry_id]; entry->domain = dom; entry->iova_pfn = iova_pfn; entry->nrpages = nrpages; entry->freelist = freelist; if (!flush_data->timer_on) { mod_timer(&flush_data->timer, jiffies + msecs_to_jiffies(10)); flush_data->timer_on = 1; } flush_data->size++; spin_unlock_irqrestore(&flush_data->lock, flags); } static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) { struct dmar_domain *domain; Loading Loading @@ -3784,7 +3663,8 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages)); dma_free_pagelist(freelist); } else { add_unmap(domain, iova_pfn, nrpages, freelist); queue_iova(&domain->iovad, iova_pfn, nrpages, (unsigned long)freelist); /* * queue up the release of the unmap to save the 1/6th of the * cpu used up by the iotlb flush operation... Loading Loading @@ -4721,7 +4601,6 @@ static void free_all_cpu_cached_iovas(unsigned int cpu) static int intel_iommu_cpu_dead(unsigned int cpu) { free_all_cpu_cached_iovas(cpu); flush_unmaps_timeout(cpu); return 0; } Loading