# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1171972300 0
# Node ID 266d203d7f39d69b14a5c020974cd843802592e8
# Parent 4b9680c58d738fa69b285b80c42e7e245ec1512c
[XEN] Fix potential race in unshadow code
And add some diagnostic printout in case it happens again
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
xen/arch/x86/mm/shadow/common.c | 36 +++++++++++++++++++++++-------------
1 files changed, 23 insertions(+), 13 deletions(-)
diff -r 4b9680c58d73 -r 266d203d7f39 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c Tue Feb 20 09:41:32 2007 +0000
+++ b/xen/arch/x86/mm/shadow/common.c Tue Feb 20 11:51:40 2007 +0000
@@ -2066,10 +2066,6 @@ void sh_remove_shadows(struct vcpu *v, m
ASSERT(!(all && fast));
- /* Bail out now if the page is not shadowed */
- if ( (pg->count_info & PGC_page_table) == 0 )
- return;
-
/* Although this is an externally visible function, we do not know
* whether the shadow lock will be held when it is called (since it
* can be called via put_page_type when we clear a shadow l1e).
@@ -2080,6 +2076,13 @@ void sh_remove_shadows(struct vcpu *v, m
SHADOW_PRINTK("d=%d, v=%d, gmfn=%05lx\n",
v->domain->domain_id, v->vcpu_id, mfn_x(gmfn));
+ /* Bail out now if the page is not shadowed */
+ if ( (pg->count_info & PGC_page_table) == 0 )
+ {
+ if ( do_locking ) shadow_unlock(v->domain);
+ return;
+ }
+
/* Search for this shadow in all appropriate shadows */
perfc_incrc(shadow_unshadow);
sh_flags = pg->shadow_flags;
@@ -2088,15 +2091,22 @@ void sh_remove_shadows(struct vcpu *v, m
* This call to hash_foreach() looks dangerous but is in fact OK: each
* call will remove at most one shadow, and terminate immediately when
* it does remove it, so we never walk the hash after doing a deletion. */
-#define DO_UNSHADOW(_type) do { \
- t = (_type); \
- smfn = shadow_hash_lookup(v, mfn_x(gmfn), t); \
- if ( sh_type_is_pinnable(v, t) ) \
- sh_unpin(v, smfn); \
- else \
- sh_remove_shadow_via_pointer(v, smfn); \
- if ( (pg->count_info & PGC_page_table) && !fast ) \
- hash_foreach(v, masks[t], callbacks, smfn); \
+#define DO_UNSHADOW(_type) do { \
+ t = (_type); \
+ smfn = shadow_hash_lookup(v, mfn_x(gmfn), t); \
+ if ( unlikely(!mfn_valid(smfn)) ) \
+ { \
+ SHADOW_ERROR(": gmfn %#lx has flags 0x%"PRIx32 \
+ " but no type-0x%"PRIx32" shadow\n", \
+ mfn_x(gmfn), sh_flags, t); \
+ break; \
+ } \
+ if ( sh_type_is_pinnable(v, t) ) \
+ sh_unpin(v, smfn); \
+ else \
+ sh_remove_shadow_via_pointer(v, smfn); \
+ if ( (pg->count_info & PGC_page_table) && !fast ) \
+ hash_foreach(v, masks[t], callbacks, smfn); \
} while (0)
if ( sh_flags & SHF_L1_32 ) DO_UNSHADOW(SH_type_l1_32_shadow);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|