direct-io.hg
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>
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 }