1*45748Smckusick /* 2*45748Smckusick * Copyright (c) 1985, Avadis Tevanian, Jr., Michael Wayne Young 3*45748Smckusick * Copyright (c) 1987 Carnegie-Mellon University 4*45748Smckusick * Copyright (c) 1991 Regents of the University of California. 5*45748Smckusick * All rights reserved. 6*45748Smckusick * 7*45748Smckusick * This code is derived from software contributed to Berkeley by 8*45748Smckusick * The Mach Operating System project at Carnegie-Mellon University. 9*45748Smckusick * 10*45748Smckusick * The CMU software License Agreement specifies the terms and conditions 11*45748Smckusick * for use and redistribution. 12*45748Smckusick * 13*45748Smckusick * @(#)vm_map.c 7.1 (Berkeley) 12/05/90 14*45748Smckusick */ 15*45748Smckusick 16*45748Smckusick /* 17*45748Smckusick * Virtual memory mapping module. 18*45748Smckusick */ 19*45748Smckusick 20*45748Smckusick #include "types.h" 21*45748Smckusick #include "malloc.h" 22*45748Smckusick #include "../vm/vm_param.h" 23*45748Smckusick #include "../vm/vm_map.h" 24*45748Smckusick #include "../vm/vm_page.h" 25*45748Smckusick #include "../vm/vm_object.h" 26*45748Smckusick 27*45748Smckusick /* 28*45748Smckusick * Virtual memory maps provide for the mapping, protection, 29*45748Smckusick * and sharing of virtual memory objects. In addition, 30*45748Smckusick * this module provides for an efficient virtual copy of 31*45748Smckusick * memory from one map to another. 32*45748Smckusick * 33*45748Smckusick * Synchronization is required prior to most operations. 34*45748Smckusick * 35*45748Smckusick * Maps consist of an ordered doubly-linked list of simple 36*45748Smckusick * entries; a single hint is used to speed up lookups. 37*45748Smckusick * 38*45748Smckusick * In order to properly represent the sharing of virtual 39*45748Smckusick * memory regions among maps, the map structure is bi-level. 40*45748Smckusick * Top-level ("address") maps refer to regions of sharable 41*45748Smckusick * virtual memory. These regions are implemented as 42*45748Smckusick * ("sharing") maps, which then refer to the actual virtual 43*45748Smckusick * memory objects. When two address maps "share" memory, 44*45748Smckusick * their top-level maps both have references to the same 45*45748Smckusick * sharing map. When memory is virtual-copied from one 46*45748Smckusick * address map to another, the references in the sharing 47*45748Smckusick * maps are actually copied -- no copying occurs at the 48*45748Smckusick * virtual memory object level. 49*45748Smckusick * 50*45748Smckusick * Since portions of maps are specified by start/end addreses, 51*45748Smckusick * which may not align with existing map entries, all 52*45748Smckusick * routines merely "clip" entries to these start/end values. 53*45748Smckusick * [That is, an entry is split into two, bordering at a 54*45748Smckusick * start or end value.] Note that these clippings may not 55*45748Smckusick * always be necessary (as the two resulting entries are then 56*45748Smckusick * not changed); however, the clipping is done for convenience. 57*45748Smckusick * No attempt is currently made to "glue back together" two 58*45748Smckusick * abutting entries. 59*45748Smckusick * 60*45748Smckusick * As mentioned above, virtual copy operations are performed 61*45748Smckusick * by copying VM object references from one sharing map to 62*45748Smckusick * another, and then marking both regions as copy-on-write. 63*45748Smckusick * It is important to note that only one writeable reference 64*45748Smckusick * to a VM object region exists in any map -- this means that 65*45748Smckusick * shadow object creation can be delayed until a write operation 66*45748Smckusick * occurs. 67*45748Smckusick */ 68*45748Smckusick 69*45748Smckusick /* 70*45748Smckusick * vm_map_init: 71*45748Smckusick * 72*45748Smckusick * Initialize the vm_map module. Must be called before 73*45748Smckusick * any other vm_map routines. 74*45748Smckusick * 75*45748Smckusick * Map and entry structures are allocated from the general 76*45748Smckusick * purpose memory pool with some exceptions: 77*45748Smckusick * 78*45748Smckusick * - The kernel map and kmem submap are allocated statically. 79*45748Smckusick * - Kernel map entries are allocated out of a static pool. 80*45748Smckusick * 81*45748Smckusick * These restrictions are necessary since malloc() uses the 82*45748Smckusick * maps and requires map entries. 83*45748Smckusick */ 84*45748Smckusick 85*45748Smckusick vm_offset_t kentry_data; 86*45748Smckusick vm_size_t kentry_data_size; 87*45748Smckusick vm_map_entry_t kentry_free; 88*45748Smckusick vm_map_t kmap_free; 89*45748Smckusick 90*45748Smckusick void vm_map_init() 91*45748Smckusick { 92*45748Smckusick register int i; 93*45748Smckusick register vm_map_entry_t mep; 94*45748Smckusick vm_map_t mp; 95*45748Smckusick 96*45748Smckusick /* 97*45748Smckusick * Static map structures for allocation before initialization of 98*45748Smckusick * kernel map or kmem map. vm_map_create knows how to deal with them. 99*45748Smckusick */ 100*45748Smckusick kmap_free = mp = (vm_map_t) kentry_data; 101*45748Smckusick i = MAX_KMAP; 102*45748Smckusick while (--i > 0) { 103*45748Smckusick mp->header.next = (vm_map_entry_t) (mp + 1); 104*45748Smckusick mp++; 105*45748Smckusick } 106*45748Smckusick mp++->header.next = VM_MAP_ENTRY_NULL; 107*45748Smckusick 108*45748Smckusick /* 109*45748Smckusick * Form a free list of statically allocated kernel map entries 110*45748Smckusick * with the rest. 111*45748Smckusick */ 112*45748Smckusick kentry_free = mep = (vm_map_entry_t) mp; 113*45748Smckusick i = (kentry_data_size - MAX_KMAP * sizeof *mp) / sizeof *mep; 114*45748Smckusick while (--i > 0) { 115*45748Smckusick mep->next = mep + 1; 116*45748Smckusick mep++; 117*45748Smckusick } 118*45748Smckusick mep->next = VM_MAP_ENTRY_NULL; 119*45748Smckusick } 120*45748Smckusick 121*45748Smckusick /* 122*45748Smckusick * vm_map_create: 123*45748Smckusick * 124*45748Smckusick * Creates and returns a new empty VM map with 125*45748Smckusick * the given physical map structure, and having 126*45748Smckusick * the given lower and upper address bounds. 127*45748Smckusick */ 128*45748Smckusick vm_map_t vm_map_create(pmap, min, max, pageable) 129*45748Smckusick pmap_t pmap; 130*45748Smckusick vm_offset_t min, max; 131*45748Smckusick boolean_t pageable; 132*45748Smckusick { 133*45748Smckusick register vm_map_t result; 134*45748Smckusick extern vm_map_t kernel_map, kmem_map; 135*45748Smckusick 136*45748Smckusick if (kmem_map == VM_MAP_NULL) { 137*45748Smckusick result = kmap_free; 138*45748Smckusick kmap_free = (vm_map_t) result->header.next; 139*45748Smckusick } else 140*45748Smckusick MALLOC(result, vm_map_t, sizeof(struct vm_map), 141*45748Smckusick M_VMMAP, M_WAITOK); 142*45748Smckusick 143*45748Smckusick if (result == VM_MAP_NULL) 144*45748Smckusick panic("vm_map_create: out of maps"); 145*45748Smckusick 146*45748Smckusick result->header.next = result->header.prev = &result->header; 147*45748Smckusick result->nentries = 0; 148*45748Smckusick result->size = 0; 149*45748Smckusick result->ref_count = 1; 150*45748Smckusick result->pmap = pmap; 151*45748Smckusick result->is_main_map = TRUE; 152*45748Smckusick result->min_offset = min; 153*45748Smckusick result->max_offset = max; 154*45748Smckusick result->entries_pageable = pageable; 155*45748Smckusick result->first_free = &result->header; 156*45748Smckusick result->hint = &result->header; 157*45748Smckusick result->timestamp = 0; 158*45748Smckusick lock_init(&result->lock, TRUE); 159*45748Smckusick simple_lock_init(&result->ref_lock); 160*45748Smckusick simple_lock_init(&result->hint_lock); 161*45748Smckusick return(result); 162*45748Smckusick } 163*45748Smckusick 164*45748Smckusick /* 165*45748Smckusick * vm_map_entry_create: [ internal use only ] 166*45748Smckusick * 167*45748Smckusick * Allocates a VM map entry for insertion. 168*45748Smckusick * No entry fields are filled in. This routine is 169*45748Smckusick */ 170*45748Smckusick vm_map_entry_t vm_map_entry_create(map) 171*45748Smckusick vm_map_t map; 172*45748Smckusick { 173*45748Smckusick vm_map_entry_t entry; 174*45748Smckusick extern vm_map_t kernel_map, kmem_map, mb_map; 175*45748Smckusick 176*45748Smckusick if (map == kernel_map || map == kmem_map || map == mb_map) { 177*45748Smckusick if (entry = kentry_free) 178*45748Smckusick kentry_free = kentry_free->next; 179*45748Smckusick } else 180*45748Smckusick MALLOC(entry, vm_map_entry_t, sizeof(struct vm_map_entry), 181*45748Smckusick M_VMMAPENT, M_WAITOK); 182*45748Smckusick if (entry == VM_MAP_ENTRY_NULL) 183*45748Smckusick panic("vm_map_entry_create: out of map entries"); 184*45748Smckusick 185*45748Smckusick return(entry); 186*45748Smckusick } 187*45748Smckusick 188*45748Smckusick /* 189*45748Smckusick * vm_map_entry_dispose: [ internal use only ] 190*45748Smckusick * 191*45748Smckusick * Inverse of vm_map_entry_create. 192*45748Smckusick */ 193*45748Smckusick void vm_map_entry_dispose(map, entry) 194*45748Smckusick vm_map_t map; 195*45748Smckusick vm_map_entry_t entry; 196*45748Smckusick { 197*45748Smckusick extern vm_map_t kernel_map, kmem_map, mb_map; 198*45748Smckusick 199*45748Smckusick if (map == kernel_map || map == kmem_map || map == mb_map) { 200*45748Smckusick entry->next = kentry_free; 201*45748Smckusick kentry_free = entry; 202*45748Smckusick } else 203*45748Smckusick FREE(entry, M_VMMAPENT); 204*45748Smckusick } 205*45748Smckusick 206*45748Smckusick /* 207*45748Smckusick * vm_map_entry_{un,}link: 208*45748Smckusick * 209*45748Smckusick * Insert/remove entries from maps. 210*45748Smckusick */ 211*45748Smckusick #define vm_map_entry_link(map, after_where, entry) \ 212*45748Smckusick { \ 213*45748Smckusick (map)->nentries++; \ 214*45748Smckusick (entry)->prev = (after_where); \ 215*45748Smckusick (entry)->next = (after_where)->next; \ 216*45748Smckusick (entry)->prev->next = (entry); \ 217*45748Smckusick (entry)->next->prev = (entry); \ 218*45748Smckusick } 219*45748Smckusick #define vm_map_entry_unlink(map, entry) \ 220*45748Smckusick { \ 221*45748Smckusick (map)->nentries--; \ 222*45748Smckusick (entry)->next->prev = (entry)->prev; \ 223*45748Smckusick (entry)->prev->next = (entry)->next; \ 224*45748Smckusick } 225*45748Smckusick 226*45748Smckusick /* 227*45748Smckusick * vm_map_reference: 228*45748Smckusick * 229*45748Smckusick * Creates another valid reference to the given map. 230*45748Smckusick * 231*45748Smckusick */ 232*45748Smckusick void vm_map_reference(map) 233*45748Smckusick register vm_map_t map; 234*45748Smckusick { 235*45748Smckusick if (map == VM_MAP_NULL) 236*45748Smckusick return; 237*45748Smckusick 238*45748Smckusick simple_lock(&map->ref_lock); 239*45748Smckusick map->ref_count++; 240*45748Smckusick simple_unlock(&map->ref_lock); 241*45748Smckusick } 242*45748Smckusick 243*45748Smckusick /* 244*45748Smckusick * vm_map_deallocate: 245*45748Smckusick * 246*45748Smckusick * Removes a reference from the specified map, 247*45748Smckusick * destroying it if no references remain. 248*45748Smckusick * The map should not be locked. 249*45748Smckusick */ 250*45748Smckusick void vm_map_deallocate(map) 251*45748Smckusick register vm_map_t map; 252*45748Smckusick { 253*45748Smckusick register int c; 254*45748Smckusick 255*45748Smckusick if (map == VM_MAP_NULL) 256*45748Smckusick return; 257*45748Smckusick 258*45748Smckusick simple_lock(&map->ref_lock); 259*45748Smckusick c = --map->ref_count; 260*45748Smckusick simple_unlock(&map->ref_lock); 261*45748Smckusick 262*45748Smckusick if (c > 0) { 263*45748Smckusick return; 264*45748Smckusick } 265*45748Smckusick 266*45748Smckusick /* 267*45748Smckusick * Lock the map, to wait out all other references 268*45748Smckusick * to it. 269*45748Smckusick */ 270*45748Smckusick 271*45748Smckusick vm_map_lock(map); 272*45748Smckusick 273*45748Smckusick (void) vm_map_delete(map, map->min_offset, map->max_offset); 274*45748Smckusick 275*45748Smckusick pmap_destroy(map->pmap); 276*45748Smckusick 277*45748Smckusick FREE(map, M_VMMAP); 278*45748Smckusick } 279*45748Smckusick 280*45748Smckusick /* 281*45748Smckusick * vm_map_insert: [ internal use only ] 282*45748Smckusick * 283*45748Smckusick * Inserts the given whole VM object into the target 284*45748Smckusick * map at the specified address range. The object's 285*45748Smckusick * size should match that of the address range. 286*45748Smckusick * 287*45748Smckusick * Requires that the map be locked, and leaves it so. 288*45748Smckusick */ 289*45748Smckusick vm_map_insert(map, object, offset, start, end) 290*45748Smckusick vm_map_t map; 291*45748Smckusick vm_object_t object; 292*45748Smckusick vm_offset_t offset; 293*45748Smckusick vm_offset_t start; 294*45748Smckusick vm_offset_t end; 295*45748Smckusick { 296*45748Smckusick register vm_map_entry_t new_entry; 297*45748Smckusick register vm_map_entry_t prev_entry; 298*45748Smckusick vm_map_entry_t temp_entry; 299*45748Smckusick 300*45748Smckusick /* 301*45748Smckusick * Check that the start and end points are not bogus. 302*45748Smckusick */ 303*45748Smckusick 304*45748Smckusick if ((start < map->min_offset) || (end > map->max_offset) || 305*45748Smckusick (start >= end)) 306*45748Smckusick return(KERN_INVALID_ADDRESS); 307*45748Smckusick 308*45748Smckusick /* 309*45748Smckusick * Find the entry prior to the proposed 310*45748Smckusick * starting address; if it's part of an 311*45748Smckusick * existing entry, this range is bogus. 312*45748Smckusick */ 313*45748Smckusick 314*45748Smckusick if (vm_map_lookup_entry(map, start, &temp_entry)) 315*45748Smckusick return(KERN_NO_SPACE); 316*45748Smckusick 317*45748Smckusick prev_entry = temp_entry; 318*45748Smckusick 319*45748Smckusick /* 320*45748Smckusick * Assert that the next entry doesn't overlap the 321*45748Smckusick * end point. 322*45748Smckusick */ 323*45748Smckusick 324*45748Smckusick if ((prev_entry->next != &map->header) && 325*45748Smckusick (prev_entry->next->start < end)) 326*45748Smckusick return(KERN_NO_SPACE); 327*45748Smckusick 328*45748Smckusick /* 329*45748Smckusick * See if we can avoid creating a new entry by 330*45748Smckusick * extending one of our neighbors. 331*45748Smckusick */ 332*45748Smckusick 333*45748Smckusick if (object == VM_OBJECT_NULL) { 334*45748Smckusick if ((prev_entry != &map->header) && 335*45748Smckusick (prev_entry->end == start) && 336*45748Smckusick (map->is_main_map) && 337*45748Smckusick (prev_entry->is_a_map == FALSE) && 338*45748Smckusick (prev_entry->is_sub_map == FALSE) && 339*45748Smckusick (prev_entry->inheritance == VM_INHERIT_DEFAULT) && 340*45748Smckusick (prev_entry->protection == VM_PROT_DEFAULT) && 341*45748Smckusick (prev_entry->max_protection == VM_PROT_DEFAULT) && 342*45748Smckusick (prev_entry->wired_count == 0)) { 343*45748Smckusick 344*45748Smckusick if (vm_object_coalesce(prev_entry->object.vm_object, 345*45748Smckusick VM_OBJECT_NULL, 346*45748Smckusick prev_entry->offset, 347*45748Smckusick (vm_offset_t) 0, 348*45748Smckusick (vm_size_t)(prev_entry->end 349*45748Smckusick - prev_entry->start), 350*45748Smckusick (vm_size_t)(end - prev_entry->end))) { 351*45748Smckusick /* 352*45748Smckusick * Coalesced the two objects - can extend 353*45748Smckusick * the previous map entry to include the 354*45748Smckusick * new range. 355*45748Smckusick */ 356*45748Smckusick map->size += (end - prev_entry->end); 357*45748Smckusick prev_entry->end = end; 358*45748Smckusick return(KERN_SUCCESS); 359*45748Smckusick } 360*45748Smckusick } 361*45748Smckusick } 362*45748Smckusick 363*45748Smckusick /* 364*45748Smckusick * Create a new entry 365*45748Smckusick */ 366*45748Smckusick 367*45748Smckusick new_entry = vm_map_entry_create(map); 368*45748Smckusick new_entry->start = start; 369*45748Smckusick new_entry->end = end; 370*45748Smckusick 371*45748Smckusick new_entry->is_a_map = FALSE; 372*45748Smckusick new_entry->is_sub_map = FALSE; 373*45748Smckusick new_entry->object.vm_object = object; 374*45748Smckusick new_entry->offset = offset; 375*45748Smckusick 376*45748Smckusick new_entry->copy_on_write = FALSE; 377*45748Smckusick new_entry->needs_copy = FALSE; 378*45748Smckusick 379*45748Smckusick if (map->is_main_map) { 380*45748Smckusick new_entry->inheritance = VM_INHERIT_DEFAULT; 381*45748Smckusick new_entry->protection = VM_PROT_DEFAULT; 382*45748Smckusick new_entry->max_protection = VM_PROT_DEFAULT; 383*45748Smckusick new_entry->wired_count = 0; 384*45748Smckusick } 385*45748Smckusick 386*45748Smckusick /* 387*45748Smckusick * Insert the new entry into the list 388*45748Smckusick */ 389*45748Smckusick 390*45748Smckusick vm_map_entry_link(map, prev_entry, new_entry); 391*45748Smckusick map->size += new_entry->end - new_entry->start; 392*45748Smckusick 393*45748Smckusick /* 394*45748Smckusick * Update the free space hint 395*45748Smckusick */ 396*45748Smckusick 397*45748Smckusick if ((map->first_free == prev_entry) && (prev_entry->end >= new_entry->start)) 398*45748Smckusick map->first_free = new_entry; 399*45748Smckusick 400*45748Smckusick return(KERN_SUCCESS); 401*45748Smckusick } 402*45748Smckusick 403*45748Smckusick /* 404*45748Smckusick * SAVE_HINT: 405*45748Smckusick * 406*45748Smckusick * Saves the specified entry as the hint for 407*45748Smckusick * future lookups. Performs necessary interlocks. 408*45748Smckusick */ 409*45748Smckusick #define SAVE_HINT(map,value) \ 410*45748Smckusick simple_lock(&(map)->hint_lock); \ 411*45748Smckusick (map)->hint = (value); \ 412*45748Smckusick simple_unlock(&(map)->hint_lock); 413*45748Smckusick 414*45748Smckusick /* 415*45748Smckusick * vm_map_lookup_entry: [ internal use only ] 416*45748Smckusick * 417*45748Smckusick * Finds the map entry containing (or 418*45748Smckusick * immediately preceding) the specified address 419*45748Smckusick * in the given map; the entry is returned 420*45748Smckusick * in the "entry" parameter. The boolean 421*45748Smckusick * result indicates whether the address is 422*45748Smckusick * actually contained in the map. 423*45748Smckusick */ 424*45748Smckusick boolean_t vm_map_lookup_entry(map, address, entry) 425*45748Smckusick register vm_map_t map; 426*45748Smckusick register vm_offset_t address; 427*45748Smckusick vm_map_entry_t *entry; /* OUT */ 428*45748Smckusick { 429*45748Smckusick register vm_map_entry_t cur; 430*45748Smckusick register vm_map_entry_t last; 431*45748Smckusick 432*45748Smckusick /* 433*45748Smckusick * Start looking either from the head of the 434*45748Smckusick * list, or from the hint. 435*45748Smckusick */ 436*45748Smckusick 437*45748Smckusick simple_lock(&map->hint_lock); 438*45748Smckusick cur = map->hint; 439*45748Smckusick simple_unlock(&map->hint_lock); 440*45748Smckusick 441*45748Smckusick if (cur == &map->header) 442*45748Smckusick cur = cur->next; 443*45748Smckusick 444*45748Smckusick if (address >= cur->start) { 445*45748Smckusick /* 446*45748Smckusick * Go from hint to end of list. 447*45748Smckusick * 448*45748Smckusick * But first, make a quick check to see if 449*45748Smckusick * we are already looking at the entry we 450*45748Smckusick * want (which is usually the case). 451*45748Smckusick * Note also that we don't need to save the hint 452*45748Smckusick * here... it is the same hint (unless we are 453*45748Smckusick * at the header, in which case the hint didn't 454*45748Smckusick * buy us anything anyway). 455*45748Smckusick */ 456*45748Smckusick last = &map->header; 457*45748Smckusick if ((cur != last) && (cur->end > address)) { 458*45748Smckusick *entry = cur; 459*45748Smckusick return(TRUE); 460*45748Smckusick } 461*45748Smckusick } 462*45748Smckusick else { 463*45748Smckusick /* 464*45748Smckusick * Go from start to hint, *inclusively* 465*45748Smckusick */ 466*45748Smckusick last = cur->next; 467*45748Smckusick cur = map->header.next; 468*45748Smckusick } 469*45748Smckusick 470*45748Smckusick /* 471*45748Smckusick * Search linearly 472*45748Smckusick */ 473*45748Smckusick 474*45748Smckusick while (cur != last) { 475*45748Smckusick if (cur->end > address) { 476*45748Smckusick if (address >= cur->start) { 477*45748Smckusick /* 478*45748Smckusick * Save this lookup for future 479*45748Smckusick * hints, and return 480*45748Smckusick */ 481*45748Smckusick 482*45748Smckusick *entry = cur; 483*45748Smckusick SAVE_HINT(map, cur); 484*45748Smckusick return(TRUE); 485*45748Smckusick } 486*45748Smckusick break; 487*45748Smckusick } 488*45748Smckusick cur = cur->next; 489*45748Smckusick } 490*45748Smckusick *entry = cur->prev; 491*45748Smckusick SAVE_HINT(map, *entry); 492*45748Smckusick return(FALSE); 493*45748Smckusick } 494*45748Smckusick 495*45748Smckusick /* 496*45748Smckusick * vm_map_find finds an unallocated region in the target address 497*45748Smckusick * map with the given length. The search is defined to be 498*45748Smckusick * first-fit from the specified address; the region found is 499*45748Smckusick * returned in the same parameter. 500*45748Smckusick * 501*45748Smckusick */ 502*45748Smckusick vm_map_find(map, object, offset, addr, length, find_space) 503*45748Smckusick vm_map_t map; 504*45748Smckusick vm_object_t object; 505*45748Smckusick vm_offset_t offset; 506*45748Smckusick vm_offset_t *addr; /* IN/OUT */ 507*45748Smckusick vm_size_t length; 508*45748Smckusick boolean_t find_space; 509*45748Smckusick { 510*45748Smckusick register vm_map_entry_t entry; 511*45748Smckusick register vm_offset_t start; 512*45748Smckusick register vm_offset_t end; 513*45748Smckusick int result; 514*45748Smckusick 515*45748Smckusick start = *addr; 516*45748Smckusick 517*45748Smckusick vm_map_lock(map); 518*45748Smckusick 519*45748Smckusick if (find_space) { 520*45748Smckusick /* 521*45748Smckusick * Calculate the first possible address. 522*45748Smckusick */ 523*45748Smckusick 524*45748Smckusick if (start < map->min_offset) 525*45748Smckusick start = map->min_offset; 526*45748Smckusick if (start > map->max_offset) { 527*45748Smckusick vm_map_unlock(map); 528*45748Smckusick return (KERN_NO_SPACE); 529*45748Smckusick } 530*45748Smckusick 531*45748Smckusick /* 532*45748Smckusick * Look for the first possible address; 533*45748Smckusick * if there's already something at this 534*45748Smckusick * address, we have to start after it. 535*45748Smckusick */ 536*45748Smckusick 537*45748Smckusick if (start == map->min_offset) { 538*45748Smckusick if ((entry = map->first_free) != &map->header) 539*45748Smckusick start = entry->end; 540*45748Smckusick } else { 541*45748Smckusick vm_map_entry_t tmp_entry; 542*45748Smckusick if (vm_map_lookup_entry(map, start, &tmp_entry)) 543*45748Smckusick start = tmp_entry->end; 544*45748Smckusick entry = tmp_entry; 545*45748Smckusick } 546*45748Smckusick 547*45748Smckusick /* 548*45748Smckusick * In any case, the "entry" always precedes 549*45748Smckusick * the proposed new region throughout the 550*45748Smckusick * loop: 551*45748Smckusick */ 552*45748Smckusick 553*45748Smckusick while (TRUE) { 554*45748Smckusick register vm_map_entry_t next; 555*45748Smckusick 556*45748Smckusick /* 557*45748Smckusick * Find the end of the proposed new region. 558*45748Smckusick * Be sure we didn't go beyond the end, or 559*45748Smckusick * wrap around the address. 560*45748Smckusick */ 561*45748Smckusick 562*45748Smckusick end = start + length; 563*45748Smckusick 564*45748Smckusick if ((end > map->max_offset) || (end < start)) { 565*45748Smckusick vm_map_unlock(map); 566*45748Smckusick return (KERN_NO_SPACE); 567*45748Smckusick } 568*45748Smckusick 569*45748Smckusick /* 570*45748Smckusick * If there are no more entries, we must win. 571*45748Smckusick */ 572*45748Smckusick 573*45748Smckusick next = entry->next; 574*45748Smckusick if (next == &map->header) 575*45748Smckusick break; 576*45748Smckusick 577*45748Smckusick /* 578*45748Smckusick * If there is another entry, it must be 579*45748Smckusick * after the end of the potential new region. 580*45748Smckusick */ 581*45748Smckusick 582*45748Smckusick if (next->start >= end) 583*45748Smckusick break; 584*45748Smckusick 585*45748Smckusick /* 586*45748Smckusick * Didn't fit -- move to the next entry. 587*45748Smckusick */ 588*45748Smckusick 589*45748Smckusick entry = next; 590*45748Smckusick start = entry->end; 591*45748Smckusick } 592*45748Smckusick *addr = start; 593*45748Smckusick 594*45748Smckusick SAVE_HINT(map, entry); 595*45748Smckusick } 596*45748Smckusick 597*45748Smckusick result = vm_map_insert(map, object, offset, start, start + length); 598*45748Smckusick 599*45748Smckusick vm_map_unlock(map); 600*45748Smckusick return(result); 601*45748Smckusick } 602*45748Smckusick 603*45748Smckusick /* 604*45748Smckusick * vm_map_simplify_entry: [ internal use only ] 605*45748Smckusick * 606*45748Smckusick * Simplify the given map entry by: 607*45748Smckusick * removing extra sharing maps 608*45748Smckusick * [XXX maybe later] merging with a neighbor 609*45748Smckusick */ 610*45748Smckusick void vm_map_simplify_entry(map, entry) 611*45748Smckusick vm_map_t map; 612*45748Smckusick vm_map_entry_t entry; 613*45748Smckusick { 614*45748Smckusick #ifdef lint 615*45748Smckusick map++; 616*45748Smckusick #endif lint 617*45748Smckusick 618*45748Smckusick /* 619*45748Smckusick * If this entry corresponds to a sharing map, then 620*45748Smckusick * see if we can remove the level of indirection. 621*45748Smckusick * If it's not a sharing map, then it points to 622*45748Smckusick * a VM object, so see if we can merge with either 623*45748Smckusick * of our neighbors. 624*45748Smckusick */ 625*45748Smckusick 626*45748Smckusick if (entry->is_sub_map) 627*45748Smckusick return; 628*45748Smckusick if (entry->is_a_map) { 629*45748Smckusick #if 0 630*45748Smckusick vm_map_t my_share_map; 631*45748Smckusick int count; 632*45748Smckusick 633*45748Smckusick my_share_map = entry->object.share_map; 634*45748Smckusick simple_lock(&my_share_map->ref_lock); 635*45748Smckusick count = my_share_map->ref_count; 636*45748Smckusick simple_unlock(&my_share_map->ref_lock); 637*45748Smckusick 638*45748Smckusick if (count == 1) { 639*45748Smckusick /* Can move the region from 640*45748Smckusick * entry->start to entry->end (+ entry->offset) 641*45748Smckusick * in my_share_map into place of entry. 642*45748Smckusick * Later. 643*45748Smckusick */ 644*45748Smckusick } 645*45748Smckusick #endif 0 646*45748Smckusick } 647*45748Smckusick else { 648*45748Smckusick /* 649*45748Smckusick * Try to merge with our neighbors. 650*45748Smckusick * 651*45748Smckusick * Conditions for merge are: 652*45748Smckusick * 653*45748Smckusick * 1. entries are adjacent. 654*45748Smckusick * 2. both entries point to objects 655*45748Smckusick * with null pagers. 656*45748Smckusick * 657*45748Smckusick * If a merge is possible, we replace the two 658*45748Smckusick * entries with a single entry, then merge 659*45748Smckusick * the two objects into a single object. 660*45748Smckusick * 661*45748Smckusick * Now, all that is left to do is write the 662*45748Smckusick * code! 663*45748Smckusick */ 664*45748Smckusick } 665*45748Smckusick } 666*45748Smckusick 667*45748Smckusick /* 668*45748Smckusick * vm_map_clip_start: [ internal use only ] 669*45748Smckusick * 670*45748Smckusick * Asserts that the given entry begins at or after 671*45748Smckusick * the specified address; if necessary, 672*45748Smckusick * it splits the entry into two. 673*45748Smckusick */ 674*45748Smckusick #define vm_map_clip_start(map, entry, startaddr) \ 675*45748Smckusick { \ 676*45748Smckusick if (startaddr > entry->start) \ 677*45748Smckusick _vm_map_clip_start(map, entry, startaddr); \ 678*45748Smckusick } 679*45748Smckusick 680*45748Smckusick /* 681*45748Smckusick * This routine is called only when it is known that 682*45748Smckusick * the entry must be split. 683*45748Smckusick */ 684*45748Smckusick void _vm_map_clip_start(map, entry, start) 685*45748Smckusick register vm_map_t map; 686*45748Smckusick register vm_map_entry_t entry; 687*45748Smckusick register vm_offset_t start; 688*45748Smckusick { 689*45748Smckusick register vm_map_entry_t new_entry; 690*45748Smckusick 691*45748Smckusick /* 692*45748Smckusick * See if we can simplify this entry first 693*45748Smckusick */ 694*45748Smckusick 695*45748Smckusick vm_map_simplify_entry(map, entry); 696*45748Smckusick 697*45748Smckusick /* 698*45748Smckusick * Split off the front portion -- 699*45748Smckusick * note that we must insert the new 700*45748Smckusick * entry BEFORE this one, so that 701*45748Smckusick * this entry has the specified starting 702*45748Smckusick * address. 703*45748Smckusick */ 704*45748Smckusick 705*45748Smckusick new_entry = vm_map_entry_create(map); 706*45748Smckusick *new_entry = *entry; 707*45748Smckusick 708*45748Smckusick new_entry->end = start; 709*45748Smckusick entry->offset += (start - entry->start); 710*45748Smckusick entry->start = start; 711*45748Smckusick 712*45748Smckusick vm_map_entry_link(map, entry->prev, new_entry); 713*45748Smckusick 714*45748Smckusick if (entry->is_a_map || entry->is_sub_map) 715*45748Smckusick vm_map_reference(new_entry->object.share_map); 716*45748Smckusick else 717*45748Smckusick vm_object_reference(new_entry->object.vm_object); 718*45748Smckusick } 719*45748Smckusick 720*45748Smckusick /* 721*45748Smckusick * vm_map_clip_end: [ internal use only ] 722*45748Smckusick * 723*45748Smckusick * Asserts that the given entry ends at or before 724*45748Smckusick * the specified address; if necessary, 725*45748Smckusick * it splits the entry into two. 726*45748Smckusick */ 727*45748Smckusick 728*45748Smckusick void _vm_map_clip_end(); 729*45748Smckusick #define vm_map_clip_end(map, entry, endaddr) \ 730*45748Smckusick { \ 731*45748Smckusick if (endaddr < entry->end) \ 732*45748Smckusick _vm_map_clip_end(map, entry, endaddr); \ 733*45748Smckusick } 734*45748Smckusick 735*45748Smckusick /* 736*45748Smckusick * This routine is called only when it is known that 737*45748Smckusick * the entry must be split. 738*45748Smckusick */ 739*45748Smckusick void _vm_map_clip_end(map, entry, end) 740*45748Smckusick register vm_map_t map; 741*45748Smckusick register vm_map_entry_t entry; 742*45748Smckusick register vm_offset_t end; 743*45748Smckusick { 744*45748Smckusick register vm_map_entry_t new_entry; 745*45748Smckusick 746*45748Smckusick /* 747*45748Smckusick * Create a new entry and insert it 748*45748Smckusick * AFTER the specified entry 749*45748Smckusick */ 750*45748Smckusick 751*45748Smckusick new_entry = vm_map_entry_create(map); 752*45748Smckusick *new_entry = *entry; 753*45748Smckusick 754*45748Smckusick new_entry->start = entry->end = end; 755*45748Smckusick new_entry->offset += (end - entry->start); 756*45748Smckusick 757*45748Smckusick vm_map_entry_link(map, entry, new_entry); 758*45748Smckusick 759*45748Smckusick if (entry->is_a_map || entry->is_sub_map) 760*45748Smckusick vm_map_reference(new_entry->object.share_map); 761*45748Smckusick else 762*45748Smckusick vm_object_reference(new_entry->object.vm_object); 763*45748Smckusick } 764*45748Smckusick 765*45748Smckusick /* 766*45748Smckusick * VM_MAP_RANGE_CHECK: [ internal use only ] 767*45748Smckusick * 768*45748Smckusick * Asserts that the starting and ending region 769*45748Smckusick * addresses fall within the valid range of the map. 770*45748Smckusick */ 771*45748Smckusick #define VM_MAP_RANGE_CHECK(map, start, end) \ 772*45748Smckusick { \ 773*45748Smckusick if (start < vm_map_min(map)) \ 774*45748Smckusick start = vm_map_min(map); \ 775*45748Smckusick if (end > vm_map_max(map)) \ 776*45748Smckusick end = vm_map_max(map); \ 777*45748Smckusick if (start > end) \ 778*45748Smckusick start = end; \ 779*45748Smckusick } 780*45748Smckusick 781*45748Smckusick /* 782*45748Smckusick * vm_map_submap: [ kernel use only ] 783*45748Smckusick * 784*45748Smckusick * Mark the given range as handled by a subordinate map. 785*45748Smckusick * 786*45748Smckusick * This range must have been created with vm_map_find, 787*45748Smckusick * and no other operations may have been performed on this 788*45748Smckusick * range prior to calling vm_map_submap. 789*45748Smckusick * 790*45748Smckusick * Only a limited number of operations can be performed 791*45748Smckusick * within this rage after calling vm_map_submap: 792*45748Smckusick * vm_fault 793*45748Smckusick * [Don't try vm_map_copy!] 794*45748Smckusick * 795*45748Smckusick * To remove a submapping, one must first remove the 796*45748Smckusick * range from the superior map, and then destroy the 797*45748Smckusick * submap (if desired). [Better yet, don't try it.] 798*45748Smckusick */ 799*45748Smckusick vm_map_submap(map, start, end, submap) 800*45748Smckusick register vm_map_t map; 801*45748Smckusick register vm_offset_t start; 802*45748Smckusick register vm_offset_t end; 803*45748Smckusick vm_map_t submap; 804*45748Smckusick { 805*45748Smckusick vm_map_entry_t entry; 806*45748Smckusick register int result = KERN_INVALID_ARGUMENT; 807*45748Smckusick 808*45748Smckusick vm_map_lock(map); 809*45748Smckusick 810*45748Smckusick VM_MAP_RANGE_CHECK(map, start, end); 811*45748Smckusick 812*45748Smckusick if (vm_map_lookup_entry(map, start, &entry)) { 813*45748Smckusick vm_map_clip_start(map, entry, start); 814*45748Smckusick } 815*45748Smckusick else 816*45748Smckusick entry = entry->next; 817*45748Smckusick 818*45748Smckusick vm_map_clip_end(map, entry, end); 819*45748Smckusick 820*45748Smckusick if ((entry->start == start) && (entry->end == end) && 821*45748Smckusick (!entry->is_a_map) && 822*45748Smckusick (entry->object.vm_object == VM_OBJECT_NULL) && 823*45748Smckusick (!entry->copy_on_write)) { 824*45748Smckusick entry->is_a_map = FALSE; 825*45748Smckusick entry->is_sub_map = TRUE; 826*45748Smckusick vm_map_reference(entry->object.sub_map = submap); 827*45748Smckusick result = KERN_SUCCESS; 828*45748Smckusick } 829*45748Smckusick vm_map_unlock(map); 830*45748Smckusick 831*45748Smckusick return(result); 832*45748Smckusick } 833*45748Smckusick 834*45748Smckusick /* 835*45748Smckusick * vm_map_protect: 836*45748Smckusick * 837*45748Smckusick * Sets the protection of the specified address 838*45748Smckusick * region in the target map. If "set_max" is 839*45748Smckusick * specified, the maximum protection is to be set; 840*45748Smckusick * otherwise, only the current protection is affected. 841*45748Smckusick */ 842*45748Smckusick vm_map_protect(map, start, end, new_prot, set_max) 843*45748Smckusick register vm_map_t map; 844*45748Smckusick register vm_offset_t start; 845*45748Smckusick register vm_offset_t end; 846*45748Smckusick register vm_prot_t new_prot; 847*45748Smckusick register boolean_t set_max; 848*45748Smckusick { 849*45748Smckusick register vm_map_entry_t current; 850*45748Smckusick vm_map_entry_t entry; 851*45748Smckusick 852*45748Smckusick vm_map_lock(map); 853*45748Smckusick 854*45748Smckusick VM_MAP_RANGE_CHECK(map, start, end); 855*45748Smckusick 856*45748Smckusick if (vm_map_lookup_entry(map, start, &entry)) { 857*45748Smckusick vm_map_clip_start(map, entry, start); 858*45748Smckusick } 859*45748Smckusick else 860*45748Smckusick entry = entry->next; 861*45748Smckusick 862*45748Smckusick /* 863*45748Smckusick * Make a first pass to check for protection 864*45748Smckusick * violations. 865*45748Smckusick */ 866*45748Smckusick 867*45748Smckusick current = entry; 868*45748Smckusick while ((current != &map->header) && (current->start < end)) { 869*45748Smckusick if (current->is_sub_map) 870*45748Smckusick return(KERN_INVALID_ARGUMENT); 871*45748Smckusick if ((new_prot & current->max_protection) != new_prot) { 872*45748Smckusick vm_map_unlock(map); 873*45748Smckusick return(KERN_PROTECTION_FAILURE); 874*45748Smckusick } 875*45748Smckusick 876*45748Smckusick current = current->next; 877*45748Smckusick } 878*45748Smckusick 879*45748Smckusick /* 880*45748Smckusick * Go back and fix up protections. 881*45748Smckusick * [Note that clipping is not necessary the second time.] 882*45748Smckusick */ 883*45748Smckusick 884*45748Smckusick current = entry; 885*45748Smckusick 886*45748Smckusick while ((current != &map->header) && (current->start < end)) { 887*45748Smckusick vm_prot_t old_prot; 888*45748Smckusick 889*45748Smckusick vm_map_clip_end(map, current, end); 890*45748Smckusick 891*45748Smckusick old_prot = current->protection; 892*45748Smckusick if (set_max) 893*45748Smckusick current->protection = 894*45748Smckusick (current->max_protection = new_prot) & 895*45748Smckusick old_prot; 896*45748Smckusick else 897*45748Smckusick current->protection = new_prot; 898*45748Smckusick 899*45748Smckusick /* 900*45748Smckusick * Update physical map if necessary. 901*45748Smckusick * Worry about copy-on-write here -- CHECK THIS XXX 902*45748Smckusick */ 903*45748Smckusick 904*45748Smckusick if (current->protection != old_prot) { 905*45748Smckusick 906*45748Smckusick #define MASK(entry) ((entry)->copy_on_write ? ~VM_PROT_WRITE : \ 907*45748Smckusick VM_PROT_ALL) 908*45748Smckusick #define max(a,b) ((a) > (b) ? (a) : (b)) 909*45748Smckusick 910*45748Smckusick if (current->is_a_map) { 911*45748Smckusick vm_map_entry_t share_entry; 912*45748Smckusick vm_offset_t share_end; 913*45748Smckusick 914*45748Smckusick vm_map_lock(current->object.share_map); 915*45748Smckusick (void) vm_map_lookup_entry( 916*45748Smckusick current->object.share_map, 917*45748Smckusick current->offset, 918*45748Smckusick &share_entry); 919*45748Smckusick share_end = current->offset + 920*45748Smckusick (current->end - current->start); 921*45748Smckusick while ((share_entry != 922*45748Smckusick ¤t->object.share_map->header) && 923*45748Smckusick (share_entry->start < share_end)) { 924*45748Smckusick 925*45748Smckusick pmap_protect(map->pmap, 926*45748Smckusick (max(share_entry->start, 927*45748Smckusick current->offset) - 928*45748Smckusick current->offset + 929*45748Smckusick current->start), 930*45748Smckusick min(share_entry->end, 931*45748Smckusick share_end) - 932*45748Smckusick current->offset + 933*45748Smckusick current->start, 934*45748Smckusick current->protection & 935*45748Smckusick MASK(share_entry)); 936*45748Smckusick 937*45748Smckusick share_entry = share_entry->next; 938*45748Smckusick } 939*45748Smckusick vm_map_unlock(current->object.share_map); 940*45748Smckusick } 941*45748Smckusick else 942*45748Smckusick pmap_protect(map->pmap, current->start, 943*45748Smckusick current->end, 944*45748Smckusick current->protection & MASK(entry)); 945*45748Smckusick #undef max 946*45748Smckusick #undef MASK 947*45748Smckusick } 948*45748Smckusick current = current->next; 949*45748Smckusick } 950*45748Smckusick 951*45748Smckusick vm_map_unlock(map); 952*45748Smckusick return(KERN_SUCCESS); 953*45748Smckusick } 954*45748Smckusick 955*45748Smckusick /* 956*45748Smckusick * vm_map_inherit: 957*45748Smckusick * 958*45748Smckusick * Sets the inheritance of the specified address 959*45748Smckusick * range in the target map. Inheritance 960*45748Smckusick * affects how the map will be shared with 961*45748Smckusick * child maps at the time of vm_map_fork. 962*45748Smckusick */ 963*45748Smckusick vm_map_inherit(map, start, end, new_inheritance) 964*45748Smckusick register vm_map_t map; 965*45748Smckusick register vm_offset_t start; 966*45748Smckusick register vm_offset_t end; 967*45748Smckusick register vm_inherit_t new_inheritance; 968*45748Smckusick { 969*45748Smckusick register vm_map_entry_t entry; 970*45748Smckusick vm_map_entry_t temp_entry; 971*45748Smckusick 972*45748Smckusick switch (new_inheritance) { 973*45748Smckusick case VM_INHERIT_NONE: 974*45748Smckusick case VM_INHERIT_COPY: 975*45748Smckusick case VM_INHERIT_SHARE: 976*45748Smckusick break; 977*45748Smckusick default: 978*45748Smckusick return(KERN_INVALID_ARGUMENT); 979*45748Smckusick } 980*45748Smckusick 981*45748Smckusick vm_map_lock(map); 982*45748Smckusick 983*45748Smckusick VM_MAP_RANGE_CHECK(map, start, end); 984*45748Smckusick 985*45748Smckusick if (vm_map_lookup_entry(map, start, &temp_entry)) { 986*45748Smckusick entry = temp_entry; 987*45748Smckusick vm_map_clip_start(map, entry, start); 988*45748Smckusick } 989*45748Smckusick else 990*45748Smckusick entry = temp_entry->next; 991*45748Smckusick 992*45748Smckusick while ((entry != &map->header) && (entry->start < end)) { 993*45748Smckusick vm_map_clip_end(map, entry, end); 994*45748Smckusick 995*45748Smckusick entry->inheritance = new_inheritance; 996*45748Smckusick 997*45748Smckusick entry = entry->next; 998*45748Smckusick } 999*45748Smckusick 1000*45748Smckusick vm_map_unlock(map); 1001*45748Smckusick return(KERN_SUCCESS); 1002*45748Smckusick } 1003*45748Smckusick 1004*45748Smckusick /* 1005*45748Smckusick * vm_map_pageable: 1006*45748Smckusick * 1007*45748Smckusick * Sets the pageability of the specified address 1008*45748Smckusick * range in the target map. Regions specified 1009*45748Smckusick * as not pageable require locked-down physical 1010*45748Smckusick * memory and physical page maps. 1011*45748Smckusick * 1012*45748Smckusick * The map must not be locked, but a reference 1013*45748Smckusick * must remain to the map throughout the call. 1014*45748Smckusick */ 1015*45748Smckusick vm_map_pageable(map, start, end, new_pageable) 1016*45748Smckusick register vm_map_t map; 1017*45748Smckusick register vm_offset_t start; 1018*45748Smckusick register vm_offset_t end; 1019*45748Smckusick register boolean_t new_pageable; 1020*45748Smckusick { 1021*45748Smckusick register vm_map_entry_t entry; 1022*45748Smckusick vm_map_entry_t temp_entry; 1023*45748Smckusick 1024*45748Smckusick vm_map_lock(map); 1025*45748Smckusick 1026*45748Smckusick VM_MAP_RANGE_CHECK(map, start, end); 1027*45748Smckusick 1028*45748Smckusick /* 1029*45748Smckusick * Only one pageability change may take place at one 1030*45748Smckusick * time, since vm_fault assumes it will be called 1031*45748Smckusick * only once for each wiring/unwiring. Therefore, we 1032*45748Smckusick * have to make sure we're actually changing the pageability 1033*45748Smckusick * for the entire region. We do so before making any changes. 1034*45748Smckusick */ 1035*45748Smckusick 1036*45748Smckusick if (vm_map_lookup_entry(map, start, &temp_entry)) { 1037*45748Smckusick entry = temp_entry; 1038*45748Smckusick vm_map_clip_start(map, entry, start); 1039*45748Smckusick } 1040*45748Smckusick else 1041*45748Smckusick entry = temp_entry->next; 1042*45748Smckusick temp_entry = entry; 1043*45748Smckusick 1044*45748Smckusick /* 1045*45748Smckusick * Actions are rather different for wiring and unwiring, 1046*45748Smckusick * so we have two separate cases. 1047*45748Smckusick */ 1048*45748Smckusick 1049*45748Smckusick if (new_pageable) { 1050*45748Smckusick 1051*45748Smckusick /* 1052*45748Smckusick * Unwiring. First ensure that the range to be 1053*45748Smckusick * unwired is really wired down. 1054*45748Smckusick */ 1055*45748Smckusick while ((entry != &map->header) && (entry->start < end)) { 1056*45748Smckusick 1057*45748Smckusick if (entry->wired_count == 0) { 1058*45748Smckusick vm_map_unlock(map); 1059*45748Smckusick return(KERN_INVALID_ARGUMENT); 1060*45748Smckusick } 1061*45748Smckusick entry = entry->next; 1062*45748Smckusick } 1063*45748Smckusick 1064*45748Smckusick /* 1065*45748Smckusick * Now decrement the wiring count for each region. 1066*45748Smckusick * If a region becomes completely unwired, 1067*45748Smckusick * unwire its physical pages and mappings. 1068*45748Smckusick */ 1069*45748Smckusick lock_set_recursive(&map->lock); 1070*45748Smckusick 1071*45748Smckusick entry = temp_entry; 1072*45748Smckusick while ((entry != &map->header) && (entry->start < end)) { 1073*45748Smckusick vm_map_clip_end(map, entry, end); 1074*45748Smckusick 1075*45748Smckusick entry->wired_count--; 1076*45748Smckusick if (entry->wired_count == 0) 1077*45748Smckusick vm_fault_unwire(map, entry->start, entry->end); 1078*45748Smckusick 1079*45748Smckusick entry = entry->next; 1080*45748Smckusick } 1081*45748Smckusick lock_clear_recursive(&map->lock); 1082*45748Smckusick } 1083*45748Smckusick 1084*45748Smckusick else { 1085*45748Smckusick /* 1086*45748Smckusick * Wiring. We must do this in two passes: 1087*45748Smckusick * 1088*45748Smckusick * 1. Holding the write lock, we increment the 1089*45748Smckusick * wiring count. For any area that is not already 1090*45748Smckusick * wired, we create any shadow objects that need 1091*45748Smckusick * to be created. 1092*45748Smckusick * 1093*45748Smckusick * 2. We downgrade to a read lock, and call 1094*45748Smckusick * vm_fault_wire to fault in the pages for any 1095*45748Smckusick * newly wired area (wired_count is 1). 1096*45748Smckusick * 1097*45748Smckusick * Downgrading to a read lock for vm_fault_wire avoids 1098*45748Smckusick * a possible deadlock with another thread that may have 1099*45748Smckusick * faulted on one of the pages to be wired (it would mark 1100*45748Smckusick * the page busy, blocking us, then in turn block on the 1101*45748Smckusick * map lock that we hold). Because of problems in the 1102*45748Smckusick * recursive lock package, we cannot upgrade to a write 1103*45748Smckusick * lock in vm_map_lookup. Thus, any actions that require 1104*45748Smckusick * the write lock must be done beforehand. Because we 1105*45748Smckusick * keep the read lock on the map, the copy-on-write status 1106*45748Smckusick * of the entries we modify here cannot change. 1107*45748Smckusick */ 1108*45748Smckusick 1109*45748Smckusick /* 1110*45748Smckusick * Pass 1. 1111*45748Smckusick */ 1112*45748Smckusick entry = temp_entry; 1113*45748Smckusick while ((entry != &map->header) && (entry->start < end)) { 1114*45748Smckusick vm_map_clip_end(map, entry, end); 1115*45748Smckusick 1116*45748Smckusick entry->wired_count++; 1117*45748Smckusick if (entry->wired_count == 1) { 1118*45748Smckusick 1119*45748Smckusick /* 1120*45748Smckusick * Perform actions of vm_map_lookup that need 1121*45748Smckusick * the write lock on the map: create a shadow 1122*45748Smckusick * object for a copy-on-write region, or an 1123*45748Smckusick * object for a zero-fill region. 1124*45748Smckusick * 1125*45748Smckusick * We don't have to do this for entries that 1126*45748Smckusick * point to sharing maps, because we won't hold 1127*45748Smckusick * the lock on the sharing map. 1128*45748Smckusick */ 1129*45748Smckusick if (!entry->is_a_map) { 1130*45748Smckusick if (entry->needs_copy && 1131*45748Smckusick ((entry->protection & VM_PROT_WRITE) != 0)) { 1132*45748Smckusick 1133*45748Smckusick vm_object_shadow(&entry->object.vm_object, 1134*45748Smckusick &entry->offset, 1135*45748Smckusick (vm_size_t)(entry->end 1136*45748Smckusick - entry->start)); 1137*45748Smckusick entry->needs_copy = FALSE; 1138*45748Smckusick } 1139*45748Smckusick else if (entry->object.vm_object == VM_OBJECT_NULL) { 1140*45748Smckusick entry->object.vm_object = 1141*45748Smckusick vm_object_allocate((vm_size_t)(entry->end 1142*45748Smckusick - entry->start)); 1143*45748Smckusick entry->offset = (vm_offset_t)0; 1144*45748Smckusick } 1145*45748Smckusick } 1146*45748Smckusick } 1147*45748Smckusick 1148*45748Smckusick entry = entry->next; 1149*45748Smckusick } 1150*45748Smckusick 1151*45748Smckusick /* 1152*45748Smckusick * Pass 2. 1153*45748Smckusick */ 1154*45748Smckusick 1155*45748Smckusick /* 1156*45748Smckusick * HACK HACK HACK HACK 1157*45748Smckusick * 1158*45748Smckusick * If we are wiring in the kernel map or a submap of it, 1159*45748Smckusick * unlock the map to avoid deadlocks. We trust that the 1160*45748Smckusick * kernel threads are well-behaved, and therefore will 1161*45748Smckusick * not do anything destructive to this region of the map 1162*45748Smckusick * while we have it unlocked. We cannot trust user threads 1163*45748Smckusick * to do the same. 1164*45748Smckusick * 1165*45748Smckusick * HACK HACK HACK HACK 1166*45748Smckusick */ 1167*45748Smckusick if (vm_map_pmap(map) == kernel_pmap) { 1168*45748Smckusick vm_map_unlock(map); /* trust me ... */ 1169*45748Smckusick } 1170*45748Smckusick else { 1171*45748Smckusick lock_set_recursive(&map->lock); 1172*45748Smckusick lock_write_to_read(&map->lock); 1173*45748Smckusick } 1174*45748Smckusick 1175*45748Smckusick entry = temp_entry; 1176*45748Smckusick while (entry != &map->header && entry->start < end) { 1177*45748Smckusick if (entry->wired_count == 1) { 1178*45748Smckusick vm_fault_wire(map, entry->start, entry->end); 1179*45748Smckusick } 1180*45748Smckusick entry = entry->next; 1181*45748Smckusick } 1182*45748Smckusick 1183*45748Smckusick if (vm_map_pmap(map) == kernel_pmap) { 1184*45748Smckusick vm_map_lock(map); 1185*45748Smckusick } 1186*45748Smckusick else { 1187*45748Smckusick lock_clear_recursive(&map->lock); 1188*45748Smckusick } 1189*45748Smckusick } 1190*45748Smckusick 1191*45748Smckusick vm_map_unlock(map); 1192*45748Smckusick 1193*45748Smckusick return(KERN_SUCCESS); 1194*45748Smckusick } 1195*45748Smckusick 1196*45748Smckusick /* 1197*45748Smckusick * vm_map_entry_unwire: [ internal use only ] 1198*45748Smckusick * 1199*45748Smckusick * Make the region specified by this entry pageable. 1200*45748Smckusick * 1201*45748Smckusick * The map in question should be locked. 1202*45748Smckusick * [This is the reason for this routine's existence.] 1203*45748Smckusick */ 1204*45748Smckusick void vm_map_entry_unwire(map, entry) 1205*45748Smckusick vm_map_t map; 1206*45748Smckusick register vm_map_entry_t entry; 1207*45748Smckusick { 1208*45748Smckusick vm_fault_unwire(map, entry->start, entry->end); 1209*45748Smckusick entry->wired_count = 0; 1210*45748Smckusick } 1211*45748Smckusick 1212*45748Smckusick /* 1213*45748Smckusick * vm_map_entry_delete: [ internal use only ] 1214*45748Smckusick * 1215*45748Smckusick * Deallocate the given entry from the target map. 1216*45748Smckusick */ 1217*45748Smckusick void vm_map_entry_delete(map, entry) 1218*45748Smckusick register vm_map_t map; 1219*45748Smckusick register vm_map_entry_t entry; 1220*45748Smckusick { 1221*45748Smckusick if (entry->wired_count != 0) 1222*45748Smckusick vm_map_entry_unwire(map, entry); 1223*45748Smckusick 1224*45748Smckusick vm_map_entry_unlink(map, entry); 1225*45748Smckusick map->size -= entry->end - entry->start; 1226*45748Smckusick 1227*45748Smckusick if (entry->is_a_map || entry->is_sub_map) 1228*45748Smckusick vm_map_deallocate(entry->object.share_map); 1229*45748Smckusick else 1230*45748Smckusick vm_object_deallocate(entry->object.vm_object); 1231*45748Smckusick 1232*45748Smckusick vm_map_entry_dispose(map, entry); 1233*45748Smckusick } 1234*45748Smckusick 1235*45748Smckusick /* 1236*45748Smckusick * vm_map_delete: [ internal use only ] 1237*45748Smckusick * 1238*45748Smckusick * Deallocates the given address range from the target 1239*45748Smckusick * map. 1240*45748Smckusick * 1241*45748Smckusick * When called with a sharing map, removes pages from 1242*45748Smckusick * that region from all physical maps. 1243*45748Smckusick */ 1244*45748Smckusick vm_map_delete(map, start, end) 1245*45748Smckusick register vm_map_t map; 1246*45748Smckusick vm_offset_t start; 1247*45748Smckusick register vm_offset_t end; 1248*45748Smckusick { 1249*45748Smckusick register vm_map_entry_t entry; 1250*45748Smckusick vm_map_entry_t first_entry; 1251*45748Smckusick 1252*45748Smckusick /* 1253*45748Smckusick * Find the start of the region, and clip it 1254*45748Smckusick */ 1255*45748Smckusick 1256*45748Smckusick if (!vm_map_lookup_entry(map, start, &first_entry)) 1257*45748Smckusick entry = first_entry->next; 1258*45748Smckusick else { 1259*45748Smckusick entry = first_entry; 1260*45748Smckusick vm_map_clip_start(map, entry, start); 1261*45748Smckusick 1262*45748Smckusick /* 1263*45748Smckusick * Fix the lookup hint now, rather than each 1264*45748Smckusick * time though the loop. 1265*45748Smckusick */ 1266*45748Smckusick 1267*45748Smckusick SAVE_HINT(map, entry->prev); 1268*45748Smckusick } 1269*45748Smckusick 1270*45748Smckusick /* 1271*45748Smckusick * Save the free space hint 1272*45748Smckusick */ 1273*45748Smckusick 1274*45748Smckusick if (map->first_free->start >= start) 1275*45748Smckusick map->first_free = entry->prev; 1276*45748Smckusick 1277*45748Smckusick /* 1278*45748Smckusick * Step through all entries in this region 1279*45748Smckusick */ 1280*45748Smckusick 1281*45748Smckusick while ((entry != &map->header) && (entry->start < end)) { 1282*45748Smckusick vm_map_entry_t next; 1283*45748Smckusick register vm_offset_t s, e; 1284*45748Smckusick register vm_object_t object; 1285*45748Smckusick 1286*45748Smckusick vm_map_clip_end(map, entry, end); 1287*45748Smckusick 1288*45748Smckusick next = entry->next; 1289*45748Smckusick s = entry->start; 1290*45748Smckusick e = entry->end; 1291*45748Smckusick 1292*45748Smckusick /* 1293*45748Smckusick * Unwire before removing addresses from the pmap; 1294*45748Smckusick * otherwise, unwiring will put the entries back in 1295*45748Smckusick * the pmap. 1296*45748Smckusick */ 1297*45748Smckusick 1298*45748Smckusick object = entry->object.vm_object; 1299*45748Smckusick if (entry->wired_count != 0) 1300*45748Smckusick vm_map_entry_unwire(map, entry); 1301*45748Smckusick 1302*45748Smckusick /* 1303*45748Smckusick * If this is a sharing map, we must remove 1304*45748Smckusick * *all* references to this data, since we can't 1305*45748Smckusick * find all of the physical maps which are sharing 1306*45748Smckusick * it. 1307*45748Smckusick */ 1308*45748Smckusick 1309*45748Smckusick if (object == kernel_object || object == kmem_object) 1310*45748Smckusick vm_object_page_remove(object, entry->offset, 1311*45748Smckusick entry->offset + (e - s)); 1312*45748Smckusick else if (!map->is_main_map) 1313*45748Smckusick vm_object_pmap_remove(object, 1314*45748Smckusick entry->offset, 1315*45748Smckusick entry->offset + (e - s)); 1316*45748Smckusick else 1317*45748Smckusick pmap_remove(map->pmap, s, e); 1318*45748Smckusick 1319*45748Smckusick /* 1320*45748Smckusick * Delete the entry (which may delete the object) 1321*45748Smckusick * only after removing all pmap entries pointing 1322*45748Smckusick * to its pages. (Otherwise, its page frames may 1323*45748Smckusick * be reallocated, and any modify bits will be 1324*45748Smckusick * set in the wrong object!) 1325*45748Smckusick */ 1326*45748Smckusick 1327*45748Smckusick vm_map_entry_delete(map, entry); 1328*45748Smckusick entry = next; 1329*45748Smckusick } 1330*45748Smckusick return(KERN_SUCCESS); 1331*45748Smckusick } 1332*45748Smckusick 1333*45748Smckusick /* 1334*45748Smckusick * vm_map_remove: 1335*45748Smckusick * 1336*45748Smckusick * Remove the given address range from the target map. 1337*45748Smckusick * This is the exported form of vm_map_delete. 1338*45748Smckusick */ 1339*45748Smckusick vm_map_remove(map, start, end) 1340*45748Smckusick register vm_map_t map; 1341*45748Smckusick register vm_offset_t start; 1342*45748Smckusick register vm_offset_t end; 1343*45748Smckusick { 1344*45748Smckusick register int result; 1345*45748Smckusick 1346*45748Smckusick vm_map_lock(map); 1347*45748Smckusick VM_MAP_RANGE_CHECK(map, start, end); 1348*45748Smckusick result = vm_map_delete(map, start, end); 1349*45748Smckusick vm_map_unlock(map); 1350*45748Smckusick 1351*45748Smckusick return(result); 1352*45748Smckusick } 1353*45748Smckusick 1354*45748Smckusick /* 1355*45748Smckusick * vm_map_check_protection: 1356*45748Smckusick * 1357*45748Smckusick * Assert that the target map allows the specified 1358*45748Smckusick * privilege on the entire address region given. 1359*45748Smckusick * The entire region must be allocated. 1360*45748Smckusick */ 1361*45748Smckusick boolean_t vm_map_check_protection(map, start, end, protection) 1362*45748Smckusick register vm_map_t map; 1363*45748Smckusick register vm_offset_t start; 1364*45748Smckusick register vm_offset_t end; 1365*45748Smckusick register vm_prot_t protection; 1366*45748Smckusick { 1367*45748Smckusick register vm_map_entry_t entry; 1368*45748Smckusick vm_map_entry_t tmp_entry; 1369*45748Smckusick 1370*45748Smckusick if (!vm_map_lookup_entry(map, start, &tmp_entry)) { 1371*45748Smckusick return(FALSE); 1372*45748Smckusick } 1373*45748Smckusick 1374*45748Smckusick entry = tmp_entry; 1375*45748Smckusick 1376*45748Smckusick while (start < end) { 1377*45748Smckusick if (entry == &map->header) { 1378*45748Smckusick return(FALSE); 1379*45748Smckusick } 1380*45748Smckusick 1381*45748Smckusick /* 1382*45748Smckusick * No holes allowed! 1383*45748Smckusick */ 1384*45748Smckusick 1385*45748Smckusick if (start < entry->start) { 1386*45748Smckusick return(FALSE); 1387*45748Smckusick } 1388*45748Smckusick 1389*45748Smckusick /* 1390*45748Smckusick * Check protection associated with entry. 1391*45748Smckusick */ 1392*45748Smckusick 1393*45748Smckusick if ((entry->protection & protection) != protection) { 1394*45748Smckusick return(FALSE); 1395*45748Smckusick } 1396*45748Smckusick 1397*45748Smckusick /* go to next entry */ 1398*45748Smckusick 1399*45748Smckusick start = entry->end; 1400*45748Smckusick entry = entry->next; 1401*45748Smckusick } 1402*45748Smckusick return(TRUE); 1403*45748Smckusick } 1404*45748Smckusick 1405*45748Smckusick /* 1406*45748Smckusick * vm_map_copy_entry: 1407*45748Smckusick * 1408*45748Smckusick * Copies the contents of the source entry to the destination 1409*45748Smckusick * entry. The entries *must* be aligned properly. 1410*45748Smckusick */ 1411*45748Smckusick void vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry) 1412*45748Smckusick vm_map_t src_map, dst_map; 1413*45748Smckusick register vm_map_entry_t src_entry, dst_entry; 1414*45748Smckusick { 1415*45748Smckusick vm_object_t temp_object; 1416*45748Smckusick 1417*45748Smckusick if (src_entry->is_sub_map || dst_entry->is_sub_map) 1418*45748Smckusick return; 1419*45748Smckusick 1420*45748Smckusick if (dst_entry->object.vm_object != VM_OBJECT_NULL && 1421*45748Smckusick !dst_entry->object.vm_object->internal) 1422*45748Smckusick printf("vm_map_copy_entry: copying over permanent data!\n"); 1423*45748Smckusick 1424*45748Smckusick /* 1425*45748Smckusick * If our destination map was wired down, 1426*45748Smckusick * unwire it now. 1427*45748Smckusick */ 1428*45748Smckusick 1429*45748Smckusick if (dst_entry->wired_count != 0) 1430*45748Smckusick vm_map_entry_unwire(dst_map, dst_entry); 1431*45748Smckusick 1432*45748Smckusick /* 1433*45748Smckusick * If we're dealing with a sharing map, we 1434*45748Smckusick * must remove the destination pages from 1435*45748Smckusick * all maps (since we cannot know which maps 1436*45748Smckusick * this sharing map belongs in). 1437*45748Smckusick */ 1438*45748Smckusick 1439*45748Smckusick if (dst_map->is_main_map) 1440*45748Smckusick pmap_remove(dst_map->pmap, dst_entry->start, dst_entry->end); 1441*45748Smckusick else 1442*45748Smckusick vm_object_pmap_remove(dst_entry->object.vm_object, 1443*45748Smckusick dst_entry->offset, 1444*45748Smckusick dst_entry->offset + 1445*45748Smckusick (dst_entry->end - dst_entry->start)); 1446*45748Smckusick 1447*45748Smckusick if (src_entry->wired_count == 0) { 1448*45748Smckusick 1449*45748Smckusick boolean_t src_needs_copy; 1450*45748Smckusick 1451*45748Smckusick /* 1452*45748Smckusick * If the source entry is marked needs_copy, 1453*45748Smckusick * it is already write-protected. 1454*45748Smckusick */ 1455*45748Smckusick if (!src_entry->needs_copy) { 1456*45748Smckusick 1457*45748Smckusick boolean_t su; 1458*45748Smckusick 1459*45748Smckusick /* 1460*45748Smckusick * If the source entry has only one mapping, 1461*45748Smckusick * we can just protect the virtual address 1462*45748Smckusick * range. 1463*45748Smckusick */ 1464*45748Smckusick if (!(su = src_map->is_main_map)) { 1465*45748Smckusick simple_lock(&src_map->ref_lock); 1466*45748Smckusick su = (src_map->ref_count == 1); 1467*45748Smckusick simple_unlock(&src_map->ref_lock); 1468*45748Smckusick } 1469*45748Smckusick 1470*45748Smckusick if (su) { 1471*45748Smckusick pmap_protect(src_map->pmap, 1472*45748Smckusick src_entry->start, 1473*45748Smckusick src_entry->end, 1474*45748Smckusick src_entry->protection & ~VM_PROT_WRITE); 1475*45748Smckusick } 1476*45748Smckusick else { 1477*45748Smckusick vm_object_pmap_copy(src_entry->object.vm_object, 1478*45748Smckusick src_entry->offset, 1479*45748Smckusick src_entry->offset + (src_entry->end 1480*45748Smckusick -src_entry->start)); 1481*45748Smckusick } 1482*45748Smckusick } 1483*45748Smckusick 1484*45748Smckusick /* 1485*45748Smckusick * Make a copy of the object. 1486*45748Smckusick */ 1487*45748Smckusick temp_object = dst_entry->object.vm_object; 1488*45748Smckusick vm_object_copy(src_entry->object.vm_object, 1489*45748Smckusick src_entry->offset, 1490*45748Smckusick (vm_size_t)(src_entry->end - 1491*45748Smckusick src_entry->start), 1492*45748Smckusick &dst_entry->object.vm_object, 1493*45748Smckusick &dst_entry->offset, 1494*45748Smckusick &src_needs_copy); 1495*45748Smckusick /* 1496*45748Smckusick * If we didn't get a copy-object now, mark the 1497*45748Smckusick * source map entry so that a shadow will be created 1498*45748Smckusick * to hold its changed pages. 1499*45748Smckusick */ 1500*45748Smckusick if (src_needs_copy) 1501*45748Smckusick src_entry->needs_copy = TRUE; 1502*45748Smckusick 1503*45748Smckusick /* 1504*45748Smckusick * The destination always needs to have a shadow 1505*45748Smckusick * created. 1506*45748Smckusick */ 1507*45748Smckusick dst_entry->needs_copy = TRUE; 1508*45748Smckusick 1509*45748Smckusick /* 1510*45748Smckusick * Mark the entries copy-on-write, so that write-enabling 1511*45748Smckusick * the entry won't make copy-on-write pages writable. 1512*45748Smckusick */ 1513*45748Smckusick src_entry->copy_on_write = TRUE; 1514*45748Smckusick dst_entry->copy_on_write = TRUE; 1515*45748Smckusick /* 1516*45748Smckusick * Get rid of the old object. 1517*45748Smckusick */ 1518*45748Smckusick vm_object_deallocate(temp_object); 1519*45748Smckusick 1520*45748Smckusick pmap_copy(dst_map->pmap, src_map->pmap, dst_entry->start, 1521*45748Smckusick dst_entry->end - dst_entry->start, src_entry->start); 1522*45748Smckusick } 1523*45748Smckusick else { 1524*45748Smckusick /* 1525*45748Smckusick * Of course, wired down pages can't be set copy-on-write. 1526*45748Smckusick * Cause wired pages to be copied into the new 1527*45748Smckusick * map by simulating faults (the new pages are 1528*45748Smckusick * pageable) 1529*45748Smckusick */ 1530*45748Smckusick vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry); 1531*45748Smckusick } 1532*45748Smckusick } 1533*45748Smckusick 1534*45748Smckusick /* 1535*45748Smckusick * vm_map_copy: 1536*45748Smckusick * 1537*45748Smckusick * Perform a virtual memory copy from the source 1538*45748Smckusick * address map/range to the destination map/range. 1539*45748Smckusick * 1540*45748Smckusick * If src_destroy or dst_alloc is requested, 1541*45748Smckusick * the source and destination regions should be 1542*45748Smckusick * disjoint, not only in the top-level map, but 1543*45748Smckusick * in the sharing maps as well. [The best way 1544*45748Smckusick * to guarantee this is to use a new intermediate 1545*45748Smckusick * map to make copies. This also reduces map 1546*45748Smckusick * fragmentation.] 1547*45748Smckusick */ 1548*45748Smckusick vm_map_copy(dst_map, src_map, 1549*45748Smckusick dst_addr, len, src_addr, 1550*45748Smckusick dst_alloc, src_destroy) 1551*45748Smckusick vm_map_t dst_map; 1552*45748Smckusick vm_map_t src_map; 1553*45748Smckusick vm_offset_t dst_addr; 1554*45748Smckusick vm_size_t len; 1555*45748Smckusick vm_offset_t src_addr; 1556*45748Smckusick boolean_t dst_alloc; 1557*45748Smckusick boolean_t src_destroy; 1558*45748Smckusick { 1559*45748Smckusick register 1560*45748Smckusick vm_map_entry_t src_entry; 1561*45748Smckusick register 1562*45748Smckusick vm_map_entry_t dst_entry; 1563*45748Smckusick vm_map_entry_t tmp_entry; 1564*45748Smckusick vm_offset_t src_start; 1565*45748Smckusick vm_offset_t src_end; 1566*45748Smckusick vm_offset_t dst_start; 1567*45748Smckusick vm_offset_t dst_end; 1568*45748Smckusick vm_offset_t src_clip; 1569*45748Smckusick vm_offset_t dst_clip; 1570*45748Smckusick int result; 1571*45748Smckusick boolean_t old_src_destroy; 1572*45748Smckusick 1573*45748Smckusick /* 1574*45748Smckusick * XXX While we figure out why src_destroy screws up, 1575*45748Smckusick * we'll do it by explicitly vm_map_delete'ing at the end. 1576*45748Smckusick */ 1577*45748Smckusick 1578*45748Smckusick old_src_destroy = src_destroy; 1579*45748Smckusick src_destroy = FALSE; 1580*45748Smckusick 1581*45748Smckusick /* 1582*45748Smckusick * Compute start and end of region in both maps 1583*45748Smckusick */ 1584*45748Smckusick 1585*45748Smckusick src_start = src_addr; 1586*45748Smckusick src_end = src_start + len; 1587*45748Smckusick dst_start = dst_addr; 1588*45748Smckusick dst_end = dst_start + len; 1589*45748Smckusick 1590*45748Smckusick /* 1591*45748Smckusick * Check that the region can exist in both source 1592*45748Smckusick * and destination. 1593*45748Smckusick */ 1594*45748Smckusick 1595*45748Smckusick if ((dst_end < dst_start) || (src_end < src_start)) 1596*45748Smckusick return(KERN_NO_SPACE); 1597*45748Smckusick 1598*45748Smckusick /* 1599*45748Smckusick * Lock the maps in question -- we avoid deadlock 1600*45748Smckusick * by ordering lock acquisition by map value 1601*45748Smckusick */ 1602*45748Smckusick 1603*45748Smckusick if (src_map == dst_map) { 1604*45748Smckusick vm_map_lock(src_map); 1605*45748Smckusick } 1606*45748Smckusick else if ((int) src_map < (int) dst_map) { 1607*45748Smckusick vm_map_lock(src_map); 1608*45748Smckusick vm_map_lock(dst_map); 1609*45748Smckusick } else { 1610*45748Smckusick vm_map_lock(dst_map); 1611*45748Smckusick vm_map_lock(src_map); 1612*45748Smckusick } 1613*45748Smckusick 1614*45748Smckusick result = KERN_SUCCESS; 1615*45748Smckusick 1616*45748Smckusick /* 1617*45748Smckusick * Check protections... source must be completely readable and 1618*45748Smckusick * destination must be completely writable. [Note that if we're 1619*45748Smckusick * allocating the destination region, we don't have to worry 1620*45748Smckusick * about protection, but instead about whether the region 1621*45748Smckusick * exists.] 1622*45748Smckusick */ 1623*45748Smckusick 1624*45748Smckusick if (src_map->is_main_map && dst_map->is_main_map) { 1625*45748Smckusick if (!vm_map_check_protection(src_map, src_start, src_end, 1626*45748Smckusick VM_PROT_READ)) { 1627*45748Smckusick result = KERN_PROTECTION_FAILURE; 1628*45748Smckusick goto Return; 1629*45748Smckusick } 1630*45748Smckusick 1631*45748Smckusick if (dst_alloc) { 1632*45748Smckusick /* XXX Consider making this a vm_map_find instead */ 1633*45748Smckusick if ((result = vm_map_insert(dst_map, VM_OBJECT_NULL, 1634*45748Smckusick (vm_offset_t) 0, dst_start, dst_end)) != KERN_SUCCESS) 1635*45748Smckusick goto Return; 1636*45748Smckusick } 1637*45748Smckusick else if (!vm_map_check_protection(dst_map, dst_start, dst_end, 1638*45748Smckusick VM_PROT_WRITE)) { 1639*45748Smckusick result = KERN_PROTECTION_FAILURE; 1640*45748Smckusick goto Return; 1641*45748Smckusick } 1642*45748Smckusick } 1643*45748Smckusick 1644*45748Smckusick /* 1645*45748Smckusick * Find the start entries and clip. 1646*45748Smckusick * 1647*45748Smckusick * Note that checking protection asserts that the 1648*45748Smckusick * lookup cannot fail. 1649*45748Smckusick * 1650*45748Smckusick * Also note that we wait to do the second lookup 1651*45748Smckusick * until we have done the first clip, as the clip 1652*45748Smckusick * may affect which entry we get! 1653*45748Smckusick */ 1654*45748Smckusick 1655*45748Smckusick (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry); 1656*45748Smckusick src_entry = tmp_entry; 1657*45748Smckusick vm_map_clip_start(src_map, src_entry, src_start); 1658*45748Smckusick 1659*45748Smckusick (void) vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry); 1660*45748Smckusick dst_entry = tmp_entry; 1661*45748Smckusick vm_map_clip_start(dst_map, dst_entry, dst_start); 1662*45748Smckusick 1663*45748Smckusick /* 1664*45748Smckusick * If both source and destination entries are the same, 1665*45748Smckusick * retry the first lookup, as it may have changed. 1666*45748Smckusick */ 1667*45748Smckusick 1668*45748Smckusick if (src_entry == dst_entry) { 1669*45748Smckusick (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry); 1670*45748Smckusick src_entry = tmp_entry; 1671*45748Smckusick } 1672*45748Smckusick 1673*45748Smckusick /* 1674*45748Smckusick * If source and destination entries are still the same, 1675*45748Smckusick * a null copy is being performed. 1676*45748Smckusick */ 1677*45748Smckusick 1678*45748Smckusick if (src_entry == dst_entry) 1679*45748Smckusick goto Return; 1680*45748Smckusick 1681*45748Smckusick /* 1682*45748Smckusick * Go through entries until we get to the end of the 1683*45748Smckusick * region. 1684*45748Smckusick */ 1685*45748Smckusick 1686*45748Smckusick while (src_start < src_end) { 1687*45748Smckusick /* 1688*45748Smckusick * Clip the entries to the endpoint of the entire region. 1689*45748Smckusick */ 1690*45748Smckusick 1691*45748Smckusick vm_map_clip_end(src_map, src_entry, src_end); 1692*45748Smckusick vm_map_clip_end(dst_map, dst_entry, dst_end); 1693*45748Smckusick 1694*45748Smckusick /* 1695*45748Smckusick * Clip each entry to the endpoint of the other entry. 1696*45748Smckusick */ 1697*45748Smckusick 1698*45748Smckusick src_clip = src_entry->start + (dst_entry->end - dst_entry->start); 1699*45748Smckusick vm_map_clip_end(src_map, src_entry, src_clip); 1700*45748Smckusick 1701*45748Smckusick dst_clip = dst_entry->start + (src_entry->end - src_entry->start); 1702*45748Smckusick vm_map_clip_end(dst_map, dst_entry, dst_clip); 1703*45748Smckusick 1704*45748Smckusick /* 1705*45748Smckusick * Both entries now match in size and relative endpoints. 1706*45748Smckusick * 1707*45748Smckusick * If both entries refer to a VM object, we can 1708*45748Smckusick * deal with them now. 1709*45748Smckusick */ 1710*45748Smckusick 1711*45748Smckusick if (!src_entry->is_a_map && !dst_entry->is_a_map) { 1712*45748Smckusick vm_map_copy_entry(src_map, dst_map, src_entry, 1713*45748Smckusick dst_entry); 1714*45748Smckusick } 1715*45748Smckusick else { 1716*45748Smckusick register vm_map_t new_dst_map; 1717*45748Smckusick vm_offset_t new_dst_start; 1718*45748Smckusick vm_size_t new_size; 1719*45748Smckusick vm_map_t new_src_map; 1720*45748Smckusick vm_offset_t new_src_start; 1721*45748Smckusick 1722*45748Smckusick /* 1723*45748Smckusick * We have to follow at least one sharing map. 1724*45748Smckusick */ 1725*45748Smckusick 1726*45748Smckusick new_size = (dst_entry->end - dst_entry->start); 1727*45748Smckusick 1728*45748Smckusick if (src_entry->is_a_map) { 1729*45748Smckusick new_src_map = src_entry->object.share_map; 1730*45748Smckusick new_src_start = src_entry->offset; 1731*45748Smckusick } 1732*45748Smckusick else { 1733*45748Smckusick new_src_map = src_map; 1734*45748Smckusick new_src_start = src_entry->start; 1735*45748Smckusick lock_set_recursive(&src_map->lock); 1736*45748Smckusick } 1737*45748Smckusick 1738*45748Smckusick if (dst_entry->is_a_map) { 1739*45748Smckusick vm_offset_t new_dst_end; 1740*45748Smckusick 1741*45748Smckusick new_dst_map = dst_entry->object.share_map; 1742*45748Smckusick new_dst_start = dst_entry->offset; 1743*45748Smckusick 1744*45748Smckusick /* 1745*45748Smckusick * Since the destination sharing entries 1746*45748Smckusick * will be merely deallocated, we can 1747*45748Smckusick * do that now, and replace the region 1748*45748Smckusick * with a null object. [This prevents 1749*45748Smckusick * splitting the source map to match 1750*45748Smckusick * the form of the destination map.] 1751*45748Smckusick * Note that we can only do so if the 1752*45748Smckusick * source and destination do not overlap. 1753*45748Smckusick */ 1754*45748Smckusick 1755*45748Smckusick new_dst_end = new_dst_start + new_size; 1756*45748Smckusick 1757*45748Smckusick if (new_dst_map != new_src_map) { 1758*45748Smckusick vm_map_lock(new_dst_map); 1759*45748Smckusick (void) vm_map_delete(new_dst_map, 1760*45748Smckusick new_dst_start, 1761*45748Smckusick new_dst_end); 1762*45748Smckusick (void) vm_map_insert(new_dst_map, 1763*45748Smckusick VM_OBJECT_NULL, 1764*45748Smckusick (vm_offset_t) 0, 1765*45748Smckusick new_dst_start, 1766*45748Smckusick new_dst_end); 1767*45748Smckusick vm_map_unlock(new_dst_map); 1768*45748Smckusick } 1769*45748Smckusick } 1770*45748Smckusick else { 1771*45748Smckusick new_dst_map = dst_map; 1772*45748Smckusick new_dst_start = dst_entry->start; 1773*45748Smckusick lock_set_recursive(&dst_map->lock); 1774*45748Smckusick } 1775*45748Smckusick 1776*45748Smckusick /* 1777*45748Smckusick * Recursively copy the sharing map. 1778*45748Smckusick */ 1779*45748Smckusick 1780*45748Smckusick (void) vm_map_copy(new_dst_map, new_src_map, 1781*45748Smckusick new_dst_start, new_size, new_src_start, 1782*45748Smckusick FALSE, FALSE); 1783*45748Smckusick 1784*45748Smckusick if (dst_map == new_dst_map) 1785*45748Smckusick lock_clear_recursive(&dst_map->lock); 1786*45748Smckusick if (src_map == new_src_map) 1787*45748Smckusick lock_clear_recursive(&src_map->lock); 1788*45748Smckusick } 1789*45748Smckusick 1790*45748Smckusick /* 1791*45748Smckusick * Update variables for next pass through the loop. 1792*45748Smckusick */ 1793*45748Smckusick 1794*45748Smckusick src_start = src_entry->end; 1795*45748Smckusick src_entry = src_entry->next; 1796*45748Smckusick dst_start = dst_entry->end; 1797*45748Smckusick dst_entry = dst_entry->next; 1798*45748Smckusick 1799*45748Smckusick /* 1800*45748Smckusick * If the source is to be destroyed, here is the 1801*45748Smckusick * place to do it. 1802*45748Smckusick */ 1803*45748Smckusick 1804*45748Smckusick if (src_destroy && src_map->is_main_map && 1805*45748Smckusick dst_map->is_main_map) 1806*45748Smckusick vm_map_entry_delete(src_map, src_entry->prev); 1807*45748Smckusick } 1808*45748Smckusick 1809*45748Smckusick /* 1810*45748Smckusick * Update the physical maps as appropriate 1811*45748Smckusick */ 1812*45748Smckusick 1813*45748Smckusick if (src_map->is_main_map && dst_map->is_main_map) { 1814*45748Smckusick if (src_destroy) 1815*45748Smckusick pmap_remove(src_map->pmap, src_addr, src_addr + len); 1816*45748Smckusick } 1817*45748Smckusick 1818*45748Smckusick /* 1819*45748Smckusick * Unlock the maps 1820*45748Smckusick */ 1821*45748Smckusick 1822*45748Smckusick Return: ; 1823*45748Smckusick 1824*45748Smckusick if (old_src_destroy) 1825*45748Smckusick vm_map_delete(src_map, src_addr, src_addr + len); 1826*45748Smckusick 1827*45748Smckusick vm_map_unlock(src_map); 1828*45748Smckusick if (src_map != dst_map) 1829*45748Smckusick vm_map_unlock(dst_map); 1830*45748Smckusick 1831*45748Smckusick return(result); 1832*45748Smckusick } 1833*45748Smckusick 1834*45748Smckusick /* 1835*45748Smckusick * vm_map_fork: 1836*45748Smckusick * 1837*45748Smckusick * Create and return a new map based on the old 1838*45748Smckusick * map, according to the inheritance values on the 1839*45748Smckusick * regions in that map. 1840*45748Smckusick * 1841*45748Smckusick * The source map must not be locked. 1842*45748Smckusick */ 1843*45748Smckusick vm_map_t vm_map_fork(old_map) 1844*45748Smckusick vm_map_t old_map; 1845*45748Smckusick { 1846*45748Smckusick vm_map_t new_map; 1847*45748Smckusick vm_map_entry_t old_entry; 1848*45748Smckusick vm_map_entry_t new_entry; 1849*45748Smckusick pmap_t new_pmap; 1850*45748Smckusick 1851*45748Smckusick vm_map_lock(old_map); 1852*45748Smckusick 1853*45748Smckusick new_pmap = pmap_create((vm_size_t) 0); 1854*45748Smckusick new_map = vm_map_create(new_pmap, 1855*45748Smckusick old_map->min_offset, 1856*45748Smckusick old_map->max_offset, 1857*45748Smckusick old_map->entries_pageable); 1858*45748Smckusick 1859*45748Smckusick old_entry = old_map->header.next; 1860*45748Smckusick 1861*45748Smckusick while (old_entry != &old_map->header) { 1862*45748Smckusick if (old_entry->is_sub_map) 1863*45748Smckusick panic("vm_map_fork: encountered a submap"); 1864*45748Smckusick 1865*45748Smckusick switch (old_entry->inheritance) { 1866*45748Smckusick case VM_INHERIT_NONE: 1867*45748Smckusick break; 1868*45748Smckusick 1869*45748Smckusick case VM_INHERIT_SHARE: 1870*45748Smckusick /* 1871*45748Smckusick * If we don't already have a sharing map: 1872*45748Smckusick */ 1873*45748Smckusick 1874*45748Smckusick if (!old_entry->is_a_map) { 1875*45748Smckusick vm_map_t new_share_map; 1876*45748Smckusick vm_map_entry_t new_share_entry; 1877*45748Smckusick 1878*45748Smckusick /* 1879*45748Smckusick * Create a new sharing map 1880*45748Smckusick */ 1881*45748Smckusick 1882*45748Smckusick new_share_map = vm_map_create(PMAP_NULL, 1883*45748Smckusick old_entry->start, 1884*45748Smckusick old_entry->end, 1885*45748Smckusick TRUE); 1886*45748Smckusick new_share_map->is_main_map = FALSE; 1887*45748Smckusick 1888*45748Smckusick /* 1889*45748Smckusick * Create the only sharing entry from the 1890*45748Smckusick * old task map entry. 1891*45748Smckusick */ 1892*45748Smckusick 1893*45748Smckusick new_share_entry = 1894*45748Smckusick vm_map_entry_create(new_share_map); 1895*45748Smckusick *new_share_entry = *old_entry; 1896*45748Smckusick 1897*45748Smckusick /* 1898*45748Smckusick * Insert the entry into the new sharing 1899*45748Smckusick * map 1900*45748Smckusick */ 1901*45748Smckusick 1902*45748Smckusick vm_map_entry_link(new_share_map, 1903*45748Smckusick new_share_map->header.prev, 1904*45748Smckusick new_share_entry); 1905*45748Smckusick 1906*45748Smckusick /* 1907*45748Smckusick * Fix up the task map entry to refer 1908*45748Smckusick * to the sharing map now. 1909*45748Smckusick */ 1910*45748Smckusick 1911*45748Smckusick old_entry->is_a_map = TRUE; 1912*45748Smckusick old_entry->object.share_map = new_share_map; 1913*45748Smckusick old_entry->offset = old_entry->start; 1914*45748Smckusick } 1915*45748Smckusick 1916*45748Smckusick /* 1917*45748Smckusick * Clone the entry, referencing the sharing map. 1918*45748Smckusick */ 1919*45748Smckusick 1920*45748Smckusick new_entry = vm_map_entry_create(new_map); 1921*45748Smckusick *new_entry = *old_entry; 1922*45748Smckusick vm_map_reference(new_entry->object.share_map); 1923*45748Smckusick 1924*45748Smckusick /* 1925*45748Smckusick * Insert the entry into the new map -- we 1926*45748Smckusick * know we're inserting at the end of the new 1927*45748Smckusick * map. 1928*45748Smckusick */ 1929*45748Smckusick 1930*45748Smckusick vm_map_entry_link(new_map, new_map->header.prev, 1931*45748Smckusick new_entry); 1932*45748Smckusick 1933*45748Smckusick /* 1934*45748Smckusick * Update the physical map 1935*45748Smckusick */ 1936*45748Smckusick 1937*45748Smckusick pmap_copy(new_map->pmap, old_map->pmap, 1938*45748Smckusick new_entry->start, 1939*45748Smckusick (old_entry->end - old_entry->start), 1940*45748Smckusick old_entry->start); 1941*45748Smckusick break; 1942*45748Smckusick 1943*45748Smckusick case VM_INHERIT_COPY: 1944*45748Smckusick /* 1945*45748Smckusick * Clone the entry and link into the map. 1946*45748Smckusick */ 1947*45748Smckusick 1948*45748Smckusick new_entry = vm_map_entry_create(new_map); 1949*45748Smckusick *new_entry = *old_entry; 1950*45748Smckusick new_entry->wired_count = 0; 1951*45748Smckusick new_entry->object.vm_object = VM_OBJECT_NULL; 1952*45748Smckusick new_entry->is_a_map = FALSE; 1953*45748Smckusick vm_map_entry_link(new_map, new_map->header.prev, 1954*45748Smckusick new_entry); 1955*45748Smckusick if (old_entry->is_a_map) { 1956*45748Smckusick int check; 1957*45748Smckusick 1958*45748Smckusick check = vm_map_copy(new_map, 1959*45748Smckusick old_entry->object.share_map, 1960*45748Smckusick new_entry->start, 1961*45748Smckusick (vm_size_t)(new_entry->end - 1962*45748Smckusick new_entry->start), 1963*45748Smckusick old_entry->offset, 1964*45748Smckusick FALSE, FALSE); 1965*45748Smckusick if (check != KERN_SUCCESS) 1966*45748Smckusick printf("vm_map_fork: copy in share_map region failed\n"); 1967*45748Smckusick } 1968*45748Smckusick else { 1969*45748Smckusick vm_map_copy_entry(old_map, new_map, old_entry, 1970*45748Smckusick new_entry); 1971*45748Smckusick } 1972*45748Smckusick break; 1973*45748Smckusick } 1974*45748Smckusick old_entry = old_entry->next; 1975*45748Smckusick } 1976*45748Smckusick 1977*45748Smckusick new_map->size = old_map->size; 1978*45748Smckusick vm_map_unlock(old_map); 1979*45748Smckusick 1980*45748Smckusick return(new_map); 1981*45748Smckusick } 1982*45748Smckusick 1983*45748Smckusick /* 1984*45748Smckusick * vm_map_lookup: 1985*45748Smckusick * 1986*45748Smckusick * Finds the VM object, offset, and 1987*45748Smckusick * protection for a given virtual address in the 1988*45748Smckusick * specified map, assuming a page fault of the 1989*45748Smckusick * type specified. 1990*45748Smckusick * 1991*45748Smckusick * Leaves the map in question locked for read; return 1992*45748Smckusick * values are guaranteed until a vm_map_lookup_done 1993*45748Smckusick * call is performed. Note that the map argument 1994*45748Smckusick * is in/out; the returned map must be used in 1995*45748Smckusick * the call to vm_map_lookup_done. 1996*45748Smckusick * 1997*45748Smckusick * A handle (out_entry) is returned for use in 1998*45748Smckusick * vm_map_lookup_done, to make that fast. 1999*45748Smckusick * 2000*45748Smckusick * If a lookup is requested with "write protection" 2001*45748Smckusick * specified, the map may be changed to perform virtual 2002*45748Smckusick * copying operations, although the data referenced will 2003*45748Smckusick * remain the same. 2004*45748Smckusick */ 2005*45748Smckusick vm_map_lookup(var_map, vaddr, fault_type, out_entry, 2006*45748Smckusick object, offset, out_prot, wired, single_use) 2007*45748Smckusick vm_map_t *var_map; /* IN/OUT */ 2008*45748Smckusick register vm_offset_t vaddr; 2009*45748Smckusick register vm_prot_t fault_type; 2010*45748Smckusick 2011*45748Smckusick vm_map_entry_t *out_entry; /* OUT */ 2012*45748Smckusick vm_object_t *object; /* OUT */ 2013*45748Smckusick vm_offset_t *offset; /* OUT */ 2014*45748Smckusick vm_prot_t *out_prot; /* OUT */ 2015*45748Smckusick boolean_t *wired; /* OUT */ 2016*45748Smckusick boolean_t *single_use; /* OUT */ 2017*45748Smckusick { 2018*45748Smckusick vm_map_t share_map; 2019*45748Smckusick vm_offset_t share_offset; 2020*45748Smckusick register vm_map_entry_t entry; 2021*45748Smckusick register vm_map_t map = *var_map; 2022*45748Smckusick register vm_prot_t prot; 2023*45748Smckusick register boolean_t su; 2024*45748Smckusick 2025*45748Smckusick RetryLookup: ; 2026*45748Smckusick 2027*45748Smckusick /* 2028*45748Smckusick * Lookup the faulting address. 2029*45748Smckusick */ 2030*45748Smckusick 2031*45748Smckusick vm_map_lock_read(map); 2032*45748Smckusick 2033*45748Smckusick #define RETURN(why) \ 2034*45748Smckusick { \ 2035*45748Smckusick vm_map_unlock_read(map); \ 2036*45748Smckusick return(why); \ 2037*45748Smckusick } 2038*45748Smckusick 2039*45748Smckusick /* 2040*45748Smckusick * If the map has an interesting hint, try it before calling 2041*45748Smckusick * full blown lookup routine. 2042*45748Smckusick */ 2043*45748Smckusick 2044*45748Smckusick simple_lock(&map->hint_lock); 2045*45748Smckusick entry = map->hint; 2046*45748Smckusick simple_unlock(&map->hint_lock); 2047*45748Smckusick 2048*45748Smckusick *out_entry = entry; 2049*45748Smckusick 2050*45748Smckusick if ((entry == &map->header) || 2051*45748Smckusick (vaddr < entry->start) || (vaddr >= entry->end)) { 2052*45748Smckusick vm_map_entry_t tmp_entry; 2053*45748Smckusick 2054*45748Smckusick /* 2055*45748Smckusick * Entry was either not a valid hint, or the vaddr 2056*45748Smckusick * was not contained in the entry, so do a full lookup. 2057*45748Smckusick */ 2058*45748Smckusick if (!vm_map_lookup_entry(map, vaddr, &tmp_entry)) 2059*45748Smckusick RETURN(KERN_INVALID_ADDRESS); 2060*45748Smckusick 2061*45748Smckusick entry = tmp_entry; 2062*45748Smckusick *out_entry = entry; 2063*45748Smckusick } 2064*45748Smckusick 2065*45748Smckusick /* 2066*45748Smckusick * Handle submaps. 2067*45748Smckusick */ 2068*45748Smckusick 2069*45748Smckusick if (entry->is_sub_map) { 2070*45748Smckusick vm_map_t old_map = map; 2071*45748Smckusick 2072*45748Smckusick *var_map = map = entry->object.sub_map; 2073*45748Smckusick vm_map_unlock_read(old_map); 2074*45748Smckusick goto RetryLookup; 2075*45748Smckusick } 2076*45748Smckusick 2077*45748Smckusick /* 2078*45748Smckusick * Check whether this task is allowed to have 2079*45748Smckusick * this page. 2080*45748Smckusick */ 2081*45748Smckusick 2082*45748Smckusick prot = entry->protection; 2083*45748Smckusick if ((fault_type & (prot)) != fault_type) 2084*45748Smckusick RETURN(KERN_PROTECTION_FAILURE); 2085*45748Smckusick 2086*45748Smckusick /* 2087*45748Smckusick * If this page is not pageable, we have to get 2088*45748Smckusick * it for all possible accesses. 2089*45748Smckusick */ 2090*45748Smckusick 2091*45748Smckusick if (*wired = (entry->wired_count != 0)) 2092*45748Smckusick prot = fault_type = entry->protection; 2093*45748Smckusick 2094*45748Smckusick /* 2095*45748Smckusick * If we don't already have a VM object, track 2096*45748Smckusick * it down. 2097*45748Smckusick */ 2098*45748Smckusick 2099*45748Smckusick if (su = !entry->is_a_map) { 2100*45748Smckusick share_map = map; 2101*45748Smckusick share_offset = vaddr; 2102*45748Smckusick } 2103*45748Smckusick else { 2104*45748Smckusick vm_map_entry_t share_entry; 2105*45748Smckusick 2106*45748Smckusick /* 2107*45748Smckusick * Compute the sharing map, and offset into it. 2108*45748Smckusick */ 2109*45748Smckusick 2110*45748Smckusick share_map = entry->object.share_map; 2111*45748Smckusick share_offset = (vaddr - entry->start) + entry->offset; 2112*45748Smckusick 2113*45748Smckusick /* 2114*45748Smckusick * Look for the backing store object and offset 2115*45748Smckusick */ 2116*45748Smckusick 2117*45748Smckusick vm_map_lock_read(share_map); 2118*45748Smckusick 2119*45748Smckusick if (!vm_map_lookup_entry(share_map, share_offset, 2120*45748Smckusick &share_entry)) { 2121*45748Smckusick vm_map_unlock_read(share_map); 2122*45748Smckusick RETURN(KERN_INVALID_ADDRESS); 2123*45748Smckusick } 2124*45748Smckusick entry = share_entry; 2125*45748Smckusick } 2126*45748Smckusick 2127*45748Smckusick /* 2128*45748Smckusick * If the entry was copy-on-write, we either ... 2129*45748Smckusick */ 2130*45748Smckusick 2131*45748Smckusick if (entry->needs_copy) { 2132*45748Smckusick /* 2133*45748Smckusick * If we want to write the page, we may as well 2134*45748Smckusick * handle that now since we've got the sharing 2135*45748Smckusick * map locked. 2136*45748Smckusick * 2137*45748Smckusick * If we don't need to write the page, we just 2138*45748Smckusick * demote the permissions allowed. 2139*45748Smckusick */ 2140*45748Smckusick 2141*45748Smckusick if (fault_type & VM_PROT_WRITE) { 2142*45748Smckusick /* 2143*45748Smckusick * Make a new object, and place it in the 2144*45748Smckusick * object chain. Note that no new references 2145*45748Smckusick * have appeared -- one just moved from the 2146*45748Smckusick * share map to the new object. 2147*45748Smckusick */ 2148*45748Smckusick 2149*45748Smckusick if (lock_read_to_write(&share_map->lock)) { 2150*45748Smckusick if (share_map != map) 2151*45748Smckusick vm_map_unlock_read(map); 2152*45748Smckusick goto RetryLookup; 2153*45748Smckusick } 2154*45748Smckusick 2155*45748Smckusick vm_object_shadow( 2156*45748Smckusick &entry->object.vm_object, 2157*45748Smckusick &entry->offset, 2158*45748Smckusick (vm_size_t) (entry->end - entry->start)); 2159*45748Smckusick 2160*45748Smckusick entry->needs_copy = FALSE; 2161*45748Smckusick 2162*45748Smckusick lock_write_to_read(&share_map->lock); 2163*45748Smckusick } 2164*45748Smckusick else { 2165*45748Smckusick /* 2166*45748Smckusick * We're attempting to read a copy-on-write 2167*45748Smckusick * page -- don't allow writes. 2168*45748Smckusick */ 2169*45748Smckusick 2170*45748Smckusick prot &= (~VM_PROT_WRITE); 2171*45748Smckusick } 2172*45748Smckusick } 2173*45748Smckusick 2174*45748Smckusick /* 2175*45748Smckusick * Create an object if necessary. 2176*45748Smckusick */ 2177*45748Smckusick if (entry->object.vm_object == VM_OBJECT_NULL) { 2178*45748Smckusick 2179*45748Smckusick if (lock_read_to_write(&share_map->lock)) { 2180*45748Smckusick if (share_map != map) 2181*45748Smckusick vm_map_unlock_read(map); 2182*45748Smckusick goto RetryLookup; 2183*45748Smckusick } 2184*45748Smckusick 2185*45748Smckusick entry->object.vm_object = vm_object_allocate( 2186*45748Smckusick (vm_size_t)(entry->end - entry->start)); 2187*45748Smckusick entry->offset = 0; 2188*45748Smckusick lock_write_to_read(&share_map->lock); 2189*45748Smckusick } 2190*45748Smckusick 2191*45748Smckusick /* 2192*45748Smckusick * Return the object/offset from this entry. If the entry 2193*45748Smckusick * was copy-on-write or empty, it has been fixed up. 2194*45748Smckusick */ 2195*45748Smckusick 2196*45748Smckusick *offset = (share_offset - entry->start) + entry->offset; 2197*45748Smckusick *object = entry->object.vm_object; 2198*45748Smckusick 2199*45748Smckusick /* 2200*45748Smckusick * Return whether this is the only map sharing this data. 2201*45748Smckusick */ 2202*45748Smckusick 2203*45748Smckusick if (!su) { 2204*45748Smckusick simple_lock(&share_map->ref_lock); 2205*45748Smckusick su = (share_map->ref_count == 1); 2206*45748Smckusick simple_unlock(&share_map->ref_lock); 2207*45748Smckusick } 2208*45748Smckusick 2209*45748Smckusick *out_prot = prot; 2210*45748Smckusick *single_use = su; 2211*45748Smckusick 2212*45748Smckusick return(KERN_SUCCESS); 2213*45748Smckusick 2214*45748Smckusick #undef RETURN 2215*45748Smckusick } 2216*45748Smckusick 2217*45748Smckusick /* 2218*45748Smckusick * vm_map_lookup_done: 2219*45748Smckusick * 2220*45748Smckusick * Releases locks acquired by a vm_map_lookup 2221*45748Smckusick * (according to the handle returned by that lookup). 2222*45748Smckusick */ 2223*45748Smckusick 2224*45748Smckusick void vm_map_lookup_done(map, entry) 2225*45748Smckusick register vm_map_t map; 2226*45748Smckusick vm_map_entry_t entry; 2227*45748Smckusick { 2228*45748Smckusick /* 2229*45748Smckusick * If this entry references a map, unlock it first. 2230*45748Smckusick */ 2231*45748Smckusick 2232*45748Smckusick if (entry->is_a_map) 2233*45748Smckusick vm_map_unlock_read(entry->object.share_map); 2234*45748Smckusick 2235*45748Smckusick /* 2236*45748Smckusick * Unlock the main-level map 2237*45748Smckusick */ 2238*45748Smckusick 2239*45748Smckusick vm_map_unlock_read(map); 2240*45748Smckusick } 2241*45748Smckusick 2242*45748Smckusick /* 2243*45748Smckusick * Routine: vm_map_simplify 2244*45748Smckusick * Purpose: 2245*45748Smckusick * Attempt to simplify the map representation in 2246*45748Smckusick * the vicinity of the given starting address. 2247*45748Smckusick * Note: 2248*45748Smckusick * This routine is intended primarily to keep the 2249*45748Smckusick * kernel maps more compact -- they generally don't 2250*45748Smckusick * benefit from the "expand a map entry" technology 2251*45748Smckusick * at allocation time because the adjacent entry 2252*45748Smckusick * is often wired down. 2253*45748Smckusick */ 2254*45748Smckusick void vm_map_simplify(map, start) 2255*45748Smckusick vm_map_t map; 2256*45748Smckusick vm_offset_t start; 2257*45748Smckusick { 2258*45748Smckusick vm_map_entry_t this_entry; 2259*45748Smckusick vm_map_entry_t prev_entry; 2260*45748Smckusick 2261*45748Smckusick vm_map_lock(map); 2262*45748Smckusick if ( 2263*45748Smckusick (vm_map_lookup_entry(map, start, &this_entry)) && 2264*45748Smckusick ((prev_entry = this_entry->prev) != &map->header) && 2265*45748Smckusick 2266*45748Smckusick (prev_entry->end == start) && 2267*45748Smckusick (map->is_main_map) && 2268*45748Smckusick 2269*45748Smckusick (prev_entry->is_a_map == FALSE) && 2270*45748Smckusick (prev_entry->is_sub_map == FALSE) && 2271*45748Smckusick 2272*45748Smckusick (this_entry->is_a_map == FALSE) && 2273*45748Smckusick (this_entry->is_sub_map == FALSE) && 2274*45748Smckusick 2275*45748Smckusick (prev_entry->inheritance == this_entry->inheritance) && 2276*45748Smckusick (prev_entry->protection == this_entry->protection) && 2277*45748Smckusick (prev_entry->max_protection == this_entry->max_protection) && 2278*45748Smckusick (prev_entry->wired_count == this_entry->wired_count) && 2279*45748Smckusick 2280*45748Smckusick (prev_entry->copy_on_write == this_entry->copy_on_write) && 2281*45748Smckusick (prev_entry->needs_copy == this_entry->needs_copy) && 2282*45748Smckusick 2283*45748Smckusick (prev_entry->object.vm_object == this_entry->object.vm_object) && 2284*45748Smckusick ((prev_entry->offset + (prev_entry->end - prev_entry->start)) 2285*45748Smckusick == this_entry->offset) 2286*45748Smckusick ) { 2287*45748Smckusick if (map->first_free == this_entry) 2288*45748Smckusick map->first_free = prev_entry; 2289*45748Smckusick 2290*45748Smckusick SAVE_HINT(map, prev_entry); 2291*45748Smckusick vm_map_entry_unlink(map, this_entry); 2292*45748Smckusick prev_entry->end = this_entry->end; 2293*45748Smckusick vm_object_deallocate(this_entry->object.vm_object); 2294*45748Smckusick vm_map_entry_dispose(map, this_entry); 2295*45748Smckusick } 2296*45748Smckusick vm_map_unlock(map); 2297*45748Smckusick } 2298*45748Smckusick 2299*45748Smckusick /* 2300*45748Smckusick * vm_map_print: [ debug ] 2301*45748Smckusick */ 2302*45748Smckusick void vm_map_print(map, full) 2303*45748Smckusick register vm_map_t map; 2304*45748Smckusick boolean_t full; 2305*45748Smckusick { 2306*45748Smckusick register vm_map_entry_t entry; 2307*45748Smckusick extern int indent; 2308*45748Smckusick 2309*45748Smckusick iprintf("%s map 0x%x: pmap=0x%x,ref=%d,nentries=%d,version=%d\n", 2310*45748Smckusick (map->is_main_map ? "Task" : "Share"), 2311*45748Smckusick (int) map, (int) (map->pmap), map->ref_count, map->nentries, 2312*45748Smckusick map->timestamp); 2313*45748Smckusick 2314*45748Smckusick if (!full && indent) 2315*45748Smckusick return; 2316*45748Smckusick 2317*45748Smckusick indent += 2; 2318*45748Smckusick for (entry = map->header.next; entry != &map->header; 2319*45748Smckusick entry = entry->next) { 2320*45748Smckusick iprintf("map entry 0x%x: start=0x%x, end=0x%x, ", 2321*45748Smckusick (int) entry, (int) entry->start, (int) entry->end); 2322*45748Smckusick if (map->is_main_map) { 2323*45748Smckusick static char *inheritance_name[4] = 2324*45748Smckusick { "share", "copy", "none", "donate_copy"}; 2325*45748Smckusick printf("prot=%x/%x/%s, ", 2326*45748Smckusick entry->protection, 2327*45748Smckusick entry->max_protection, 2328*45748Smckusick inheritance_name[entry->inheritance]); 2329*45748Smckusick if (entry->wired_count != 0) 2330*45748Smckusick printf("wired, "); 2331*45748Smckusick } 2332*45748Smckusick 2333*45748Smckusick if (entry->is_a_map || entry->is_sub_map) { 2334*45748Smckusick printf("share=0x%x, offset=0x%x\n", 2335*45748Smckusick (int) entry->object.share_map, 2336*45748Smckusick (int) entry->offset); 2337*45748Smckusick if ((entry->prev == &map->header) || 2338*45748Smckusick (!entry->prev->is_a_map) || 2339*45748Smckusick (entry->prev->object.share_map != 2340*45748Smckusick entry->object.share_map)) { 2341*45748Smckusick indent += 2; 2342*45748Smckusick vm_map_print(entry->object.share_map, full); 2343*45748Smckusick indent -= 2; 2344*45748Smckusick } 2345*45748Smckusick 2346*45748Smckusick } 2347*45748Smckusick else { 2348*45748Smckusick printf("object=0x%x, offset=0x%x", 2349*45748Smckusick (int) entry->object.vm_object, 2350*45748Smckusick (int) entry->offset); 2351*45748Smckusick if (entry->copy_on_write) 2352*45748Smckusick printf(", copy (%s)", 2353*45748Smckusick entry->needs_copy ? "needed" : "done"); 2354*45748Smckusick printf("\n"); 2355*45748Smckusick 2356*45748Smckusick if ((entry->prev == &map->header) || 2357*45748Smckusick (entry->prev->is_a_map) || 2358*45748Smckusick (entry->prev->object.vm_object != 2359*45748Smckusick entry->object.vm_object)) { 2360*45748Smckusick indent += 2; 2361*45748Smckusick vm_object_print(entry->object.vm_object, full); 2362*45748Smckusick indent -= 2; 2363*45748Smckusick } 2364*45748Smckusick } 2365*45748Smckusick } 2366*45748Smckusick indent -= 2; 2367*45748Smckusick } 2368