File 560e6d34-x86-p2m-pt-tighten-conditions-of-IOMMU-mapping-updates.patch of Package xen.1589
# Commit 660fd65d5578a95ec5eac522128bba23325179eb
# Date 2015-10-02 13:40:36 +0200
# Author Jan Beulich <jbeulich@suse.com>
# Committer Jan Beulich <jbeulich@suse.com>
x86/p2m-pt: correct condition of IOMMU mapping updates
Whether the MFN changes does not depend on the new entry being valid
(but solely on the old one).
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/mm/p2m-pt.c
+++ b/xen/arch/x86/mm/p2m-pt.c
@@ -293,7 +293,8 @@ p2m_set_entry(struct p2m_domain *p2m, un
unsigned int iommu_pte_flags = (p2mt == p2m_ram_rw) ?
IOMMUF_readable|IOMMUF_writable:
0;
- unsigned long old_mfn = 0;
+ unsigned int flags;
+ unsigned long old_mfn = INVALID_MFN;
if ( tb_init_done )
{
@@ -326,12 +327,13 @@ p2m_set_entry(struct p2m_domain *p2m, un
L3_PAGETABLE_SHIFT - PAGE_SHIFT,
L3_PAGETABLE_ENTRIES);
ASSERT(p2m_entry);
- if ( (l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) &&
- !(l1e_get_flags(*p2m_entry) & _PAGE_PSE) )
+ flags = l1e_get_flags(*p2m_entry);
+ if ( flags & _PAGE_PRESENT )
{
- /* We're replacing a non-SP page with a superpage. Make sure to
- * handle freeing the table properly. */
- intermediate_entry = *p2m_entry;
+ if ( flags & _PAGE_PSE )
+ old_mfn = l1e_get_pfn(*p2m_entry);
+ else
+ intermediate_entry = *p2m_entry;
}
ASSERT(!mfn_valid(mfn) || p2mt != p2m_mmio_direct);
@@ -342,10 +344,7 @@ p2m_set_entry(struct p2m_domain *p2m, un
entry_content.l1 = l3e_content.l3;
if ( entry_content.l1 != 0 )
- {
p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
- old_mfn = l1e_get_pfn(*p2m_entry);
- }
p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 3);
/* NB: paging_write_p2m_entry() handles tlb flushes properly */
@@ -366,7 +365,8 @@ p2m_set_entry(struct p2m_domain *p2m, un
p2m_entry = p2m_find_entry(table, &gfn_remainder, gfn,
0, L1_PAGETABLE_ENTRIES);
ASSERT(p2m_entry);
-
+ old_mfn = l1e_get_pfn(*p2m_entry);
+
if ( mfn_valid(mfn) || (p2mt == p2m_mmio_direct)
|| p2m_is_paging(p2mt) )
entry_content = p2m_l1e_from_pfn(mfn_x(mfn),
@@ -375,10 +375,8 @@ p2m_set_entry(struct p2m_domain *p2m, un
entry_content = l1e_empty();
if ( entry_content.l1 != 0 )
- {
p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
- old_mfn = l1e_get_pfn(*p2m_entry);
- }
+
/* level 1 entry */
p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 1);
/* NB: paging_write_p2m_entry() handles tlb flushes properly */
@@ -389,14 +387,13 @@ p2m_set_entry(struct p2m_domain *p2m, un
L2_PAGETABLE_SHIFT - PAGE_SHIFT,
L2_PAGETABLE_ENTRIES);
ASSERT(p2m_entry);
-
- /* FIXME: Deal with 4k replaced by 2meg pages */
- if ( (l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) &&
- !(l1e_get_flags(*p2m_entry) & _PAGE_PSE) )
- {
- /* We're replacing a non-SP page with a superpage. Make sure to
- * handle freeing the table properly. */
- intermediate_entry = *p2m_entry;
+ flags = l1e_get_flags(*p2m_entry);
+ if ( flags & _PAGE_PRESENT )
+ {
+ if ( flags & _PAGE_PSE )
+ old_mfn = l1e_get_pfn(*p2m_entry);
+ else
+ intermediate_entry = *p2m_entry;
}
ASSERT(!mfn_valid(mfn) || p2mt != p2m_mmio_direct);
@@ -410,10 +407,7 @@ p2m_set_entry(struct p2m_domain *p2m, un
entry_content.l1 = l2e_content.l2;
if ( entry_content.l1 != 0 )
- {
p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
- old_mfn = l1e_get_pfn(*p2m_entry);
- }
p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 2);
/* NB: paging_write_p2m_entry() handles tlb flushes properly */
@@ -424,11 +418,11 @@ p2m_set_entry(struct p2m_domain *p2m, un
&& (gfn + (1UL << page_order) - 1 > p2m->max_mapped_pfn) )
p2m->max_mapped_pfn = gfn + (1UL << page_order) - 1;
- if ( iommu_enabled && need_iommu(p2m->domain) )
+ if ( iommu_enabled && need_iommu(p2m->domain) && old_mfn != mfn_x(mfn) )
{
if ( iommu_use_hap_pt(p2m->domain) )
{
- if ( old_mfn && (old_mfn != mfn_x(mfn)) )
+ if ( old_mfn != INVALID_MFN )
amd_iommu_flush_pages(p2m->domain, gfn, page_order);
}
else