Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46ac18c3 authored by Joerg Roedel's avatar Joerg Roedel
Browse files

iommu/amd: Check PM_LEVEL_SIZE() condition in locked section



The increase_address_space() function has to check the PM_LEVEL_SIZE()
condition again under the domain->lock to avoid a false trigger of the
WARN_ON_ONCE() and to avoid that the address space is increase more
often than necessary.

Reported-by: default avatarQian Cai <cai@lca.pw>
Fixes: 754265bc ("iommu/amd: Fix race in increase_address_space()")
Reviewed-by: default avatarJerry Snitselaar <jsnitsel@redhat.com>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent ec21f17a
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -1464,6 +1464,7 @@ static void free_pagetable(struct protection_domain *domain)
 * to 64 bits.
 */
static bool increase_address_space(struct protection_domain *domain,
				   unsigned long address,
				   gfp_t gfp)
{
	unsigned long flags;
@@ -1472,8 +1473,8 @@ static bool increase_address_space(struct protection_domain *domain,

	spin_lock_irqsave(&domain->lock, flags);

	if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
		/* address space already 64 bit large */
	if (address <= PM_LEVEL_SIZE(domain->mode) ||
	    WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
		goto out;

	pte = (void *)get_zeroed_page(gfp);
@@ -1506,7 +1507,7 @@ static u64 *alloc_pte(struct protection_domain *domain,
	BUG_ON(!is_power_of_2(page_size));

	while (address > PM_LEVEL_SIZE(domain->mode))
		*updated = increase_address_space(domain, gfp) || *updated;
		*updated = increase_address_space(domain, address, gfp) || *updated;

	level   = domain->mode - 1;
	pte     = &domain->pt_root[PM_LEVEL_INDEX(level, address)];