Commit 4ba2fdff authored by Shivaprasad G Bhat's avatar Shivaprasad G Bhat Committed by Michael Ellerman
Browse files

vfio/spapr: Always clear TCEs before unsetting the window



The PAPR expects the TCE table to have no entries at the time of
unset window(i.e. remove-pe). The TCE clear right now is done
before freeing the iommu table. On pSeries, the unset window
makes those entries inaccessible to the OS and the H_PUT/GET calls
fail on them with H_CONSTRAINED.

On PowerNV, this has no side effect as the TCE clear can be done
before the DMA window removal as well.

Signed-off-by: default avatarShivaprasad G Bhat <sbhat@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/171923273535.1397.1236742071894414895.stgit@linux.ibm.com
parent aed6e494
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -364,7 +364,6 @@ static void tce_iommu_release(void *iommu_data)
		if (!tbl)
			continue;

		tce_iommu_clear(container, tbl, tbl->it_offset, tbl->it_size);
		tce_iommu_free_table(container, tbl);
	}

@@ -720,6 +719,8 @@ static long tce_iommu_remove_window(struct tce_container *container,

	BUG_ON(!tbl->it_size);

	tce_iommu_clear(container, tbl, tbl->it_offset, tbl->it_size);

	/* Detach groups from IOMMUs */
	list_for_each_entry(tcegrp, &container->group_list, next) {
		table_group = iommu_group_get_iommudata(tcegrp->grp);
@@ -738,7 +739,6 @@ static long tce_iommu_remove_window(struct tce_container *container,
	}

	/* Free table */
	tce_iommu_clear(container, tbl, tbl->it_offset, tbl->it_size);
	tce_iommu_free_table(container, tbl);
	container->tables[num] = NULL;

@@ -1197,10 +1197,15 @@ static void tce_iommu_release_ownership(struct tce_container *container,
		return;
	}

	for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i)
		if (container->tables[i])
	for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
		if (container->tables[i]) {
			tce_iommu_clear(container, container->tables[i],
					container->tables[i]->it_offset,
					container->tables[i]->it_size);
			table_group->ops->unset_window(table_group, i);
		}
	}
}

static long tce_iommu_take_ownership(struct tce_container *container,
		struct iommu_table_group *table_group)