if (domain->force_snooping)
flags |= PASID_FLAG_PAGE_SNOOP;
+ if (!(domain->fspt.x86_64_pt.common.features &
+ BIT(PT_FEAT_DMA_INCOHERENT)))
+ flags |= PASID_FLAG_PWSNP;
+
return __domain_setup_first_level(iommu, dev, pasid,
domain_id_iommu(domain, iommu),
pt_info.gcr3_pt, flags, old);
if (!sm_supported(iommu) || !ecap_flts(iommu->ecap))
return -EINVAL;
- if (!!ecap_smpwc(iommu->ecap) !=
+ if (!ecap_smpwc(iommu->ecap) &&
!(dmar_domain->fspt.x86_64_pt.common.features &
BIT(PT_FEAT_DMA_INCOHERENT)))
return -EINVAL;
if (sm_supported(iommu) && !ecap_slts(iommu->ecap))
return -EINVAL;
- if (iommu_paging_structure_coherency(iommu) !=
+ if (!iommu_paging_structure_coherency(iommu) &&
!(dmar_domain->sspt.vtdss_pt.common.features &
BIT(PT_FEAT_DMA_INCOHERENT)))
return -EINVAL;
pasid_set_domain_id(pte, did);
pasid_set_address_width(pte, iommu->agaw);
- pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
+ pasid_set_page_snoop(pte, flags & PASID_FLAG_PWSNP);
/* Setup Present and PASID Granular Transfer Type: */
pasid_set_translation_type(pte, PASID_ENTRY_PGTT_FL_ONLY);
*/
static void pasid_pte_config_second_level(struct intel_iommu *iommu,
struct pasid_entry *pte,
- u64 pgd_val, int agaw, u16 did,
- bool dirty_tracking)
+ struct dmar_domain *domain, u16 did)
{
+ struct pt_iommu_vtdss_hw_info pt_info;
+
lockdep_assert_held(&iommu->lock);
+ pt_iommu_vtdss_hw_info(&domain->sspt, &pt_info);
pasid_clear_entry(pte);
pasid_set_domain_id(pte, did);
- pasid_set_slptr(pte, pgd_val);
- pasid_set_address_width(pte, agaw);
+ pasid_set_slptr(pte, pt_info.ssptptr);
+ pasid_set_address_width(pte, pt_info.aw);
pasid_set_translation_type(pte, PASID_ENTRY_PGTT_SL_ONLY);
pasid_set_fault_enable(pte);
- pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
- if (dirty_tracking)
+ pasid_set_page_snoop(pte, !(domain->sspt.vtdss_pt.common.features &
+ BIT(PT_FEAT_DMA_INCOHERENT)));
+ if (domain->dirty_tracking)
pasid_set_ssade(pte);
pasid_set_present(pte);
struct dmar_domain *domain,
struct device *dev, u32 pasid)
{
- struct pt_iommu_vtdss_hw_info pt_info;
struct pasid_entry *pte;
u16 did;
- pt_iommu_vtdss_hw_info(&domain->sspt, &pt_info);
/*
* If hardware advertises no support for second level
return -EBUSY;
}
- pasid_pte_config_second_level(iommu, pte, pt_info.ssptptr, pt_info.aw,
- did, domain->dirty_tracking);
+ pasid_pte_config_second_level(iommu, pte, domain, did);
spin_unlock(&iommu->lock);
pasid_flush_caches(iommu, pte, pasid, did);
struct device *dev, u16 old_did,
u32 pasid)
{
- struct pt_iommu_vtdss_hw_info pt_info;
struct pasid_entry *pte, new_pte;
u16 did;
- pt_iommu_vtdss_hw_info(&domain->sspt, &pt_info);
-
/*
* If hardware advertises no support for second level
* translation, return directly.
did = domain_id_iommu(domain, iommu);
- pasid_pte_config_second_level(iommu, &new_pte, pt_info.ssptptr,
- pt_info.aw, did, domain->dirty_tracking);
+ pasid_pte_config_second_level(iommu, &new_pte, domain, did);
spin_lock(&iommu->lock);
pte = intel_pasid_get_entry(dev, pasid);
pasid_set_fault_enable(pte);
pasid_set_domain_id(pte, did);
pasid_set_address_width(pte, pt_info.aw);
- pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
+ pasid_set_page_snoop(pte, !(s2_domain->sspt.vtdss_pt.common.features &
+ BIT(PT_FEAT_DMA_INCOHERENT)));
if (s2_domain->dirty_tracking)
pasid_set_ssade(pte);
pasid_set_translation_type(pte, PASID_ENTRY_PGTT_NESTED);