ia64/xen-unstable

changeset 19120:e1352667df95

PoD: Check refcount, not type count when reclaiming zero pages

Check the page refcount rather than the type count when deciding if a
page is still mapped.

This catches pages which are mapped by qemu; it also removes the need
for gnttab_is_granted().

Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jan 29 16:40:48 2009 +0000 (2009-01-29)
parents aa89d1afb287
children 988aee72f73d
files xen/arch/x86/mm/p2m.c xen/common/grant_table.c xen/include/xen/grant_table.h
line diff
     1.1 --- a/xen/arch/x86/mm/p2m.c	Thu Jan 29 16:39:56 2009 +0000
     1.2 +++ b/xen/arch/x86/mm/p2m.c	Thu Jan 29 16:40:48 2009 +0000
     1.3 @@ -723,10 +723,15 @@ p2m_pod_zero_check_superpage(struct doma
     1.4      unsigned long * map = NULL;
     1.5      int ret=0, reset = 0;
     1.6      int i, j;
     1.7 +    int max_ref = 1;
     1.8  
     1.9      if ( !superpage_aligned(gfn) )
    1.10          goto out;
    1.11  
    1.12 +    /* Allow an extra refcount for one shadow pt mapping in shadowed domains */
    1.13 +    if ( paging_mode_shadow(d) )
    1.14 +        max_ref++;
    1.15 +
    1.16      /* Look up the mfns, checking to make sure they're the same mfn
    1.17       * and aligned, and mapping them. */
    1.18      for ( i=0; i<(1<<9); i++ )
    1.19 @@ -743,13 +748,19 @@ p2m_pod_zero_check_superpage(struct doma
    1.20          /* Conditions that must be met for superpage-superpage:
    1.21           * + All gfns are ram types
    1.22           * + All gfns have the same type
    1.23 +         * + All of the mfns are allocated to a domain
    1.24           * + None of the mfns are used as pagetables
    1.25           * + The first mfn is 2-meg aligned
    1.26           * + All the other mfns are in sequence
    1.27 +         * Adding for good measure:
    1.28 +         * + None of the mfns are likely to be mapped elsewhere (refcount
    1.29 +         *   2 or less for shadow, 1 for hap)
    1.30           */
    1.31          if ( !p2m_is_ram(type)
    1.32               || type != type0
    1.33 +             || ( (mfn_to_page(mfn)->count_info & PGC_allocated) == 0 )
    1.34               || ( (mfn_to_page(mfn)->count_info & PGC_page_table) != 0 )
    1.35 +             || ( (mfn_to_page(mfn)->count_info & PGC_count_mask) > max_ref )
    1.36               || !( ( i == 0 && superpage_aligned(mfn_x(mfn0)) )
    1.37                     || ( i != 0 && mfn_x(mfn) == (mfn_x(mfn0) + i) ) ) )
    1.38              goto out;
    1.39 @@ -777,26 +788,16 @@ p2m_pod_zero_check_superpage(struct doma
    1.40                    _mfn(POPULATE_ON_DEMAND_MFN), 9,
    1.41                    p2m_populate_on_demand);
    1.42  
    1.43 -    if ( (mfn_to_page(mfn0)->u.inuse.type_info & PGT_count_mask) != 0 )
    1.44 +    /* Make none of the MFNs are used elsewhere... for example, mapped
    1.45 +     * via the grant table interface, or by qemu.  Allow one refcount for
    1.46 +     * being allocated to the domain. */
    1.47 +    for ( i=0; i < (1<<9); i++ )
    1.48      {
    1.49 -        reset = 1;
    1.50 -        goto out_reset;
    1.51 -    }
    1.52 -
    1.53 -    /* Timing here is important.  We need to make sure not to reclaim
    1.54 -     * a page which has been grant-mapped to another domain.  But we
    1.55 -     * can't grab the grant table lock, because we may be invoked from
    1.56 -     * the grant table code!  So we first remove the page from the
    1.57 -     * p2m, then check to see if the gpfn has been granted.  Once this
    1.58 -     * gpfn is marked PoD, any future gfn_to_mfn() call will block
    1.59 -     * waiting for the p2m lock.  If we find that it has been granted, we
    1.60 -     * simply restore the old value.
    1.61 -     */
    1.62 -    if ( gnttab_is_granted(d, gfn, 9) )
    1.63 -    {
    1.64 -        printk("gfn contains grant table %lx\n", gfn);
    1.65 -        reset = 1;
    1.66 -        goto out_reset;
    1.67 +        if ( (mfn_to_page(mfn0+i)->count_info & PGC_count_mask) > 1 )
    1.68 +        {
    1.69 +            reset = 1;
    1.70 +            goto out_reset;
    1.71 +        }
    1.72      }
    1.73  
    1.74      /* Finally, do a full zero-check */
    1.75 @@ -838,15 +839,22 @@ p2m_pod_zero_check(struct domain *d, uns
    1.76      unsigned long * map[count];
    1.77  
    1.78      int i, j;
    1.79 +    int max_ref = 1;
    1.80 +
    1.81 +    /* Allow an extra refcount for one shadow pt mapping in shadowed domains */
    1.82 +    if ( paging_mode_shadow(d) )
    1.83 +        max_ref++;
    1.84  
    1.85      /* First, get the gfn list, translate to mfns, and map the pages. */
    1.86      for ( i=0; i<count; i++ )
    1.87      {
    1.88          mfns[i] = gfn_to_mfn_query(d, gfns[i], types + i);
    1.89 -        /* If this is ram, and not a pagetable, map it; otherwise,
    1.90 -         * skip. */
    1.91 +        /* If this is ram, and not a pagetable, and probably not mapped
    1.92 +           elsewhere, map it; otherwise, skip. */
    1.93          if ( p2m_is_ram(types[i])
    1.94 -             && ( (mfn_to_page(mfns[i])->count_info & PGC_page_table) == 0 ) )
    1.95 +             && ( (mfn_to_page(mfns[i])->count_info & PGC_allocated) != 0 ) 
    1.96 +             && ( (mfn_to_page(mfns[i])->count_info & PGC_page_table) == 0 ) 
    1.97 +             && ( (mfn_to_page(mfns[i])->count_info & PGC_count_mask) <= max_ref ) )
    1.98              map[i] = map_domain_page(mfn_x(mfns[i]));
    1.99          else
   1.100              map[i] = NULL;
   1.101 @@ -876,7 +884,9 @@ p2m_pod_zero_check(struct domain *d, uns
   1.102                        _mfn(POPULATE_ON_DEMAND_MFN), 0,
   1.103                        p2m_populate_on_demand);
   1.104  
   1.105 -        if ( (mfn_to_page(mfns[i])->u.inuse.type_info & PGT_count_mask) != 0 )
   1.106 +        /* See if the page was successfully unmapped.  (Allow one refcount
   1.107 +         * for being allocated to a domain.) */
   1.108 +        if ( (mfn_to_page(mfns[i])->count_info & PGC_count_mask) > 1 )
   1.109          {
   1.110              unmap_domain_page(map[i]);
   1.111              map[i] = NULL;
   1.112 @@ -899,8 +909,7 @@ p2m_pod_zero_check(struct domain *d, uns
   1.113  
   1.114          /* See comment in p2m_pod_zero_check_superpage() re gnttab
   1.115           * check timing.  */
   1.116 -        if ( j < PAGE_SIZE/sizeof(*map[i])
   1.117 -             || gnttab_is_granted(d, gfns[i], 0) )
   1.118 +        if ( j < PAGE_SIZE/sizeof(*map[i]) )
   1.119          {
   1.120              set_p2m_entry(d, gfns[i], mfns[i], 0, types[i]);
   1.121              continue;
     2.1 --- a/xen/common/grant_table.c	Thu Jan 29 16:39:56 2009 +0000
     2.2 +++ b/xen/common/grant_table.c	Thu Jan 29 16:40:48 2009 +0000
     2.3 @@ -111,33 +111,6 @@ static unsigned inline int max_nr_maptra
     2.4  #define active_entry(t, e) \
     2.5      ((t)->active[(e)/ACGNT_PER_PAGE][(e)%ACGNT_PER_PAGE])
     2.6  
     2.7 -/* The p2m emergency sweep code should not reclaim a frame that is currenlty
     2.8 - * grant mapped by another domain.  That would involve checking all other
     2.9 - * domains grant maps, which is impractical.  Instead, we check the active
    2.10 - * grant table for this domain to see if it's been granted.  Since this
    2.11 - * may be called as a result of a grant table op, we can't grab the lock. */
    2.12 -int
    2.13 -gnttab_is_granted(struct domain *d, xen_pfn_t gfn, int order)
    2.14 -{
    2.15 -    int i, found=0;
    2.16 -    struct active_grant_entry *act;
    2.17 -
    2.18 -    /* We need to compare with active grant entries to make sure that
    2.19 -     * pinned (== currently mapped) entries don't disappear under our
    2.20 -     * feet. */
    2.21 -    for ( i=0; i<nr_grant_entries(d->grant_table); i++ )
    2.22 -    {
    2.23 -        act = &active_entry(d->grant_table, i);
    2.24 -        if ( act->gfn >> order == gfn >> order )
    2.25 -        {
    2.26 -            found = 1;
    2.27 -            break;
    2.28 -        }
    2.29 -    }
    2.30 -
    2.31 -    return found;
    2.32 -}
    2.33 -
    2.34  static inline int
    2.35  __get_maptrack_handle(
    2.36      struct grant_table *t)
     3.1 --- a/xen/include/xen/grant_table.h	Thu Jan 29 16:39:56 2009 +0000
     3.2 +++ b/xen/include/xen/grant_table.h	Thu Jan 29 16:40:48 2009 +0000
     3.3 @@ -147,7 +147,4 @@ nr_active_grant_frames(struct grant_tabl
     3.4      return num_act_frames_from_sha_frames(nr_grant_frames(gt));
     3.5  }
     3.6  
     3.7 -int
     3.8 -gnttab_is_granted(struct domain *d, xen_pfn_t gfn, int order);
     3.9 -
    3.10  #endif /* __XEN_GRANT_TABLE_H__ */