]> git.saurik.com Git - apple/xnu.git/blame - osfmk/vm/vm_kern.c
xnu-1228.7.58.tar.gz
[apple/xnu.git] / osfmk / vm / vm_kern.c
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56/*
57 */
58/*
59 * File: vm/vm_kern.c
60 * Author: Avadis Tevanian, Jr., Michael Wayne Young
61 * Date: 1985
62 *
63 * Kernel memory management.
64 */
65
1c79356b
A
66#include <mach/kern_return.h>
67#include <mach/vm_param.h>
68#include <kern/assert.h>
69#include <kern/lock.h>
70#include <kern/thread.h>
71#include <vm/vm_kern.h>
72#include <vm/vm_map.h>
73#include <vm/vm_object.h>
74#include <vm/vm_page.h>
75#include <vm/vm_pageout.h>
76#include <kern/misc_protos.h>
77#include <vm/cpm.h>
78
79#include <string.h>
2d21ac55
A
80
81#include <libkern/OSDebug.h>
82#include <sys/kdebug.h>
83
1c79356b
A
84/*
85 * Variables exported by this module.
86 */
87
88vm_map_t kernel_map;
89vm_map_t kernel_pageable_map;
90
2d21ac55
A
91extern boolean_t vm_kernel_ready;
92
1c79356b
A
93/*
94 * Forward declarations for internal functions.
95 */
96extern kern_return_t kmem_alloc_pages(
97 register vm_object_t object,
98 register vm_object_offset_t offset,
91447636 99 register vm_object_size_t size);
1c79356b
A
100
101extern void kmem_remap_pages(
102 register vm_object_t object,
103 register vm_object_offset_t offset,
104 register vm_offset_t start,
105 register vm_offset_t end,
106 vm_prot_t protection);
107
108kern_return_t
109kmem_alloc_contig(
91447636
A
110 vm_map_t map,
111 vm_offset_t *addrp,
112 vm_size_t size,
113 vm_offset_t mask,
2d21ac55 114 ppnum_t max_pnum,
91447636 115 int flags)
1c79356b
A
116{
117 vm_object_t object;
1c79356b 118 vm_object_offset_t offset;
91447636
A
119 vm_map_offset_t map_addr;
120 vm_map_offset_t map_mask;
121 vm_map_size_t map_size, i;
1c79356b 122 vm_map_entry_t entry;
91447636
A
123 vm_page_t m, pages;
124 kern_return_t kr;
1c79356b
A
125
126 if (map == VM_MAP_NULL || (flags && (flags ^ KMA_KOBJECT)))
127 return KERN_INVALID_ARGUMENT;
128
129 if (size == 0) {
130 *addrp = 0;
131 return KERN_INVALID_ARGUMENT;
132 }
133
91447636
A
134 map_size = vm_map_round_page(size);
135 map_mask = (vm_map_offset_t)mask;
1c79356b 136
91447636
A
137 /*
138 * Allocate a new object (if necessary) and the reference we
139 * will be donating to the map entry. We must do this before
140 * locking the map, or risk deadlock with the default pager.
141 */
142 if ((flags & KMA_KOBJECT) != 0) {
143 object = kernel_object;
144 vm_object_reference(object);
1c79356b 145 } else {
91447636 146 object = vm_object_allocate(map_size);
1c79356b
A
147 }
148
0c530ab8 149 kr = vm_map_find_space(map, &map_addr, map_size, map_mask, 0, &entry);
91447636
A
150 if (KERN_SUCCESS != kr) {
151 vm_object_deallocate(object);
1c79356b
A
152 return kr;
153 }
154
91447636
A
155 entry->object.vm_object = object;
156 entry->offset = offset = (object == kernel_object) ?
157 map_addr - VM_MIN_KERNEL_ADDRESS : 0;
158
159 /* Take an extra object ref in case the map entry gets deleted */
160 vm_object_reference(object);
1c79356b
A
161 vm_map_unlock(map);
162
2d21ac55 163 kr = cpm_allocate(CAST_DOWN(vm_size_t, map_size), &pages, max_pnum, FALSE);
1c79356b
A
164
165 if (kr != KERN_SUCCESS) {
91447636
A
166 vm_map_remove(map, vm_map_trunc_page(map_addr),
167 vm_map_round_page(map_addr + map_size), 0);
168 vm_object_deallocate(object);
1c79356b
A
169 *addrp = 0;
170 return kr;
171 }
172
173 vm_object_lock(object);
91447636 174 for (i = 0; i < map_size; i += PAGE_SIZE) {
1c79356b
A
175 m = pages;
176 pages = NEXT_PAGE(m);
0c530ab8 177 *(NEXT_PAGE_PTR(m)) = VM_PAGE_NULL;
1c79356b
A
178 m->busy = FALSE;
179 vm_page_insert(m, object, offset + i);
180 }
181 vm_object_unlock(object);
182
91447636
A
183 if ((kr = vm_map_wire(map, vm_map_trunc_page(map_addr),
184 vm_map_round_page(map_addr + map_size), VM_PROT_DEFAULT, FALSE))
1c79356b
A
185 != KERN_SUCCESS) {
186 if (object == kernel_object) {
187 vm_object_lock(object);
91447636 188 vm_object_page_remove(object, offset, offset + map_size);
1c79356b
A
189 vm_object_unlock(object);
190 }
91447636
A
191 vm_map_remove(map, vm_map_trunc_page(map_addr),
192 vm_map_round_page(map_addr + map_size), 0);
193 vm_object_deallocate(object);
1c79356b
A
194 return kr;
195 }
91447636
A
196 vm_object_deallocate(object);
197
1c79356b 198 if (object == kernel_object)
91447636 199 vm_map_simplify(map, map_addr);
1c79356b 200
91447636 201 *addrp = map_addr;
1c79356b
A
202 return KERN_SUCCESS;
203}
204
205/*
206 * Master entry point for allocating kernel memory.
207 * NOTE: this routine is _never_ interrupt safe.
208 *
209 * map : map to allocate into
210 * addrp : pointer to start address of new memory
211 * size : size of memory requested
212 * flags : options
213 * KMA_HERE *addrp is base address, else "anywhere"
214 * KMA_NOPAGEWAIT don't wait for pages if unavailable
215 * KMA_KOBJECT use kernel_object
0c530ab8
A
216 * KMA_LOMEM support for 32 bit devices in a 64 bit world
217 * if set and a lomemory pool is available
218 * grab pages from it... this also implies
219 * KMA_NOPAGEWAIT
1c79356b
A
220 */
221
222kern_return_t
223kernel_memory_allocate(
224 register vm_map_t map,
225 register vm_offset_t *addrp,
226 register vm_size_t size,
227 register vm_offset_t mask,
228 int flags)
229{
91447636
A
230 vm_object_t object;
231 vm_object_offset_t offset;
1c79356b 232 vm_map_entry_t entry;
2d21ac55 233 vm_map_offset_t map_addr, fill_start;
91447636 234 vm_map_offset_t map_mask;
2d21ac55 235 vm_map_size_t map_size, fill_size;
91447636 236 vm_map_size_t i;
1c79356b 237 kern_return_t kr;
2d21ac55
A
238 vm_page_t mem;
239 int vm_alloc_flags;
240
241 if (! vm_kernel_ready) {
242 panic("kernel_memory_allocate: VM is not ready");
243 }
1c79356b 244
91447636
A
245 if (size == 0) {
246 *addrp = 0;
247 return KERN_INVALID_ARGUMENT;
1c79356b 248 }
0c530ab8
A
249 if (flags & KMA_LOMEM) {
250 if ( !(flags & KMA_NOPAGEWAIT) ) {
251 *addrp = 0;
252 return KERN_INVALID_ARGUMENT;
253 }
254 }
91447636
A
255
256 map_size = vm_map_round_page(size);
257 map_mask = (vm_map_offset_t) mask;
2d21ac55
A
258 vm_alloc_flags = 0;
259
260 /*
261 * Guard pages:
262 *
263 * Guard pages are implemented as ficticious pages. By placing guard pages
264 * on either end of a stack, they can help detect cases where a thread walks
265 * off either end of its stack. They are allocated and set up here and attempts
266 * to access those pages are trapped in vm_fault_page().
267 *
268 * The map_size we were passed may include extra space for
269 * guard pages. If those were requested, then back it out of fill_size
270 * since vm_map_find_space() takes just the actual size not including
271 * guard pages. Similarly, fill_start indicates where the actual pages
272 * will begin in the range.
273 */
274
275 fill_start = 0;
276 fill_size = map_size;
277 if (flags & KMA_GUARD_FIRST) {
278 vm_alloc_flags |= VM_FLAGS_GUARD_BEFORE;
279 fill_start += PAGE_SIZE_64;
280 fill_size -= PAGE_SIZE_64;
281 if (map_size < fill_start + fill_size) {
282 /* no space for a guard page */
283 *addrp = 0;
284 return KERN_INVALID_ARGUMENT;
285 }
286 }
287 if (flags & KMA_GUARD_LAST) {
288 vm_alloc_flags |= VM_FLAGS_GUARD_AFTER;
289 fill_size -= PAGE_SIZE_64;
290 if (map_size <= fill_start + fill_size) {
291 /* no space for a guard page */
292 *addrp = 0;
293 return KERN_INVALID_ARGUMENT;
294 }
295 }
91447636
A
296
297 /*
298 * Allocate a new object (if necessary). We must do this before
299 * locking the map, or risk deadlock with the default pager.
300 */
301 if ((flags & KMA_KOBJECT) != 0) {
1c79356b 302 object = kernel_object;
91447636
A
303 vm_object_reference(object);
304 } else {
305 object = vm_object_allocate(map_size);
1c79356b 306 }
91447636 307
2d21ac55
A
308 kr = vm_map_find_space(map, &map_addr,
309 fill_size, map_mask,
310 vm_alloc_flags, &entry);
91447636
A
311 if (KERN_SUCCESS != kr) {
312 vm_object_deallocate(object);
1c79356b
A
313 return kr;
314 }
2d21ac55 315
91447636
A
316 entry->object.vm_object = object;
317 entry->offset = offset = (object == kernel_object) ?
318 map_addr - VM_MIN_KERNEL_ADDRESS : 0;
1c79356b 319
b4c24cb9 320 vm_object_reference(object);
1c79356b
A
321 vm_map_unlock(map);
322
323 vm_object_lock(object);
1c79356b 324
2d21ac55
A
325 /*
326 * Allocate the lower guard page if one was requested. The guard
327 * page extends up to fill_start which is where the real memory
328 * begins.
329 */
330
331 for (i = 0; i < fill_start; i += PAGE_SIZE) {
332 for (;;) {
333 mem = vm_page_alloc_guard(object, offset + i);
334 if (mem != VM_PAGE_NULL)
335 break;
336 if (flags & KMA_NOPAGEWAIT) {
337 kr = KERN_RESOURCE_SHORTAGE;
338 goto nopage;
339 }
340 vm_object_unlock(object);
341 vm_page_more_fictitious();
342 vm_object_lock(object);
343 }
344 mem->busy = FALSE;
345 }
346
347 /*
348 * Allocate the real memory here. This extends from offset fill_start
349 * for fill_size bytes.
350 */
351
352 for (i = fill_start; i < fill_start + fill_size; i += PAGE_SIZE) {
0c530ab8
A
353 for (;;) {
354 if (flags & KMA_LOMEM)
355 mem = vm_page_alloclo(object, offset + i);
356 else
357 mem = vm_page_alloc(object, offset + i);
358
359 if (mem != VM_PAGE_NULL)
360 break;
361
1c79356b 362 if (flags & KMA_NOPAGEWAIT) {
2d21ac55
A
363 kr = KERN_RESOURCE_SHORTAGE;
364 goto nopage;
1c79356b
A
365 }
366 vm_object_unlock(object);
367 VM_PAGE_WAIT();
368 vm_object_lock(object);
369 }
370 mem->busy = FALSE;
371 }
1c79356b 372
2d21ac55
A
373 /*
374 * Lastly, allocate the ending guard page if requested. This starts at the ending
375 * address from the loop above up to the map_size that was originaly
376 * requested.
377 */
378
379 for (i = fill_start + fill_size; i < map_size; i += PAGE_SIZE) {
380 for (;;) {
381 mem = vm_page_alloc_guard(object, offset + i);
382 if (mem != VM_PAGE_NULL)
383 break;
384 if (flags & KMA_NOPAGEWAIT) {
385 kr = KERN_RESOURCE_SHORTAGE;
386 goto nopage;
387 }
1c79356b 388 vm_object_unlock(object);
2d21ac55
A
389 vm_page_more_fictitious();
390 vm_object_lock(object);
1c79356b 391 }
2d21ac55 392 mem->busy = FALSE;
1c79356b 393 }
2d21ac55
A
394 vm_object_unlock(object);
395
396 kr = vm_map_wire(map, map_addr, map_addr + map_size,
397 VM_PROT_DEFAULT, FALSE);
398 if (kr != KERN_SUCCESS) {
399 vm_object_lock(object);
400 goto nopage;
401 }
402
b4c24cb9
A
403 /* now that the page is wired, we no longer have to fear coalesce */
404 vm_object_deallocate(object);
1c79356b 405 if (object == kernel_object)
91447636 406 vm_map_simplify(map, map_addr);
1c79356b
A
407
408 /*
409 * Return the memory, not zeroed.
410 */
91447636 411 *addrp = CAST_DOWN(vm_offset_t, map_addr);
1c79356b 412 return KERN_SUCCESS;
2d21ac55
A
413
414nopage:
415 if (object == kernel_object)
416 vm_object_page_remove(object, offset, offset + i);
417 vm_object_unlock(object);
418 vm_map_remove(map, map_addr, map_addr + map_size, 0);
419 vm_object_deallocate(object);
420 return KERN_RESOURCE_SHORTAGE;
1c79356b
A
421}
422
423/*
424 * kmem_alloc:
425 *
426 * Allocate wired-down memory in the kernel's address map
427 * or a submap. The memory is not zero-filled.
428 */
429
430kern_return_t
431kmem_alloc(
432 vm_map_t map,
433 vm_offset_t *addrp,
434 vm_size_t size)
435{
2d21ac55
A
436 kern_return_t kr = kernel_memory_allocate(map, addrp, size, 0, 0);
437 TRACE_MACHLEAKS(KMEM_ALLOC_CODE, KMEM_ALLOC_CODE_2, size, *addrp);
438 return kr;
1c79356b
A
439}
440
441/*
442 * kmem_realloc:
443 *
444 * Reallocate wired-down memory in the kernel's address map
445 * or a submap. Newly allocated pages are not zeroed.
446 * This can only be used on regions allocated with kmem_alloc.
447 *
448 * If successful, the pages in the old region are mapped twice.
449 * The old region is unchanged. Use kmem_free to get rid of it.
450 */
451kern_return_t
452kmem_realloc(
91447636
A
453 vm_map_t map,
454 vm_offset_t oldaddr,
455 vm_size_t oldsize,
456 vm_offset_t *newaddrp,
457 vm_size_t newsize)
1c79356b 458{
91447636
A
459 vm_object_t object;
460 vm_object_offset_t offset;
461 vm_map_offset_t oldmapmin;
462 vm_map_offset_t oldmapmax;
463 vm_map_offset_t newmapaddr;
464 vm_map_size_t oldmapsize;
465 vm_map_size_t newmapsize;
466 vm_map_entry_t oldentry;
467 vm_map_entry_t newentry;
468 vm_page_t mem;
469 kern_return_t kr;
1c79356b 470
91447636
A
471 oldmapmin = vm_map_trunc_page(oldaddr);
472 oldmapmax = vm_map_round_page(oldaddr + oldsize);
473 oldmapsize = oldmapmax - oldmapmin;
474 newmapsize = vm_map_round_page(newsize);
1c79356b 475
1c79356b
A
476
477 /*
478 * Find the VM object backing the old region.
479 */
480
b4c24cb9
A
481 vm_map_lock(map);
482
91447636 483 if (!vm_map_lookup_entry(map, oldmapmin, &oldentry))
1c79356b
A
484 panic("kmem_realloc");
485 object = oldentry->object.vm_object;
486
487 /*
488 * Increase the size of the object and
489 * fill in the new region.
490 */
491
492 vm_object_reference(object);
b4c24cb9
A
493 /* by grabbing the object lock before unlocking the map */
494 /* we guarantee that we will panic if more than one */
495 /* attempt is made to realloc a kmem_alloc'd area */
1c79356b 496 vm_object_lock(object);
b4c24cb9 497 vm_map_unlock(map);
91447636 498 if (object->size != oldmapsize)
1c79356b 499 panic("kmem_realloc");
91447636 500 object->size = newmapsize;
1c79356b
A
501 vm_object_unlock(object);
502
b4c24cb9
A
503 /* allocate the new pages while expanded portion of the */
504 /* object is still not mapped */
91447636
A
505 kmem_alloc_pages(object, vm_object_round_page(oldmapsize),
506 vm_object_round_page(newmapsize-oldmapsize));
1c79356b
A
507
508 /*
b4c24cb9 509 * Find space for the new region.
1c79356b
A
510 */
511
91447636 512 kr = vm_map_find_space(map, &newmapaddr, newmapsize,
0c530ab8 513 (vm_map_offset_t) 0, 0, &newentry);
b4c24cb9
A
514 if (kr != KERN_SUCCESS) {
515 vm_object_lock(object);
91447636
A
516 for(offset = oldmapsize;
517 offset < newmapsize; offset += PAGE_SIZE) {
b4c24cb9
A
518 if ((mem = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
519 vm_page_lock_queues();
520 vm_page_free(mem);
521 vm_page_unlock_queues();
522 }
523 }
91447636 524 object->size = oldmapsize;
b4c24cb9
A
525 vm_object_unlock(object);
526 vm_object_deallocate(object);
527 return kr;
528 }
529 newentry->object.vm_object = object;
530 newentry->offset = 0;
531 assert (newentry->wired_count == 0);
532
533
534 /* add an extra reference in case we have someone doing an */
535 /* unexpected deallocate */
536 vm_object_reference(object);
1c79356b
A
537 vm_map_unlock(map);
538
91447636
A
539 kr = vm_map_wire(map, newmapaddr, newmapaddr + newmapsize, VM_PROT_DEFAULT, FALSE);
540 if (KERN_SUCCESS != kr) {
541 vm_map_remove(map, newmapaddr, newmapaddr + newmapsize, 0);
b4c24cb9 542 vm_object_lock(object);
91447636 543 for(offset = oldsize; offset < newmapsize; offset += PAGE_SIZE) {
b4c24cb9
A
544 if ((mem = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
545 vm_page_lock_queues();
546 vm_page_free(mem);
547 vm_page_unlock_queues();
548 }
549 }
91447636 550 object->size = oldmapsize;
b4c24cb9
A
551 vm_object_unlock(object);
552 vm_object_deallocate(object);
553 return (kr);
554 }
555 vm_object_deallocate(object);
1c79356b 556
91447636 557 *newaddrp = CAST_DOWN(vm_offset_t, newmapaddr);
1c79356b
A
558 return KERN_SUCCESS;
559}
560
561/*
562 * kmem_alloc_wired:
563 *
564 * Allocate wired-down memory in the kernel's address map
565 * or a submap. The memory is not zero-filled.
566 *
567 * The memory is allocated in the kernel_object.
568 * It may not be copied with vm_map_copy, and
569 * it may not be reallocated with kmem_realloc.
570 */
571
572kern_return_t
573kmem_alloc_wired(
574 vm_map_t map,
575 vm_offset_t *addrp,
576 vm_size_t size)
577{
578 return kernel_memory_allocate(map, addrp, size, 0, KMA_KOBJECT);
579}
580
581/*
582 * kmem_alloc_aligned:
583 *
584 * Like kmem_alloc_wired, except that the memory is aligned.
585 * The size should be a power-of-2.
586 */
587
588kern_return_t
589kmem_alloc_aligned(
590 vm_map_t map,
591 vm_offset_t *addrp,
592 vm_size_t size)
593{
594 if ((size & (size - 1)) != 0)
595 panic("kmem_alloc_aligned: size not aligned");
596 return kernel_memory_allocate(map, addrp, size, size - 1, KMA_KOBJECT);
597}
598
599/*
600 * kmem_alloc_pageable:
601 *
602 * Allocate pageable memory in the kernel's address map.
603 */
604
605kern_return_t
606kmem_alloc_pageable(
607 vm_map_t map,
608 vm_offset_t *addrp,
609 vm_size_t size)
610{
91447636
A
611 vm_map_offset_t map_addr;
612 vm_map_size_t map_size;
1c79356b
A
613 kern_return_t kr;
614
615#ifndef normal
91447636 616 map_addr = (vm_map_min(map)) + 0x1000;
1c79356b 617#else
91447636 618 map_addr = vm_map_min(map);
1c79356b 619#endif
91447636
A
620 map_size = vm_map_round_page(size);
621
622 kr = vm_map_enter(map, &map_addr, map_size,
623 (vm_map_offset_t) 0, VM_FLAGS_ANYWHERE,
1c79356b
A
624 VM_OBJECT_NULL, (vm_object_offset_t) 0, FALSE,
625 VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
91447636 626
1c79356b
A
627 if (kr != KERN_SUCCESS)
628 return kr;
629
91447636 630 *addrp = CAST_DOWN(vm_offset_t, map_addr);
1c79356b
A
631 return KERN_SUCCESS;
632}
633
634/*
635 * kmem_free:
636 *
637 * Release a region of kernel virtual memory allocated
638 * with kmem_alloc, kmem_alloc_wired, or kmem_alloc_pageable,
639 * and return the physical pages associated with that region.
640 */
641
642void
643kmem_free(
644 vm_map_t map,
645 vm_offset_t addr,
646 vm_size_t size)
647{
648 kern_return_t kr;
649
2d21ac55
A
650 TRACE_MACHLEAKS(KMEM_FREE_CODE, KMEM_FREE_CODE_2, size, addr);
651
91447636
A
652 kr = vm_map_remove(map, vm_map_trunc_page(addr),
653 vm_map_round_page(addr + size),
55e303ae 654 VM_MAP_REMOVE_KUNWIRE);
1c79356b
A
655 if (kr != KERN_SUCCESS)
656 panic("kmem_free");
657}
658
659/*
b4c24cb9 660 * Allocate new pages in an object.
1c79356b
A
661 */
662
663kern_return_t
664kmem_alloc_pages(
665 register vm_object_t object,
666 register vm_object_offset_t offset,
91447636 667 register vm_object_size_t size)
1c79356b 668{
91447636 669 vm_object_size_t alloc_size;
1c79356b 670
91447636 671 alloc_size = vm_object_round_page(size);
b4c24cb9 672 vm_object_lock(object);
91447636 673 while (alloc_size) {
1c79356b
A
674 register vm_page_t mem;
675
1c79356b
A
676
677 /*
678 * Allocate a page
679 */
91447636
A
680 while (VM_PAGE_NULL ==
681 (mem = vm_page_alloc(object, offset))) {
1c79356b
A
682 vm_object_unlock(object);
683 VM_PAGE_WAIT();
684 vm_object_lock(object);
685 }
91447636 686 mem->busy = FALSE;
1c79356b 687
91447636 688 alloc_size -= PAGE_SIZE;
b4c24cb9 689 offset += PAGE_SIZE;
1c79356b 690 }
b4c24cb9 691 vm_object_unlock(object);
1c79356b
A
692 return KERN_SUCCESS;
693}
694
695/*
696 * Remap wired pages in an object into a new region.
697 * The object is assumed to be mapped into the kernel map or
698 * a submap.
699 */
700void
701kmem_remap_pages(
702 register vm_object_t object,
703 register vm_object_offset_t offset,
704 register vm_offset_t start,
705 register vm_offset_t end,
706 vm_prot_t protection)
707{
91447636
A
708
709 vm_map_offset_t map_start;
710 vm_map_offset_t map_end;
711
1c79356b
A
712 /*
713 * Mark the pmap region as not pageable.
714 */
91447636
A
715 map_start = vm_map_trunc_page(start);
716 map_end = vm_map_round_page(end);
1c79356b 717
91447636
A
718 pmap_pageable(kernel_pmap, map_start, map_end, FALSE);
719
720 while (map_start < map_end) {
1c79356b
A
721 register vm_page_t mem;
722
723 vm_object_lock(object);
724
725 /*
726 * Find a page
727 */
728 if ((mem = vm_page_lookup(object, offset)) == VM_PAGE_NULL)
729 panic("kmem_remap_pages");
730
731 /*
732 * Wire it down (again)
733 */
2d21ac55 734 vm_page_lockspin_queues();
1c79356b
A
735 vm_page_wire(mem);
736 vm_page_unlock_queues();
737 vm_object_unlock(object);
738
91447636
A
739 /*
740 * ENCRYPTED SWAP:
741 * The page is supposed to be wired now, so it
742 * shouldn't be encrypted at this point. It can
743 * safely be entered in the page table.
744 */
745 ASSERT_PAGE_DECRYPTED(mem);
746
1c79356b
A
747 /*
748 * Enter it in the kernel pmap. The page isn't busy,
749 * but this shouldn't be a problem because it is wired.
750 */
91447636 751 PMAP_ENTER(kernel_pmap, map_start, mem, protection,
55e303ae
A
752 ((unsigned int)(mem->object->wimg_bits))
753 & VM_WIMG_MASK,
754 TRUE);
1c79356b 755
91447636 756 map_start += PAGE_SIZE;
1c79356b
A
757 offset += PAGE_SIZE;
758 }
759}
760
761/*
762 * kmem_suballoc:
763 *
764 * Allocates a map to manage a subrange
765 * of the kernel virtual address space.
766 *
767 * Arguments are as follows:
768 *
769 * parent Map to take range from
770 * addr Address of start of range (IN/OUT)
771 * size Size of range to find
772 * pageable Can region be paged
773 * anywhere Can region be located anywhere in map
774 * new_map Pointer to new submap
775 */
776kern_return_t
777kmem_suballoc(
778 vm_map_t parent,
779 vm_offset_t *addr,
780 vm_size_t size,
781 boolean_t pageable,
91447636 782 int flags,
1c79356b
A
783 vm_map_t *new_map)
784{
91447636
A
785 vm_map_t map;
786 vm_map_offset_t map_addr;
787 vm_map_size_t map_size;
788 kern_return_t kr;
1c79356b 789
91447636 790 map_size = vm_map_round_page(size);
1c79356b
A
791
792 /*
793 * Need reference on submap object because it is internal
794 * to the vm_system. vm_object_enter will never be called
795 * on it (usual source of reference for vm_map_enter).
796 */
797 vm_object_reference(vm_submap_object);
798
91447636
A
799 map_addr = (flags & VM_FLAGS_ANYWHERE) ?
800 vm_map_min(parent) : vm_map_trunc_page(*addr);
801
802 kr = vm_map_enter(parent, &map_addr, map_size,
803 (vm_map_offset_t) 0, flags,
1c79356b
A
804 vm_submap_object, (vm_object_offset_t) 0, FALSE,
805 VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
806 if (kr != KERN_SUCCESS) {
807 vm_object_deallocate(vm_submap_object);
808 return (kr);
809 }
810
811 pmap_reference(vm_map_pmap(parent));
91447636 812 map = vm_map_create(vm_map_pmap(parent), map_addr, map_addr + map_size, pageable);
1c79356b
A
813 if (map == VM_MAP_NULL)
814 panic("kmem_suballoc: vm_map_create failed"); /* "can't happen" */
815
91447636 816 kr = vm_map_submap(parent, map_addr, map_addr + map_size, map, map_addr, FALSE);
1c79356b
A
817 if (kr != KERN_SUCCESS) {
818 /*
819 * See comment preceding vm_map_submap().
820 */
91447636 821 vm_map_remove(parent, map_addr, map_addr + map_size, VM_MAP_NO_FLAGS);
1c79356b
A
822 vm_map_deallocate(map); /* also removes ref to pmap */
823 vm_object_deallocate(vm_submap_object);
824 return (kr);
825 }
91447636 826 *addr = CAST_DOWN(vm_offset_t, map_addr);
1c79356b
A
827 *new_map = map;
828 return (KERN_SUCCESS);
829}
830
831/*
832 * kmem_init:
833 *
834 * Initialize the kernel's virtual memory map, taking
835 * into account all memory allocated up to this time.
836 */
837void
838kmem_init(
839 vm_offset_t start,
840 vm_offset_t end)
841{
91447636
A
842 vm_map_offset_t map_start;
843 vm_map_offset_t map_end;
844
845 map_start = vm_map_trunc_page(start);
846 map_end = vm_map_round_page(end);
847
848 kernel_map = vm_map_create(pmap_kernel(),VM_MIN_KERNEL_ADDRESS,
0c530ab8 849 map_end, FALSE);
1c79356b
A
850 /*
851 * Reserve virtual memory allocated up to this time.
852 */
1c79356b 853 if (start != VM_MIN_KERNEL_ADDRESS) {
91447636 854 vm_map_offset_t map_addr;
0c530ab8 855
91447636 856 map_addr = VM_MIN_KERNEL_ADDRESS;
1c79356b 857 (void) vm_map_enter(kernel_map,
0c530ab8
A
858 &map_addr,
859 (vm_map_size_t)(map_start - VM_MIN_KERNEL_ADDRESS),
860 (vm_map_offset_t) 0,
861 VM_FLAGS_ANYWHERE | VM_FLAGS_NO_PMAP_CHECK,
862 VM_OBJECT_NULL,
863 (vm_object_offset_t) 0, FALSE,
864 VM_PROT_NONE, VM_PROT_NONE,
865 VM_INHERIT_DEFAULT);
1c79356b
A
866 }
867
2d21ac55 868
1c79356b
A
869 /*
870 * Account for kernel memory (text, data, bss, vm shenanigans).
871 * This may include inaccessible "holes" as determined by what
55e303ae 872 * the machine-dependent init code includes in max_mem.
1c79356b 873 */
55e303ae 874 vm_page_wire_count = (atop_64(max_mem) - (vm_page_free_count
1c79356b
A
875 + vm_page_active_count
876 + vm_page_inactive_count));
2d21ac55
A
877
878 /*
879 * Set the default global user wire limit which limits the amount of
880 * memory that can be locked via mlock(). We set this to the total number of
881 * pages that are potentially usable by a user app (max_mem) minus
882 * 1000 pages. This keeps 4MB in reserve for the kernel which will hopefully be
883 * enough to avoid memory deadlocks. If for some reason the system has less than
884 * 2000 pages of memory at this point, then we'll allow users to lock up to 80%
885 * of that. This can be overridden via a sysctl.
886 */
887
888 if (max_mem > 2000)
889 vm_global_user_wire_limit = max_mem - 1000;
890 else
891 vm_global_user_wire_limit = max_mem * 100 / 80;
892
893 vm_user_wire_limit = vm_global_user_wire_limit; /* the default per user limit is the same as the global limit */
1c79356b
A
894}
895
1c79356b 896
1c79356b
A
897/*
898 * Routine: copyinmap
899 * Purpose:
900 * Like copyin, except that fromaddr is an address
901 * in the specified VM map. This implementation
902 * is incomplete; it handles the current user map
903 * and the kernel map/submaps.
904 */
91447636 905kern_return_t
1c79356b 906copyinmap(
91447636
A
907 vm_map_t map,
908 vm_map_offset_t fromaddr,
909 void *todata,
910 vm_size_t length)
1c79356b 911{
91447636
A
912 kern_return_t kr = KERN_SUCCESS;
913 vm_map_t oldmap;
914
915 if (vm_map_pmap(map) == pmap_kernel())
916 {
1c79356b 917 /* assume a correct copy */
91447636
A
918 memcpy(todata, CAST_DOWN(void *, fromaddr), length);
919 }
920 else if (current_map() == map)
921 {
922 if (copyin(fromaddr, todata, length) != 0)
923 kr = KERN_INVALID_ADDRESS;
1c79356b 924 }
91447636
A
925 else
926 {
927 vm_map_reference(map);
928 oldmap = vm_map_switch(map);
929 if (copyin(fromaddr, todata, length) != 0)
930 kr = KERN_INVALID_ADDRESS;
931 vm_map_switch(oldmap);
932 vm_map_deallocate(map);
933 }
934 return kr;
1c79356b
A
935}
936
937/*
938 * Routine: copyoutmap
939 * Purpose:
940 * Like copyout, except that toaddr is an address
941 * in the specified VM map. This implementation
942 * is incomplete; it handles the current user map
943 * and the kernel map/submaps.
944 */
91447636 945kern_return_t
1c79356b 946copyoutmap(
91447636
A
947 vm_map_t map,
948 void *fromdata,
949 vm_map_address_t toaddr,
950 vm_size_t length)
1c79356b
A
951{
952 if (vm_map_pmap(map) == pmap_kernel()) {
953 /* assume a correct copy */
91447636
A
954 memcpy(CAST_DOWN(void *, toaddr), fromdata, length);
955 return KERN_SUCCESS;
1c79356b
A
956 }
957
91447636
A
958 if (current_map() != map)
959 return KERN_NOT_SUPPORTED;
960
961 if (copyout(fromdata, toaddr, length) != 0)
962 return KERN_INVALID_ADDRESS;
1c79356b 963
91447636 964 return KERN_SUCCESS;
1c79356b 965}
9bccf70c
A
966
967
968kern_return_t
969vm_conflict_check(
970 vm_map_t map,
91447636
A
971 vm_map_offset_t off,
972 vm_map_size_t len,
973 memory_object_t pager,
9bccf70c
A
974 vm_object_offset_t file_off)
975{
976 vm_map_entry_t entry;
977 vm_object_t obj;
978 vm_object_offset_t obj_off;
979 vm_map_t base_map;
91447636
A
980 vm_map_offset_t base_offset;
981 vm_map_offset_t original_offset;
9bccf70c 982 kern_return_t kr;
91447636 983 vm_map_size_t local_len;
9bccf70c
A
984
985 base_map = map;
986 base_offset = off;
987 original_offset = off;
988 kr = KERN_SUCCESS;
989 vm_map_lock(map);
990 while(vm_map_lookup_entry(map, off, &entry)) {
991 local_len = len;
992
993 if (entry->object.vm_object == VM_OBJECT_NULL) {
994 vm_map_unlock(map);
995 return KERN_SUCCESS;
996 }
997 if (entry->is_sub_map) {
998 vm_map_t old_map;
55e303ae 999
9bccf70c
A
1000 old_map = map;
1001 vm_map_lock(entry->object.sub_map);
1002 map = entry->object.sub_map;
1003 off = entry->offset + (off - entry->vme_start);
1004 vm_map_unlock(old_map);
1005 continue;
1006 }
1007 obj = entry->object.vm_object;
1008 obj_off = (off - entry->vme_start) + entry->offset;
1009 while(obj->shadow) {
1010 obj_off += obj->shadow_offset;
1011 obj = obj->shadow;
1012 }
1013 if((obj->pager_created) && (obj->pager == pager)) {
1014 if(((obj->paging_offset) + obj_off) == file_off) {
1015 if(off != base_offset) {
1016 vm_map_unlock(map);
1017 return KERN_FAILURE;
1018 }
1019 kr = KERN_ALREADY_WAITING;
55e303ae
A
1020 } else {
1021 vm_object_offset_t obj_off_aligned;
1022 vm_object_offset_t file_off_aligned;
1023
1024 obj_off_aligned = obj_off & ~PAGE_MASK;
1025 file_off_aligned = file_off & ~PAGE_MASK;
1026
1027 if (file_off_aligned == (obj->paging_offset + obj_off_aligned)) {
1028 /*
1029 * the target map and the file offset start in the same page
1030 * but are not identical...
1031 */
1032 vm_map_unlock(map);
1033 return KERN_FAILURE;
1034 }
1035 if ((file_off < (obj->paging_offset + obj_off_aligned)) &&
1036 ((file_off + len) > (obj->paging_offset + obj_off_aligned))) {
1037 /*
1038 * some portion of the tail of the I/O will fall
1039 * within the encompass of the target map
1040 */
1041 vm_map_unlock(map);
1042 return KERN_FAILURE;
1043 }
1044 if ((file_off_aligned > (obj->paging_offset + obj_off)) &&
1045 (file_off_aligned < (obj->paging_offset + obj_off) + len)) {
1046 /*
1047 * the beginning page of the file offset falls within
1048 * the target map's encompass
1049 */
1050 vm_map_unlock(map);
1051 return KERN_FAILURE;
1052 }
9bccf70c
A
1053 }
1054 } else if(kr != KERN_SUCCESS) {
55e303ae 1055 vm_map_unlock(map);
9bccf70c
A
1056 return KERN_FAILURE;
1057 }
1058
55e303ae 1059 if(len <= ((entry->vme_end - entry->vme_start) -
9bccf70c
A
1060 (off - entry->vme_start))) {
1061 vm_map_unlock(map);
1062 return kr;
1063 } else {
1064 len -= (entry->vme_end - entry->vme_start) -
1065 (off - entry->vme_start);
1066 }
1067 base_offset = base_offset + (local_len - len);
1068 file_off = file_off + (local_len - len);
1069 off = base_offset;
1070 if(map != base_map) {
1071 vm_map_unlock(map);
1072 vm_map_lock(base_map);
1073 map = base_map;
1074 }
1075 }
1076
1077 vm_map_unlock(map);
1078 return kr;
9bccf70c 1079}