diff options
Diffstat (limited to 'drivers/iommu/intel/pasid.c')
| -rw-r--r-- | drivers/iommu/intel/pasid.c | 20 | 
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c index fb3c7020028d..633e0a4a01e7 100644 --- a/drivers/iommu/intel/pasid.c +++ b/drivers/iommu/intel/pasid.c @@ -128,6 +128,9 @@ int intel_pasid_alloc_table(struct device *dev)  	pasid_table->max_pasid = 1 << (order + PAGE_SHIFT + 3);  	info->pasid_table = pasid_table; +	if (!ecap_coherent(info->iommu->ecap)) +		clflush_cache_range(pasid_table->table, size); +  	return 0;  } @@ -200,7 +203,7 @@ static struct pasid_entry *intel_pasid_get_entry(struct device *dev, u32 pasid)  retry:  	entries = get_pasid_table_from_pde(&dir[dir_index]);  	if (!entries) { -		entries = alloc_pgtable_page(info->iommu->node); +		entries = alloc_pgtable_page(info->iommu->node, GFP_ATOMIC);  		if (!entries)  			return NULL; @@ -215,6 +218,10 @@ retry:  			free_pgtable_page(entries);  			goto retry;  		} +		if (!ecap_coherent(info->iommu->ecap)) { +			clflush_cache_range(entries, VTD_PAGE_SIZE); +			clflush_cache_range(&dir[dir_index].val, sizeof(*dir)); +		}  	}  	return &entries[index]; @@ -365,6 +372,16 @@ static inline void pasid_set_page_snoop(struct pasid_entry *pe, bool value)  }  /* + * Setup No Execute Enable bit (Bit 133) of a scalable mode PASID + * entry. It is required when XD bit of the first level page table + * entry is about to be set. + */ +static inline void pasid_set_nxe(struct pasid_entry *pe) +{ +	pasid_set_bits(&pe->val[2], 1 << 5, 1 << 5); +} + +/*   * Setup the Page Snoop (PGSNP) field (Bit 88) of a scalable mode   * PASID entry.   */ @@ -557,6 +574,7 @@ int intel_pasid_setup_first_level(struct intel_iommu *iommu,  	pasid_set_domain_id(pte, did);  	pasid_set_address_width(pte, iommu->agaw);  	pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap)); +	pasid_set_nxe(pte);  	/* Setup Present and PASID Granular Transfer Type: */  	pasid_set_translation_type(pte, PASID_ENTRY_PGTT_FL_ONLY);  |