[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen stable-4.12] x86/EPT: ept_set_middle_entry() related adjustments



commit 731bdaf416800809bc71f19dbdeb726203a2b3ef
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue Jul 7 15:09:50 2020 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Jul 7 15:09:50 2020 +0200

    x86/EPT: ept_set_middle_entry() related adjustments
    
    ept_split_super_page() wants to further modify the newly allocated
    table, so have ept_set_middle_entry() return the mapped pointer rather
    than tearing it down and then getting re-established right again.
    
    Similarly ept_next_level() wants to hand back a mapped pointer of
    the next level page, so re-use the one established by
    ept_set_middle_entry() in case that path was taken.
    
    Pull the setting of suppress_ve ahead of insertion into the higher level
    table, and don't have ept_split_super_page() set the field a 2nd time.
    
    This is part of XSA-328.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
    master commit: 1104288186ee73a7f9bfa41cbaa5bb7611521028
    master date: 2020-07-07 14:36:52 +0200
---
 xen/arch/x86/mm/p2m-ept.c | 41 ++++++++++++++++++-----------------------
 1 file changed, 18 insertions(+), 23 deletions(-)

diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index 7937a2214a..eb42248d56 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -187,8 +187,9 @@ static void ept_p2m_type_to_flags(struct p2m_domain *p2m, 
ept_entry_t *entry,
 #define GUEST_TABLE_SUPER_PAGE  2
 #define GUEST_TABLE_POD_PAGE    3
 
-/* Fill in middle levels of ept table */
-static int ept_set_middle_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry)
+/* Fill in middle level of ept table; return pointer to mapped new table. */
+static ept_entry_t *ept_set_middle_entry(struct p2m_domain *p2m,
+                                         ept_entry_t *ept_entry)
 {
     mfn_t mfn;
     ept_entry_t *table;
@@ -196,7 +197,12 @@ static int ept_set_middle_entry(struct p2m_domain *p2m, 
ept_entry_t *ept_entry)
 
     mfn = p2m_alloc_ptp(p2m, 0);
     if ( mfn_eq(mfn, INVALID_MFN) )
-        return 0;
+        return NULL;
+
+    table = map_domain_page(mfn);
+
+    for ( i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
+        table[i].suppress_ve = 1;
 
     ept_entry->epte = 0;
     ept_entry->mfn = mfn_x(mfn);
@@ -208,14 +214,7 @@ static int ept_set_middle_entry(struct p2m_domain *p2m, 
ept_entry_t *ept_entry)
 
     ept_entry->suppress_ve = 1;
 
-    table = map_domain_page(mfn);
-
-    for ( i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
-        table[i].suppress_ve = 1;
-
-    unmap_domain_page(table);
-
-    return 1;
+    return table;
 }
 
 /* free ept sub tree behind an entry */
@@ -253,10 +252,10 @@ static bool_t ept_split_super_page(struct p2m_domain *p2m,
 
     ASSERT(is_epte_superpage(ept_entry));
 
-    if ( !ept_set_middle_entry(p2m, &new_ept) )
+    table = ept_set_middle_entry(p2m, &new_ept);
+    if ( !table )
         return 0;
 
-    table = map_domain_page(_mfn(new_ept.mfn));
     trunk = 1UL << ((level - 1) * EPT_TABLE_ORDER);
 
     for ( i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
@@ -267,7 +266,6 @@ static bool_t ept_split_super_page(struct p2m_domain *p2m,
         epte->sp = (level > 1);
         epte->mfn += i * trunk;
         epte->snp = (iommu_enabled && iommu_snoop);
-        epte->suppress_ve = 1;
 
         ept_p2m_type_to_flags(p2m, epte, epte->sa_p2mt, epte->access);
 
@@ -306,8 +304,7 @@ static int ept_next_level(struct p2m_domain *p2m, bool_t 
read_only,
                           ept_entry_t **table, unsigned long *gfn_remainder,
                           int next_level)
 {
-    unsigned long mfn;
-    ept_entry_t *ept_entry, e;
+    ept_entry_t *ept_entry, *next = NULL, e;
     u32 shift, index;
 
     shift = next_level * EPT_TABLE_ORDER;
@@ -332,19 +329,17 @@ static int ept_next_level(struct p2m_domain *p2m, bool_t 
read_only,
         if ( read_only )
             return GUEST_TABLE_MAP_FAILED;
 
-        if ( !ept_set_middle_entry(p2m, ept_entry) )
+        next = ept_set_middle_entry(p2m, ept_entry);
+        if ( !next )
             return GUEST_TABLE_MAP_FAILED;
-        else
-            e = atomic_read_ept_entry(ept_entry); /* Refresh */
+        /* e is now stale and hence may not be used anymore below. */
     }
-
     /* The only time sp would be set here is if we had hit a superpage */
-    if ( is_epte_superpage(&e) )
+    else if ( is_epte_superpage(&e) )
         return GUEST_TABLE_SUPER_PAGE;
 
-    mfn = e.mfn;
     unmap_domain_page(*table);
-    *table = map_domain_page(_mfn(mfn));
+    *table = next ?: map_domain_page(_mfn(e.mfn));
     *gfn_remainder &= (1UL << shift) - 1;
     return GUEST_TABLE_NORMAL_PAGE;
 }
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.12



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.