ia64/xen-unstable

changeset 6145:100837b7abec

This changest allows grant mappings to arbitrary PTEs.

The map operation now takes PTE addresses as well as virtual
addresses. The contains_pte flag is used to indicate what sort of
address is in the map request.

Additionally, this patch:

- fixes grant mappings to user space.
- fixes overflow testing when you run out of maptrack entry space.

Signed-off-by: Andrew Warfield <andrew.warfield@cl.cam.ac.uk>
Signed-off-by: Leoffrey Lefebvre <geoffrey.g.lefebvre@intel.com>
author akw27@arcadians.cl.cam.ac.uk
date Fri Aug 12 17:52:47 2005 +0000 (2005-08-12)
parents 46cf22571980 4995d5f167c9
children f056b0cc171e
files xen/arch/x86/mm.c xen/common/grant_table.c xen/include/asm-x86/mm.h xen/include/public/grant_table.h xen/include/xen/grant_table.h
line diff
     1.1 --- a/xen/arch/x86/mm.c	Fri Aug 12 13:33:57 2005 +0000
     1.2 +++ b/xen/arch/x86/mm.c	Fri Aug 12 17:52:47 2005 +0000
     1.3 @@ -2268,6 +2268,197 @@ int do_mmu_update(
     1.4      return rc;
     1.5  }
     1.6  
     1.7 +
     1.8 +int update_grant_va_mapping_pte(unsigned long pte_addr,
     1.9 +                            l1_pgentry_t _nl1e, 
    1.10 +                            struct domain *d,
    1.11 +                            struct vcpu *v)
    1.12 +{
    1.13 +    /* Caller must:
    1.14 +     * . own d's BIGLOCK 
    1.15 +     * . already have 'get_page' correctly on the to-be-installed nl1e
    1.16 +     * . be responsible for flushing the TLB
    1.17 +     * . check PTE being installed isn't DISALLOWED
    1.18 +     */
    1.19 +
    1.20 +    int rc = GNTST_okay;
    1.21 +    void *va;
    1.22 +    unsigned long gpfn, mfn;
    1.23 +    struct pfn_info *page;
    1.24 +    struct domain_mmap_cache mapcache, sh_mapcache;
    1.25 +    u32 type_info;
    1.26 +    l1_pgentry_t    ol1e;
    1.27 +
    1.28 +    /* Grant tables and shadow mode don't currently work together. */
    1.29 +    ASSERT( !shadow_mode_refcounts(d) );
    1.30 +
    1.31 +    /* There shouldn't be any strange bits set on the PTE. */
    1.32 +    ASSERT( (l1e_get_flags(_nl1e) & L1_DISALLOW_MASK) == 0);
    1.33 +
    1.34 +    cleanup_writable_pagetable(d);
    1.35 +
    1.36 +    domain_mmap_cache_init(&mapcache);
    1.37 +    domain_mmap_cache_init(&sh_mapcache);
    1.38 +
    1.39 +    gpfn = pte_addr >> PAGE_SHIFT;
    1.40 +    mfn = __gpfn_to_mfn(d, gpfn);
    1.41 +
    1.42 +    if ( unlikely(!get_page_from_pagenr(mfn, current->domain)) )
    1.43 +    {
    1.44 +        MEM_LOG("Could not get page for normal update");
    1.45 +        rc = -EINVAL;
    1.46 +        goto failed_norefs;
    1.47 +    }
    1.48 +    
    1.49 +    va = map_domain_page_with_cache(mfn, &mapcache);
    1.50 +    va = (void *)((unsigned long)va +
    1.51 +                  (unsigned long)(pte_addr & ~PAGE_MASK));
    1.52 +    page = &frame_table[mfn];
    1.53 +
    1.54 +    type_info = page->u.inuse.type_info;
    1.55 +    if ( (type_info & PGT_type_mask) != PGT_l1_page_table) {
    1.56 +        DPRINTK("Grant map attempted to update a non-L1 page\n");
    1.57 +        rc = -EINVAL;
    1.58 +        goto failed;
    1.59 +    }
    1.60 +
    1.61 +    if ( likely(get_page_type(page, type_info & (PGT_type_mask|PGT_va_mask))) )
    1.62 +    {
    1.63 +
    1.64 +        if ( unlikely(__copy_from_user(&ol1e, (l1_pgentry_t *)va, 
    1.65 +                                       sizeof(ol1e)) != 0) ) {
    1.66 +            put_page_type(page);
    1.67 +            rc = -EINVAL;
    1.68 +            goto failed;
    1.69 +        } 
    1.70 +
    1.71 +        if ( update_l1e(va, ol1e, _nl1e) )
    1.72 +        {
    1.73 +            put_page_from_l1e(ol1e, d);
    1.74 +
    1.75 +            if ( l1e_get_flags(ol1e) & _PAGE_PRESENT )
    1.76 +                rc = GNTST_flush_all; /* We don't know what vaddr to flush */
    1.77 +            else
    1.78 +                rc = GNTST_okay; /* Caller need not invalidate TLB entry */
    1.79 +
    1.80 +            if (  unlikely(shadow_mode_enabled(d)) )
    1.81 +                shadow_l1_normal_pt_update(d, pte_addr, _nl1e, &sh_mapcache);
    1.82 +        }
    1.83 +        else
    1.84 +            rc = -EINVAL;
    1.85 + 
    1.86 +        put_page_type(page);
    1.87 +    }
    1.88 +
    1.89 + failed:
    1.90 +    unmap_domain_page_with_cache(va, &mapcache);
    1.91 +    put_page(page);
    1.92 +
    1.93 + failed_norefs:
    1.94 +    domain_mmap_cache_destroy(&mapcache);
    1.95 +    domain_mmap_cache_destroy(&sh_mapcache);
    1.96 +
    1.97 +    return rc;
    1.98 +}
    1.99 +
   1.100 +
   1.101 +
   1.102 +int clear_grant_va_mapping_pte(unsigned long addr, unsigned long frame,
   1.103 +                               struct domain *d)
   1.104 +{
   1.105 +    /* Caller must:
   1.106 +     * . own d's BIGLOCK 
   1.107 +     * . already have 'get_page' correctly on the to-be-installed nl1e
   1.108 +     * . be responsible for flushing the TLB
   1.109 +     * . check PTE being installed isn't DISALLOWED
   1.110 +     */
   1.111 +
   1.112 +    int rc = GNTST_okay;
   1.113 +    void *va;
   1.114 +    unsigned long gpfn, mfn;
   1.115 +    struct pfn_info *page;
   1.116 +    struct domain_mmap_cache mapcache, sh_mapcache;
   1.117 +    u32 type_info;
   1.118 +    l1_pgentry_t    ol1e;
   1.119 +
   1.120 +    /* Grant tables and shadow mode don't work together. */
   1.121 +    ASSERT( !shadow_mode_refcounts(d) );
   1.122 +
   1.123 +    cleanup_writable_pagetable(d);
   1.124 +
   1.125 +    domain_mmap_cache_init(&mapcache);
   1.126 +    domain_mmap_cache_init(&sh_mapcache);
   1.127 +
   1.128 +    gpfn = addr >> PAGE_SHIFT;
   1.129 +    mfn = __gpfn_to_mfn(d, gpfn);
   1.130 +
   1.131 +    if ( unlikely(!get_page_from_pagenr(mfn, current->domain)) )
   1.132 +    {
   1.133 +        MEM_LOG("Could not get page for normal update");
   1.134 +        rc = -EINVAL;
   1.135 +        goto failed_norefs;
   1.136 +    }
   1.137 +    
   1.138 +    va = map_domain_page_with_cache(mfn, &mapcache);
   1.139 +    va = (void *)((unsigned long)va +
   1.140 +                  (unsigned long)(addr & ~PAGE_MASK));
   1.141 +    page = &frame_table[mfn];
   1.142 +
   1.143 +    type_info = page->u.inuse.type_info;
   1.144 +    if ( (type_info & PGT_type_mask) != PGT_l1_page_table) {
   1.145 +        DPRINTK("Grant map attempted to update a non-L1 page\n");
   1.146 +        rc = -EINVAL;
   1.147 +        goto failed;
   1.148 +    }
   1.149 +
   1.150 +    if ( likely(get_page_type(page, type_info & (PGT_type_mask|PGT_va_mask))) )
   1.151 +    {
   1.152 +        if ( unlikely(__copy_from_user(&ol1e, (l1_pgentry_t *)va, 
   1.153 +                                       sizeof(ol1e)) != 0) ) 
   1.154 +        {
   1.155 +            rc = -EINVAL;
   1.156 +            put_page_type(page);
   1.157 +            goto failed;
   1.158 +        }
   1.159 +    
   1.160 +        /*
   1.161 +         * Check that the virtual address supplied is actually mapped to frame.
   1.162 +         */
   1.163 +        if ( unlikely((l1e_get_intpte(ol1e) >> PAGE_SHIFT) != frame ))
   1.164 +        {
   1.165 +            DPRINTK("PTE entry %lx for address %lx doesn't match frame %lx\n",
   1.166 +                    (unsigned long)l1e_get_intpte(ol1e), addr, frame);
   1.167 +            rc =  -EINVAL;
   1.168 +            put_page_type(page);
   1.169 +            goto failed;
   1.170 +        }
   1.171 +
   1.172 +        /* Delete pagetable entry. */
   1.173 +        if ( unlikely(__put_user(0, (unsigned long *)va)))
   1.174 +        {
   1.175 +            DPRINTK("Cannot delete PTE entry at %p.\n", va);
   1.176 +            rc = -EINVAL;
   1.177 +        } else {
   1.178 +            if ( unlikely(shadow_mode_enabled(d)) )
   1.179 +                shadow_l1_normal_pt_update(d, addr, l1e_empty(), 
   1.180 +                                           &sh_mapcache);
   1.181 +        }
   1.182 +        put_page_type(page);
   1.183 +    }
   1.184 +
   1.185 + failed:
   1.186 +    unmap_domain_page_with_cache(va, &mapcache);
   1.187 +    put_page(page);
   1.188 +
   1.189 + failed_norefs:
   1.190 +    domain_mmap_cache_destroy(&mapcache);
   1.191 +    domain_mmap_cache_destroy(&sh_mapcache);
   1.192 +
   1.193 +    return rc;
   1.194 +}
   1.195 +
   1.196 +
   1.197 +
   1.198  /* This function assumes the caller is holding the domain's BIGLOCK
   1.199   * and is running in a shadow mode
   1.200   */
   1.201 @@ -2283,7 +2474,7 @@ int update_grant_va_mapping(unsigned lon
   1.202       * . check PTE being installed isn't DISALLOWED
   1.203       */
   1.204  
   1.205 -    int             rc = 0;
   1.206 +    int             rc = GNTST_okay;
   1.207      l1_pgentry_t   *pl1e;
   1.208      l1_pgentry_t    ol1e;
   1.209      
   1.210 @@ -2305,9 +2496,9 @@ int update_grant_va_mapping(unsigned lon
   1.211          {
   1.212              put_page_from_l1e(ol1e, d);
   1.213              if ( l1e_get_flags(ol1e) & _PAGE_PRESENT )
   1.214 -                rc = 0; /* Caller needs to invalidate TLB entry */
   1.215 +                rc = GNTST_flush_one;
   1.216              else
   1.217 -                rc = 1; /* Caller need not invalidate TLB entry */
   1.218 +                rc = GNTST_okay; /* Caller need not invalidate TLB entry */
   1.219          }
   1.220          else
   1.221              rc = -EINVAL;
   1.222 @@ -2324,6 +2515,40 @@ int update_grant_va_mapping(unsigned lon
   1.223      return rc;
   1.224  }
   1.225  
   1.226 +int clear_grant_va_mapping(unsigned long addr, unsigned long frame)
   1.227 +{
   1.228 +    l1_pgentry_t   *pl1e;
   1.229 +    unsigned long   _ol1e;
   1.230 +    
   1.231 +    pl1e = &linear_pg_table[l1_linear_offset(addr)];
   1.232 +
   1.233 +    if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
   1.234 +    {
   1.235 +        DPRINTK("Could not find PTE entry for address %lx\n", addr);
   1.236 +        return -EINVAL;
   1.237 +    }
   1.238 +
   1.239 +    /*
   1.240 +     * Check that the virtual address supplied is actually mapped to
   1.241 +     * frame.
   1.242 +     */
   1.243 +    if ( unlikely((_ol1e >> PAGE_SHIFT) != frame ))
   1.244 +    {
   1.245 +        DPRINTK("PTE entry %lx for address %lx doesn't match frame %lx\n",
   1.246 +                _ol1e, addr, frame);
   1.247 +        return -EINVAL;
   1.248 +    }
   1.249 +
   1.250 +    /* Delete pagetable entry. */
   1.251 +    if ( unlikely(__put_user(0, (unsigned long *)pl1e)))
   1.252 +    {
   1.253 +        DPRINTK("Cannot delete PTE entry at %p.\n", (unsigned long *)pl1e);
   1.254 +        return -EINVAL;
   1.255 +    }
   1.256 +    
   1.257 +    return 0;
   1.258 +}
   1.259 +
   1.260  
   1.261  int do_update_va_mapping(unsigned long va, u64 val64,
   1.262                           unsigned long flags)
     2.1 --- a/xen/common/grant_table.c	Fri Aug 12 13:33:57 2005 +0000
     2.2 +++ b/xen/common/grant_table.c	Fri Aug 12 17:52:47 2005 +0000
     2.3 @@ -6,6 +6,8 @@
     2.4   * 
     2.5   * Copyright (c) 2005 Christopher Clark
     2.6   * Copyright (c) 2004 K A Fraser
     2.7 + * Copyright (c) 2005 Andrew Warfield
     2.8 + * Modifications by Geoffrey Lefebvre are (c) Intel Research Cambridge
     2.9   * 
    2.10   * This program is free software; you can redistribute it and/or modify
    2.11   * it under the terms of the GNU General Public License as published by
    2.12 @@ -50,7 +52,7 @@ get_maptrack_handle(
    2.13      grant_table_t *t)
    2.14  {
    2.15      unsigned int h;
    2.16 -    if ( unlikely((h = t->maptrack_head) == t->maptrack_limit) )
    2.17 +    if ( unlikely((h = t->maptrack_head) == (t->maptrack_limit - 1)) )
    2.18          return -1;
    2.19      t->maptrack_head = t->maptrack[h].ref_and_flags >> MAPTRACK_REF_SHIFT;
    2.20      t->map_count++;
    2.21 @@ -73,7 +75,7 @@ static int
    2.22      struct domain          *granting_d,
    2.23      grant_ref_t             ref,
    2.24      u16                     dev_hst_ro_flags,
    2.25 -    unsigned long           host_virt_addr,
    2.26 +    unsigned long           addr,
    2.27      unsigned long          *pframe )            /* OUT */
    2.28  {
    2.29      domid_t               sdom;
    2.30 @@ -121,6 +123,10 @@ static int
    2.31          sflags = sha->flags;
    2.32          sdom   = sha->domid;
    2.33  
    2.34 +        /* This loop attempts to set the access (reading/writing) flags
    2.35 +         * in the grant table entry.  It tries a cmpxchg on the field
    2.36 +         * up to five times, and then fails under the assumption that 
    2.37 +         * the guest is misbehaving. */
    2.38          for ( ; ; )
    2.39          {
    2.40              u32 scombo, prev_scombo, new_scombo;
    2.41 @@ -253,28 +259,37 @@ static int
    2.42  
    2.43      /*
    2.44       * At this point:
    2.45 -     * act->pin updated to reflect mapping.
    2.46 +     * act->pin updated to reference count mappings.
    2.47       * sha->flags updated to indicate to granting domain mapping done.
    2.48       * frame contains the mfn.
    2.49       */
    2.50  
    2.51      spin_unlock(&granting_d->grant_table->lock);
    2.52  
    2.53 -    if ( (host_virt_addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
    2.54 +
    2.55 +    if ( (addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
    2.56      {
    2.57          /* Write update into the pagetable. */
    2.58          l1_pgentry_t pte;
    2.59          pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
    2.60 +        
    2.61 +        if ( (dev_hst_ro_flags & GNTMAP_application_map) )
    2.62 +            l1e_add_flags(pte,_PAGE_USER);
    2.63          if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
    2.64              l1e_add_flags(pte,_PAGE_RW);
    2.65 -        rc = update_grant_va_mapping( host_virt_addr, pte, 
    2.66 -                       mapping_d, mapping_ed );
    2.67  
    2.68 -        /*
    2.69 -         * IMPORTANT: (rc == 0) => must flush / invalidate entry in TLB.
    2.70 -         * This is done in the outer gnttab_map_grant_ref.
    2.71 -         */
    2.72 +        if (!(dev_hst_ro_flags & GNTMAP_contains_pte))
    2.73 +        {
    2.74 +            rc = update_grant_va_mapping( addr, pte, 
    2.75 +                                          mapping_d, mapping_ed );
    2.76 +        } else {
    2.77 +            rc = update_grant_va_mapping_pte( addr, pte, 
    2.78 +                                              mapping_d, mapping_ed );
    2.79 +        }
    2.80  
    2.81 +        /* IMPORTANT: rc indicates the degree of TLB flush that is required.
    2.82 +         * GNTST_flush_one (1) or GNTST_flush_all (2). This is done in the 
    2.83 +         * outer gnttab_map_grant_ref. */
    2.84          if ( rc < 0 )
    2.85          {
    2.86              /* Failure: undo and abort. */
    2.87 @@ -317,6 +332,9 @@ static int
    2.88  /*
    2.89   * Returns 0 if TLB flush / invalidate required by caller.
    2.90   * va will indicate the address to be invalidated.
    2.91 + * 
    2.92 + * addr is _either_ a host virtual address, or the address of the pte to
    2.93 + * update, as indicated by the GNTMAP_contains_pte flag.
    2.94   */
    2.95  static int
    2.96  __gnttab_map_grant_ref(
    2.97 @@ -326,10 +344,10 @@ static int
    2.98      domid_t               dom;
    2.99      grant_ref_t           ref;
   2.100      struct domain        *ld, *rd;
   2.101 -    struct vcpu   *led;
   2.102 +    struct vcpu          *led;
   2.103      u16                   dev_hst_ro_flags;
   2.104      int                   handle;
   2.105 -    unsigned long         frame = 0, host_virt_addr;
   2.106 +    unsigned long         frame = 0, addr;
   2.107      int                   rc;
   2.108  
   2.109      led = current;
   2.110 @@ -338,19 +356,20 @@ static int
   2.111      /* Bitwise-OR avoids short-circuiting which screws control flow. */
   2.112      if ( unlikely(__get_user(dom, &uop->dom) |
   2.113                    __get_user(ref, &uop->ref) |
   2.114 -                  __get_user(host_virt_addr, &uop->host_virt_addr) |
   2.115 +                  __get_user(addr, &uop->host_virt_addr) |
   2.116                    __get_user(dev_hst_ro_flags, &uop->flags)) )
   2.117      {
   2.118          DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n");
   2.119          return -EFAULT; /* don't set status */
   2.120      }
   2.121  
   2.122 -
   2.123 -    if ( ((host_virt_addr != 0) || (dev_hst_ro_flags & GNTMAP_host_map)) &&
   2.124 -         unlikely(!__addr_ok(host_virt_addr)))
   2.125 +    if ( (dev_hst_ro_flags & GNTMAP_host_map) &&
   2.126 +         ( (addr == 0) ||
   2.127 +           (!(dev_hst_ro_flags & GNTMAP_contains_pte) && 
   2.128 +            unlikely(!__addr_ok(addr))) ) )
   2.129      {
   2.130          DPRINTK("Bad virtual address (%lx) or flags (%x).\n",
   2.131 -                host_virt_addr, dev_hst_ro_flags);
   2.132 +                addr, dev_hst_ro_flags);
   2.133          (void)__put_user(GNTST_bad_virt_addr, &uop->handle);
   2.134          return GNTST_bad_gntref;
   2.135      }
   2.136 @@ -386,12 +405,20 @@ static int
   2.137          grant_mapping_t *new_mt;
   2.138          grant_table_t   *lgt      = ld->grant_table;
   2.139  
   2.140 +        if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES )
   2.141 +        {
   2.142 +            put_domain(rd);
   2.143 +            DPRINTK("Maptrack table is at maximum size.\n");
   2.144 +            (void)__put_user(GNTST_no_device_space, &uop->handle);
   2.145 +            return GNTST_no_device_space;
   2.146 +        }
   2.147 +
   2.148          /* Grow the maptrack table. */
   2.149          new_mt = alloc_xenheap_pages(lgt->maptrack_order + 1);
   2.150          if ( new_mt == NULL )
   2.151          {
   2.152              put_domain(rd);
   2.153 -            DPRINTK("No more map handles available\n");
   2.154 +            DPRINTK("No more map handles available.\n");
   2.155              (void)__put_user(GNTST_no_device_space, &uop->handle);
   2.156              return GNTST_no_device_space;
   2.157          }
   2.158 @@ -405,7 +432,7 @@ static int
   2.159          lgt->maptrack_order   += 1;
   2.160          lgt->maptrack_limit  <<= 1;
   2.161  
   2.162 -        printk("Doubled maptrack size\n");
   2.163 +        DPRINTK("Doubled maptrack size\n");
   2.164          handle = get_maptrack_handle(ld->grant_table);
   2.165      }
   2.166  
   2.167 @@ -416,7 +443,7 @@ static int
   2.168  
   2.169      if ( 0 <= ( rc = __gnttab_activate_grant_ref( ld, led, rd, ref,
   2.170                                                    dev_hst_ro_flags,
   2.171 -                                                  host_virt_addr, &frame)))
   2.172 +                                                  addr, &frame)))
   2.173      {
   2.174          /*
   2.175           * Only make the maptrack live _after_ writing the pte, in case we 
   2.176 @@ -430,8 +457,9 @@ static int
   2.177  
   2.178          (void)__put_user(frame, &uop->dev_bus_addr);
   2.179  
   2.180 -        if ( dev_hst_ro_flags & GNTMAP_host_map )
   2.181 -            *va = host_virt_addr;
   2.182 +        if ( ( dev_hst_ro_flags & GNTMAP_host_map ) &&
   2.183 +             !( dev_hst_ro_flags & GNTMAP_contains_pte) )
   2.184 +            *va = addr;
   2.185  
   2.186          (void)__put_user(handle, &uop->handle);
   2.187      }
   2.188 @@ -449,12 +477,12 @@ static long
   2.189  gnttab_map_grant_ref(
   2.190      gnttab_map_grant_ref_t *uop, unsigned int count)
   2.191  {
   2.192 -    int i, flush = 0;
   2.193 +    int i, rc, flush = 0;
   2.194      unsigned long va = 0;
   2.195  
   2.196      for ( i = 0; i < count; i++ )
   2.197 -        if ( __gnttab_map_grant_ref(&uop[i], &va) == 0 )
   2.198 -            flush++;
   2.199 +        if ( (rc =__gnttab_map_grant_ref(&uop[i], &va)) >= 0 )
   2.200 +            flush += rc;
   2.201  
   2.202      if ( flush == 1 )
   2.203          flush_tlb_one_mask(current->domain->cpumask, va);
   2.204 @@ -479,12 +507,12 @@ static int
   2.205      grant_mapping_t *map;
   2.206      u16            flags;
   2.207      s16            rc = 1;
   2.208 -    unsigned long  frame, virt;
   2.209 +    unsigned long  frame, addr;
   2.210  
   2.211      ld = current->domain;
   2.212  
   2.213      /* Bitwise-OR avoids short-circuiting which screws control flow. */
   2.214 -    if ( unlikely(__get_user(virt, &uop->host_virt_addr) |
   2.215 +    if ( unlikely(__get_user(addr, &uop->host_virt_addr) |
   2.216                    __get_user(frame, &uop->dev_bus_addr) |
   2.217                    __get_user(handle, &uop->handle)) )
   2.218      {
   2.219 @@ -554,41 +582,17 @@ static int
   2.220          /* Frame is now unmapped for device access. */
   2.221      }
   2.222  
   2.223 -    if ( (virt != 0) &&
   2.224 +    if ( (addr != 0) &&
   2.225           (flags & GNTMAP_host_map) &&
   2.226           ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0))
   2.227      {
   2.228 -        l1_pgentry_t   *pl1e;
   2.229 -        unsigned long   _ol1e;
   2.230 -
   2.231 -        pl1e = &linear_pg_table[l1_linear_offset(virt)];
   2.232 -
   2.233 -        if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
   2.234 +        if (flags & GNTMAP_contains_pte) 
   2.235          {
   2.236 -            DPRINTK("Could not find PTE entry for address %lx\n", virt);
   2.237 -            rc = -EINVAL;
   2.238 -            goto unmap_out;
   2.239 -        }
   2.240 -
   2.241 -        /*
   2.242 -         * Check that the virtual address supplied is actually mapped to 
   2.243 -         * act->frame.
   2.244 -         */
   2.245 -        if ( unlikely((_ol1e >> PAGE_SHIFT) != frame ))
   2.246 -        {
   2.247 -            DPRINTK("PTE entry %lx for address %lx doesn't match frame %lx\n",
   2.248 -                    _ol1e, virt, frame);
   2.249 -            rc = -EINVAL;
   2.250 -            goto unmap_out;
   2.251 -        }
   2.252 -
   2.253 -        /* Delete pagetable entry. */
   2.254 -        if ( unlikely(__put_user(0, (unsigned long *)pl1e)))
   2.255 -        {
   2.256 -            DPRINTK("Cannot delete PTE entry at %p for virtual address %lx\n",
   2.257 -                    pl1e, virt);
   2.258 -            rc = -EINVAL;
   2.259 -            goto unmap_out;
   2.260 +            if ( (rc = clear_grant_va_mapping_pte(addr, frame, ld)) < 0 )
   2.261 +                goto unmap_out;
   2.262 +        } else {
   2.263 +            if ( (rc = clear_grant_va_mapping(addr, frame)) < 0 )
   2.264 +                goto unmap_out;
   2.265          }
   2.266  
   2.267          map->ref_and_flags &= ~GNTMAP_host_map;
   2.268 @@ -606,7 +610,8 @@ static int
   2.269          }
   2.270  
   2.271          rc = 0;
   2.272 -        *va = virt;
   2.273 +        if ( !( flags & GNTMAP_contains_pte) )
   2.274 +            *va = addr;
   2.275      }
   2.276  
   2.277      if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0)
   2.278 @@ -630,6 +635,7 @@ static int
   2.279  
   2.280      if ( act->pin == 0 )
   2.281      {
   2.282 +        act->frame = 0xdeadbeef;
   2.283          clear_bit(_GTF_reading, &sha->flags);
   2.284          put_page(&frame_table[frame]);
   2.285      }
   2.286 @@ -769,7 +775,8 @@ gnttab_dump_table(gnttab_dump_table_t *u
   2.287          {
   2.288              DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) "
   2.289                      "dom:(%hu) frame:(%lx)\n",
   2.290 -                    op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame);
   2.291 +                    op.dom, i, sha_copy.flags, sha_copy.domid, 
   2.292 +                    (unsigned long) sha_copy.frame);
   2.293          }
   2.294      }
   2.295  
   2.296 @@ -823,7 +830,7 @@ gnttab_donate(gnttab_donate_t *uop, unsi
   2.297          gnttab_donate_t *gop = &uop[i];
   2.298  #if GRANT_DEBUG
   2.299          printk("gnttab_donate: i=%d mfn=%08x domid=%d gref=%08x\n",
   2.300 -               i, gop->mfn, gop->domid, gop->handle);
   2.301 +               i, (unsigned int)gop->mfn, gop->domid, gop->handle);
   2.302  #endif
   2.303          page = &frame_table[gop->mfn];
   2.304  
   2.305 @@ -1027,7 +1034,7 @@ gnttab_check_unmap(
   2.306      if ( ld->domain_id != 0 )
   2.307      {
   2.308          DPRINTK("Foreign unref rd(%d) ld(%d) frm(%x) flgs(%x).\n",
   2.309 -                rd->domain_id, ld->domain_id, frame, readonly);
   2.310 +                rd->domain_id, ld->domain_id, (unsigned int)frame, readonly);
   2.311      }
   2.312  #endif
   2.313  
     3.1 --- a/xen/include/asm-x86/mm.h	Fri Aug 12 13:33:57 2005 +0000
     3.2 +++ b/xen/include/asm-x86/mm.h	Fri Aug 12 17:52:47 2005 +0000
     3.3 @@ -365,4 +365,13 @@ int update_grant_va_mapping(unsigned lon
     3.4                              l1_pgentry_t _nl1e, 
     3.5                              struct domain *d,
     3.6                              struct vcpu *v);
     3.7 +int update_grant_va_mapping_pte(unsigned long pte_addr,
     3.8 +                            l1_pgentry_t _nl1e, 
     3.9 +                            struct domain *d,
    3.10 +                            struct vcpu *v);
    3.11 +
    3.12 +int clear_grant_va_mapping(unsigned long addr, unsigned long frame);
    3.13 +int clear_grant_va_mapping_pte(unsigned long addr, unsigned long frame,
    3.14 +                            struct domain *d);
    3.15 +
    3.16  #endif /* __ASM_X86_MM_H__ */
     4.1 --- a/xen/include/public/grant_table.h	Fri Aug 12 13:33:57 2005 +0000
     4.2 +++ b/xen/include/public/grant_table.h	Fri Aug 12 17:52:47 2005 +0000
     4.3 @@ -150,7 +150,10 @@ typedef u16 grant_ref_t;
     4.4  #define GNTTABOP_map_grant_ref        0
     4.5  typedef struct gnttab_map_grant_ref {
     4.6      /* IN parameters. */
     4.7 -    memory_t    host_virt_addr;
     4.8 +    union {
     4.9 +        memory_t  pte_addr;
    4.10 +        memory_t  host_virt_addr;
    4.11 +    };
    4.12      domid_t     dom;
    4.13      grant_ref_t ref;
    4.14      u16         flags;                /* GNTMAP_* */
    4.15 @@ -173,7 +176,10 @@ typedef struct gnttab_map_grant_ref {
    4.16  #define GNTTABOP_unmap_grant_ref      1
    4.17  typedef struct gnttab_unmap_grant_ref {
    4.18      /* IN parameters. */
    4.19 -    memory_t    host_virt_addr;
    4.20 +    union {
    4.21 +        memory_t  pte_addr;
    4.22 +        memory_t  host_virt_addr;
    4.23 +    };
    4.24      memory_t    dev_bus_addr;
    4.25      u16         handle;
    4.26      /* OUT parameters. */
    4.27 @@ -247,10 +253,20 @@ typedef struct {
    4.28  #define _GNTMAP_application_map (3)
    4.29  #define GNTMAP_application_map  (1<<_GNTMAP_application_map)
    4.30  
    4.31 + /*
    4.32 +  * GNTMAP_contains_pte subflag:
    4.33 +  *  0 => This map request contains a host virtual address.
    4.34 +  *  1 => This map request contains the machine addess of the PTE to update.
    4.35 +  */ 
    4.36 +#define _GNTMAP_contains_pte    (4)
    4.37 +#define GNTMAP_contains_pte     (1<<_GNTMAP_contains_pte)
    4.38 +
    4.39  /*
    4.40   * Values for error status returns. All errors are -ve.
    4.41   */
    4.42 -#define GNTST_okay             (0)
    4.43 +#define GNTST_flush_all        (2)  /* Success, need to flush entire TLB.    */
    4.44 +#define GNTST_flush_one        (1)  /* Success, need to flush a vaddr.       */
    4.45 +#define GNTST_okay             (0)  /* Normal return.                        */
    4.46  #define GNTST_general_error    (-1) /* General undefined error.              */
    4.47  #define GNTST_bad_domain       (-2) /* Unrecognsed domain id.                */
    4.48  #define GNTST_bad_gntref       (-3) /* Unrecognised or inappropriate gntref. */
     5.1 --- a/xen/include/xen/grant_table.h	Fri Aug 12 13:33:57 2005 +0000
     5.2 +++ b/xen/include/xen/grant_table.h	Fri Aug 12 17:52:47 2005 +0000
     5.3 @@ -61,11 +61,12 @@ typedef struct {
     5.4   * table of these, indexes into which are returned as a 'mapping handle'.
     5.5   */
     5.6  typedef struct {
     5.7 -    u16      ref_and_flags; /* 0-2: GNTMAP_* ; 3-15: grant ref */
     5.8 +    u16      ref_and_flags; /* 0-4: GNTMAP_* ; 5-15: grant ref */
     5.9      domid_t  domid;         /* granting domain */
    5.10  } grant_mapping_t;
    5.11 -#define MAPTRACK_GNTMAP_MASK 7
    5.12 -#define MAPTRACK_REF_SHIFT   3
    5.13 +#define MAPTRACK_GNTMAP_MASK  0x1f
    5.14 +#define MAPTRACK_REF_SHIFT       5
    5.15 +#define MAPTRACK_MAX_ENTRIES ( 1 << (16 - MAPTRACK_REF_SHIFT) )
    5.16  
    5.17  /* Per-domain grant information. */
    5.18  typedef struct {