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

[Xen-devel] [PATCH] x86/ioreq server: Fix DomU couldn't reboot when using p2m_ioreq_server p2m_type



'commit 1679e0df3df6 ("x86/ioreq server: asynchronously reset
outstanding p2m_ioreq_server entries")' will call
p2m_change_entry_type_global() which set entry.recalc=1. Then
the following get_entry(p2m_ioreq_server) will return
p2m_ram_rw type.
But 'commit 6d774a951696 ("x86/ioreq server: synchronously reset
outstanding p2m_ioreq_server entries when an ioreq server unmaps")'
assume get_entry(p2m_ioreq_server) will return p2m_ioreq_server
type, then reset p2m_ioreq_server entries. The fact is the assumption
isn't true, and sysnchronously reset function couldn't work. Then
ioreq.entry_count is larger than zero after an ioreq server unmaps,
finally this results DomU couldn't reboot.

This patch add a P2M_PRE_RECALC flag to p2m_query_t, then
get_entry(P2M_PRE_RECALC) will return p2m_ioreq_server type
for p2m_ioreq_server pfn, and finally change mem type through set_entry.

Fix: 'commit 6d774a951696 ("x86/ioreq server: synchronously reset
      outstanding p2m_ioreq_server entries when an ioreq server unmaps")'

Signed-off-by: Xiong Zhang <xiong.y.zhang@xxxxxxxxx>
Signed-off-by: Yu Zhang <yu.c.zhang@xxxxxxxxxxxxxxx>
---
 xen/arch/x86/mm/p2m-ept.c |  7 +++++--
 xen/arch/x86/mm/p2m-pt.c  | 19 ++++++++++++++-----
 xen/arch/x86/mm/p2m.c     |  8 +++++---
 xen/include/asm-x86/p2m.h |  1 +
 4 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index f37a1f2..8f88d2b 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -991,8 +991,11 @@ static mfn_t ept_get_entry(struct p2m_domain *p2m,
 
     if ( is_epte_valid(ept_entry) )
     {
-        *t = p2m_recalc_type(recalc || ept_entry->recalc,
-                             ept_entry->sa_p2mt, p2m, gfn);
+        if ( !(q & P2M_PRE_RECALC) )
+            *t = p2m_recalc_type(recalc || ept_entry->recalc,
+                                 ept_entry->sa_p2mt, p2m, gfn);
+        else
+            *t = ept_entry->sa_p2mt;
         *a = ept_entry->access;
         if ( sve )
             *sve = ept_entry->suppress_ve;
diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c
index 5079b59..50e74f5 100644
--- a/xen/arch/x86/mm/p2m-pt.c
+++ b/xen/arch/x86/mm/p2m-pt.c
@@ -840,8 +840,11 @@ pod_retry_l3:
             mfn = _mfn(l3e_get_pfn(*l3e) +
                        l2_table_offset(addr) * L1_PAGETABLE_ENTRIES +
                        l1_table_offset(addr));
-            *t = p2m_recalc_type(recalc || _needs_recalc(flags),
-                                 p2m_flags_to_type(flags), p2m, gfn);
+            if ( !(q & P2M_PRE_RECALC) )
+                *t = p2m_recalc_type(recalc || _needs_recalc(flags),
+                                p2m_flags_to_type(flags), p2m, gfn);
+            else
+                *t = p2m_flags_to_type(flags);
             unmap_domain_page(l3e);
 
             ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t));
@@ -879,8 +882,11 @@ pod_retry_l2:
     if ( flags & _PAGE_PSE )
     {
         mfn = _mfn(l2e_get_pfn(*l2e) + l1_table_offset(addr));
-        *t = p2m_recalc_type(recalc || _needs_recalc(flags),
-                             p2m_flags_to_type(flags), p2m, gfn);
+        if ( !(q & P2M_PRE_RECALC) )
+            *t = p2m_recalc_type(recalc || _needs_recalc(flags),
+                                p2m_flags_to_type(flags), p2m, gfn);
+        else
+            *t = p2m_flags_to_type(flags);
         unmap_domain_page(l2e);
         
         ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t));
@@ -916,7 +922,10 @@ pod_retry_l1:
         return INVALID_MFN;
     }
     mfn = _mfn(l1e_get_pfn(*l1e));
-    *t = p2m_recalc_type(recalc || _needs_recalc(flags), l1t, p2m, gfn);
+    if ( !(q & P2M_PRE_RECALC) )
+        *t = p2m_recalc_type(recalc || _needs_recalc(flags), l1t, p2m, gfn);
+    else
+        *t = l1t;
     unmap_domain_page(l1e);
 
     ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t) || p2m_is_paging(*t));
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 1d57e5c..1c3e22f 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -1020,6 +1020,8 @@ void p2m_finish_type_change(struct domain *d,
     p2m_type_t t;
     unsigned long gfn = gfn_x(first_gfn);
     unsigned long last_gfn = gfn + max_nr - 1;
+    mfn_t mfn;
+    p2m_access_t a;
 
     ASSERT(ot != nt);
     ASSERT(p2m_is_changeable(ot) && p2m_is_changeable(nt));
@@ -1029,10 +1031,10 @@ void p2m_finish_type_change(struct domain *d,
     last_gfn = min(last_gfn, p2m->max_mapped_pfn);
     while ( gfn <= last_gfn )
     {
-        get_gfn_query_unlocked(d, gfn, &t);
-
+        mfn = p2m->get_entry(p2m, gfn, &t, &a, P2M_PRE_RECALC, NULL, NULL);
         if ( t == ot )
-            p2m_change_type_one(d, gfn, t, nt);
+            p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, nt,
+                          p2m->default_access);
 
         gfn++;
     }
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index 7574a9b..9645260 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -78,6 +78,7 @@ typedef enum {
 typedef unsigned int p2m_query_t;
 #define P2M_ALLOC    (1u<<0)   /* Populate PoD and paged-out entries */
 #define P2M_UNSHARE  (1u<<1)   /* Break CoW sharing */
+#define P2M_PRE_RECALC (1u<<2)   /* Get p2m type before recalc */
 
 /* We use bitmaps and maks to handle groups of types */
 #define p2m_to_mask(_t) (1UL << (_t))
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

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