ia64/xen-unstable

changeset 15932:91a5b7eaede3

[shadow] Be smarter about what we check to avoid unnecessary brute-force searches

The old code checked only if the page was still a pagetable before
doing a brute-force search, rather than checking if it was still
shadowed as the type indicated. This meant that if a page was shadowed
as two different types, it was guaranteed to do a full brute-force search
even if all references could be found by up-pointers.

This checks the proper thing so that it will only do a brute-force if
necessary.

It also re-orders the unshadows so that higher levels are done first. In
many cases, lower-level shadows will be destroyed in the process of
higher-level shadows being destroyed, again saving brute-force searches.
author George Dunlap <gdunlap@xensource.com>
date Wed Sep 19 11:58:04 2007 +0100 (2007-09-19)
parents fadd1f8222b3
children 202153d094d8
files xen/arch/x86/mm/shadow/common.c
line diff
     1.1 --- a/xen/arch/x86/mm/shadow/common.c	Wed Sep 19 11:42:05 2007 +0100
     1.2 +++ b/xen/arch/x86/mm/shadow/common.c	Wed Sep 19 11:58:04 2007 +0100
     1.3 @@ -1981,7 +1981,6 @@ void sh_remove_shadows(struct vcpu *v, m
     1.4  {
     1.5      struct page_info *pg = mfn_to_page(gmfn);
     1.6      mfn_t smfn;
     1.7 -    u32 sh_flags;
     1.8      int do_locking;
     1.9      unsigned char t;
    1.10      
    1.11 @@ -2065,42 +2064,46 @@ void sh_remove_shadows(struct vcpu *v, m
    1.12  
    1.13      /* Search for this shadow in all appropriate shadows */
    1.14      perfc_incr(shadow_unshadow);
    1.15 -    sh_flags = pg->shadow_flags;
    1.16  
    1.17      /* Lower-level shadows need to be excised from upper-level shadows.
    1.18       * This call to hash_foreach() looks dangerous but is in fact OK: each
    1.19       * call will remove at most one shadow, and terminate immediately when
    1.20       * it does remove it, so we never walk the hash after doing a deletion.  */
    1.21 -#define DO_UNSHADOW(_type) do {                                 \
    1.22 -    t = (_type);                                                \
    1.23 -    smfn = shadow_hash_lookup(v, mfn_x(gmfn), t);               \
    1.24 -    if ( unlikely(!mfn_valid(smfn)) )                           \
    1.25 -    {                                                           \
    1.26 -        SHADOW_ERROR(": gmfn %#lx has flags 0x%"PRIx32          \
    1.27 -                     " but no type-0x%"PRIx32" shadow\n",       \
    1.28 -                     mfn_x(gmfn), sh_flags, t);                 \
    1.29 -        break;                                                  \
    1.30 -    }                                                           \
    1.31 -    if ( sh_type_is_pinnable(v, t) )                            \
    1.32 -        sh_unpin(v, smfn);                                      \
    1.33 -    else                                                        \
    1.34 -        sh_remove_shadow_via_pointer(v, smfn);                  \
    1.35 -    if ( (pg->count_info & PGC_page_table) && !fast )           \
    1.36 -        hash_foreach(v, masks[t], callbacks, smfn);             \
    1.37 +#define DO_UNSHADOW(_type) do {                                         \
    1.38 +    t = (_type);                                                        \
    1.39 +    if( !(pg->count_info & PGC_page_table)                              \
    1.40 +        || !(pg->shadow_flags & (1 << t)) )                             \
    1.41 +        break;                                                          \
    1.42 +    smfn = shadow_hash_lookup(v, mfn_x(gmfn), t);                       \
    1.43 +    if ( unlikely(!mfn_valid(smfn)) )                                   \
    1.44 +    {                                                                   \
    1.45 +        SHADOW_ERROR(": gmfn %#lx has flags 0x%"PRIx32                  \
    1.46 +                     " but no type-0x%"PRIx32" shadow\n",               \
    1.47 +                     mfn_x(gmfn), (uint32_t)pg->shadow_flags, t);       \
    1.48 +        break;                                                          \
    1.49 +    }                                                                   \
    1.50 +    if ( sh_type_is_pinnable(v, t) )                                    \
    1.51 +        sh_unpin(v, smfn);                                              \
    1.52 +    else                                                                \
    1.53 +        sh_remove_shadow_via_pointer(v, smfn);                          \
    1.54 +    if( !fast                                                           \
    1.55 +        && (pg->count_info & PGC_page_table)                            \
    1.56 +        && (pg->shadow_flags & (1 << t)) )                              \
    1.57 +        hash_foreach(v, masks[t], callbacks, smfn);                     \
    1.58  } while (0)
    1.59  
    1.60 -    if ( sh_flags & SHF_L1_32 )   DO_UNSHADOW(SH_type_l1_32_shadow);
    1.61 -    if ( sh_flags & SHF_L2_32 )   DO_UNSHADOW(SH_type_l2_32_shadow);
    1.62 +    DO_UNSHADOW(SH_type_l2_32_shadow);
    1.63 +    DO_UNSHADOW(SH_type_l1_32_shadow);
    1.64  #if CONFIG_PAGING_LEVELS >= 3
    1.65 -    if ( sh_flags & SHF_L1_PAE )  DO_UNSHADOW(SH_type_l1_pae_shadow);
    1.66 -    if ( sh_flags & SHF_L2_PAE )  DO_UNSHADOW(SH_type_l2_pae_shadow);
    1.67 -    if ( sh_flags & SHF_L2H_PAE ) DO_UNSHADOW(SH_type_l2h_pae_shadow);
    1.68 +    DO_UNSHADOW(SH_type_l2h_pae_shadow);
    1.69 +    DO_UNSHADOW(SH_type_l2_pae_shadow);
    1.70 +    DO_UNSHADOW(SH_type_l1_pae_shadow);
    1.71  #if CONFIG_PAGING_LEVELS >= 4
    1.72 -    if ( sh_flags & SHF_L1_64 )   DO_UNSHADOW(SH_type_l1_64_shadow);
    1.73 -    if ( sh_flags & SHF_L2_64 )   DO_UNSHADOW(SH_type_l2_64_shadow);
    1.74 -    if ( sh_flags & SHF_L2H_64 )  DO_UNSHADOW(SH_type_l2h_64_shadow);
    1.75 -    if ( sh_flags & SHF_L3_64 )   DO_UNSHADOW(SH_type_l3_64_shadow);
    1.76 -    if ( sh_flags & SHF_L4_64 )   DO_UNSHADOW(SH_type_l4_64_shadow);
    1.77 +    DO_UNSHADOW(SH_type_l4_64_shadow);
    1.78 +    DO_UNSHADOW(SH_type_l3_64_shadow);
    1.79 +    DO_UNSHADOW(SH_type_l2h_64_shadow);
    1.80 +    DO_UNSHADOW(SH_type_l2_64_shadow);
    1.81 +    DO_UNSHADOW(SH_type_l1_64_shadow);
    1.82  #endif
    1.83  #endif
    1.84