[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen stable-4.11] AMD/IOMMU: update live PTEs atomically
commit 7739ffda81784853ca6b0156331f5d1923303fa7 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Tue Oct 20 15:16:49 2020 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Oct 20 15:16:49 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> master commit: 3b055121c5410e2c3105d6d06aa24ca0d58868cd master date: 2020-10-20 14:22:52 +0200 --- xen/drivers/passthrough/amd/iommu_map.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c index aa382dbabd..56b4337e5b 100644 --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -41,7 +41,7 @@ static void clear_iommu_pte_present(unsigned long l1_mfn, unsigned long gfn) table = map_domain_page(_mfn(l1_mfn)); pte = table + pfn_to_pde_idx(gfn, IOMMU_PAGING_MODE_LEVEL_1); - *pte = 0; + write_atomic(pte, 0); unmap_domain_page(table); } @@ -49,7 +49,7 @@ static bool_t set_iommu_pde_present(u32 *pde, unsigned long next_mfn, unsigned int next_level, bool_t iw, bool_t ir) { - uint64_t addr_lo, addr_hi, maddr_next; + uint64_t addr_lo, addr_hi, maddr_next, full; u32 entry; bool need_flush = false, old_present; @@ -106,7 +106,7 @@ static bool_t set_iommu_pde_present(u32 *pde, unsigned long next_mfn, if ( next_level == IOMMU_PAGING_MODE_LEVEL_0 ) set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, IOMMU_PTE_FC_MASK, IOMMU_PTE_FC_SHIFT, &entry); - pde[1] = entry; + full = (uint64_t)entry << 32; /* mark next level as 'present' */ set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0, @@ -118,7 +118,9 @@ static bool_t set_iommu_pde_present(u32 *pde, unsigned long next_mfn, set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, IOMMU_PDE_PRESENT_MASK, IOMMU_PDE_PRESENT_SHIFT, &entry); - pde[0] = entry; + full |= entry; + + write_atomic((uint64_t *)pde, full); return need_flush; } -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.11
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |