]> git.saurik.com Git - apple/xnu.git/blame_incremental - osfmk/vm/vm_kern.c
xnu-1228.7.58.tar.gz
[apple/xnu.git] / osfmk / vm / vm_kern.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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
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>
80
81#include <libkern/OSDebug.h>
82#include <sys/kdebug.h>
83
84/*
85 * Variables exported by this module.
86 */
87
88vm_map_t kernel_map;
89vm_map_t kernel_pageable_map;
90
91extern boolean_t vm_kernel_ready;
92
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,
99 register vm_object_size_t size);
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(
110 vm_map_t map,
111 vm_offset_t *addrp,
112 vm_size_t size,
113 vm_offset_t mask,
114 ppnum_t max_pnum,
115 int flags)
116{
117 vm_object_t object;
118 vm_object_offset_t offset;
119 vm_map_offset_t map_addr;
120 vm_map_offset_t map_mask;
121 vm_map_size_t map_size, i;
122 vm_map_entry_t entry;
123 vm_page_t m, pages;
124 kern_return_t kr;
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
134 map_size = vm_map_round_page(size);
135 map_mask = (vm_map_offset_t)mask;
136
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);
145 } else {
146 object = vm_object_allocate(map_size);
147 }
148
149 kr = vm_map_find_space(map, &map_addr, map_size, map_mask, 0, &entry);
150 if (KERN_SUCCESS != kr) {
151 vm_object_deallocate(object);
152 return kr;
153 }
154
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);
161 vm_map_unlock(map);
162
163 kr = cpm_allocate(CAST_DOWN(vm_size_t, map_size), &pages, max_pnum, FALSE);
164
165 if (kr != KERN_SUCCESS) {
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);
169 *addrp = 0;
170 return kr;
171 }
172
173 vm_object_lock(object);
174 for (i = 0; i < map_size; i += PAGE_SIZE) {
175 m = pages;
176 pages = NEXT_PAGE(m);
177 *(NEXT_PAGE_PTR(m)) = VM_PAGE_NULL;
178 m->busy = FALSE;
179 vm_page_insert(m, object, offset + i);
180 }
181 vm_object_unlock(object);
182
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))
185 != KERN_SUCCESS) {
186 if (object == kernel_object) {
187 vm_object_lock(object);
188 vm_object_page_remove(object, offset, offset + map_size);
189 vm_object_unlock(object);
190 }
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);
194 return kr;
195 }
196 vm_object_deallocate(object);
197
198 if (object == kernel_object)
199 vm_map_simplify(map, map_addr);
200
201 *addrp = map_addr;
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
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
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{
230 vm_object_t object;
231 vm_object_offset_t offset;
232 vm_map_entry_t entry;
233 vm_map_offset_t map_addr, fill_start;
234 vm_map_offset_t map_mask;
235 vm_map_size_t map_size, fill_size;
236 vm_map_size_t i;
237 kern_return_t kr;
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 }
244
245 if (size == 0) {
246 *addrp = 0;
247 return KERN_INVALID_ARGUMENT;
248 }
249 if (flags & KMA_LOMEM) {
250 if ( !(flags & KMA_NOPAGEWAIT) ) {
251 *addrp = 0;
252 return KERN_INVALID_ARGUMENT;
253 }
254 }
255
256 map_size = vm_map_round_page(size);
257 map_mask = (vm_map_offset_t) mask;
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 }
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) {
302 object = kernel_object;
303 vm_object_reference(object);
304 } else {
305 object = vm_object_allocate(map_size);
306 }
307
308 kr = vm_map_find_space(map, &map_addr,
309 fill_size, map_mask,
310 vm_alloc_flags, &entry);
311 if (KERN_SUCCESS != kr) {
312 vm_object_deallocate(object);
313 return kr;
314 }
315
316 entry->object.vm_object = object;
317 entry->offset = offset = (object == kernel_object) ?
318 map_addr - VM_MIN_KERNEL_ADDRESS : 0;
319
320 vm_object_reference(object);
321 vm_map_unlock(map);
322
323 vm_object_lock(object);
324
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) {
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
362 if (flags & KMA_NOPAGEWAIT) {
363 kr = KERN_RESOURCE_SHORTAGE;
364 goto nopage;
365 }
366 vm_object_unlock(object);
367 VM_PAGE_WAIT();
368 vm_object_lock(object);
369 }
370 mem->busy = FALSE;
371 }
372
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 }
388 vm_object_unlock(object);
389 vm_page_more_fictitious();
390 vm_object_lock(object);
391 }
392 mem->busy = FALSE;
393 }
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
403 /* now that the page is wired, we no longer have to fear coalesce */
404 vm_object_deallocate(object);
405 if (object == kernel_object)
406 vm_map_simplify(map, map_addr);
407
408 /*
409 * Return the memory, not zeroed.
410 */
411 *addrp = CAST_DOWN(vm_offset_t, map_addr);
412 return KERN_SUCCESS;
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;
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{
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;
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(
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)
458{
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;
470
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);
475
476
477 /*
478 * Find the VM object backing the old region.
479 */
480
481 vm_map_lock(map);
482
483 if (!vm_map_lookup_entry(map, oldmapmin, &oldentry))
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);
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 */
496 vm_object_lock(object);
497 vm_map_unlock(map);
498 if (object->size != oldmapsize)
499 panic("kmem_realloc");
500 object->size = newmapsize;
501 vm_object_unlock(object);
502
503 /* allocate the new pages while expanded portion of the */
504 /* object is still not mapped */
505 kmem_alloc_pages(object, vm_object_round_page(oldmapsize),
506 vm_object_round_page(newmapsize-oldmapsize));
507
508 /*
509 * Find space for the new region.
510 */
511
512 kr = vm_map_find_space(map, &newmapaddr, newmapsize,
513 (vm_map_offset_t) 0, 0, &newentry);
514 if (kr != KERN_SUCCESS) {
515 vm_object_lock(object);
516 for(offset = oldmapsize;
517 offset < newmapsize; offset += PAGE_SIZE) {
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 }
524 object->size = oldmapsize;
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);
537 vm_map_unlock(map);
538
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);
542 vm_object_lock(object);
543 for(offset = oldsize; offset < newmapsize; offset += PAGE_SIZE) {
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 }
550 object->size = oldmapsize;
551 vm_object_unlock(object);
552 vm_object_deallocate(object);
553 return (kr);
554 }
555 vm_object_deallocate(object);
556
557 *newaddrp = CAST_DOWN(vm_offset_t, newmapaddr);
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{
611 vm_map_offset_t map_addr;
612 vm_map_size_t map_size;
613 kern_return_t kr;
614
615#ifndef normal
616 map_addr = (vm_map_min(map)) + 0x1000;
617#else
618 map_addr = vm_map_min(map);
619#endif
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,
624 VM_OBJECT_NULL, (vm_object_offset_t) 0, FALSE,
625 VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
626
627 if (kr != KERN_SUCCESS)
628 return kr;
629
630 *addrp = CAST_DOWN(vm_offset_t, map_addr);
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
650 TRACE_MACHLEAKS(KMEM_FREE_CODE, KMEM_FREE_CODE_2, size, addr);
651
652 kr = vm_map_remove(map, vm_map_trunc_page(addr),
653 vm_map_round_page(addr + size),
654 VM_MAP_REMOVE_KUNWIRE);
655 if (kr != KERN_SUCCESS)
656 panic("kmem_free");
657}
658
659/*
660 * Allocate new pages in an object.
661 */
662
663kern_return_t
664kmem_alloc_pages(
665 register vm_object_t object,
666 register vm_object_offset_t offset,
667 register vm_object_size_t size)
668{
669 vm_object_size_t alloc_size;
670
671 alloc_size = vm_object_round_page(size);
672 vm_object_lock(object);
673 while (alloc_size) {
674 register vm_page_t mem;
675
676
677 /*
678 * Allocate a page
679 */
680 while (VM_PAGE_NULL ==
681 (mem = vm_page_alloc(object, offset))) {
682 vm_object_unlock(object);
683 VM_PAGE_WAIT();
684 vm_object_lock(object);
685 }
686 mem->busy = FALSE;
687
688 alloc_size -= PAGE_SIZE;
689 offset += PAGE_SIZE;
690 }
691 vm_object_unlock(object);
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{
708
709 vm_map_offset_t map_start;
710 vm_map_offset_t map_end;
711
712 /*
713 * Mark the pmap region as not pageable.
714 */
715 map_start = vm_map_trunc_page(start);
716 map_end = vm_map_round_page(end);
717
718 pmap_pageable(kernel_pmap, map_start, map_end, FALSE);
719
720 while (map_start < map_end) {
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 */
734 vm_page_lockspin_queues();
735 vm_page_wire(mem);
736 vm_page_unlock_queues();
737 vm_object_unlock(object);
738
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
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 */
751 PMAP_ENTER(kernel_pmap, map_start, mem, protection,
752 ((unsigned int)(mem->object->wimg_bits))
753 & VM_WIMG_MASK,
754 TRUE);
755
756 map_start += PAGE_SIZE;
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,
782 int flags,
783 vm_map_t *new_map)
784{
785 vm_map_t map;
786 vm_map_offset_t map_addr;
787 vm_map_size_t map_size;
788 kern_return_t kr;
789
790 map_size = vm_map_round_page(size);
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
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,
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));
812 map = vm_map_create(vm_map_pmap(parent), map_addr, map_addr + map_size, pageable);
813 if (map == VM_MAP_NULL)
814 panic("kmem_suballoc: vm_map_create failed"); /* "can't happen" */
815
816 kr = vm_map_submap(parent, map_addr, map_addr + map_size, map, map_addr, FALSE);
817 if (kr != KERN_SUCCESS) {
818 /*
819 * See comment preceding vm_map_submap().
820 */
821 vm_map_remove(parent, map_addr, map_addr + map_size, VM_MAP_NO_FLAGS);
822 vm_map_deallocate(map); /* also removes ref to pmap */
823 vm_object_deallocate(vm_submap_object);
824 return (kr);
825 }
826 *addr = CAST_DOWN(vm_offset_t, map_addr);
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{
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,
849 map_end, FALSE);
850 /*
851 * Reserve virtual memory allocated up to this time.
852 */
853 if (start != VM_MIN_KERNEL_ADDRESS) {
854 vm_map_offset_t map_addr;
855
856 map_addr = VM_MIN_KERNEL_ADDRESS;
857 (void) vm_map_enter(kernel_map,
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);
866 }
867
868
869 /*
870 * Account for kernel memory (text, data, bss, vm shenanigans).
871 * This may include inaccessible "holes" as determined by what
872 * the machine-dependent init code includes in max_mem.
873 */
874 vm_page_wire_count = (atop_64(max_mem) - (vm_page_free_count
875 + vm_page_active_count
876 + vm_page_inactive_count));
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 */
894}
895
896
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 */
905kern_return_t
906copyinmap(
907 vm_map_t map,
908 vm_map_offset_t fromaddr,
909 void *todata,
910 vm_size_t length)
911{
912 kern_return_t kr = KERN_SUCCESS;
913 vm_map_t oldmap;
914
915 if (vm_map_pmap(map) == pmap_kernel())
916 {
917 /* assume a correct copy */
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;
924 }
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;
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 */
945kern_return_t
946copyoutmap(
947 vm_map_t map,
948 void *fromdata,
949 vm_map_address_t toaddr,
950 vm_size_t length)
951{
952 if (vm_map_pmap(map) == pmap_kernel()) {
953 /* assume a correct copy */
954 memcpy(CAST_DOWN(void *, toaddr), fromdata, length);
955 return KERN_SUCCESS;
956 }
957
958 if (current_map() != map)
959 return KERN_NOT_SUPPORTED;
960
961 if (copyout(fromdata, toaddr, length) != 0)
962 return KERN_INVALID_ADDRESS;
963
964 return KERN_SUCCESS;
965}
966
967
968kern_return_t
969vm_conflict_check(
970 vm_map_t map,
971 vm_map_offset_t off,
972 vm_map_size_t len,
973 memory_object_t pager,
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;
980 vm_map_offset_t base_offset;
981 vm_map_offset_t original_offset;
982 kern_return_t kr;
983 vm_map_size_t local_len;
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;
999
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;
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 }
1053 }
1054 } else if(kr != KERN_SUCCESS) {
1055 vm_map_unlock(map);
1056 return KERN_FAILURE;
1057 }
1058
1059 if(len <= ((entry->vme_end - entry->vme_start) -
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;
1079}