| .. | .. |
|---|
| 24 | 24 | /* |
|---|
| 25 | 25 | * Intel IOMMU system wide PASID name space: |
|---|
| 26 | 26 | */ |
|---|
| 27 | | -static DEFINE_SPINLOCK(pasid_lock); |
|---|
| 28 | 27 | u32 intel_pasid_max_id = PASID_MAX; |
|---|
| 29 | 28 | |
|---|
| 30 | 29 | int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid) |
|---|
| .. | .. |
|---|
| 187 | 186 | attach_out: |
|---|
| 188 | 187 | device_attach_pasid_table(info, pasid_table); |
|---|
| 189 | 188 | |
|---|
| 189 | + if (!ecap_coherent(info->iommu->ecap)) |
|---|
| 190 | + clflush_cache_range(pasid_table->table, (1 << order) * PAGE_SIZE); |
|---|
| 191 | + |
|---|
| 190 | 192 | return 0; |
|---|
| 191 | 193 | } |
|---|
| 192 | 194 | |
|---|
| .. | .. |
|---|
| 259 | 261 | dir_index = pasid >> PASID_PDE_SHIFT; |
|---|
| 260 | 262 | index = pasid & PASID_PTE_MASK; |
|---|
| 261 | 263 | |
|---|
| 262 | | - spin_lock(&pasid_lock); |
|---|
| 264 | +retry: |
|---|
| 263 | 265 | entries = get_pasid_table_from_pde(&dir[dir_index]); |
|---|
| 264 | 266 | if (!entries) { |
|---|
| 265 | 267 | entries = alloc_pgtable_page(info->iommu->node); |
|---|
| 266 | | - if (!entries) { |
|---|
| 267 | | - spin_unlock(&pasid_lock); |
|---|
| 268 | + if (!entries) |
|---|
| 268 | 269 | return NULL; |
|---|
| 269 | | - } |
|---|
| 270 | 270 | |
|---|
| 271 | | - WRITE_ONCE(dir[dir_index].val, |
|---|
| 272 | | - (u64)virt_to_phys(entries) | PASID_PTE_PRESENT); |
|---|
| 271 | + /* |
|---|
| 272 | + * The pasid directory table entry won't be freed after |
|---|
| 273 | + * allocation. No worry about the race with free and |
|---|
| 274 | + * clear. However, this entry might be populated by others |
|---|
| 275 | + * while we are preparing it. Use theirs with a retry. |
|---|
| 276 | + */ |
|---|
| 277 | + if (cmpxchg64(&dir[dir_index].val, 0ULL, |
|---|
| 278 | + (u64)virt_to_phys(entries) | PASID_PTE_PRESENT)) { |
|---|
| 279 | + free_pgtable_page(entries); |
|---|
| 280 | + goto retry; |
|---|
| 281 | + } |
|---|
| 282 | + if (!ecap_coherent(info->iommu->ecap)) { |
|---|
| 283 | + clflush_cache_range(entries, VTD_PAGE_SIZE); |
|---|
| 284 | + clflush_cache_range(&dir[dir_index].val, sizeof(*dir)); |
|---|
| 285 | + } |
|---|
| 273 | 286 | } |
|---|
| 274 | | - spin_unlock(&pasid_lock); |
|---|
| 275 | 287 | |
|---|
| 276 | 288 | return &entries[index]; |
|---|
| 277 | 289 | } |
|---|