]> git.saurik.com Git - apple/xnu.git/blame - osfmk/vm/vm_kern.c
xnu-2050.48.11.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,
b0d623f7 115 ppnum_t pnum_mask,
91447636 116 int flags)
1c79356b
A
117{
118 vm_object_t object;
1c79356b 119 vm_object_offset_t offset;
91447636
A
120 vm_map_offset_t map_addr;
121 vm_map_offset_t map_mask;
122 vm_map_size_t map_size, i;
1c79356b 123 vm_map_entry_t entry;
91447636
A
124 vm_page_t m, pages;
125 kern_return_t kr;
1c79356b 126
b0d623f7 127 if (map == VM_MAP_NULL || (flags & ~(KMA_KOBJECT | KMA_LOMEM | KMA_NOPAGEWAIT)))
1c79356b 128 return KERN_INVALID_ARGUMENT;
316670eb
A
129
130 map_size = vm_map_round_page(size);
131 map_mask = (vm_map_offset_t)mask;
1c79356b 132
316670eb
A
133 /* Check for zero allocation size (either directly or via overflow) */
134 if (map_size == 0) {
1c79356b
A
135 *addrp = 0;
136 return KERN_INVALID_ARGUMENT;
137 }
138
91447636
A
139 /*
140 * Allocate a new object (if necessary) and the reference we
141 * will be donating to the map entry. We must do this before
142 * locking the map, or risk deadlock with the default pager.
143 */
144 if ((flags & KMA_KOBJECT) != 0) {
145 object = kernel_object;
146 vm_object_reference(object);
1c79356b 147 } else {
91447636 148 object = vm_object_allocate(map_size);
1c79356b
A
149 }
150
0c530ab8 151 kr = vm_map_find_space(map, &map_addr, map_size, map_mask, 0, &entry);
91447636
A
152 if (KERN_SUCCESS != kr) {
153 vm_object_deallocate(object);
1c79356b
A
154 return kr;
155 }
156
91447636
A
157 entry->object.vm_object = object;
158 entry->offset = offset = (object == kernel_object) ?
b0d623f7 159 map_addr : 0;
91447636
A
160
161 /* Take an extra object ref in case the map entry gets deleted */
162 vm_object_reference(object);
1c79356b
A
163 vm_map_unlock(map);
164
b0d623f7 165 kr = cpm_allocate(CAST_DOWN(vm_size_t, map_size), &pages, max_pnum, pnum_mask, FALSE, flags);
1c79356b
A
166
167 if (kr != KERN_SUCCESS) {
91447636
A
168 vm_map_remove(map, vm_map_trunc_page(map_addr),
169 vm_map_round_page(map_addr + map_size), 0);
170 vm_object_deallocate(object);
1c79356b
A
171 *addrp = 0;
172 return kr;
173 }
174
175 vm_object_lock(object);
91447636 176 for (i = 0; i < map_size; i += PAGE_SIZE) {
1c79356b
A
177 m = pages;
178 pages = NEXT_PAGE(m);
0c530ab8 179 *(NEXT_PAGE_PTR(m)) = VM_PAGE_NULL;
1c79356b
A
180 m->busy = FALSE;
181 vm_page_insert(m, object, offset + i);
182 }
183 vm_object_unlock(object);
184
91447636
A
185 if ((kr = vm_map_wire(map, vm_map_trunc_page(map_addr),
186 vm_map_round_page(map_addr + map_size), VM_PROT_DEFAULT, FALSE))
1c79356b
A
187 != KERN_SUCCESS) {
188 if (object == kernel_object) {
189 vm_object_lock(object);
91447636 190 vm_object_page_remove(object, offset, offset + map_size);
1c79356b
A
191 vm_object_unlock(object);
192 }
91447636
A
193 vm_map_remove(map, vm_map_trunc_page(map_addr),
194 vm_map_round_page(map_addr + map_size), 0);
195 vm_object_deallocate(object);
1c79356b
A
196 return kr;
197 }
91447636
A
198 vm_object_deallocate(object);
199
1c79356b 200 if (object == kernel_object)
91447636 201 vm_map_simplify(map, map_addr);
1c79356b 202
b0d623f7
A
203 *addrp = (vm_offset_t) map_addr;
204 assert((vm_map_offset_t) *addrp == map_addr);
1c79356b
A
205 return KERN_SUCCESS;
206}
207
208/*
209 * Master entry point for allocating kernel memory.
210 * NOTE: this routine is _never_ interrupt safe.
211 *
212 * map : map to allocate into
213 * addrp : pointer to start address of new memory
214 * size : size of memory requested
215 * flags : options
216 * KMA_HERE *addrp is base address, else "anywhere"
217 * KMA_NOPAGEWAIT don't wait for pages if unavailable
218 * KMA_KOBJECT use kernel_object
0c530ab8
A
219 * KMA_LOMEM support for 32 bit devices in a 64 bit world
220 * if set and a lomemory pool is available
221 * grab pages from it... this also implies
222 * KMA_NOPAGEWAIT
1c79356b
A
223 */
224
225kern_return_t
226kernel_memory_allocate(
227 register vm_map_t map,
228 register vm_offset_t *addrp,
229 register vm_size_t size,
230 register vm_offset_t mask,
231 int flags)
232{
91447636
A
233 vm_object_t object;
234 vm_object_offset_t offset;
b0d623f7 235 vm_object_offset_t pg_offset;
bd504ef0 236 vm_map_entry_t entry = NULL;
2d21ac55 237 vm_map_offset_t map_addr, fill_start;
91447636 238 vm_map_offset_t map_mask;
2d21ac55 239 vm_map_size_t map_size, fill_size;
1c79356b 240 kern_return_t kr;
2d21ac55 241 vm_page_t mem;
b0d623f7
A
242 vm_page_t guard_page_list = NULL;
243 vm_page_t wired_page_list = NULL;
244 int guard_page_count = 0;
245 int wired_page_count = 0;
246 int i;
2d21ac55 247 int vm_alloc_flags;
316670eb 248 vm_prot_t kma_prot;
2d21ac55
A
249
250 if (! vm_kernel_ready) {
251 panic("kernel_memory_allocate: VM is not ready");
252 }
1c79356b 253
91447636
A
254 map_size = vm_map_round_page(size);
255 map_mask = (vm_map_offset_t) mask;
2d21ac55
A
256 vm_alloc_flags = 0;
257
316670eb
A
258 /* Check for zero allocation size (either directly or via overflow) */
259 if (map_size == 0) {
260 *addrp = 0;
261 return KERN_INVALID_ARGUMENT;
262 }
b0d623f7
A
263
264 /*
265 * limit the size of a single extent of wired memory
266 * to try and limit the damage to the system if
267 * too many pages get wired down
268 */
269 if (map_size > (1 << 30)) {
270 return KERN_RESOURCE_SHORTAGE;
271 }
272
2d21ac55
A
273 /*
274 * Guard pages:
275 *
276 * Guard pages are implemented as ficticious pages. By placing guard pages
277 * on either end of a stack, they can help detect cases where a thread walks
278 * off either end of its stack. They are allocated and set up here and attempts
279 * to access those pages are trapped in vm_fault_page().
280 *
281 * The map_size we were passed may include extra space for
282 * guard pages. If those were requested, then back it out of fill_size
283 * since vm_map_find_space() takes just the actual size not including
284 * guard pages. Similarly, fill_start indicates where the actual pages
285 * will begin in the range.
286 */
287
288 fill_start = 0;
289 fill_size = map_size;
b0d623f7 290
2d21ac55
A
291 if (flags & KMA_GUARD_FIRST) {
292 vm_alloc_flags |= VM_FLAGS_GUARD_BEFORE;
293 fill_start += PAGE_SIZE_64;
294 fill_size -= PAGE_SIZE_64;
295 if (map_size < fill_start + fill_size) {
296 /* no space for a guard page */
297 *addrp = 0;
298 return KERN_INVALID_ARGUMENT;
299 }
b0d623f7 300 guard_page_count++;
2d21ac55
A
301 }
302 if (flags & KMA_GUARD_LAST) {
303 vm_alloc_flags |= VM_FLAGS_GUARD_AFTER;
304 fill_size -= PAGE_SIZE_64;
305 if (map_size <= fill_start + fill_size) {
306 /* no space for a guard page */
307 *addrp = 0;
308 return KERN_INVALID_ARGUMENT;
309 }
b0d623f7
A
310 guard_page_count++;
311 }
312 wired_page_count = (int) (fill_size / PAGE_SIZE_64);
313 assert(wired_page_count * PAGE_SIZE_64 == fill_size);
314
315 for (i = 0; i < guard_page_count; i++) {
316 for (;;) {
317 mem = vm_page_grab_guard();
318
319 if (mem != VM_PAGE_NULL)
320 break;
321 if (flags & KMA_NOPAGEWAIT) {
322 kr = KERN_RESOURCE_SHORTAGE;
323 goto out;
324 }
325 vm_page_more_fictitious();
326 }
327 mem->pageq.next = (queue_entry_t)guard_page_list;
328 guard_page_list = mem;
329 }
330
331 for (i = 0; i < wired_page_count; i++) {
332 uint64_t unavailable;
333
334 for (;;) {
335 if (flags & KMA_LOMEM)
336 mem = vm_page_grablo();
337 else
338 mem = vm_page_grab();
339
340 if (mem != VM_PAGE_NULL)
341 break;
342
343 if (flags & KMA_NOPAGEWAIT) {
344 kr = KERN_RESOURCE_SHORTAGE;
345 goto out;
346 }
0b4c1975
A
347 if ((flags & KMA_LOMEM) && (vm_lopage_needed == TRUE)) {
348 kr = KERN_RESOURCE_SHORTAGE;
349 goto out;
350 }
b0d623f7
A
351 unavailable = (vm_page_wire_count + vm_page_free_target) * PAGE_SIZE;
352
353 if (unavailable > max_mem || map_size > (max_mem - unavailable)) {
354 kr = KERN_RESOURCE_SHORTAGE;
355 goto out;
356 }
357 VM_PAGE_WAIT();
358 }
359 mem->pageq.next = (queue_entry_t)wired_page_list;
360 wired_page_list = mem;
2d21ac55 361 }
91447636
A
362
363 /*
364 * Allocate a new object (if necessary). We must do this before
365 * locking the map, or risk deadlock with the default pager.
366 */
367 if ((flags & KMA_KOBJECT) != 0) {
1c79356b 368 object = kernel_object;
91447636
A
369 vm_object_reference(object);
370 } else {
371 object = vm_object_allocate(map_size);
1c79356b 372 }
91447636 373
2d21ac55
A
374 kr = vm_map_find_space(map, &map_addr,
375 fill_size, map_mask,
376 vm_alloc_flags, &entry);
91447636
A
377 if (KERN_SUCCESS != kr) {
378 vm_object_deallocate(object);
b0d623f7 379 goto out;
1c79356b 380 }
2d21ac55 381
91447636
A
382 entry->object.vm_object = object;
383 entry->offset = offset = (object == kernel_object) ?
b0d623f7 384 map_addr : 0;
1c79356b 385
b0d623f7
A
386 entry->wired_count++;
387
388 if (flags & KMA_PERMANENT)
389 entry->permanent = TRUE;
390
391 if (object != kernel_object)
392 vm_object_reference(object);
1c79356b
A
393
394 vm_object_lock(object);
b0d623f7 395 vm_map_unlock(map);
1c79356b 396
b0d623f7
A
397 pg_offset = 0;
398
399 if (fill_start) {
400 if (guard_page_list == NULL)
401 panic("kernel_memory_allocate: guard_page_list == NULL");
402
403 mem = guard_page_list;
404 guard_page_list = (vm_page_t)mem->pageq.next;
405 mem->pageq.next = NULL;
406
407 vm_page_insert(mem, object, offset + pg_offset);
2d21ac55 408
2d21ac55 409 mem->busy = FALSE;
b0d623f7 410 pg_offset += PAGE_SIZE_64;
2d21ac55 411 }
316670eb
A
412
413 kma_prot = VM_PROT_READ | VM_PROT_WRITE;
414
b0d623f7
A
415 for (pg_offset = fill_start; pg_offset < fill_start + fill_size; pg_offset += PAGE_SIZE_64) {
416 if (wired_page_list == NULL)
417 panic("kernel_memory_allocate: wired_page_list == NULL");
2d21ac55 418
b0d623f7
A
419 mem = wired_page_list;
420 wired_page_list = (vm_page_t)mem->pageq.next;
421 mem->pageq.next = NULL;
422 mem->wire_count++;
2d21ac55 423
b0d623f7 424 vm_page_insert(mem, object, offset + pg_offset);
0c530ab8 425
1c79356b 426 mem->busy = FALSE;
b0d623f7
A
427 mem->pmapped = TRUE;
428 mem->wpmapped = TRUE;
429
430 PMAP_ENTER(kernel_pmap, map_addr + pg_offset, mem,
316670eb 431 kma_prot, VM_PROT_NONE, ((flags & KMA_KSTACK) ? VM_MEM_STACK : 0), TRUE);
0b4c1975
A
432
433 if (flags & KMA_NOENCRYPT) {
434 bzero(CAST_DOWN(void *, (map_addr + pg_offset)), PAGE_SIZE);
435
436 pmap_set_noencrypt(mem->phys_page);
437 }
1c79356b 438 }
b0d623f7
A
439 if ((fill_start + fill_size) < map_size) {
440 if (guard_page_list == NULL)
441 panic("kernel_memory_allocate: guard_page_list == NULL");
1c79356b 442
b0d623f7
A
443 mem = guard_page_list;
444 guard_page_list = (vm_page_t)mem->pageq.next;
445 mem->pageq.next = NULL;
446
447 vm_page_insert(mem, object, offset + pg_offset);
2d21ac55 448
2d21ac55 449 mem->busy = FALSE;
1c79356b 450 }
b0d623f7
A
451 if (guard_page_list || wired_page_list)
452 panic("kernel_memory_allocate: non empty list\n");
2d21ac55 453
b0d623f7
A
454 vm_page_lockspin_queues();
455 vm_page_wire_count += wired_page_count;
456 vm_page_unlock_queues();
2d21ac55 457
b0d623f7
A
458 vm_object_unlock(object);
459
460 /*
461 * now that the pages are wired, we no longer have to fear coalesce
462 */
1c79356b 463 if (object == kernel_object)
91447636 464 vm_map_simplify(map, map_addr);
b0d623f7
A
465 else
466 vm_object_deallocate(object);
1c79356b
A
467
468 /*
469 * Return the memory, not zeroed.
470 */
91447636 471 *addrp = CAST_DOWN(vm_offset_t, map_addr);
1c79356b 472 return KERN_SUCCESS;
2d21ac55 473
b0d623f7
A
474out:
475 if (guard_page_list)
476 vm_page_free_list(guard_page_list, FALSE);
477
478 if (wired_page_list)
479 vm_page_free_list(wired_page_list, FALSE);
480
481 return kr;
1c79356b
A
482}
483
484/*
485 * kmem_alloc:
486 *
487 * Allocate wired-down memory in the kernel's address map
488 * or a submap. The memory is not zero-filled.
489 */
490
491kern_return_t
492kmem_alloc(
493 vm_map_t map,
494 vm_offset_t *addrp,
495 vm_size_t size)
496{
2d21ac55
A
497 kern_return_t kr = kernel_memory_allocate(map, addrp, size, 0, 0);
498 TRACE_MACHLEAKS(KMEM_ALLOC_CODE, KMEM_ALLOC_CODE_2, size, *addrp);
499 return kr;
1c79356b
A
500}
501
502/*
503 * kmem_realloc:
504 *
505 * Reallocate wired-down memory in the kernel's address map
506 * or a submap. Newly allocated pages are not zeroed.
507 * This can only be used on regions allocated with kmem_alloc.
508 *
509 * If successful, the pages in the old region are mapped twice.
510 * The old region is unchanged. Use kmem_free to get rid of it.
511 */
512kern_return_t
513kmem_realloc(
91447636
A
514 vm_map_t map,
515 vm_offset_t oldaddr,
516 vm_size_t oldsize,
517 vm_offset_t *newaddrp,
518 vm_size_t newsize)
1c79356b 519{
91447636
A
520 vm_object_t object;
521 vm_object_offset_t offset;
522 vm_map_offset_t oldmapmin;
523 vm_map_offset_t oldmapmax;
524 vm_map_offset_t newmapaddr;
525 vm_map_size_t oldmapsize;
526 vm_map_size_t newmapsize;
527 vm_map_entry_t oldentry;
528 vm_map_entry_t newentry;
529 vm_page_t mem;
530 kern_return_t kr;
1c79356b 531
91447636
A
532 oldmapmin = vm_map_trunc_page(oldaddr);
533 oldmapmax = vm_map_round_page(oldaddr + oldsize);
534 oldmapsize = oldmapmax - oldmapmin;
535 newmapsize = vm_map_round_page(newsize);
1c79356b 536
1c79356b
A
537
538 /*
539 * Find the VM object backing the old region.
540 */
541
b4c24cb9
A
542 vm_map_lock(map);
543
91447636 544 if (!vm_map_lookup_entry(map, oldmapmin, &oldentry))
1c79356b
A
545 panic("kmem_realloc");
546 object = oldentry->object.vm_object;
547
548 /*
549 * Increase the size of the object and
550 * fill in the new region.
551 */
552
553 vm_object_reference(object);
b4c24cb9
A
554 /* by grabbing the object lock before unlocking the map */
555 /* we guarantee that we will panic if more than one */
556 /* attempt is made to realloc a kmem_alloc'd area */
1c79356b 557 vm_object_lock(object);
b4c24cb9 558 vm_map_unlock(map);
6d2010ae 559 if (object->vo_size != oldmapsize)
1c79356b 560 panic("kmem_realloc");
6d2010ae 561 object->vo_size = newmapsize;
1c79356b
A
562 vm_object_unlock(object);
563
b4c24cb9
A
564 /* allocate the new pages while expanded portion of the */
565 /* object is still not mapped */
91447636
A
566 kmem_alloc_pages(object, vm_object_round_page(oldmapsize),
567 vm_object_round_page(newmapsize-oldmapsize));
1c79356b
A
568
569 /*
b4c24cb9 570 * Find space for the new region.
1c79356b
A
571 */
572
91447636 573 kr = vm_map_find_space(map, &newmapaddr, newmapsize,
0c530ab8 574 (vm_map_offset_t) 0, 0, &newentry);
b4c24cb9
A
575 if (kr != KERN_SUCCESS) {
576 vm_object_lock(object);
91447636
A
577 for(offset = oldmapsize;
578 offset < newmapsize; offset += PAGE_SIZE) {
b4c24cb9 579 if ((mem = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
b0d623f7 580 VM_PAGE_FREE(mem);
b4c24cb9
A
581 }
582 }
6d2010ae 583 object->vo_size = oldmapsize;
b4c24cb9
A
584 vm_object_unlock(object);
585 vm_object_deallocate(object);
586 return kr;
587 }
588 newentry->object.vm_object = object;
589 newentry->offset = 0;
590 assert (newentry->wired_count == 0);
591
592
593 /* add an extra reference in case we have someone doing an */
594 /* unexpected deallocate */
595 vm_object_reference(object);
1c79356b
A
596 vm_map_unlock(map);
597
91447636
A
598 kr = vm_map_wire(map, newmapaddr, newmapaddr + newmapsize, VM_PROT_DEFAULT, FALSE);
599 if (KERN_SUCCESS != kr) {
600 vm_map_remove(map, newmapaddr, newmapaddr + newmapsize, 0);
b4c24cb9 601 vm_object_lock(object);
91447636 602 for(offset = oldsize; offset < newmapsize; offset += PAGE_SIZE) {
b4c24cb9 603 if ((mem = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
b0d623f7 604 VM_PAGE_FREE(mem);
b4c24cb9
A
605 }
606 }
6d2010ae 607 object->vo_size = oldmapsize;
b4c24cb9
A
608 vm_object_unlock(object);
609 vm_object_deallocate(object);
610 return (kr);
611 }
612 vm_object_deallocate(object);
1c79356b 613
91447636 614 *newaddrp = CAST_DOWN(vm_offset_t, newmapaddr);
1c79356b
A
615 return KERN_SUCCESS;
616}
617
618/*
b0d623f7 619 * kmem_alloc_kobject:
1c79356b
A
620 *
621 * Allocate wired-down memory in the kernel's address map
622 * or a submap. The memory is not zero-filled.
623 *
624 * The memory is allocated in the kernel_object.
625 * It may not be copied with vm_map_copy, and
626 * it may not be reallocated with kmem_realloc.
627 */
628
629kern_return_t
b0d623f7 630kmem_alloc_kobject(
1c79356b
A
631 vm_map_t map,
632 vm_offset_t *addrp,
633 vm_size_t size)
634{
635 return kernel_memory_allocate(map, addrp, size, 0, KMA_KOBJECT);
636}
637
638/*
639 * kmem_alloc_aligned:
640 *
b0d623f7 641 * Like kmem_alloc_kobject, except that the memory is aligned.
1c79356b
A
642 * The size should be a power-of-2.
643 */
644
645kern_return_t
646kmem_alloc_aligned(
647 vm_map_t map,
648 vm_offset_t *addrp,
649 vm_size_t size)
650{
651 if ((size & (size - 1)) != 0)
652 panic("kmem_alloc_aligned: size not aligned");
653 return kernel_memory_allocate(map, addrp, size, size - 1, KMA_KOBJECT);
654}
655
656/*
657 * kmem_alloc_pageable:
658 *
659 * Allocate pageable memory in the kernel's address map.
660 */
661
662kern_return_t
663kmem_alloc_pageable(
664 vm_map_t map,
665 vm_offset_t *addrp,
666 vm_size_t size)
667{
91447636
A
668 vm_map_offset_t map_addr;
669 vm_map_size_t map_size;
1c79356b
A
670 kern_return_t kr;
671
672#ifndef normal
91447636 673 map_addr = (vm_map_min(map)) + 0x1000;
1c79356b 674#else
91447636 675 map_addr = vm_map_min(map);
1c79356b 676#endif
91447636
A
677 map_size = vm_map_round_page(size);
678
679 kr = vm_map_enter(map, &map_addr, map_size,
680 (vm_map_offset_t) 0, VM_FLAGS_ANYWHERE,
1c79356b
A
681 VM_OBJECT_NULL, (vm_object_offset_t) 0, FALSE,
682 VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
91447636 683
1c79356b
A
684 if (kr != KERN_SUCCESS)
685 return kr;
686
91447636 687 *addrp = CAST_DOWN(vm_offset_t, map_addr);
1c79356b
A
688 return KERN_SUCCESS;
689}
690
691/*
692 * kmem_free:
693 *
694 * Release a region of kernel virtual memory allocated
b0d623f7 695 * with kmem_alloc, kmem_alloc_kobject, or kmem_alloc_pageable,
1c79356b
A
696 * and return the physical pages associated with that region.
697 */
698
699void
700kmem_free(
701 vm_map_t map,
702 vm_offset_t addr,
703 vm_size_t size)
704{
705 kern_return_t kr;
706
b0d623f7
A
707 assert(addr >= VM_MIN_KERNEL_AND_KEXT_ADDRESS);
708
2d21ac55
A
709 TRACE_MACHLEAKS(KMEM_FREE_CODE, KMEM_FREE_CODE_2, size, addr);
710
b0d623f7
A
711 if(size == 0) {
712#if MACH_ASSERT
713 printf("kmem_free called with size==0 for map: %p with addr: 0x%llx\n",map,(uint64_t)addr);
714#endif
715 return;
716 }
717
91447636
A
718 kr = vm_map_remove(map, vm_map_trunc_page(addr),
719 vm_map_round_page(addr + size),
55e303ae 720 VM_MAP_REMOVE_KUNWIRE);
1c79356b
A
721 if (kr != KERN_SUCCESS)
722 panic("kmem_free");
723}
724
725/*
b4c24cb9 726 * Allocate new pages in an object.
1c79356b
A
727 */
728
729kern_return_t
730kmem_alloc_pages(
731 register vm_object_t object,
732 register vm_object_offset_t offset,
91447636 733 register vm_object_size_t size)
1c79356b 734{
91447636 735 vm_object_size_t alloc_size;
1c79356b 736
91447636 737 alloc_size = vm_object_round_page(size);
b4c24cb9 738 vm_object_lock(object);
91447636 739 while (alloc_size) {
1c79356b
A
740 register vm_page_t mem;
741
1c79356b
A
742
743 /*
744 * Allocate a page
745 */
91447636
A
746 while (VM_PAGE_NULL ==
747 (mem = vm_page_alloc(object, offset))) {
1c79356b
A
748 vm_object_unlock(object);
749 VM_PAGE_WAIT();
750 vm_object_lock(object);
751 }
91447636 752 mem->busy = FALSE;
1c79356b 753
91447636 754 alloc_size -= PAGE_SIZE;
b4c24cb9 755 offset += PAGE_SIZE;
1c79356b 756 }
b4c24cb9 757 vm_object_unlock(object);
1c79356b
A
758 return KERN_SUCCESS;
759}
760
761/*
762 * Remap wired pages in an object into a new region.
763 * The object is assumed to be mapped into the kernel map or
764 * a submap.
765 */
766void
767kmem_remap_pages(
768 register vm_object_t object,
769 register vm_object_offset_t offset,
770 register vm_offset_t start,
771 register vm_offset_t end,
772 vm_prot_t protection)
773{
91447636
A
774
775 vm_map_offset_t map_start;
776 vm_map_offset_t map_end;
777
1c79356b
A
778 /*
779 * Mark the pmap region as not pageable.
780 */
91447636
A
781 map_start = vm_map_trunc_page(start);
782 map_end = vm_map_round_page(end);
1c79356b 783
91447636
A
784 pmap_pageable(kernel_pmap, map_start, map_end, FALSE);
785
786 while (map_start < map_end) {
1c79356b
A
787 register vm_page_t mem;
788
789 vm_object_lock(object);
790
791 /*
792 * Find a page
793 */
794 if ((mem = vm_page_lookup(object, offset)) == VM_PAGE_NULL)
795 panic("kmem_remap_pages");
796
797 /*
798 * Wire it down (again)
799 */
2d21ac55 800 vm_page_lockspin_queues();
1c79356b
A
801 vm_page_wire(mem);
802 vm_page_unlock_queues();
803 vm_object_unlock(object);
804
91447636
A
805 /*
806 * ENCRYPTED SWAP:
807 * The page is supposed to be wired now, so it
808 * shouldn't be encrypted at this point. It can
809 * safely be entered in the page table.
810 */
811 ASSERT_PAGE_DECRYPTED(mem);
812
1c79356b
A
813 /*
814 * Enter it in the kernel pmap. The page isn't busy,
815 * but this shouldn't be a problem because it is wired.
816 */
b0d623f7
A
817
818 mem->pmapped = TRUE;
819 mem->wpmapped = TRUE;
820
316670eb 821 PMAP_ENTER(kernel_pmap, map_start, mem, protection, VM_PROT_NONE, 0, TRUE);
1c79356b 822
91447636 823 map_start += PAGE_SIZE;
1c79356b
A
824 offset += PAGE_SIZE;
825 }
826}
827
828/*
829 * kmem_suballoc:
830 *
831 * Allocates a map to manage a subrange
832 * of the kernel virtual address space.
833 *
834 * Arguments are as follows:
835 *
836 * parent Map to take range from
837 * addr Address of start of range (IN/OUT)
838 * size Size of range to find
839 * pageable Can region be paged
840 * anywhere Can region be located anywhere in map
841 * new_map Pointer to new submap
842 */
843kern_return_t
844kmem_suballoc(
845 vm_map_t parent,
846 vm_offset_t *addr,
847 vm_size_t size,
848 boolean_t pageable,
91447636 849 int flags,
1c79356b
A
850 vm_map_t *new_map)
851{
91447636
A
852 vm_map_t map;
853 vm_map_offset_t map_addr;
854 vm_map_size_t map_size;
855 kern_return_t kr;
1c79356b 856
91447636 857 map_size = vm_map_round_page(size);
1c79356b
A
858
859 /*
860 * Need reference on submap object because it is internal
861 * to the vm_system. vm_object_enter will never be called
862 * on it (usual source of reference for vm_map_enter).
863 */
864 vm_object_reference(vm_submap_object);
865
91447636
A
866 map_addr = (flags & VM_FLAGS_ANYWHERE) ?
867 vm_map_min(parent) : vm_map_trunc_page(*addr);
868
869 kr = vm_map_enter(parent, &map_addr, map_size,
870 (vm_map_offset_t) 0, flags,
1c79356b
A
871 vm_submap_object, (vm_object_offset_t) 0, FALSE,
872 VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
873 if (kr != KERN_SUCCESS) {
874 vm_object_deallocate(vm_submap_object);
875 return (kr);
876 }
877
878 pmap_reference(vm_map_pmap(parent));
91447636 879 map = vm_map_create(vm_map_pmap(parent), map_addr, map_addr + map_size, pageable);
1c79356b
A
880 if (map == VM_MAP_NULL)
881 panic("kmem_suballoc: vm_map_create failed"); /* "can't happen" */
882
91447636 883 kr = vm_map_submap(parent, map_addr, map_addr + map_size, map, map_addr, FALSE);
1c79356b
A
884 if (kr != KERN_SUCCESS) {
885 /*
886 * See comment preceding vm_map_submap().
887 */
91447636 888 vm_map_remove(parent, map_addr, map_addr + map_size, VM_MAP_NO_FLAGS);
1c79356b
A
889 vm_map_deallocate(map); /* also removes ref to pmap */
890 vm_object_deallocate(vm_submap_object);
891 return (kr);
892 }
91447636 893 *addr = CAST_DOWN(vm_offset_t, map_addr);
1c79356b
A
894 *new_map = map;
895 return (KERN_SUCCESS);
896}
897
898/*
899 * kmem_init:
900 *
901 * Initialize the kernel's virtual memory map, taking
902 * into account all memory allocated up to this time.
903 */
904void
905kmem_init(
906 vm_offset_t start,
907 vm_offset_t end)
908{
91447636
A
909 vm_map_offset_t map_start;
910 vm_map_offset_t map_end;
911
912 map_start = vm_map_trunc_page(start);
913 map_end = vm_map_round_page(end);
914
6d2010ae 915 kernel_map = vm_map_create(pmap_kernel(),VM_MIN_KERNEL_AND_KEXT_ADDRESS,
0c530ab8 916 map_end, FALSE);
1c79356b
A
917 /*
918 * Reserve virtual memory allocated up to this time.
919 */
6d2010ae 920 if (start != VM_MIN_KERNEL_AND_KEXT_ADDRESS) {
91447636 921 vm_map_offset_t map_addr;
6d2010ae 922 kern_return_t kr;
0c530ab8 923
6d2010ae
A
924 map_addr = VM_MIN_KERNEL_AND_KEXT_ADDRESS;
925 kr = vm_map_enter(kernel_map,
926 &map_addr,
927 (vm_map_size_t)(map_start - VM_MIN_KERNEL_AND_KEXT_ADDRESS),
928 (vm_map_offset_t) 0,
929 VM_FLAGS_FIXED | VM_FLAGS_NO_PMAP_CHECK,
930 VM_OBJECT_NULL,
931 (vm_object_offset_t) 0, FALSE,
932 VM_PROT_NONE, VM_PROT_NONE,
933 VM_INHERIT_DEFAULT);
934
935 if (kr != KERN_SUCCESS) {
936 panic("kmem_init(0x%llx,0x%llx): vm_map_enter(0x%llx,0x%llx) error 0x%x\n",
937 (uint64_t) start, (uint64_t) end,
938 (uint64_t) VM_MIN_KERNEL_AND_KEXT_ADDRESS,
939 (uint64_t) (map_start - VM_MIN_KERNEL_AND_KEXT_ADDRESS),
940 kr);
941 }
1c79356b 942 }
6d2010ae 943
2d21ac55
A
944 /*
945 * Set the default global user wire limit which limits the amount of
b0d623f7
A
946 * memory that can be locked via mlock(). We set this to the total
947 * amount of memory that are potentially usable by a user app (max_mem)
948 * minus a certain amount. This can be overridden via a sysctl.
2d21ac55 949 */
b0d623f7
A
950 vm_global_no_user_wire_amount = MIN(max_mem*20/100,
951 VM_NOT_USER_WIREABLE);
952 vm_global_user_wire_limit = max_mem - vm_global_no_user_wire_amount;
2d21ac55 953
b0d623f7
A
954 /* the default per user limit is the same as the global limit */
955 vm_user_wire_limit = vm_global_user_wire_limit;
1c79356b
A
956}
957
1c79356b 958
1c79356b
A
959/*
960 * Routine: copyinmap
961 * Purpose:
962 * Like copyin, except that fromaddr is an address
963 * in the specified VM map. This implementation
964 * is incomplete; it handles the current user map
965 * and the kernel map/submaps.
966 */
91447636 967kern_return_t
1c79356b 968copyinmap(
91447636
A
969 vm_map_t map,
970 vm_map_offset_t fromaddr,
971 void *todata,
972 vm_size_t length)
1c79356b 973{
91447636
A
974 kern_return_t kr = KERN_SUCCESS;
975 vm_map_t oldmap;
976
977 if (vm_map_pmap(map) == pmap_kernel())
978 {
1c79356b 979 /* assume a correct copy */
91447636
A
980 memcpy(todata, CAST_DOWN(void *, fromaddr), length);
981 }
982 else if (current_map() == map)
983 {
984 if (copyin(fromaddr, todata, length) != 0)
985 kr = KERN_INVALID_ADDRESS;
1c79356b 986 }
91447636
A
987 else
988 {
989 vm_map_reference(map);
990 oldmap = vm_map_switch(map);
991 if (copyin(fromaddr, todata, length) != 0)
992 kr = KERN_INVALID_ADDRESS;
993 vm_map_switch(oldmap);
994 vm_map_deallocate(map);
995 }
996 return kr;
1c79356b
A
997}
998
999/*
1000 * Routine: copyoutmap
1001 * Purpose:
1002 * Like copyout, except that toaddr is an address
1003 * in the specified VM map. This implementation
1004 * is incomplete; it handles the current user map
1005 * and the kernel map/submaps.
1006 */
91447636 1007kern_return_t
1c79356b 1008copyoutmap(
91447636
A
1009 vm_map_t map,
1010 void *fromdata,
1011 vm_map_address_t toaddr,
1012 vm_size_t length)
1c79356b
A
1013{
1014 if (vm_map_pmap(map) == pmap_kernel()) {
1015 /* assume a correct copy */
91447636
A
1016 memcpy(CAST_DOWN(void *, toaddr), fromdata, length);
1017 return KERN_SUCCESS;
1c79356b
A
1018 }
1019
91447636
A
1020 if (current_map() != map)
1021 return KERN_NOT_SUPPORTED;
1022
1023 if (copyout(fromdata, toaddr, length) != 0)
1024 return KERN_INVALID_ADDRESS;
1c79356b 1025
91447636 1026 return KERN_SUCCESS;
1c79356b 1027}
9bccf70c
A
1028
1029
1030kern_return_t
1031vm_conflict_check(
1032 vm_map_t map,
91447636
A
1033 vm_map_offset_t off,
1034 vm_map_size_t len,
1035 memory_object_t pager,
9bccf70c
A
1036 vm_object_offset_t file_off)
1037{
1038 vm_map_entry_t entry;
1039 vm_object_t obj;
1040 vm_object_offset_t obj_off;
1041 vm_map_t base_map;
91447636
A
1042 vm_map_offset_t base_offset;
1043 vm_map_offset_t original_offset;
9bccf70c 1044 kern_return_t kr;
91447636 1045 vm_map_size_t local_len;
9bccf70c
A
1046
1047 base_map = map;
1048 base_offset = off;
1049 original_offset = off;
1050 kr = KERN_SUCCESS;
1051 vm_map_lock(map);
1052 while(vm_map_lookup_entry(map, off, &entry)) {
1053 local_len = len;
1054
1055 if (entry->object.vm_object == VM_OBJECT_NULL) {
1056 vm_map_unlock(map);
1057 return KERN_SUCCESS;
1058 }
1059 if (entry->is_sub_map) {
1060 vm_map_t old_map;
55e303ae 1061
9bccf70c
A
1062 old_map = map;
1063 vm_map_lock(entry->object.sub_map);
1064 map = entry->object.sub_map;
1065 off = entry->offset + (off - entry->vme_start);
1066 vm_map_unlock(old_map);
1067 continue;
1068 }
1069 obj = entry->object.vm_object;
1070 obj_off = (off - entry->vme_start) + entry->offset;
1071 while(obj->shadow) {
6d2010ae 1072 obj_off += obj->vo_shadow_offset;
9bccf70c
A
1073 obj = obj->shadow;
1074 }
1075 if((obj->pager_created) && (obj->pager == pager)) {
1076 if(((obj->paging_offset) + obj_off) == file_off) {
1077 if(off != base_offset) {
1078 vm_map_unlock(map);
1079 return KERN_FAILURE;
1080 }
1081 kr = KERN_ALREADY_WAITING;
55e303ae
A
1082 } else {
1083 vm_object_offset_t obj_off_aligned;
1084 vm_object_offset_t file_off_aligned;
1085
1086 obj_off_aligned = obj_off & ~PAGE_MASK;
1087 file_off_aligned = file_off & ~PAGE_MASK;
1088
1089 if (file_off_aligned == (obj->paging_offset + obj_off_aligned)) {
1090 /*
1091 * the target map and the file offset start in the same page
1092 * but are not identical...
1093 */
1094 vm_map_unlock(map);
1095 return KERN_FAILURE;
1096 }
1097 if ((file_off < (obj->paging_offset + obj_off_aligned)) &&
1098 ((file_off + len) > (obj->paging_offset + obj_off_aligned))) {
1099 /*
1100 * some portion of the tail of the I/O will fall
1101 * within the encompass of the target map
1102 */
1103 vm_map_unlock(map);
1104 return KERN_FAILURE;
1105 }
1106 if ((file_off_aligned > (obj->paging_offset + obj_off)) &&
1107 (file_off_aligned < (obj->paging_offset + obj_off) + len)) {
1108 /*
1109 * the beginning page of the file offset falls within
1110 * the target map's encompass
1111 */
1112 vm_map_unlock(map);
1113 return KERN_FAILURE;
1114 }
9bccf70c
A
1115 }
1116 } else if(kr != KERN_SUCCESS) {
55e303ae 1117 vm_map_unlock(map);
9bccf70c
A
1118 return KERN_FAILURE;
1119 }
1120
55e303ae 1121 if(len <= ((entry->vme_end - entry->vme_start) -
9bccf70c
A
1122 (off - entry->vme_start))) {
1123 vm_map_unlock(map);
1124 return kr;
1125 } else {
1126 len -= (entry->vme_end - entry->vme_start) -
1127 (off - entry->vme_start);
1128 }
1129 base_offset = base_offset + (local_len - len);
1130 file_off = file_off + (local_len - len);
1131 off = base_offset;
1132 if(map != base_map) {
1133 vm_map_unlock(map);
1134 vm_map_lock(base_map);
1135 map = base_map;
1136 }
1137 }
1138
1139 vm_map_unlock(map);
1140 return kr;
9bccf70c 1141}