Commit 70fcd359 authored by Joerg Roedel's avatar Joerg Roedel
Browse files

iommu/amd: Add helper functions to update domain->pt_root



Do not call atomic64_set() directly to update the domain page-table
root and use two new helper functions.

This makes it easier to implement additional work necessary when
the page-table is updated.

Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
Link: https://lore.kernel.org/r/20200626080547.24865-2-joro@8bytes.org
parent 9a295ff0
Loading
Loading
Loading
Loading
+20 −11
Original line number Original line Diff line number Diff line
@@ -162,7 +162,18 @@ static void amd_iommu_domain_get_pgtable(struct protection_domain *domain,
	pgtable->mode = pt_root & 7; /* lowest 3 bits encode pgtable mode */
	pgtable->mode = pt_root & 7; /* lowest 3 bits encode pgtable mode */
}
}


static u64 amd_iommu_domain_encode_pgtable(u64 *root, int mode)
static void amd_iommu_domain_set_pt_root(struct protection_domain *domain, u64 root)
{
	atomic64_set(&domain->pt_root, root);
}

static void amd_iommu_domain_clr_pt_root(struct protection_domain *domain)
{
	amd_iommu_domain_set_pt_root(domain, 0);
}

static void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
					 u64 *root, int mode)
{
{
	u64 pt_root;
	u64 pt_root;


@@ -170,7 +181,7 @@ static u64 amd_iommu_domain_encode_pgtable(u64 *root, int mode)
	pt_root = mode & 7;
	pt_root = mode & 7;
	pt_root |= (u64)root;
	pt_root |= (u64)root;


	return pt_root;
	amd_iommu_domain_set_pt_root(domain, pt_root);
}
}


static struct iommu_dev_data *alloc_dev_data(u16 devid)
static struct iommu_dev_data *alloc_dev_data(u16 devid)
@@ -1410,7 +1421,7 @@ static bool increase_address_space(struct protection_domain *domain,
	struct domain_pgtable pgtable;
	struct domain_pgtable pgtable;
	unsigned long flags;
	unsigned long flags;
	bool ret = true;
	bool ret = true;
	u64 *pte, root;
	u64 *pte;


	spin_lock_irqsave(&domain->lock, flags);
	spin_lock_irqsave(&domain->lock, flags);


@@ -1438,8 +1449,7 @@ static bool increase_address_space(struct protection_domain *domain,
	 * Device Table needs to be updated and flushed before the new root can
	 * Device Table needs to be updated and flushed before the new root can
	 * be published.
	 * be published.
	 */
	 */
	root = amd_iommu_domain_encode_pgtable(pte, pgtable.mode);
	amd_iommu_domain_set_pgtable(domain, pte, pgtable.mode);
	atomic64_set(&domain->pt_root, root);


	ret = true;
	ret = true;


@@ -2319,7 +2329,7 @@ static void protection_domain_free(struct protection_domain *domain)
		domain_id_free(domain->id);
		domain_id_free(domain->id);


	amd_iommu_domain_get_pgtable(domain, &pgtable);
	amd_iommu_domain_get_pgtable(domain, &pgtable);
	atomic64_set(&domain->pt_root, 0);
	amd_iommu_domain_clr_pt_root(domain);
	free_pagetable(&pgtable);
	free_pagetable(&pgtable);


	kfree(domain);
	kfree(domain);
@@ -2327,7 +2337,7 @@ static void protection_domain_free(struct protection_domain *domain)


static int protection_domain_init(struct protection_domain *domain, int mode)
static int protection_domain_init(struct protection_domain *domain, int mode)
{
{
	u64 *pt_root = NULL, root;
	u64 *pt_root = NULL;


	BUG_ON(mode < PAGE_MODE_NONE || mode > PAGE_MODE_6_LEVEL);
	BUG_ON(mode < PAGE_MODE_NONE || mode > PAGE_MODE_6_LEVEL);


@@ -2343,8 +2353,7 @@ static int protection_domain_init(struct protection_domain *domain, int mode)
			return -ENOMEM;
			return -ENOMEM;
	}
	}


	root = amd_iommu_domain_encode_pgtable(pt_root, mode);
	amd_iommu_domain_set_pgtable(domain, pt_root, mode);
	atomic64_set(&domain->pt_root, root);


	return 0;
	return 0;
}
}
@@ -2713,8 +2722,8 @@ void amd_iommu_domain_direct_map(struct iommu_domain *dom)
	/* First save pgtable configuration*/
	/* First save pgtable configuration*/
	amd_iommu_domain_get_pgtable(domain, &pgtable);
	amd_iommu_domain_get_pgtable(domain, &pgtable);


	/* Update data structure */
	/* Remove page-table from domain */
	atomic64_set(&domain->pt_root, 0);
	amd_iommu_domain_clr_pt_root(domain);


	/* Make changes visible to IOMMUs */
	/* Make changes visible to IOMMUs */
	update_domain(domain);
	update_domain(domain);