ia64/xen-unstable

changeset 14020:266d203d7f39

[XEN] Fix potential race in unshadow code
And add some diagnostic printout in case it happens again
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Tue Feb 20 11:51:40 2007 +0000 (2007-02-20)
parents 4b9680c58d73
children 4990b2236f06
files xen/arch/x86/mm/shadow/common.c
line diff
     1.1 --- a/xen/arch/x86/mm/shadow/common.c	Tue Feb 20 09:41:32 2007 +0000
     1.2 +++ b/xen/arch/x86/mm/shadow/common.c	Tue Feb 20 11:51:40 2007 +0000
     1.3 @@ -2066,10 +2066,6 @@ void sh_remove_shadows(struct vcpu *v, m
     1.4  
     1.5      ASSERT(!(all && fast));
     1.6  
     1.7 -    /* Bail out now if the page is not shadowed */
     1.8 -    if ( (pg->count_info & PGC_page_table) == 0 )
     1.9 -        return;
    1.10 -
    1.11      /* Although this is an externally visible function, we do not know
    1.12       * whether the shadow lock will be held when it is called (since it
    1.13       * can be called via put_page_type when we clear a shadow l1e).
    1.14 @@ -2080,6 +2076,13 @@ void sh_remove_shadows(struct vcpu *v, m
    1.15      SHADOW_PRINTK("d=%d, v=%d, gmfn=%05lx\n",
    1.16                     v->domain->domain_id, v->vcpu_id, mfn_x(gmfn));
    1.17  
    1.18 +    /* Bail out now if the page is not shadowed */
    1.19 +    if ( (pg->count_info & PGC_page_table) == 0 )
    1.20 +    {
    1.21 +        if ( do_locking ) shadow_unlock(v->domain);
    1.22 +        return;
    1.23 +    }
    1.24 +
    1.25      /* Search for this shadow in all appropriate shadows */
    1.26      perfc_incrc(shadow_unshadow);
    1.27      sh_flags = pg->shadow_flags;
    1.28 @@ -2088,15 +2091,22 @@ void sh_remove_shadows(struct vcpu *v, m
    1.29       * This call to hash_foreach() looks dangerous but is in fact OK: each
    1.30       * call will remove at most one shadow, and terminate immediately when
    1.31       * it does remove it, so we never walk the hash after doing a deletion.  */
    1.32 -#define DO_UNSHADOW(_type) do {                         \
    1.33 -    t = (_type);                                        \
    1.34 -    smfn = shadow_hash_lookup(v, mfn_x(gmfn), t);       \
    1.35 -    if ( sh_type_is_pinnable(v, t) )                    \
    1.36 -        sh_unpin(v, smfn);                              \
    1.37 -    else                                                \
    1.38 -        sh_remove_shadow_via_pointer(v, smfn);          \
    1.39 -    if ( (pg->count_info & PGC_page_table) && !fast )   \
    1.40 -        hash_foreach(v, masks[t], callbacks, smfn);     \
    1.41 +#define DO_UNSHADOW(_type) do {                                 \
    1.42 +    t = (_type);                                                \
    1.43 +    smfn = shadow_hash_lookup(v, mfn_x(gmfn), t);               \
    1.44 +    if ( unlikely(!mfn_valid(smfn)) )                           \
    1.45 +    {                                                           \
    1.46 +        SHADOW_ERROR(": gmfn %#lx has flags 0x%"PRIx32          \
    1.47 +                     " but no type-0x%"PRIx32" shadow\n",       \
    1.48 +                     mfn_x(gmfn), sh_flags, t);                 \
    1.49 +        break;                                                  \
    1.50 +    }                                                           \
    1.51 +    if ( sh_type_is_pinnable(v, t) )                            \
    1.52 +        sh_unpin(v, smfn);                                      \
    1.53 +    else                                                        \
    1.54 +        sh_remove_shadow_via_pointer(v, smfn);                  \
    1.55 +    if ( (pg->count_info & PGC_page_table) && !fast )           \
    1.56 +        hash_foreach(v, masks[t], callbacks, smfn);             \
    1.57  } while (0)
    1.58  
    1.59      if ( sh_flags & SHF_L1_32 )   DO_UNSHADOW(SH_type_l1_32_shadow);