From: Tim Deegan Date: Wed, 16 Mar 2011 09:35:32 +0000 (+0000) Subject: This fixes a bug in changeset 22526:7a5ee3800417, where the wrong X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=a63cc098560710c97ff62a797d4ad25ad7fa9a96;p=xen.git This fixes a bug in changeset 22526:7a5ee3800417, where the wrong value is read when deciding whether to flush the VTd tables. The effect is minor: in situations where the p2m entry is changed but the mfn is the same, the VTd tables will be unnecessarily flushed. old_entry is left untouched in the second case, since having a present old_entry will cause the an unnecessary check to be taken at the end of the function. Spotted-by: Zhang, Peng Fei Signed-off-by: George Dunlap Acked-by: Tim Deegan --- diff --git a/xen/arch/x86/mm/hap/p2m-ept.c b/xen/arch/x86/mm/hap/p2m-ept.c index 49f379a2ef..f1c2b0ee4d 100644 --- a/xen/arch/x86/mm/hap/p2m-ept.c +++ b/xen/arch/x86/mm/hap/p2m-ept.c @@ -374,7 +374,9 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, needs_sync = 0; /* If we're replacing a non-leaf entry with a leaf entry (1GiB or 2MiB), - * the intermediate tables will be freed below after the ept flush */ + * the intermediate tables will be freed below after the ept flush + * + * Read-then-write is OK because we hold the p2m lock. */ old_entry = *ept_entry; if ( mfn_valid(mfn_x(mfn)) || direct_mmio || p2m_is_paged(p2mt) || @@ -390,10 +392,10 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, new_entry.access = p2ma; new_entry.rsvd2_snp = (iommu_enabled && iommu_snoop); - if ( new_entry.mfn == mfn_x(mfn) ) + new_entry.mfn = mfn_x(mfn); + + if ( old_entry.mfn == new_entry.mfn ) need_modify_vtd_table = 0; - else - new_entry.mfn = mfn_x(mfn); ept_p2m_type_to_flags(&new_entry, p2mt, p2ma); } @@ -438,10 +440,12 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, new_entry.access = p2ma; new_entry.rsvd2_snp = (iommu_enabled && iommu_snoop); - if ( new_entry.mfn == mfn_x(mfn) ) + /* the caller should take care of the previous page */ + new_entry.mfn = mfn_x(mfn); + + /* Safe to read-then-write because we hold the p2m lock */ + if ( ept_entry->mfn == new_entry.mfn ) need_modify_vtd_table = 0; - else /* the caller should take care of the previous page */ - new_entry.mfn = mfn_x(mfn); ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);