Commit e5b0feb4 authored by Lu Baolu's avatar Lu Baolu Committed by Joerg Roedel
Browse files

iommu/vt-d: Use real field for indication of first level



The dmar_domain uses bit field members to indicate the behaviors. Add
a bit field for using first level and remove the flags member to avoid
duplication.

Signed-off-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Link: https://lore.kernel.org/r/20221118132451.114406-8-baolu.lu@linux.intel.com


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent b1cf1563
Loading
Loading
Loading
Loading
+10 −15
Original line number Diff line number Diff line
@@ -383,11 +383,6 @@ static inline int domain_type_is_si(struct dmar_domain *domain)
	return domain->domain.type == IOMMU_DOMAIN_IDENTITY;
}

static inline bool domain_use_first_level(struct dmar_domain *domain)
{
	return domain->flags & DOMAIN_FLAG_USE_FIRST_LEVEL;
}

static inline int domain_pfn_supported(struct dmar_domain *domain,
				       unsigned long pfn)
{
@@ -501,7 +496,7 @@ static int domain_update_iommu_superpage(struct dmar_domain *domain,
	rcu_read_lock();
	for_each_active_iommu(iommu, drhd) {
		if (iommu != skip) {
			if (domain && domain_use_first_level(domain)) {
			if (domain && domain->use_first_level) {
				if (!cap_fl1gp_support(iommu->cap))
					mask = 0x1;
			} else {
@@ -579,7 +574,7 @@ static void domain_update_iommu_cap(struct dmar_domain *domain)
	 * paging and 57-bits with 5-level paging). Hence, skip bit
	 * [N-1].
	 */
	if (domain_use_first_level(domain))
	if (domain->use_first_level)
		domain->domain.geometry.aperture_end = __DOMAIN_MAX_ADDR(domain->gaw - 1);
	else
		domain->domain.geometry.aperture_end = __DOMAIN_MAX_ADDR(domain->gaw);
@@ -947,7 +942,7 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,

			domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
			pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
			if (domain_use_first_level(domain))
			if (domain->use_first_level)
				pteval |= DMA_FL_PTE_XD | DMA_FL_PTE_US | DMA_FL_PTE_ACCESS;

			if (cmpxchg64(&pte->val, 0ULL, pteval))
@@ -1498,7 +1493,7 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
	if (ih)
		ih = 1 << 6;

	if (domain_use_first_level(domain)) {
	if (domain->use_first_level) {
		qi_flush_piotlb(iommu, did, PASID_RID2PASID, addr, pages, ih);
	} else {
		unsigned long bitmask = aligned_pages - 1;
@@ -1552,7 +1547,7 @@ static inline void __mapping_notify_one(struct intel_iommu *iommu,
	 * It's a non-present to present mapping. Only flush if caching mode
	 * and second level.
	 */
	if (cap_caching_mode(iommu->cap) && !domain_use_first_level(domain))
	if (cap_caching_mode(iommu->cap) && !domain->use_first_level)
		iommu_flush_iotlb_psi(iommu, domain, pfn, pages, 0, 1);
	else
		iommu_flush_write_buffer(iommu);
@@ -1568,7 +1563,7 @@ static void intel_flush_iotlb_all(struct iommu_domain *domain)
		struct intel_iommu *iommu = info->iommu;
		u16 did = domain_id_iommu(dmar_domain, iommu);

		if (domain_use_first_level(dmar_domain))
		if (dmar_domain->use_first_level)
			qi_flush_piotlb(iommu, did, PASID_RID2PASID, 0, -1, 0);
		else
			iommu->flush.flush_iotlb(iommu, did, 0, 0,
@@ -1741,7 +1736,7 @@ static struct dmar_domain *alloc_domain(unsigned int type)

	domain->nid = NUMA_NO_NODE;
	if (first_level_by_default(type))
		domain->flags |= DOMAIN_FLAG_USE_FIRST_LEVEL;
		domain->use_first_level = true;
	domain->has_iotlb_device = false;
	INIT_LIST_HEAD(&domain->devices);
	spin_lock_init(&domain->lock);
@@ -2173,7 +2168,7 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,

	attr = prot & (DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP);
	attr |= DMA_FL_PTE_PRESENT;
	if (domain_use_first_level(domain)) {
	if (domain->use_first_level) {
		attr |= DMA_FL_PTE_XD | DMA_FL_PTE_US | DMA_FL_PTE_ACCESS;
		if (prot & DMA_PTE_WRITE)
			attr |= DMA_FL_PTE_DIRTY;
@@ -2443,7 +2438,7 @@ static int dmar_domain_attach_device(struct dmar_domain *domain,
		if (hw_pass_through && domain_type_is_si(domain))
			ret = intel_pasid_setup_pass_through(iommu, domain,
					dev, PASID_RID2PASID);
		else if (domain_use_first_level(domain))
		else if (domain->use_first_level)
			ret = domain_setup_first_level(iommu, domain, dev,
					PASID_RID2PASID);
		else
@@ -4412,7 +4407,7 @@ static void domain_set_force_snooping(struct dmar_domain *domain)
	 * Second level page table supports per-PTE snoop control. The
	 * iommu_map() interface will handle this by setting SNP bit.
	 */
	if (!domain_use_first_level(domain)) {
	if (!domain->use_first_level) {
		domain->set_pte_snp = true;
		return;
	}
+5 −10
Original line number Diff line number Diff line
@@ -517,14 +517,6 @@ struct context_entry {
	u64 hi;
};

/*
 * When VT-d works in the scalable mode, it allows DMA translation to
 * happen through either first level or second level page table. This
 * bit marks that the DMA translation for the domain goes through the
 * first level page table, otherwise, it goes through the second level.
 */
#define DOMAIN_FLAG_USE_FIRST_LEVEL		BIT(1)

struct iommu_domain_info {
	struct intel_iommu *iommu;
	unsigned int refcnt;		/* Refcount of devices per iommu */
@@ -541,6 +533,11 @@ struct dmar_domain {
	u8 iommu_coherency: 1;		/* indicate coherency of iommu access */
	u8 force_snooping : 1;		/* Create IOPTEs with snoop control */
	u8 set_pte_snp:1;
	u8 use_first_level:1;		/* DMA translation for the domain goes
					 * through the first level page table,
					 * otherwise, goes through the second
					 * level.
					 */

	spinlock_t lock;		/* Protect device tracking lists */
	struct list_head devices;	/* all devices' list */
@@ -550,8 +547,6 @@ struct dmar_domain {

	/* adjusted guest address width, 0 is level 2 30-bit */
	int		agaw;

	int		flags;		/* flags to find out type of domain */
	int		iommu_superpage;/* Level of superpages supported:
					   0 == 4KiB (no superpages), 1 == 2MiB,
					   2 == 1GiB, 3 == 512GiB, 4 == 1TiB */