From: David Woodhouse Date: Tue, 13 Oct 2015 13:11:13 +0000 (+0100) Subject: iommu/vt-d: Implement deferred invalidate for SVM X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=907fea3491d52063bb37b1f1ce0cf8a4ae70944c;p=deliverable%2Flinux.git iommu/vt-d: Implement deferred invalidate for SVM Signed-off-by: David Woodhouse --- diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 60b66d27e655..58ecd52af43b 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4981,6 +4981,8 @@ int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sd ctx_lo |= CONTEXT_TT_PT_PASID << 2; } ctx_lo |= CONTEXT_PASIDE; + if (iommu->pasid_state_table) + ctx_lo |= CONTEXT_DINVE; context[0].lo = ctx_lo; wmb(); iommu->flush.flush_context(iommu, sdev->did, sdev->sid, diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index 82d53e15b865..a64720b5bd34 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -26,6 +26,10 @@ struct pasid_entry { u64 val; }; +struct pasid_state_entry { + u64 val; +}; + int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu) { struct page *pages; @@ -127,6 +131,11 @@ static void intel_flush_svm_range(struct intel_svm *svm, unsigned long address, { struct intel_svm_dev *sdev; + /* Try deferred invalidate if available */ + if (svm->iommu->pasid_state_table && + !cmpxchg64(&svm->iommu->pasid_state_table[svm->pasid].val, 0, 1ULL << 63)) + return; + rcu_read_lock(); list_for_each_entry_rcu(sdev, &svm->devs, list) intel_flush_svm_range_dev(svm, sdev, address, pages, ih); diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h index 0e114bfabeed..187c10299722 100644 --- a/include/linux/dma_remapping.h +++ b/include/linux/dma_remapping.h @@ -25,6 +25,7 @@ #define CONTEXT_TT_PT_PASID_DEV_IOTLB 5 #define CONTEXT_TT_MASK (7ULL << 2) +#define CONTEXT_DINVE (1ULL << 8) #define CONTEXT_PRS (1ULL << 9) #define CONTEXT_PASIDE (1ULL << 11)