|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |