direct-io.hg

changeset 7968:dede6fb4c90e

When a foreign page is mapped via a grant reference, it
must also be unmapped explicitly via the grant-table
interface (GNTTABOP_unmap_grant_ref). If not, the guest
ends up with a dangling grant reference that is not cleared
up until the guest dies.

Because this can obviously lead to deferred hard-to-debug
problems, debug builds of Xen use a 'spare' PTE flag to
track granted mappings and to crash a domain if it attempts
to free such a PTE without using GNTTABOP_unmap_grant_ref.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Nov 22 15:53:22 2005 +0100 (2005-11-22)
parents 13b2e5c94595
children bc1bfdb35f29
files xen/arch/ia64/xen/grant_table.c xen/arch/x86/domain.c xen/arch/x86/mm.c xen/common/grant_table.c xen/include/asm-x86/page.h xen/include/asm-x86/x86_32/page-2level.h xen/include/asm-x86/x86_32/page-3level.h xen/include/asm-x86/x86_32/page.h xen/include/asm-x86/x86_64/page.h xen/include/xen/grant_table.h
line diff
     1.1 --- a/xen/arch/ia64/xen/grant_table.c	Tue Nov 22 12:04:03 2005 +0100
     1.2 +++ b/xen/arch/ia64/xen/grant_table.c	Tue Nov 22 15:53:22 2005 +0100
     1.3 @@ -1054,114 +1054,6 @@ do_grant_table_op(
     1.4      return rc;
     1.5  }
     1.6  
     1.7 -int
     1.8 -gnttab_check_unmap(
     1.9 -    struct domain *rd, struct domain *ld, unsigned long frame, int readonly)
    1.10 -{
    1.11 -    /* Called when put_page is invoked on a page belonging to a foreign domain.
    1.12 -     * Instead of decrementing the frame table ref count, locate the grant
    1.13 -     * table entry, if any, and if found, decrement that count.
    1.14 -     * Called a _lot_ at domain creation because pages mapped by priv domains
    1.15 -     * also traverse this.
    1.16 -     */
    1.17 -    
    1.18 -    /* Note: If the same frame is mapped multiple times, and then one of
    1.19 -     *       the ptes is overwritten, which maptrack handle gets invalidated?
    1.20 -     * Advice: Don't do it. Explicitly unmap.
    1.21 -     */
    1.22 -    
    1.23 -    unsigned int handle, ref, refcount;
    1.24 -    grant_table_t        *lgt, *rgt;
    1.25 -    active_grant_entry_t *act;
    1.26 -    grant_mapping_t      *map;
    1.27 -    int found = 0;
    1.28 -    
    1.29 -    lgt = ld->grant_table;
    1.30 -    
    1.31 -#if GRANT_DEBUG_VERBOSE
    1.32 -    if ( ld->domain_ id != 0 ) {
    1.33 -            DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
    1.34 -                    rd->domain_id, ld->domain_id, frame, readonly);
    1.35 -      }
    1.36 -#endif
    1.37 -    
    1.38 -    /* Fast exit if we're not mapping anything using grant tables */
    1.39 -    if ( lgt->map_count == 0 )
    1.40 -        return 0;
    1.41 -    
    1.42 -    if ( get_domain(rd) == 0 ) {
    1.43 -        DPRINTK("gnttab_check_unmap: couldn't get_domain rd(%d)\n",
    1.44 -                rd->domain_id);
    1.45 -        return 0;
    1.46 -    }
    1.47 -    
    1.48 -    rgt = rd->grant_table;
    1.49 -    
    1.50 -    for ( handle = 0; handle < lgt->maptrack_limit; handle++ ) {
    1.51 -
    1.52 -        map = &lgt->maptrack[handle];
    1.53 -            
    1.54 -        if ( map->domid != rd->domain_id )
    1.55 -            continue;
    1.56 -        
    1.57 -        if ( ( map->ref_and_flags & MAPTRACK_GNTMAP_MASK ) &&
    1.58 -             ( readonly ? 1 : (!(map->ref_and_flags & GNTMAP_readonly)))) {
    1.59 -
    1.60 -            ref = (map->ref_and_flags >> MAPTRACK_REF_SHIFT);
    1.61 -            act = &rgt->active[ref];
    1.62 -                    
    1.63 -            spin_lock(&rgt->lock);
    1.64 -                    
    1.65 -            if ( act->frame != frame ) {
    1.66 -                spin_unlock(&rgt->lock);
    1.67 -                continue;
    1.68 -            }
    1.69 -                    
    1.70 -            refcount = act->pin & ( readonly ? GNTPIN_hstr_mask
    1.71 -                                    : GNTPIN_hstw_mask );
    1.72 -
    1.73 -            if ( refcount == 0 ) {
    1.74 -                spin_unlock(&rgt->lock);
    1.75 -                continue;
    1.76 -            }
    1.77 -                    
    1.78 -            /* gotcha */
    1.79 -            DPRINTK("Grant unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
    1.80 -                    rd->domain_id, ld->domain_id, frame, readonly);
    1.81 -                    
    1.82 -            if ( readonly )
    1.83 -                act->pin -= GNTPIN_hstr_inc;
    1.84 -            else {
    1.85 -                act->pin -= GNTPIN_hstw_inc;
    1.86 -                            
    1.87 -                /* any more granted writable mappings? */
    1.88 -                if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 ) {
    1.89 -                    clear_bit(_GTF_writing, &rgt->shared[ref].flags);
    1.90 -                    put_page_type(&frame_table[frame]);
    1.91 -                }
    1.92 -            }
    1.93 -                
    1.94 -            if ( act->pin == 0 ) {
    1.95 -                clear_bit(_GTF_reading, &rgt->shared[ref].flags);
    1.96 -                put_page(&frame_table[frame]);
    1.97 -            }
    1.98 -
    1.99 -            spin_unlock(&rgt->lock);
   1.100 -                    
   1.101 -            clear_bit(GNTMAP_host_map, &map->ref_and_flags);
   1.102 -                    
   1.103 -            if ( !(map->ref_and_flags & GNTMAP_device_map) )
   1.104 -                put_maptrack_handle(lgt, handle);
   1.105 -                    
   1.106 -            found = 1;
   1.107 -            break;
   1.108 -        }
   1.109 -    }
   1.110 -    put_domain(rd);
   1.111 -    
   1.112 -    return found;
   1.113 -}
   1.114 -
   1.115  int 
   1.116  gnttab_prepare_for_transfer(
   1.117      struct domain *rd, struct domain *ld, grant_ref_t ref)
   1.118 @@ -1355,8 +1247,10 @@ grant_table_create(
   1.119  }
   1.120  
   1.121  void
   1.122 -gnttab_release_dev_mappings(grant_table_t *gt)
   1.123 +gnttab_release_mappings(
   1.124 +    struct domain *ld)
   1.125  {
   1.126 +    grant_table_t          *gt = ld->grant_table;
   1.127      grant_mapping_t        *map;
   1.128      domid_t                 dom;
   1.129      grant_ref_t             ref;
   1.130 @@ -1366,8 +1260,6 @@ gnttab_release_dev_mappings(grant_table_
   1.131      active_grant_entry_t   *act;
   1.132      grant_entry_t          *sha;
   1.133  
   1.134 -    ld = current->domain;
   1.135 -
   1.136      for ( handle = 0; handle < gt->maptrack_limit; handle++ )
   1.137      {
   1.138          map = &gt->maptrack[handle];
     2.1 --- a/xen/arch/x86/domain.c	Tue Nov 22 12:04:03 2005 +0100
     2.2 +++ b/xen/arch/x86/domain.c	Tue Nov 22 15:53:22 2005 +0100
     2.3 @@ -960,8 +960,7 @@ void domain_relinquish_resources(struct 
     2.4  
     2.5      ptwr_destroy(d);
     2.6  
     2.7 -    /* Release device mappings of other domains */
     2.8 -    gnttab_release_dev_mappings(d->grant_table);
     2.9 +    gnttab_release_mappings(d);
    2.10  
    2.11      /* Drop the in-use references to page-table bases. */
    2.12      for_each_vcpu ( d, v )
     3.1 --- a/xen/arch/x86/mm.c	Tue Nov 22 12:04:03 2005 +0100
     3.2 +++ b/xen/arch/x86/mm.c	Tue Nov 22 15:53:22 2005 +0100
     3.3 @@ -594,23 +594,26 @@ void put_page_from_l1e(l1_pgentry_t l1e,
     3.4          return;
     3.5  
     3.6      e = page_get_owner(page);
     3.7 -    if ( unlikely(e != d) )
     3.8 +
     3.9 +    /*
    3.10 +     * Check if this is a mapping that was established via a grant reference.
    3.11 +     * If it was then we should not be here: we require that such mappings are
    3.12 +     * explicitly destroyed via the grant-table interface.
    3.13 +     * 
    3.14 +     * The upshot of this is that the guest can end up with active grants that
    3.15 +     * it cannot destroy (because it no longer has a PTE to present to the
    3.16 +     * grant-table interface). This can lead to subtle hard-to-catch bugs,
    3.17 +     * hence a special grant PTE flag can be enabled to catch the bug early.
    3.18 +     * 
    3.19 +     * (Note that the undestroyable active grants are not a security hole in
    3.20 +     * Xen. All active grants can safely be cleaned up when the domain dies.)
    3.21 +     */
    3.22 +    if ( (l1e_get_flags(l1e) & _PAGE_GNTTAB) &&
    3.23 +         !(d->domain_flags & (DOMF_shutdown|DOMF_dying)) )
    3.24      {
    3.25 -        /*
    3.26 -         * Unmap a foreign page that may have been mapped via a grant table.
    3.27 -         * Note that this can fail for a privileged domain that can map foreign
    3.28 -         * pages via MMUEXT_SET_FOREIGNDOM. Such domains can have some mappings
    3.29 -         * counted via a grant entry and some counted directly in the page
    3.30 -         * structure's reference count. Note that reference counts won't get
    3.31 -         * dangerously confused as long as we always try to decrement the
    3.32 -         * grant entry first. We may end up with a mismatch between which
    3.33 -         * mappings and which unmappings are counted via the grant entry, but
    3.34 -         * really it doesn't matter as privileged domains have carte blanche.
    3.35 -         */
    3.36 -        if (likely(gnttab_check_unmap(e, d, pfn,
    3.37 -                                      !(l1e_get_flags(l1e) & _PAGE_RW))))
    3.38 -            return;
    3.39 -        /* Assume this mapping was made via MMUEXT_SET_FOREIGNDOM... */
    3.40 +        MEM_LOG("Attempt to implicitly unmap a granted PTE %" PRIpte,
    3.41 +                l1e_get_intpte(l1e));
    3.42 +        domain_crash(d);
    3.43      }
    3.44  
    3.45      if ( l1e_get_flags(l1e) & _PAGE_RW )
    3.46 @@ -2317,7 +2320,6 @@ int update_grant_pte_mapping(
    3.47  
    3.48      ASSERT(spin_is_locked(&d->big_lock));
    3.49      ASSERT(!shadow_mode_refcounts(d));
    3.50 -    ASSERT((l1e_get_flags(_nl1e) & L1_DISALLOW_MASK) == 0);
    3.51  
    3.52      gpfn = pte_addr >> PAGE_SHIFT;
    3.53      mfn = __gpfn_to_mfn(d, gpfn);
    3.54 @@ -2452,7 +2454,6 @@ int update_grant_va_mapping(
    3.55      
    3.56      ASSERT(spin_is_locked(&d->big_lock));
    3.57      ASSERT(!shadow_mode_refcounts(d));
    3.58 -    ASSERT((l1e_get_flags(_nl1e) & L1_DISALLOW_MASK) == 0);
    3.59  
    3.60      /*
    3.61       * This is actually overkill - we don't need to sync the L1 itself,
     4.1 --- a/xen/common/grant_table.c	Tue Nov 22 12:04:03 2005 +0100
     4.2 +++ b/xen/common/grant_table.c	Tue Nov 22 15:53:22 2005 +0100
     4.3 @@ -31,17 +31,11 @@
     4.4  #include <acm/acm_hooks.h>
     4.5  #include <xen/trace.h>
     4.6  
     4.7 -#if defined(CONFIG_X86_64)
     4.8 -#define GRANT_PTE_FLAGS (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
     4.9 -#else
    4.10 -#define GRANT_PTE_FLAGS (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY)
    4.11 -#endif
    4.12 -
    4.13 -#define PIN_FAIL(_lbl, _rc, _f, _a...)   \
    4.14 -    do {                           \
    4.15 -        DPRINTK( _f, ## _a );      \
    4.16 -        rc = (_rc);                \
    4.17 -        goto _lbl;                 \
    4.18 +#define PIN_FAIL(_lbl, _rc, _f, _a...)          \
    4.19 +    do {                                        \
    4.20 +        DPRINTK( _f, ## _a );                   \
    4.21 +        rc = (_rc);                             \
    4.22 +        goto _lbl;                              \
    4.23      } while ( 0 )
    4.24  
    4.25  static inline int
    4.26 @@ -519,12 +513,12 @@ static int
    4.27  
    4.28      /* If just unmapped a writable mapping, mark as dirtied */
    4.29      if ( unlikely(shadow_mode_log_dirty(rd)) &&
    4.30 -        !( flags & GNTMAP_readonly ) )
    4.31 +         !(flags & GNTMAP_readonly) )
    4.32           mark_dirty(rd, frame);
    4.33  
    4.34      /* If the last writable mapping has been removed, put_page_type */
    4.35 -    if ( ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask) ) == 0) &&
    4.36 -         ( !( flags & GNTMAP_readonly ) ) )
    4.37 +    if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
    4.38 +         !(flags & GNTMAP_readonly) )
    4.39      {
    4.40          clear_bit(_GTF_writing, &sha->flags);
    4.41          put_page_type(&frame_table[frame]);
    4.42 @@ -880,108 +874,6 @@ do_grant_table_op(
    4.43      return rc;
    4.44  }
    4.45  
    4.46 -int
    4.47 -gnttab_check_unmap(
    4.48 -    struct domain *rd, struct domain *ld, unsigned long frame, int readonly)
    4.49 -{
    4.50 -    /* Called when put_page is invoked on a page belonging to a foreign domain.
    4.51 -     * Instead of decrementing the frame table ref count, locate the grant
    4.52 -     * table entry, if any, and if found, decrement that count.
    4.53 -     * Called a _lot_ at domain creation because pages mapped by priv domains
    4.54 -     * also traverse this.
    4.55 -     */
    4.56 -    
    4.57 -    /* Note: If the same frame is mapped multiple times, and then one of
    4.58 -     *       the ptes is overwritten, which maptrack handle gets invalidated?
    4.59 -     * Advice: Don't do it. Explicitly unmap.
    4.60 -     */
    4.61 -    
    4.62 -    unsigned int handle, ref, refcount;
    4.63 -    grant_table_t        *lgt, *rgt;
    4.64 -    active_grant_entry_t *act;
    4.65 -    grant_mapping_t      *map;
    4.66 -    int found = 0;
    4.67 -    
    4.68 -    lgt = ld->grant_table;
    4.69 -    
    4.70 -    /* Fast exit if we're not mapping anything using grant tables */
    4.71 -    if ( lgt->map_count == 0 )
    4.72 -        return 0;
    4.73 -    
    4.74 -    if ( get_domain(rd) == 0 )
    4.75 -    {
    4.76 -        DPRINTK("gnttab_check_unmap: couldn't get_domain rd(%d)\n",
    4.77 -                rd->domain_id);
    4.78 -        return 0;
    4.79 -    }
    4.80 -    
    4.81 -    rgt = rd->grant_table;
    4.82 -    
    4.83 -    for ( handle = 0; handle < lgt->maptrack_limit; handle++ ) {
    4.84 -
    4.85 -        map = &lgt->maptrack[handle];
    4.86 -            
    4.87 -        if ( map->domid != rd->domain_id )
    4.88 -            continue;
    4.89 -        
    4.90 -        if ( ( map->ref_and_flags & MAPTRACK_GNTMAP_MASK ) &&
    4.91 -             ( readonly ? 1 : (!(map->ref_and_flags & GNTMAP_readonly)))) {
    4.92 -
    4.93 -            ref = (map->ref_and_flags >> MAPTRACK_REF_SHIFT);
    4.94 -            act = &rgt->active[ref];
    4.95 -                    
    4.96 -            spin_lock(&rgt->lock);
    4.97 -                    
    4.98 -            if ( act->frame != frame ) {
    4.99 -                spin_unlock(&rgt->lock);
   4.100 -                continue;
   4.101 -            }
   4.102 -                    
   4.103 -            refcount = act->pin & ( readonly ? GNTPIN_hstr_mask
   4.104 -                                    : GNTPIN_hstw_mask );
   4.105 -
   4.106 -            if ( refcount == 0 ) {
   4.107 -                spin_unlock(&rgt->lock);
   4.108 -                continue;
   4.109 -            }
   4.110 -                    
   4.111 -            /* gotcha */
   4.112 -            DPRINTK("Grant unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
   4.113 -                    rd->domain_id, ld->domain_id, frame, readonly);
   4.114 -                    
   4.115 -            if ( readonly )
   4.116 -                act->pin -= GNTPIN_hstr_inc;
   4.117 -            else {
   4.118 -                act->pin -= GNTPIN_hstw_inc;
   4.119 -                            
   4.120 -                /* any more granted writable mappings? */
   4.121 -                if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 ) {
   4.122 -                    clear_bit(_GTF_writing, &rgt->shared[ref].flags);
   4.123 -                    put_page_type(&frame_table[frame]);
   4.124 -                }
   4.125 -            }
   4.126 -                
   4.127 -            if ( act->pin == 0 ) {
   4.128 -                clear_bit(_GTF_reading, &rgt->shared[ref].flags);
   4.129 -                put_page(&frame_table[frame]);
   4.130 -            }
   4.131 -
   4.132 -            spin_unlock(&rgt->lock);
   4.133 -                    
   4.134 -            clear_bit(GNTMAP_host_map, &map->ref_and_flags);
   4.135 -                    
   4.136 -            if ( !(map->ref_and_flags & GNTMAP_device_map) )
   4.137 -                put_maptrack_handle(lgt, handle);
   4.138 -                    
   4.139 -            found = 1;
   4.140 -            break;
   4.141 -        }
   4.142 -    }
   4.143 -    put_domain(rd);
   4.144 -    
   4.145 -    return found;
   4.146 -}
   4.147 -
   4.148  int 
   4.149  gnttab_prepare_for_transfer(
   4.150      struct domain *rd, struct domain *ld, grant_ref_t ref)
   4.151 @@ -1124,70 +1016,85 @@ grant_table_create(
   4.152  }
   4.153  
   4.154  void
   4.155 -gnttab_release_dev_mappings(grant_table_t *gt)
   4.156 +gnttab_release_mappings(
   4.157 +    struct domain *d)
   4.158  {
   4.159 -    grant_mapping_t        *map;
   4.160 -    domid_t                 dom;
   4.161 -    grant_ref_t             ref;
   4.162 -    u16                     handle;
   4.163 -    struct domain          *ld, *rd;
   4.164 -    unsigned long           frame;
   4.165 -    active_grant_entry_t   *act;
   4.166 -    grant_entry_t          *sha;
   4.167 +    grant_table_t        *gt = d->grant_table;
   4.168 +    grant_mapping_t      *map;
   4.169 +    grant_ref_t           ref;
   4.170 +    u16                   handle;
   4.171 +    struct domain        *rd;
   4.172 +    active_grant_entry_t *act;
   4.173 +    grant_entry_t        *sha;
   4.174  
   4.175 -    ld = current->domain;
   4.176 +    BUG_ON(!test_bit(_DOMF_dying, &d->domain_flags));
   4.177  
   4.178      for ( handle = 0; handle < gt->maptrack_limit; handle++ )
   4.179      {
   4.180          map = &gt->maptrack[handle];
   4.181 -
   4.182 -        if ( !(map->ref_and_flags & GNTMAP_device_map) )
   4.183 +        if ( !(map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) )
   4.184              continue;
   4.185  
   4.186 -        dom = map->domid;
   4.187          ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
   4.188  
   4.189          DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n",
   4.190 -                handle, ref, map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom);
   4.191 +                handle, ref, map->ref_and_flags & MAPTRACK_GNTMAP_MASK,
   4.192 +                map->domid);
   4.193  
   4.194 -        if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
   4.195 -             unlikely(ld == rd) )
   4.196 -        {
   4.197 -            if ( rd != NULL )
   4.198 -                put_domain(rd);
   4.199 -            printk(KERN_WARNING "Grant release: No dom%d\n", dom);
   4.200 -            continue;
   4.201 -        }
   4.202 +        rd = find_domain_by_id(map->domid);
   4.203 +        BUG_ON(rd == NULL);
   4.204 +
   4.205 +        spin_lock(&rd->grant_table->lock);
   4.206  
   4.207          act = &rd->grant_table->active[ref];
   4.208          sha = &rd->grant_table->shared[ref];
   4.209  
   4.210 -        spin_lock(&rd->grant_table->lock);
   4.211 -
   4.212 -        if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) )
   4.213 +        if ( map->ref_and_flags & GNTMAP_readonly )
   4.214          {
   4.215 -            frame = act->frame;
   4.216 +            if ( map->ref_and_flags & GNTMAP_device_map )
   4.217 +            {
   4.218 +                BUG_ON((act->pin & GNTPIN_devr_mask) == 0);
   4.219 +                act->pin -= GNTPIN_devr_inc;
   4.220 +            }
   4.221  
   4.222 -            if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) &&
   4.223 -                 ( (act->pin & GNTPIN_devw_mask) >  0 ) )
   4.224 +            if ( map->ref_and_flags & GNTMAP_host_map )
   4.225 +            {
   4.226 +                BUG_ON((act->pin & GNTPIN_hstr_mask) == 0);
   4.227 +                act->pin -= GNTPIN_hstr_inc;
   4.228 +            }
   4.229 +        }
   4.230 +        else
   4.231 +        {
   4.232 +            if ( map->ref_and_flags & GNTMAP_device_map )
   4.233 +            {
   4.234 +                BUG_ON((act->pin & GNTPIN_devw_mask) == 0);
   4.235 +                act->pin -= GNTPIN_devw_inc;
   4.236 +            }
   4.237 +
   4.238 +            if ( map->ref_and_flags & GNTMAP_host_map )
   4.239 +            {
   4.240 +                BUG_ON((act->pin & GNTPIN_hstw_mask) == 0);
   4.241 +                act->pin -= GNTPIN_hstw_inc;
   4.242 +            }
   4.243 +
   4.244 +            if ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0 )
   4.245              {
   4.246                  clear_bit(_GTF_writing, &sha->flags);
   4.247 -                put_page_type(&frame_table[frame]);
   4.248 +                put_page_type(&frame_table[act->frame]);
   4.249              }
   4.250 +        }
   4.251  
   4.252 -            map->ref_and_flags &= ~GNTMAP_device_map;
   4.253 -            act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask);
   4.254 -            if ( act->pin == 0 )
   4.255 -            {
   4.256 -                clear_bit(_GTF_reading, &sha->flags);
   4.257 -                map->ref_and_flags = 0;
   4.258 -                put_page(&frame_table[frame]);
   4.259 -            }
   4.260 +        if ( act->pin == 0 )
   4.261 +        {
   4.262 +            clear_bit(_GTF_reading, &sha->flags);
   4.263 +            put_page(&frame_table[act->frame]);
   4.264          }
   4.265  
   4.266          spin_unlock(&rd->grant_table->lock);
   4.267  
   4.268          put_domain(rd);
   4.269 +
   4.270 +        map->ref_and_flags = 0;
   4.271      }
   4.272  }
   4.273  
     5.1 --- a/xen/include/asm-x86/page.h	Tue Nov 22 12:04:03 2005 +0100
     5.2 +++ b/xen/include/asm-x86/page.h	Tue Nov 22 15:53:22 2005 +0100
     5.3 @@ -273,6 +273,24 @@ extern void paging_init(void);
     5.4  #define _PAGE_AVAIL2   0x800U
     5.5  #define _PAGE_AVAIL    0xE00U
     5.6  
     5.7 +/*
     5.8 + * Debug option: Ensure that granted mappings are not implicitly unmapped.
     5.9 + * WARNING: This will need to be disabled to run OSes that use the spare PTE
    5.10 + * bits themselves (e.g., *BSD).
    5.11 + */
    5.12 +#ifndef NDEBUG
    5.13 +#define _PAGE_GNTTAB   _PAGE_AVAIL2
    5.14 +#else
    5.15 +#define _PAGE_GNTTAB   0
    5.16 +#endif
    5.17 +
    5.18 +/*
    5.19 + * Disallow unused flag bits plus PAT, PSE and GLOBAL. Also disallow GNTTAB
    5.20 + * if we are using it for grant-table debugging. Permit the NX bit if the
    5.21 + * hardware supports it.
    5.22 + */
    5.23 +#define BASE_DISALLOW_MASK ((0xFFFFF180U | _PAGE_GNTTAB) & ~_PAGE_NX)
    5.24 +
    5.25  #define __PAGE_HYPERVISOR \
    5.26      (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
    5.27  #define __PAGE_HYPERVISOR_NOCACHE \
     6.1 --- a/xen/include/asm-x86/x86_32/page-2level.h	Tue Nov 22 12:04:03 2005 +0100
     6.2 +++ b/xen/include/asm-x86/x86_32/page-2level.h	Tue Nov 22 15:53:22 2005 +0100
     6.3 @@ -1,5 +1,5 @@
     6.4 -#ifndef __X86_32_PAGE_2L_H__
     6.5 -#define __X86_32_PAGE_2L_H__
     6.6 +#ifndef __X86_32_PAGE_2LEVEL_H__
     6.7 +#define __X86_32_PAGE_2LEVEL_H__
     6.8  
     6.9  #define L1_PAGETABLE_SHIFT      12
    6.10  #define L2_PAGETABLE_SHIFT      22
    6.11 @@ -52,7 +52,7 @@ typedef l2_pgentry_t root_pgentry_t;
    6.12  #define get_pte_flags(x) ((int)(x) & 0xFFF)
    6.13  #define put_pte_flags(x) ((intpte_t)((x) & 0xFFF))
    6.14  
    6.15 -#define L1_DISALLOW_MASK (0xFFFFF180U) /* PAT/GLOBAL */
    6.16 -#define L2_DISALLOW_MASK (0xFFFFF180U) /* PSE/GLOBAL */
    6.17 +#define L1_DISALLOW_MASK BASE_DISALLOW_MASK
    6.18 +#define L2_DISALLOW_MASK BASE_DISALLOW_MASK
    6.19  
    6.20 -#endif /* __X86_32_PAGE_2L_H__ */
    6.21 +#endif /* __X86_32_PAGE_2LEVEL_H__ */
     7.1 --- a/xen/include/asm-x86/x86_32/page-3level.h	Tue Nov 22 12:04:03 2005 +0100
     7.2 +++ b/xen/include/asm-x86/x86_32/page-3level.h	Tue Nov 22 15:53:22 2005 +0100
     7.3 @@ -1,5 +1,5 @@
     7.4 -#ifndef __X86_32_PAGE_3L_H__
     7.5 -#define __X86_32_PAGE_3L_H__
     7.6 +#ifndef __X86_32_PAGE_3LEVEL_H__
     7.7 +#define __X86_32_PAGE_3LEVEL_H__
     7.8  
     7.9  #define L1_PAGETABLE_SHIFT      12
    7.10  #define L2_PAGETABLE_SHIFT      21
    7.11 @@ -65,8 +65,8 @@ typedef l3_pgentry_t root_pgentry_t;
    7.12  #define get_pte_flags(x) (((int)((x) >> 32) & ~0xFFF) | ((int)(x) & 0xFFF))
    7.13  #define put_pte_flags(x) (((intpte_t)((x) & ~0xFFF) << 32) | ((x) & 0xFFF))
    7.14  
    7.15 -#define L1_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* PAT/GLOBAL */
    7.16 -#define L2_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* PSE/GLOBAL */
    7.17 -#define L3_DISALLOW_MASK (0xFFFFF1E6U)             /* must-be-zero */
    7.18 +#define L1_DISALLOW_MASK BASE_DISALLOW_MASK
    7.19 +#define L2_DISALLOW_MASK BASE_DISALLOW_MASK
    7.20 +#define L3_DISALLOW_MASK 0xFFFFF1E6U /* must-be-zero */
    7.21  
    7.22 -#endif /* __X86_32_PAGE_3L_H__ */
    7.23 +#endif /* __X86_32_PAGE_3LEVEL_H__ */
     8.1 --- a/xen/include/asm-x86/x86_32/page.h	Tue Nov 22 12:04:03 2005 +0100
     8.2 +++ b/xen/include/asm-x86/x86_32/page.h	Tue Nov 22 15:53:22 2005 +0100
     8.3 @@ -23,6 +23,9 @@ extern unsigned int PAGE_HYPERVISOR;
     8.4  extern unsigned int PAGE_HYPERVISOR_NOCACHE;
     8.5  #endif
     8.6  
     8.7 +#define GRANT_PTE_FLAGS \
     8.8 +    (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_GNTTAB)
     8.9 +
    8.10  #endif /* __X86_32_PAGE_H__ */
    8.11  
    8.12  /*
     9.1 --- a/xen/include/asm-x86/x86_64/page.h	Tue Nov 22 12:04:03 2005 +0100
     9.2 +++ b/xen/include/asm-x86/x86_64/page.h	Tue Nov 22 15:53:22 2005 +0100
     9.3 @@ -72,14 +72,17 @@ typedef l4_pgentry_t root_pgentry_t;
     9.4  /* Bit 23 of a 24-bit flag mask. This corresponds to bit 63 of a pte.*/
     9.5  #define _PAGE_NX (cpu_has_nx ? (1U<<23) : 0U)
     9.6  
     9.7 -#define L1_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* PAT/GLOBAL */
     9.8 -#define L2_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* PSE/GLOBAL */
     9.9 -#define L3_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* must-be-zero */
    9.10 -#define L4_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX) /* must-be-zero */
    9.11 +#define L1_DISALLOW_MASK BASE_DISALLOW_MASK
    9.12 +#define L2_DISALLOW_MASK BASE_DISALLOW_MASK
    9.13 +#define L3_DISALLOW_MASK (BASE_DISALLOW_MASK | 0x180U /* must-be-zero */)
    9.14 +#define L4_DISALLOW_MASK (BASE_DISALLOW_MASK | 0x180U /* must-be-zero */)
    9.15  
    9.16  #define PAGE_HYPERVISOR         (__PAGE_HYPERVISOR         | _PAGE_GLOBAL)
    9.17  #define PAGE_HYPERVISOR_NOCACHE (__PAGE_HYPERVISOR_NOCACHE | _PAGE_GLOBAL)
    9.18  
    9.19 +#define GRANT_PTE_FLAGS \
    9.20 +    (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_GNTTAB|_PAGE_USER)
    9.21 +
    9.22  #endif /* __X86_64_PAGE_H__ */
    9.23  
    9.24  /*
    10.1 --- a/xen/include/xen/grant_table.h	Tue Nov 22 12:04:03 2005 +0100
    10.2 +++ b/xen/include/xen/grant_table.h	Tue Nov 22 15:53:22 2005 +0100
    10.3 @@ -94,10 +94,6 @@ int grant_table_create(
    10.4  void grant_table_destroy(
    10.5      struct domain *d);
    10.6  
    10.7 -/* Destroy host-CPU mappings via a grant-table entry. */
    10.8 -int gnttab_check_unmap(
    10.9 -    struct domain *rd, struct domain *ld, unsigned long frame, int readonly);
   10.10 -
   10.11  /*
   10.12   * Check that the given grant reference (rd,ref) allows 'ld' to transfer
   10.13   * ownership of a page frame. If so, lock down the grant entry.
   10.14 @@ -106,8 +102,9 @@ int
   10.15  gnttab_prepare_for_transfer(
   10.16      struct domain *rd, struct domain *ld, grant_ref_t ref);
   10.17  
   10.18 -/* Domain death release of granted device mappings of other domains.*/
   10.19 +/* Domain death release of granted mappings of other domains' memory. */
   10.20  void
   10.21 -gnttab_release_dev_mappings(grant_table_t *gt);
   10.22 +gnttab_release_mappings(
   10.23 +    struct domain *d);
   10.24  
   10.25  #endif /* __XEN_GRANT_H__ */