/* Check if an existing cache tag can be reused for a new association. */ staticbool cache_tage_match(struct cache_tag *tag, u16 domain_id, struct intel_iommu *iommu, struct device *dev,
ioasid_t pasid, enum cache_tag_type type)
{ if (tag->type != type) returnfalse;
if (tag->domain_id != domain_id || tag->pasid != pasid) returnfalse;
if (type == CACHE_TAG_IOTLB || type == CACHE_TAG_NESTING_IOTLB) return tag->iommu == iommu;
if (type == CACHE_TAG_DEVTLB || type == CACHE_TAG_NESTING_DEVTLB) return tag->dev == dev;
returnfalse;
}
/* Assign a cache tag with specified type to domain. */ int cache_tag_assign(struct dmar_domain *domain, u16 did, struct device *dev,
ioasid_t pasid, enum cache_tag_type type)
{ struct device_domain_info *info = dev_iommu_priv_get(dev); struct intel_iommu *iommu = info->iommu; struct cache_tag *tag, *temp; struct list_head *prev; unsignedlong flags;
tag = kzalloc(sizeof(*tag), GFP_KERNEL); if (!tag) return -ENOMEM;
/* domain->qi_batch will be freed in iommu_free_domain() path. */ staticint domain_qi_batch_alloc(struct dmar_domain *domain)
{ unsignedlong flags; int ret = 0;
spin_lock_irqsave(&domain->cache_lock, flags); if (domain->qi_batch) goto out_unlock;
domain->qi_batch = kzalloc(sizeof(*domain->qi_batch), GFP_ATOMIC); if (!domain->qi_batch)
ret = -ENOMEM;
out_unlock:
spin_unlock_irqrestore(&domain->cache_lock, flags);
/* * The driver assigns different domain IDs for all domains except * the SVA type.
*/ if (domain->domain.type == IOMMU_DOMAIN_SVA) return FLPT_DEFAULT_DID;
return domain_id_iommu(domain, iommu);
}
/* * Assign cache tags to a domain when it's associated with a device's * PASID using a specific domain ID. * * On success (return value of 0), cache tags are created and added to the * domain's cache tag list. On failure (negative return value), an error * code is returned indicating the reason for the failure.
*/ int cache_tag_assign_domain(struct dmar_domain *domain, struct device *dev, ioasid_t pasid)
{
u16 did = domain_get_id_for_dev(domain, dev); int ret;
ret = __cache_tag_assign_domain(domain, did, dev, pasid); if (ret || domain->domain.type != IOMMU_DOMAIN_NESTED) return ret;
ret = __cache_tag_assign_parent_domain(domain->s2_domain, did, dev, pasid); if (ret)
__cache_tag_unassign_domain(domain, did, dev, pasid);
return ret;
}
/* * Remove the cache tags associated with a device's PASID when the domain is * detached from the device. * * The cache tags must be previously assigned to the domain by calling the * assign interface.
*/ void cache_tag_unassign_domain(struct dmar_domain *domain, struct device *dev, ioasid_t pasid)
{
u16 did = domain_get_id_for_dev(domain, dev);
/* * PSI masks the low order bits of the base address. If the * address isn't aligned to the mask, then compute a mask value * needed to ensure the target range is flushed.
*/ if (unlikely(bitmask & pfn)) { unsignedlong end_pfn = pfn + pages - 1, shared_bits;
/* * Since end_pfn <= pfn + bitmask, the only way bits * higher than bitmask can differ in pfn and end_pfn is * by carrying. This means after masking out bitmask, * high bits starting with the first set bit in * shared_bits are all equal in both pfn and end_pfn.
*/
shared_bits = ~(pfn ^ end_pfn) & ~bitmask;
mask = shared_bits ? __ffs(shared_bits) : MAX_AGAW_PFN_WIDTH;
aligned_pages = 1UL << mask;
}
/* * Fallback to domain selective flush if no PSI support or the size * is too big.
*/ if (!cap_pgsel_inv(iommu->cap) ||
mask > cap_max_amask_val(iommu->cap) || pages == -1) {
addr = 0;
mask = 0;
ih = 0;
type = DMA_TLB_DSI_FLUSH;
}
/* * Invalidates a range of IOVA from @start (inclusive) to @end (inclusive) * when the memory mappings in the target domain have been modified.
*/ void cache_tag_flush_range(struct dmar_domain *domain, unsignedlong start, unsignedlong end, int ih)
{ struct intel_iommu *iommu = NULL; unsignedlong pages, mask, addr; struct cache_tag *tag; unsignedlong flags;
switch (tag->type) { case CACHE_TAG_IOTLB: case CACHE_TAG_NESTING_IOTLB:
cache_tag_flush_iotlb(domain, tag, addr, pages, mask, ih); break; case CACHE_TAG_NESTING_DEVTLB: /* * Address translation cache in device side caches the * result of nested translation. There is no easy way * to identify the exact set of nested translations * affected by a change in S2. So just flush the entire * device cache.
*/
addr = 0;
mask = MAX_AGAW_PFN_WIDTH;
fallthrough; case CACHE_TAG_DEVTLB:
cache_tag_flush_devtlb_psi(domain, tag, addr, mask); break;
}
/* * Invalidates all ranges of IOVA when the memory mappings in the target * domain have been modified.
*/ void cache_tag_flush_all(struct dmar_domain *domain)
{
cache_tag_flush_range(domain, 0, ULONG_MAX, 0);
}
/* * Invalidate a range of IOVA when new mappings are created in the target * domain. * * - VT-d spec, Section 6.1 Caching Mode: When the CM field is reported as * Set, any software updates to remapping structures other than first- * stage mapping requires explicit invalidation of the caches. * - VT-d spec, Section 6.8 Write Buffer Flushing: For hardware that requires * write buffer flushing, software must explicitly perform write-buffer * flushing, if cache invalidation is not required.
*/ void cache_tag_flush_range_np(struct dmar_domain *domain, unsignedlong start, unsignedlong end)
{ struct intel_iommu *iommu = NULL; unsignedlong pages, mask, addr; struct cache_tag *tag; unsignedlong flags;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.