diff options
Diffstat (limited to 'drivers/iommu/intel/pasid.c')
| -rw-r--r-- | drivers/iommu/intel/pasid.c | 45 | 
1 files changed, 42 insertions, 3 deletions
| diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c index f8d215d85695..cb4c1d0cf25c 100644 --- a/drivers/iommu/intel/pasid.c +++ b/drivers/iommu/intel/pasid.c @@ -710,9 +710,6 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,  	pasid_set_fault_enable(pte);  	pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap)); -	if (domain->domain.type == IOMMU_DOMAIN_UNMANAGED) -		pasid_set_pgsnp(pte); -  	/*  	 * Since it is a second level only translation setup, we should  	 * set SRE bit as well (addresses are expected to be GPAs). @@ -762,3 +759,45 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu,  	return 0;  } + +/* + * Set the page snoop control for a pasid entry which has been set up. + */ +void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu, +					  struct device *dev, u32 pasid) +{ +	struct pasid_entry *pte; +	u16 did; + +	spin_lock(&iommu->lock); +	pte = intel_pasid_get_entry(dev, pasid); +	if (WARN_ON(!pte || !pasid_pte_is_present(pte))) { +		spin_unlock(&iommu->lock); +		return; +	} + +	pasid_set_pgsnp(pte); +	did = pasid_get_domain_id(pte); +	spin_unlock(&iommu->lock); + +	if (!ecap_coherent(iommu->ecap)) +		clflush_cache_range(pte, sizeof(*pte)); + +	/* +	 * VT-d spec 3.4 table23 states guides for cache invalidation: +	 * +	 * - PASID-selective-within-Domain PASID-cache invalidation +	 * - PASID-selective PASID-based IOTLB invalidation +	 * - If (pasid is RID_PASID) +	 *    - Global Device-TLB invalidation to affected functions +	 *   Else +	 *    - PASID-based Device-TLB invalidation (with S=1 and +	 *      Addr[63:12]=0x7FFFFFFF_FFFFF) to affected functions +	 */ +	pasid_cache_invalidation_with_pasid(iommu, did, pasid); +	qi_flush_piotlb(iommu, did, pasid, 0, -1, 0); + +	/* Device IOTLB doesn't need to be flushed in caching mode. */ +	if (!cap_caching_mode(iommu->cap)) +		devtlb_invalidation_with_pasid(iommu, dev, pasid); +} | 
