iommu/vt-d: Implement deferred invalidate for SVM
authorDavid Woodhouse <David.Woodhouse@intel.com>
Tue, 13 Oct 2015 13:11:13 +0000 (14:11 +0100)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Thu, 15 Oct 2015 12:22:35 +0000 (13:22 +0100)
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
drivers/iommu/intel-iommu.c
drivers/iommu/intel-svm.c
include/linux/dma_remapping.h

index 60b66d2..58ecd52 100644 (file)
@@ -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,
index 82d53e1..a64720b 100644 (file)
@@ -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);
index 0e114bf..187c102 100644 (file)
@@ -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)