|
10 | 10 | #include "iommu-priv.h" |
11 | 11 |
|
12 | 12 | static DEFINE_MUTEX(iommu_sva_lock); |
| 13 | +static bool iommu_sva_present; |
| 14 | +static LIST_HEAD(iommu_sva_mms); |
13 | 15 | static struct iommu_domain *iommu_sva_domain_alloc(struct device *dev, |
14 | 16 | struct mm_struct *mm); |
15 | 17 |
|
@@ -42,6 +44,7 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de |
42 | 44 | return ERR_PTR(-ENOSPC); |
43 | 45 | } |
44 | 46 | iommu_mm->pasid = pasid; |
| 47 | + iommu_mm->mm = mm; |
45 | 48 | INIT_LIST_HEAD(&iommu_mm->sva_domains); |
46 | 49 | /* |
47 | 50 | * Make sure the write to mm->iommu_mm is not reordered in front of |
@@ -77,9 +80,6 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm |
77 | 80 | if (!group) |
78 | 81 | return ERR_PTR(-ENODEV); |
79 | 82 |
|
80 | | - if (IS_ENABLED(CONFIG_X86)) |
81 | | - return ERR_PTR(-EOPNOTSUPP); |
82 | | - |
83 | 83 | mutex_lock(&iommu_sva_lock); |
84 | 84 |
|
85 | 85 | /* Allocate mm->pasid if necessary. */ |
@@ -135,8 +135,13 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm |
135 | 135 | if (ret) |
136 | 136 | goto out_free_domain; |
137 | 137 | domain->users = 1; |
138 | | - list_add(&domain->next, &mm->iommu_mm->sva_domains); |
139 | 138 |
|
| 139 | + if (list_empty(&iommu_mm->sva_domains)) { |
| 140 | + if (list_empty(&iommu_sva_mms)) |
| 141 | + iommu_sva_present = true; |
| 142 | + list_add(&iommu_mm->mm_list_elm, &iommu_sva_mms); |
| 143 | + } |
| 144 | + list_add(&domain->next, &iommu_mm->sva_domains); |
140 | 145 | out: |
141 | 146 | refcount_set(&handle->users, 1); |
142 | 147 | mutex_unlock(&iommu_sva_lock); |
@@ -178,6 +183,13 @@ void iommu_sva_unbind_device(struct iommu_sva *handle) |
178 | 183 | list_del(&domain->next); |
179 | 184 | iommu_domain_free(domain); |
180 | 185 | } |
| 186 | + |
| 187 | + if (list_empty(&iommu_mm->sva_domains)) { |
| 188 | + list_del(&iommu_mm->mm_list_elm); |
| 189 | + if (list_empty(&iommu_sva_mms)) |
| 190 | + iommu_sva_present = false; |
| 191 | + } |
| 192 | + |
181 | 193 | mutex_unlock(&iommu_sva_lock); |
182 | 194 | kfree(handle); |
183 | 195 | } |
@@ -315,3 +327,15 @@ static struct iommu_domain *iommu_sva_domain_alloc(struct device *dev, |
315 | 327 |
|
316 | 328 | return domain; |
317 | 329 | } |
| 330 | + |
| 331 | +void iommu_sva_invalidate_kva_range(unsigned long start, unsigned long end) |
| 332 | +{ |
| 333 | + struct iommu_mm_data *iommu_mm; |
| 334 | + |
| 335 | + guard(mutex)(&iommu_sva_lock); |
| 336 | + if (!iommu_sva_present) |
| 337 | + return; |
| 338 | + |
| 339 | + list_for_each_entry(iommu_mm, &iommu_sva_mms, mm_list_elm) |
| 340 | + mmu_notifier_arch_invalidate_secondary_tlbs(iommu_mm->mm, start, end); |
| 341 | +} |
0 commit comments