Skip to content

Commit 3297d04

Browse files
TinaZhangZWjoergroedel
authored andcommitted
iommu/vt-d: Refactor IOTLB and Dev-IOTLB flush for batching
Extracts IOTLB and Dev-IOTLB invalidation logic from cache tag flush interfaces into dedicated helper functions. It prepares the codebase for upcoming changes to support batched cache invalidations. To enable direct use of qi_flush helpers in the new functions, iommu->flush.flush_iotlb and quirk_extra_dev_tlb_flush() are opened up. No functional changes are intended. Co-developed-by: Lu Baolu <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Signed-off-by: Tina Zhang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent f701c9f commit 3297d04

File tree

3 files changed

+83
-67
lines changed

3 files changed

+83
-67
lines changed

drivers/iommu/intel/cache.c

Lines changed: 78 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,78 @@ static unsigned long calculate_psi_aligned_address(unsigned long start,
255255
return ALIGN_DOWN(start, VTD_PAGE_SIZE << mask);
256256
}
257257

258+
static void cache_tag_flush_iotlb(struct dmar_domain *domain, struct cache_tag *tag,
259+
unsigned long addr, unsigned long pages,
260+
unsigned long mask, int ih)
261+
{
262+
struct intel_iommu *iommu = tag->iommu;
263+
u64 type = DMA_TLB_PSI_FLUSH;
264+
265+
if (domain->use_first_level) {
266+
qi_flush_piotlb(iommu, tag->domain_id, tag->pasid, addr, pages, ih);
267+
return;
268+
}
269+
270+
/*
271+
* Fallback to domain selective flush if no PSI support or the size
272+
* is too big.
273+
*/
274+
if (!cap_pgsel_inv(iommu->cap) ||
275+
mask > cap_max_amask_val(iommu->cap) || pages == -1) {
276+
addr = 0;
277+
mask = 0;
278+
ih = 0;
279+
type = DMA_TLB_DSI_FLUSH;
280+
}
281+
282+
if (ecap_qis(iommu->ecap))
283+
qi_flush_iotlb(iommu, tag->domain_id, addr | ih, mask, type);
284+
else
285+
__iommu_flush_iotlb(iommu, tag->domain_id, addr | ih, mask, type);
286+
}
287+
288+
static void cache_tag_flush_devtlb_psi(struct dmar_domain *domain, struct cache_tag *tag,
289+
unsigned long addr, unsigned long mask)
290+
{
291+
struct intel_iommu *iommu = tag->iommu;
292+
struct device_domain_info *info;
293+
u16 sid;
294+
295+
info = dev_iommu_priv_get(tag->dev);
296+
sid = PCI_DEVID(info->bus, info->devfn);
297+
298+
if (tag->pasid == IOMMU_NO_PASID) {
299+
qi_flush_dev_iotlb(iommu, sid, info->pfsid, info->ats_qdep,
300+
addr, mask);
301+
if (info->dtlb_extra_inval)
302+
qi_flush_dev_iotlb(iommu, sid, info->pfsid,
303+
info->ats_qdep, addr, mask);
304+
return;
305+
}
306+
307+
qi_flush_dev_iotlb_pasid(iommu, sid, info->pfsid, tag->pasid,
308+
info->ats_qdep, addr, mask);
309+
if (info->dtlb_extra_inval)
310+
qi_flush_dev_iotlb_pasid(iommu, sid, info->pfsid, tag->pasid,
311+
info->ats_qdep, addr, mask);
312+
}
313+
314+
static void cache_tag_flush_devtlb_all(struct dmar_domain *domain, struct cache_tag *tag)
315+
{
316+
struct intel_iommu *iommu = tag->iommu;
317+
struct device_domain_info *info;
318+
u16 sid;
319+
320+
info = dev_iommu_priv_get(tag->dev);
321+
sid = PCI_DEVID(info->bus, info->devfn);
322+
323+
qi_flush_dev_iotlb(iommu, sid, info->pfsid, info->ats_qdep, 0,
324+
MAX_AGAW_PFN_WIDTH);
325+
if (info->dtlb_extra_inval)
326+
qi_flush_dev_iotlb(iommu, sid, info->pfsid, info->ats_qdep, 0,
327+
MAX_AGAW_PFN_WIDTH);
328+
}
329+
258330
/*
259331
* Invalidates a range of IOVA from @start (inclusive) to @end (inclusive)
260332
* when the memory mappings in the target domain have been modified.
@@ -270,30 +342,10 @@ void cache_tag_flush_range(struct dmar_domain *domain, unsigned long start,
270342

271343
spin_lock_irqsave(&domain->cache_lock, flags);
272344
list_for_each_entry(tag, &domain->cache_tags, node) {
273-
struct intel_iommu *iommu = tag->iommu;
274-
struct device_domain_info *info;
275-
u16 sid;
276-
277345
switch (tag->type) {
278346
case CACHE_TAG_IOTLB:
279347
case CACHE_TAG_NESTING_IOTLB:
280-
if (domain->use_first_level) {
281-
qi_flush_piotlb(iommu, tag->domain_id,
282-
tag->pasid, addr, pages, ih);
283-
} else {
284-
/*
285-
* Fallback to domain selective flush if no
286-
* PSI support or the size is too big.
287-
*/
288-
if (!cap_pgsel_inv(iommu->cap) ||
289-
mask > cap_max_amask_val(iommu->cap))
290-
iommu->flush.flush_iotlb(iommu, tag->domain_id,
291-
0, 0, DMA_TLB_DSI_FLUSH);
292-
else
293-
iommu->flush.flush_iotlb(iommu, tag->domain_id,
294-
addr | ih, mask,
295-
DMA_TLB_PSI_FLUSH);
296-
}
348+
cache_tag_flush_iotlb(domain, tag, addr, pages, mask, ih);
297349
break;
298350
case CACHE_TAG_NESTING_DEVTLB:
299351
/*
@@ -307,18 +359,7 @@ void cache_tag_flush_range(struct dmar_domain *domain, unsigned long start,
307359
mask = MAX_AGAW_PFN_WIDTH;
308360
fallthrough;
309361
case CACHE_TAG_DEVTLB:
310-
info = dev_iommu_priv_get(tag->dev);
311-
sid = PCI_DEVID(info->bus, info->devfn);
312-
313-
if (tag->pasid == IOMMU_NO_PASID)
314-
qi_flush_dev_iotlb(iommu, sid, info->pfsid,
315-
info->ats_qdep, addr, mask);
316-
else
317-
qi_flush_dev_iotlb_pasid(iommu, sid, info->pfsid,
318-
tag->pasid, info->ats_qdep,
319-
addr, mask);
320-
321-
quirk_extra_dev_tlb_flush(info, addr, mask, tag->pasid, info->ats_qdep);
362+
cache_tag_flush_devtlb_psi(domain, tag, addr, mask);
322363
break;
323364
}
324365

@@ -338,29 +379,14 @@ void cache_tag_flush_all(struct dmar_domain *domain)
338379

339380
spin_lock_irqsave(&domain->cache_lock, flags);
340381
list_for_each_entry(tag, &domain->cache_tags, node) {
341-
struct intel_iommu *iommu = tag->iommu;
342-
struct device_domain_info *info;
343-
u16 sid;
344-
345382
switch (tag->type) {
346383
case CACHE_TAG_IOTLB:
347384
case CACHE_TAG_NESTING_IOTLB:
348-
if (domain->use_first_level)
349-
qi_flush_piotlb(iommu, tag->domain_id,
350-
tag->pasid, 0, -1, 0);
351-
else
352-
iommu->flush.flush_iotlb(iommu, tag->domain_id,
353-
0, 0, DMA_TLB_DSI_FLUSH);
385+
cache_tag_flush_iotlb(domain, tag, 0, -1, 0, 0);
354386
break;
355387
case CACHE_TAG_DEVTLB:
356388
case CACHE_TAG_NESTING_DEVTLB:
357-
info = dev_iommu_priv_get(tag->dev);
358-
sid = PCI_DEVID(info->bus, info->devfn);
359-
360-
qi_flush_dev_iotlb(iommu, sid, info->pfsid, info->ats_qdep,
361-
0, MAX_AGAW_PFN_WIDTH);
362-
quirk_extra_dev_tlb_flush(info, 0, MAX_AGAW_PFN_WIDTH,
363-
IOMMU_NO_PASID, info->ats_qdep);
389+
cache_tag_flush_devtlb_all(domain, tag);
364390
break;
365391
}
366392

@@ -399,20 +425,8 @@ void cache_tag_flush_range_np(struct dmar_domain *domain, unsigned long start,
399425
}
400426

401427
if (tag->type == CACHE_TAG_IOTLB ||
402-
tag->type == CACHE_TAG_NESTING_IOTLB) {
403-
/*
404-
* Fallback to domain selective flush if no
405-
* PSI support or the size is too big.
406-
*/
407-
if (!cap_pgsel_inv(iommu->cap) ||
408-
mask > cap_max_amask_val(iommu->cap))
409-
iommu->flush.flush_iotlb(iommu, tag->domain_id,
410-
0, 0, DMA_TLB_DSI_FLUSH);
411-
else
412-
iommu->flush.flush_iotlb(iommu, tag->domain_id,
413-
addr, mask,
414-
DMA_TLB_PSI_FLUSH);
415-
}
428+
tag->type == CACHE_TAG_NESTING_IOTLB)
429+
cache_tag_flush_iotlb(domain, tag, addr, pages, mask, 0);
416430

417431
trace_cache_tag_flush_range_np(tag, start, end, addr, pages, mask);
418432
}

drivers/iommu/intel/iommu.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,9 +1184,8 @@ static void __iommu_flush_context(struct intel_iommu *iommu,
11841184
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
11851185
}
11861186

1187-
/* return value determine if we need a write buffer flush */
1188-
static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1189-
u64 addr, unsigned int size_order, u64 type)
1187+
void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
1188+
unsigned int size_order, u64 type)
11901189
{
11911190
int tlb_offset = ecap_iotlb_offset(iommu->ecap);
11921191
u64 val = 0, val_iva = 0;

drivers/iommu/intel/iommu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,9 @@ void qi_flush_pasid_cache(struct intel_iommu *iommu, u16 did, u64 granu,
12061206

12071207
int qi_submit_sync(struct intel_iommu *iommu, struct qi_desc *desc,
12081208
unsigned int count, unsigned long options);
1209+
1210+
void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
1211+
unsigned int size_order, u64 type);
12091212
/*
12101213
* Options used in qi_submit_sync:
12111214
* QI_OPT_WAIT_DRAIN - Wait for PRQ drain completion, spec 6.5.2.8.

0 commit comments

Comments
 (0)