|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * File: vm/vm_user.c ! 28: * Author: Avadis Tevanian, Jr., Michael Wayne Young ! 29: * ! 30: * User-exported virtual memory functions. ! 31: */ ! 32: ! 33: #include <mach/boolean.h> ! 34: #include <mach/kern_return.h> ! 35: #include <mach/mach_types.h> /* to get vm_address_t */ ! 36: #include <mach/memory_object.h> ! 37: #include <mach/std_types.h> /* to get pointer_t */ ! 38: #include <mach/vm_attributes.h> ! 39: #include <mach/vm_param.h> ! 40: #include <mach/vm_statistics.h> ! 41: #include <kern/host.h> ! 42: #include <kern/task.h> ! 43: #include <vm/vm_fault.h> ! 44: #include <vm/vm_map.h> ! 45: #include <vm/vm_object.h> ! 46: #include <vm/vm_page.h> ! 47: ! 48: ! 49: ! 50: vm_statistics_data_t vm_stat; ! 51: ! 52: /* ! 53: * vm_allocate allocates "zero fill" memory in the specfied ! 54: * map. ! 55: */ ! 56: kern_return_t vm_allocate(map, addr, size, anywhere) ! 57: register vm_map_t map; ! 58: register vm_offset_t *addr; ! 59: register vm_size_t size; ! 60: boolean_t anywhere; ! 61: { ! 62: kern_return_t result; ! 63: ! 64: if (map == VM_MAP_NULL) ! 65: return(KERN_INVALID_ARGUMENT); ! 66: if (size == 0) { ! 67: *addr = 0; ! 68: return(KERN_SUCCESS); ! 69: } ! 70: ! 71: if (anywhere) ! 72: *addr = vm_map_min(map); ! 73: else ! 74: *addr = trunc_page(*addr); ! 75: size = round_page(size); ! 76: ! 77: result = vm_map_enter( ! 78: map, ! 79: addr, ! 80: size, ! 81: (vm_offset_t)0, ! 82: anywhere, ! 83: VM_OBJECT_NULL, ! 84: (vm_offset_t)0, ! 85: FALSE, ! 86: VM_PROT_DEFAULT, ! 87: VM_PROT_ALL, ! 88: VM_INHERIT_DEFAULT); ! 89: ! 90: return(result); ! 91: } ! 92: ! 93: /* ! 94: * vm_deallocate deallocates the specified range of addresses in the ! 95: * specified address map. ! 96: */ ! 97: kern_return_t vm_deallocate(map, start, size) ! 98: register vm_map_t map; ! 99: vm_offset_t start; ! 100: vm_size_t size; ! 101: { ! 102: if (map == VM_MAP_NULL) ! 103: return(KERN_INVALID_ARGUMENT); ! 104: ! 105: if (size == (vm_offset_t) 0) ! 106: return(KERN_SUCCESS); ! 107: ! 108: return(vm_map_remove(map, trunc_page(start), round_page(start+size))); ! 109: } ! 110: ! 111: /* ! 112: * vm_inherit sets the inheritance of the specified range in the ! 113: * specified map. ! 114: */ ! 115: kern_return_t vm_inherit(map, start, size, new_inheritance) ! 116: register vm_map_t map; ! 117: vm_offset_t start; ! 118: vm_size_t size; ! 119: vm_inherit_t new_inheritance; ! 120: { ! 121: if (map == VM_MAP_NULL) ! 122: return(KERN_INVALID_ARGUMENT); ! 123: ! 124: switch (new_inheritance) { ! 125: case VM_INHERIT_NONE: ! 126: case VM_INHERIT_COPY: ! 127: case VM_INHERIT_SHARE: ! 128: break; ! 129: default: ! 130: return(KERN_INVALID_ARGUMENT); ! 131: } ! 132: ! 133: /*Check if range includes projected buffer; ! 134: user is not allowed direct manipulation in that case*/ ! 135: if (projected_buffer_in_range(map, start, start+size)) ! 136: return(KERN_INVALID_ARGUMENT); ! 137: ! 138: return(vm_map_inherit(map, ! 139: trunc_page(start), ! 140: round_page(start+size), ! 141: new_inheritance)); ! 142: } ! 143: ! 144: /* ! 145: * vm_protect sets the protection of the specified range in the ! 146: * specified map. ! 147: */ ! 148: ! 149: kern_return_t vm_protect(map, start, size, set_maximum, new_protection) ! 150: register vm_map_t map; ! 151: vm_offset_t start; ! 152: vm_size_t size; ! 153: boolean_t set_maximum; ! 154: vm_prot_t new_protection; ! 155: { ! 156: if ((map == VM_MAP_NULL) || ! 157: (new_protection & ~(VM_PROT_ALL|VM_PROT_NOTIFY))) ! 158: return(KERN_INVALID_ARGUMENT); ! 159: ! 160: /*Check if range includes projected buffer; ! 161: user is not allowed direct manipulation in that case*/ ! 162: if (projected_buffer_in_range(map, start, start+size)) ! 163: return(KERN_INVALID_ARGUMENT); ! 164: ! 165: return(vm_map_protect(map, ! 166: trunc_page(start), ! 167: round_page(start+size), ! 168: new_protection, ! 169: set_maximum)); ! 170: } ! 171: ! 172: kern_return_t vm_statistics(map, stat) ! 173: vm_map_t map; ! 174: vm_statistics_data_t *stat; ! 175: { ! 176: if (map == VM_MAP_NULL) ! 177: return(KERN_INVALID_ARGUMENT); ! 178: ! 179: *stat = vm_stat; ! 180: ! 181: stat->pagesize = PAGE_SIZE; ! 182: stat->free_count = vm_page_free_count; ! 183: stat->active_count = vm_page_active_count; ! 184: stat->inactive_count = vm_page_inactive_count; ! 185: stat->wire_count = vm_page_wire_count; ! 186: ! 187: return(KERN_SUCCESS); ! 188: } ! 189: ! 190: /* ! 191: * Handle machine-specific attributes for a mapping, such ! 192: * as cachability, migrability, etc. ! 193: */ ! 194: kern_return_t vm_machine_attribute(map, address, size, attribute, value) ! 195: vm_map_t map; ! 196: vm_address_t address; ! 197: vm_size_t size; ! 198: vm_machine_attribute_t attribute; ! 199: vm_machine_attribute_val_t* value; /* IN/OUT */ ! 200: { ! 201: extern kern_return_t vm_map_machine_attribute(); ! 202: ! 203: if (map == VM_MAP_NULL) ! 204: return(KERN_INVALID_ARGUMENT); ! 205: ! 206: /*Check if range includes projected buffer; ! 207: user is not allowed direct manipulation in that case*/ ! 208: if (projected_buffer_in_range(map, address, address+size)) ! 209: return(KERN_INVALID_ARGUMENT); ! 210: ! 211: return vm_map_machine_attribute(map, address, size, attribute, value); ! 212: } ! 213: ! 214: kern_return_t vm_read(map, address, size, data, data_size) ! 215: vm_map_t map; ! 216: vm_address_t address; ! 217: vm_size_t size; ! 218: pointer_t *data; ! 219: vm_size_t *data_size; ! 220: { ! 221: kern_return_t error; ! 222: vm_map_copy_t ipc_address; ! 223: ! 224: if (map == VM_MAP_NULL) ! 225: return(KERN_INVALID_ARGUMENT); ! 226: ! 227: if ((error = vm_map_copyin(map, ! 228: address, ! 229: size, ! 230: FALSE, /* src_destroy */ ! 231: &ipc_address)) == KERN_SUCCESS) { ! 232: *data = (pointer_t) ipc_address; ! 233: *data_size = size; ! 234: } ! 235: return(error); ! 236: } ! 237: ! 238: kern_return_t vm_write(map, address, data, size) ! 239: vm_map_t map; ! 240: vm_address_t address; ! 241: pointer_t data; ! 242: vm_size_t size; ! 243: { ! 244: if (map == VM_MAP_NULL) ! 245: return KERN_INVALID_ARGUMENT; ! 246: ! 247: return vm_map_copy_overwrite(map, address, (vm_map_copy_t) data, ! 248: FALSE /* interruptible XXX */); ! 249: } ! 250: ! 251: kern_return_t vm_copy(map, source_address, size, dest_address) ! 252: vm_map_t map; ! 253: vm_address_t source_address; ! 254: vm_size_t size; ! 255: vm_address_t dest_address; ! 256: { ! 257: vm_map_copy_t copy; ! 258: kern_return_t kr; ! 259: ! 260: if (map == VM_MAP_NULL) ! 261: return KERN_INVALID_ARGUMENT; ! 262: ! 263: kr = vm_map_copyin(map, source_address, size, ! 264: FALSE, ©); ! 265: if (kr != KERN_SUCCESS) ! 266: return kr; ! 267: ! 268: kr = vm_map_copy_overwrite(map, dest_address, copy, ! 269: FALSE /* interruptible XXX */); ! 270: if (kr != KERN_SUCCESS) { ! 271: vm_map_copy_discard(copy); ! 272: return kr; ! 273: } ! 274: ! 275: return KERN_SUCCESS; ! 276: } ! 277: ! 278: /* ! 279: * Routine: vm_map ! 280: */ ! 281: kern_return_t vm_map( ! 282: target_map, ! 283: address, size, mask, anywhere, ! 284: memory_object, offset, ! 285: copy, ! 286: cur_protection, max_protection, inheritance) ! 287: vm_map_t target_map; ! 288: vm_offset_t *address; ! 289: vm_size_t size; ! 290: vm_offset_t mask; ! 291: boolean_t anywhere; ! 292: ipc_port_t memory_object; ! 293: vm_offset_t offset; ! 294: boolean_t copy; ! 295: vm_prot_t cur_protection; ! 296: vm_prot_t max_protection; ! 297: vm_inherit_t inheritance; ! 298: { ! 299: register ! 300: vm_object_t object; ! 301: register ! 302: kern_return_t result; ! 303: ! 304: if ((target_map == VM_MAP_NULL) || ! 305: (cur_protection & ~VM_PROT_ALL) || ! 306: (max_protection & ~VM_PROT_ALL)) ! 307: return(KERN_INVALID_ARGUMENT); ! 308: ! 309: switch (inheritance) { ! 310: case VM_INHERIT_NONE: ! 311: case VM_INHERIT_COPY: ! 312: case VM_INHERIT_SHARE: ! 313: break; ! 314: default: ! 315: return(KERN_INVALID_ARGUMENT); ! 316: } ! 317: ! 318: *address = trunc_page(*address); ! 319: size = round_page(size); ! 320: ! 321: if (!IP_VALID(memory_object)) { ! 322: object = VM_OBJECT_NULL; ! 323: offset = 0; ! 324: copy = FALSE; ! 325: } else if ((object = vm_object_enter(memory_object, size, FALSE)) ! 326: == VM_OBJECT_NULL) ! 327: return(KERN_INVALID_ARGUMENT); ! 328: ! 329: /* ! 330: * Perform the copy if requested ! 331: */ ! 332: ! 333: if (copy) { ! 334: vm_object_t new_object; ! 335: vm_offset_t new_offset; ! 336: ! 337: result = vm_object_copy_strategically(object, offset, size, ! 338: &new_object, &new_offset, ! 339: ©); ! 340: ! 341: /* ! 342: * Throw away the reference to the ! 343: * original object, as it won't be mapped. ! 344: */ ! 345: ! 346: vm_object_deallocate(object); ! 347: ! 348: if (result != KERN_SUCCESS) ! 349: return (result); ! 350: ! 351: object = new_object; ! 352: offset = new_offset; ! 353: } ! 354: ! 355: if ((result = vm_map_enter(target_map, ! 356: address, size, mask, anywhere, ! 357: object, offset, ! 358: copy, ! 359: cur_protection, max_protection, inheritance ! 360: )) != KERN_SUCCESS) ! 361: vm_object_deallocate(object); ! 362: return(result); ! 363: } ! 364: ! 365: /* ! 366: * Specify that the range of the virtual address space ! 367: * of the target task must not cause page faults for ! 368: * the indicated accesses. ! 369: * ! 370: * [ To unwire the pages, specify VM_PROT_NONE. ] ! 371: */ ! 372: kern_return_t vm_wire(host, map, start, size, access) ! 373: host_t host; ! 374: register vm_map_t map; ! 375: vm_offset_t start; ! 376: vm_size_t size; ! 377: vm_prot_t access; ! 378: { ! 379: if (host == HOST_NULL) ! 380: return KERN_INVALID_HOST; ! 381: ! 382: if (map == VM_MAP_NULL) ! 383: return KERN_INVALID_TASK; ! 384: ! 385: if (access & ~VM_PROT_ALL) ! 386: return KERN_INVALID_ARGUMENT; ! 387: ! 388: /*Check if range includes projected buffer; ! 389: user is not allowed direct manipulation in that case*/ ! 390: if (projected_buffer_in_range(map, start, start+size)) ! 391: return(KERN_INVALID_ARGUMENT); ! 392: ! 393: return vm_map_pageable_user(map, ! 394: trunc_page(start), ! 395: round_page(start+size), ! 396: access); ! 397: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.