ia64/xen-unstable

changeset 4571:e90dde144eb9

bitkeeper revision 1.1325 (4264f4e1_pBZ5zLLX0b0JxQ8LKictQ)

Grant-table cleanups, reduce break-even point for INVLPG vs. full flush,
and fix TLB flushing for SMP guests.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Apr 19 12:09:05 2005 +0000 (2005-04-19)
parents 4d0b44989cce
children 147d96171c0e
files xen/common/grant_table.c
line diff
     1.1 --- a/xen/common/grant_table.c	Tue Apr 19 00:03:29 2005 +0000
     1.2 +++ b/xen/common/grant_table.c	Tue Apr 19 12:09:05 2005 +0000
     1.3 @@ -191,7 +191,8 @@ static int
     1.4           * A more accurate check cannot be done with a single comparison.
     1.5           */
     1.6          if ( (act->pin & 0x80808080U) != 0 )
     1.7 -            PIN_FAIL(unlock_out, ENOSPC, "Risk of counter overflow %08x\n", act->pin);
     1.8 +            PIN_FAIL(unlock_out, ENOSPC,
     1.9 +                     "Risk of counter overflow %08x\n", act->pin);
    1.10  
    1.11          frame = act->frame;
    1.12  
    1.13 @@ -236,12 +237,14 @@ static int
    1.14          if ( dev_hst_ro_flags & GNTMAP_device_map )
    1.15              act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ? 
    1.16                  GNTPIN_devr_inc : GNTPIN_devw_inc;
    1.17 +
    1.18          if ( dev_hst_ro_flags & GNTMAP_host_map )
    1.19              act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
    1.20                  GNTPIN_hstr_inc : GNTPIN_hstw_inc;
    1.21      }
    1.22  
    1.23 -    /* At this point:
    1.24 +    /*
    1.25 +     * At this point:
    1.26       * act->pin updated to reflect mapping.
    1.27       * sha->flags updated to indicate to granting domain mapping done.
    1.28       * frame contains the mfn.
    1.29 @@ -251,9 +254,7 @@ static int
    1.30  
    1.31      if ( (host_virt_addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
    1.32      {
    1.33 -        /* Write update into the pagetable
    1.34 -         */
    1.35 -
    1.36 +        /* Write update into the pagetable. */
    1.37          rc = update_grant_va_mapping( host_virt_addr,
    1.38                                  (frame << PAGE_SHIFT) | _PAGE_PRESENT  |
    1.39                                                          _PAGE_ACCESSED |
    1.40 @@ -261,18 +262,21 @@ static int
    1.41                         ((dev_hst_ro_flags & GNTMAP_readonly) ? 0 : _PAGE_RW),
    1.42                         mapping_d, mapping_ed );
    1.43  
    1.44 -        /* IMPORTANT: (rc == 0) => must flush / invalidate entry in TLB.
    1.45 +        /*
    1.46 +         * IMPORTANT: (rc == 0) => must flush / invalidate entry in TLB.
    1.47           * This is done in the outer gnttab_map_grant_ref.
    1.48           */
    1.49  
    1.50 -        if ( 0 > rc )
    1.51 +        if ( rc < 0 )
    1.52          {
    1.53 -            /* Abort. */
    1.54 +            /* Failure: undo and abort. */
    1.55  
    1.56              spin_lock(&granting_d->grant_table->lock);
    1.57  
    1.58              if ( dev_hst_ro_flags & GNTMAP_readonly )
    1.59 +            {
    1.60                  act->pin -= GNTPIN_hstr_inc;
    1.61 +            }
    1.62              else
    1.63              {
    1.64                  act->pin -= GNTPIN_hstw_inc;
    1.65 @@ -282,6 +286,7 @@ static int
    1.66                      put_page_type(&frame_table[frame]);
    1.67                  }
    1.68              }
    1.69 +
    1.70              if ( act->pin == 0 )
    1.71              {
    1.72                  clear_bit(_GTF_reading, &sha->flags);
    1.73 @@ -292,6 +297,7 @@ static int
    1.74          }
    1.75  
    1.76      }
    1.77 +
    1.78      *pframe = frame;
    1.79      return rc;
    1.80  
    1.81 @@ -300,6 +306,10 @@ static int
    1.82      return rc;
    1.83  }
    1.84  
    1.85 +/*
    1.86 + * Returns 0 if TLB flush / invalidate required by caller.
    1.87 + * va will indicate the address to be invalidated.
    1.88 + */
    1.89  static int
    1.90  __gnttab_map_grant_ref(
    1.91      gnttab_map_grant_ref_t *uop,
    1.92 @@ -314,9 +324,6 @@ static int
    1.93      unsigned long         frame = 0, host_virt_addr;
    1.94      int                   rc;
    1.95  
    1.96 -    /* Returns 0 if TLB flush / invalidate required by caller.
    1.97 -     * va will indicate the address to be invalidated. */
    1.98 -
    1.99      led = current;
   1.100      ld = led->domain;
   1.101  
   1.102 @@ -331,7 +338,7 @@ static int
   1.103      }
   1.104  
   1.105  
   1.106 -    if ( ((host_virt_addr != 0) || (dev_hst_ro_flags & GNTMAP_host_map) ) &&
   1.107 +    if ( ((host_virt_addr != 0) || (dev_hst_ro_flags & GNTMAP_host_map)) &&
   1.108           unlikely(!__addr_ok(host_virt_addr)))
   1.109      {
   1.110          DPRINTK("Bad virtual address (%x) or flags (%x).\n",
   1.111 @@ -341,8 +348,8 @@ static int
   1.112      }
   1.113  
   1.114      if ( unlikely(ref >= NR_GRANT_ENTRIES) ||
   1.115 -         unlikely((dev_hst_ro_flags & (GNTMAP_device_map|GNTMAP_host_map)) ==
   1.116 -0) )
   1.117 +         unlikely((dev_hst_ro_flags &
   1.118 +                   (GNTMAP_device_map|GNTMAP_host_map)) == 0) )
   1.119      {
   1.120          DPRINTK("Bad ref (%d) or flags (%x).\n", ref, dev_hst_ro_flags);
   1.121          (void)__put_user(GNTST_bad_gntref, &uop->handle);
   1.122 @@ -359,15 +366,16 @@ 0) )
   1.123          return GNTST_bad_domain;
   1.124      }
   1.125  
   1.126 -    /* get a maptrack handle */
   1.127 +    /* Get a maptrack handle. */
   1.128      if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
   1.129      {
   1.130          int              i;
   1.131          grant_mapping_t *new_mt;
   1.132          grant_table_t   *lgt      = ld->grant_table;
   1.133  
   1.134 -        /* grow the maptrack table */
   1.135 -        if ( (new_mt = (void *)alloc_xenheap_pages(lgt->maptrack_order + 1)) == NULL )
   1.136 +        /* Grow the maptrack table. */
   1.137 +        new_mt = (void *)alloc_xenheap_pages(lgt->maptrack_order + 1);
   1.138 +        if ( new_mt == NULL )
   1.139          {
   1.140              put_domain(rd);
   1.141              DPRINTK("No more map handles available\n");
   1.142 @@ -397,9 +405,9 @@ 0) )
   1.143                                                    dev_hst_ro_flags,
   1.144                                                    host_virt_addr, &frame)))
   1.145      {
   1.146 -        /* Only make the maptrack live _after_ writing the pte,
   1.147 -         * in case we overwrite the same frame number, causing a
   1.148 -         *  maptrack walk to find it
   1.149 +        /*
   1.150 +         * Only make the maptrack live _after_ writing the pte, in case we 
   1.151 +         * overwrite the same frame number, causing a maptrack walk to find it
   1.152           */
   1.153          ld->grant_table->maptrack[handle].domid = dom;
   1.154  
   1.155 @@ -429,21 +437,16 @@ gnttab_map_grant_ref(
   1.156      gnttab_map_grant_ref_t *uop, unsigned int count)
   1.157  {
   1.158      int i, flush = 0;
   1.159 -    unsigned long va[8];
   1.160 +    unsigned long va;
   1.161  
   1.162      for ( i = 0; i < count; i++ )
   1.163 -        if ( __gnttab_map_grant_ref(&uop[i],
   1.164 -             &va[ (flush < 8 ? flush : 0) ]   ) == 0)
   1.165 +        if ( __gnttab_map_grant_ref(&uop[i], &va) == 0 )
   1.166              flush++;
   1.167  
   1.168 -    if ( flush != 0 )
   1.169 -    {
   1.170 -        if ( flush <= 8 )
   1.171 -            for ( i = 0; i < flush; i++ )
   1.172 -                flush_tlb_one_mask(current->domain->cpuset, va[i]);
   1.173 -        else 
   1.174 -            local_flush_tlb();
   1.175 -    }
   1.176 +    if ( flush == 1 )
   1.177 +        flush_tlb_one_mask(current->domain->cpuset, va);
   1.178 +    else if ( flush != 0 ) 
   1.179 +        flush_tlb_mask(current->domain->cpuset);
   1.180  
   1.181      return 0;
   1.182  }
   1.183 @@ -499,6 +502,7 @@ static int
   1.184          (void)__put_user(GNTST_bad_domain, &uop->status);
   1.185          return GNTST_bad_domain;
   1.186      }
   1.187 +
   1.188  #if GRANT_DEBUG_VERBOSE
   1.189      DPRINTK("Unmapping grant ref (%hu) for domain (%hu) with handle (%hu)\n",
   1.190              ref, dom, handle);
   1.191 @@ -510,15 +514,17 @@ static int
   1.192      spin_lock(&rd->grant_table->lock);
   1.193  
   1.194      if ( frame == 0 )
   1.195 +    {
   1.196          frame = act->frame;
   1.197 +    }
   1.198      else if ( frame == GNTUNMAP_DEV_FROM_VIRT )
   1.199      {
   1.200          if ( !( flags & GNTMAP_device_map ) )
   1.201              PIN_FAIL(unmap_out, GNTST_bad_dev_addr,
   1.202 -                     "Bad frame number: frame not mapped for device access.\n");
   1.203 +                     "Bad frame number: frame not mapped for dev access.\n");
   1.204          frame = act->frame;
   1.205  
   1.206 -        /* frame will be unmapped for device access below if virt addr ok */
   1.207 +        /* Frame will be unmapped for device access below if virt addr okay. */
   1.208      }
   1.209      else
   1.210      {
   1.211 @@ -532,7 +538,7 @@ static int
   1.212          map->ref_and_flags &= ~GNTMAP_device_map;
   1.213          (void)__put_user(0, &uop->dev_bus_addr);
   1.214  
   1.215 -        /* frame is now unmapped for device access */
   1.216 +        /* Frame is now unmapped for device access. */
   1.217      }
   1.218  
   1.219      if ( (virt != 0) &&
   1.220 @@ -543,7 +549,7 @@ static int
   1.221          unsigned long   _ol1e;
   1.222  
   1.223          pl1e = &linear_pg_table[l1_linear_offset(virt)];
   1.224 -                                                                                            
   1.225 +
   1.226          if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
   1.227          {
   1.228              DPRINTK("Could not find PTE entry for address %x\n", virt);
   1.229 @@ -551,8 +557,9 @@ static int
   1.230              goto unmap_out;
   1.231          }
   1.232  
   1.233 -        /* check that the virtual address supplied is actually
   1.234 -         * mapped to act->frame.
   1.235 +        /*
   1.236 +         * Check that the virtual address supplied is actually mapped to 
   1.237 +         * act->frame.
   1.238           */
   1.239          if ( unlikely((_ol1e >> PAGE_SHIFT) != frame ))
   1.240          {
   1.241 @@ -562,8 +569,7 @@ static int
   1.242              goto unmap_out;
   1.243          }
   1.244  
   1.245 -        /* Delete pagetable entry
   1.246 -         */
   1.247 +        /* Delete pagetable entry. */
   1.248          if ( unlikely(__put_user(0, (unsigned long *)pl1e)))
   1.249          {
   1.250              DPRINTK("Cannot delete PTE entry at %x for virtual address %x\n",
   1.251 @@ -627,21 +633,16 @@ gnttab_unmap_grant_ref(
   1.252      gnttab_unmap_grant_ref_t *uop, unsigned int count)
   1.253  {
   1.254      int i, flush = 0;
   1.255 -    unsigned long va[8];
   1.256 +    unsigned long va;
   1.257  
   1.258      for ( i = 0; i < count; i++ )
   1.259 -        if ( __gnttab_unmap_grant_ref(&uop[i],
   1.260 -             &va[ (flush < 8 ? flush : 0) ]   ) == 0)
   1.261 +        if ( __gnttab_unmap_grant_ref(&uop[i], &va) == 0 )
   1.262              flush++;
   1.263  
   1.264 -    if ( flush != 0 )
   1.265 -    {
   1.266 -        if ( flush <= 8 )
   1.267 -            for ( i = 0; i < flush; i++ )
   1.268 -                flush_tlb_one_mask(current->domain->cpuset, va[i]);
   1.269 -        else 
   1.270 -            local_flush_tlb();
   1.271 -    }
   1.272 +    if ( flush == 1 )
   1.273 +        flush_tlb_one_mask(current->domain->cpuset, va);
   1.274 +    else if ( flush != 0 ) 
   1.275 +        flush_tlb_mask(current->domain->cpuset);
   1.276  
   1.277      return 0;
   1.278  }
   1.279 @@ -665,7 +666,7 @@ gnttab_setup_table(
   1.280  
   1.281      if ( unlikely(op.nr_frames > NR_GRANT_FRAMES) )
   1.282      {
   1.283 -        DPRINTK("Xen only supports at most %d grant-table frames per domain.\n",
   1.284 +        DPRINTK("Xen only supports up to %d grant-table frames per domain.\n",
   1.285                  NR_GRANT_FRAMES);
   1.286          (void)put_user(GNTST_general_error, &uop->status);
   1.287          return 0;
   1.288 @@ -692,11 +693,10 @@ gnttab_setup_table(
   1.289      {
   1.290          ASSERT(d->grant_table != NULL);
   1.291          (void)put_user(GNTST_okay, &uop->status);
   1.292 -
   1.293          for ( i = 0; i < op.nr_frames; i++ )
   1.294 -            (void)put_user( (
   1.295 -                virt_to_phys( (char*)(d->grant_table->shared)+(i*PAGE_SIZE) )
   1.296 -                              >> PAGE_SHIFT ), &uop->frame_list[i]);
   1.297 +            (void)put_user(
   1.298 +                (virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT) + i,
   1.299 +                &uop->frame_list[i]);
   1.300      }
   1.301  
   1.302      put_domain(d);
   1.303 @@ -754,7 +754,8 @@ gnttab_dump_table(gnttab_dump_table_t *u
   1.304  
   1.305          if ( sha_copy.flags )
   1.306          {
   1.307 -            DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) frame:(%lx)\n",
   1.308 +            DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) "
   1.309 +                    "dom:(%hu) frame:(%lx)\n",
   1.310                      op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame);
   1.311          }
   1.312      }
   1.313 @@ -767,7 +768,8 @@ gnttab_dump_table(gnttab_dump_table_t *u
   1.314  
   1.315          if ( act->pin )
   1.316          {
   1.317 -            DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) dom:(%hu) frame:(%lx)\n",
   1.318 +            DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) "
   1.319 +                    "dom:(%hu) frame:(%lx)\n",
   1.320                      op.dom, i, act->pin, act->domid, act->frame);
   1.321          }
   1.322      }
   1.323 @@ -778,7 +780,8 @@ gnttab_dump_table(gnttab_dump_table_t *u
   1.324  
   1.325          if ( maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK )
   1.326          {
   1.327 -            DPRINTK("Grant: dom (%hu) MAP (%d) ref:(%hu) flags:(%x) dom:(%hu)\n",
   1.328 +            DPRINTK("Grant: dom (%hu) MAP (%d) ref:(%hu) flags:(%x) "
   1.329 +                    "dom:(%hu)\n",
   1.330                      op.dom, i,
   1.331                      maptrack->ref_and_flags >> MAPTRACK_REF_SHIFT,
   1.332                      maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK,
   1.333 @@ -849,9 +852,9 @@ gnttab_check_unmap(
   1.334       * also traverse this.
   1.335       */
   1.336  
   1.337 -    /* Note: if the same frame is mapped multiple times, and then one of
   1.338 +    /* Note: If the same frame is mapped multiple times, and then one of
   1.339       *       the ptes is overwritten, which maptrack handle gets invalidated?
   1.340 -     * Advice: don't do it.
   1.341 +     * Advice: Don't do it. Explicitly unmap.
   1.342       */
   1.343  
   1.344      unsigned int handle, ref, refcount;
   1.345 @@ -886,11 +889,6 @@ gnttab_check_unmap(
   1.346      {
   1.347          map = &lgt->maptrack[handle];
   1.348  
   1.349 -
   1.350 -        /* cwc22: if multiple grants of the same frame are disallowed,
   1.351 -         * then the readonly check here can be changed to cause an early abort
   1.352 -         * if we've matched on frame, but not on write permission.
   1.353 -         */
   1.354          if ( ( map->ref_and_flags & MAPTRACK_GNTMAP_MASK ) &&
   1.355               ( readonly ? 1 : (!(map->ref_and_flags & GNTMAP_readonly))))
   1.356          {
   1.357 @@ -1103,15 +1101,17 @@ grant_table_create(
   1.358          t->maptrack[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
   1.359  
   1.360      /* Shared grant table. */
   1.361 -    if ( (t->shared = (void *)alloc_xenheap_pages(ORDER_GRANT_FRAMES)) == NULL )
   1.362 +    t->shared = (void *)alloc_xenheap_pages(ORDER_GRANT_FRAMES);
   1.363 +    if ( t->shared == NULL )
   1.364          goto no_mem;
   1.365      memset(t->shared, 0, NR_GRANT_FRAMES * PAGE_SIZE);
   1.366  
   1.367      for ( i = 0; i < NR_GRANT_FRAMES; i++ )
   1.368      {
   1.369 -        SHARE_PFN_WITH_DOMAIN(virt_to_page((char *)(t->shared)+(i*PAGE_SIZE)), d);
   1.370 -        machine_to_phys_mapping[ (virt_to_phys((char*)(t->shared)+(i*PAGE_SIZE))
   1.371 -                                 >> PAGE_SHIFT) ] = INVALID_M2P_ENTRY;
   1.372 +        SHARE_PFN_WITH_DOMAIN(
   1.373 +            virt_to_page((char *)(t->shared)+(i*PAGE_SIZE)), d);
   1.374 +        machine_to_phys_mapping[(virt_to_phys(t->shared) >> PAGE_SHIFT) + i] =
   1.375 +            INVALID_M2P_ENTRY;
   1.376      }
   1.377  
   1.378      /* Okay, install the structure. */
   1.379 @@ -1164,7 +1164,7 @@ gnttab_release_dev_mappings(grant_table_
   1.380                  if ( rd != NULL )
   1.381                      put_domain(rd);
   1.382  
   1.383 -                printk(KERN_WARNING "Grant release: Could not find domain %d\n", dom);
   1.384 +                printk(KERN_WARNING "Grant release: No dom%d\n", dom);
   1.385                  continue;
   1.386              }
   1.387  
   1.388 @@ -1215,7 +1215,7 @@ grant_table_destroy(
   1.389          /* Free memory relating to this grant table. */
   1.390          d->grant_table = NULL;
   1.391          free_xenheap_pages((unsigned long)t->shared, ORDER_GRANT_FRAMES);
   1.392 -        free_xenheap_page((unsigned long)t->maptrack); //cwc22
   1.393 +        free_xenheap_page((unsigned long)t->maptrack);
   1.394          xfree(t->active);
   1.395          xfree(t);
   1.396      }