[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] AMD/IOMMU: update live PTEs atomically
commit 3b055121c5410e2c3105d6d06aa24ca0d58868cd Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Tue Oct 20 14:22:52 2020 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Oct 20 14:22:52 2020 +0200 AMD/IOMMU: update live PTEs atomically Updating a live PTE bitfield by bitfield risks the compiler re-ordering the individual updates as well as splitting individual updates into multiple memory writes. Construct the new entry fully in a local variable, do the check to determine the flushing needs on the thus established new entry, and then write the new entry by a single insn. Similarly using memset() to clear a PTE is unsafe, as the order of writes the function does is, at least in principle, undefined. This is part of XSA-347. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Paul Durrant <paul@xxxxxxx> --- xen/drivers/passthrough/amd/iommu_map.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c index 050eca838b..480cd41c58 100644 --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -41,7 +41,7 @@ static unsigned int clear_iommu_pte_present(unsigned long l1_mfn, pte = &table[pfn_to_pde_idx(dfn, 1)]; flush_flags = pte->pr ? IOMMU_FLUSHF_modified : 0; - memset(pte, 0, sizeof(*pte)); + write_atomic(&pte->raw, 0); unmap_domain_page(table); @@ -53,26 +53,30 @@ static unsigned int set_iommu_pde_present(union amd_iommu_pte *pte, unsigned int next_level, bool iw, bool ir) { + union amd_iommu_pte new = {}, old; unsigned int flush_flags = IOMMU_FLUSHF_added; - if ( pte->pr && - (pte->mfn != next_mfn || - pte->iw != iw || - pte->ir != ir || - pte->next_level != next_level) ) - flush_flags |= IOMMU_FLUSHF_modified; - /* * FC bit should be enabled in PTE, this helps to solve potential * issues with ATS devices */ - pte->fc = !next_level; + new.fc = !next_level; + + new.mfn = next_mfn; + new.iw = iw; + new.ir = ir; + new.next_level = next_level; + new.pr = true; + + old.raw = read_atomic(&pte->raw); + old.ign0 = 0; + old.ign1 = 0; + old.ign2 = 0; + + if ( old.pr && old.raw != new.raw ) + flush_flags |= IOMMU_FLUSHF_modified; - pte->mfn = next_mfn; - pte->iw = iw; - pte->ir = ir; - pte->next_level = next_level; - pte->pr = 1; + write_atomic(&pte->raw, new.raw); return flush_flags; } -- generated by git-patchbot for /home/xen/git/xen.git#staging
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |