|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
4: * Copyright (c) 1993,1994 The University of Utah and
5: * the Computer Systems Laboratory (CSL).
6: * All rights reserved.
7: *
8: * Permission to use, copy, modify and distribute this software and its
9: * documentation is hereby granted, provided that both the copyright
10: * notice and this permission notice appear in all copies of the
11: * software, derivative works or modified versions, and any portions
12: * thereof, and that both notices appear in supporting documentation.
13: *
14: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
15: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
16: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
17: * THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or [email protected]
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie Mellon
27: * the rights to redistribute these changes.
28: */
29: /*
30: * File: vm/vm_kern.c
31: * Author: Avadis Tevanian, Jr., Michael Wayne Young
32: * Date: 1985
33: *
34: * Kernel memory management.
35: */
36:
1.1.1.2 root 37: #include <string.h>
38:
1.1 root 39: #include <mach/kern_return.h>
1.1.1.2 root 40: #include <machine/locore.h>
41: #include <machine/vm_param.h>
1.1 root 42: #include <kern/assert.h>
1.1.1.2 root 43: #include <kern/debug.h>
1.1 root 44: #include <kern/lock.h>
1.1.1.3 ! root 45: #include <kern/slab.h>
1.1 root 46: #include <kern/thread.h>
1.1.1.2 root 47: #include <kern/printf.h>
48: #include <vm/pmap.h>
1.1 root 49: #include <vm/vm_fault.h>
50: #include <vm/vm_kern.h>
51: #include <vm/vm_map.h>
52: #include <vm/vm_object.h>
53: #include <vm/vm_page.h>
54: #include <vm/vm_pageout.h>
55:
56:
57:
58: /*
59: * Variables exported by this module.
60: */
61:
1.1.1.2 root 62: static struct vm_map kernel_map_store;
63: vm_map_t kernel_map = &kernel_map_store;
1.1 root 64: vm_map_t kernel_pageable_map;
65:
66: /*
67: * projected_buffer_allocate
68: *
69: * Allocate a wired-down buffer shared between kernel and user task.
70: * Fresh, zero-filled memory is allocated.
71: * If persistence is false, this buffer can only be deallocated from
72: * user task using projected_buffer_deallocate, and deallocation
73: * from user task also deallocates the buffer from the kernel map.
74: * projected_buffer_collect is called from vm_map_deallocate to
75: * automatically deallocate projected buffers on task_deallocate.
76: * Sharing with more than one user task is achieved by using
77: * projected_buffer_map for the second and subsequent tasks.
78: * The user is precluded from manipulating the VM entry of this buffer
79: * (i.e. changing protection, inheritance or machine attributes).
80: */
81:
82: kern_return_t
1.1.1.3 ! root 83: projected_buffer_allocate(
! 84: vm_map_t map,
! 85: vm_size_t size,
! 86: int persistence,
! 87: vm_offset_t *kernel_p,
! 88: vm_offset_t *user_p,
! 89: vm_prot_t protection,
! 90: vm_inherit_t inheritance) /*Currently only VM_INHERIT_NONE supported*/
1.1 root 91: {
92: vm_object_t object;
93: vm_map_entry_t u_entry, k_entry;
94: vm_offset_t addr;
95: vm_size_t r_size;
96: kern_return_t kr;
97:
98: if (map == VM_MAP_NULL || map == kernel_map)
99: return(KERN_INVALID_ARGUMENT);
100:
101: /*
102: * Allocate a new object.
103: */
104:
105: size = round_page(size);
106: object = vm_object_allocate(size);
107:
108: vm_map_lock(kernel_map);
109: kr = vm_map_find_entry(kernel_map, &addr, size, (vm_offset_t) 0,
110: VM_OBJECT_NULL, &k_entry);
111: if (kr != KERN_SUCCESS) {
112: vm_map_unlock(kernel_map);
113: vm_object_deallocate(object);
114: return kr;
115: }
116:
117: k_entry->object.vm_object = object;
118: if (!persistence)
119: k_entry->projected_on = (vm_map_entry_t) -1;
120: /*Mark entry so as to automatically deallocate it when
121: last corresponding user entry is deallocated*/
122: vm_map_unlock(kernel_map);
123: *kernel_p = addr;
124:
125: vm_map_lock(map);
126: kr = vm_map_find_entry(map, &addr, size, (vm_offset_t) 0,
127: VM_OBJECT_NULL, &u_entry);
128: if (kr != KERN_SUCCESS) {
129: vm_map_unlock(map);
130: vm_map_lock(kernel_map);
131: vm_map_entry_delete(kernel_map, k_entry);
132: vm_map_unlock(kernel_map);
133: vm_object_deallocate(object);
134: return kr;
135: }
136:
137: u_entry->object.vm_object = object;
138: vm_object_reference(object);
139: u_entry->projected_on = k_entry;
140: /*Creates coupling with kernel mapping of the buffer, and
141: also guarantees that user cannot directly manipulate
142: buffer VM entry*/
143: u_entry->protection = protection;
144: u_entry->max_protection = protection;
145: u_entry->inheritance = inheritance;
146: vm_map_unlock(map);
147: *user_p = addr;
148:
149: /*
150: * Allocate wired-down memory in the object,
151: * and enter it in the kernel pmap.
152: */
153: kmem_alloc_pages(object, 0,
154: *kernel_p, *kernel_p + size,
155: VM_PROT_READ | VM_PROT_WRITE);
1.1.1.2 root 156: memset((void*) *kernel_p, 0, size); /*Zero fill*/
1.1 root 157:
158: /* Set up physical mappings for user pmap */
159:
160: pmap_pageable(map->pmap, *user_p, *user_p + size, FALSE);
161: for (r_size = 0; r_size < size; r_size += PAGE_SIZE) {
162: addr = pmap_extract(kernel_pmap, *kernel_p + r_size);
163: pmap_enter(map->pmap, *user_p + r_size, addr,
164: protection, TRUE);
165: }
166:
167: return(KERN_SUCCESS);
168: }
169:
170:
171: /*
172: * projected_buffer_map
173: *
174: * Map an area of kernel memory onto a task's address space.
175: * No new memory is allocated; the area must previously exist in the
176: * kernel memory map.
177: */
178:
179: kern_return_t
1.1.1.3 ! root 180: projected_buffer_map(
! 181: vm_map_t map,
! 182: vm_offset_t kernel_addr,
! 183: vm_size_t size,
! 184: vm_offset_t *user_p,
! 185: vm_prot_t protection,
! 186: vm_inherit_t inheritance) /*Currently only VM_INHERIT_NONE supported*/
1.1 root 187: {
188: vm_map_entry_t u_entry, k_entry;
189: vm_offset_t physical_addr, user_addr;
190: vm_size_t r_size;
191: kern_return_t kr;
192:
193: /*
194: * Find entry in kernel map
195: */
196:
197: size = round_page(size);
198: if (map == VM_MAP_NULL || map == kernel_map ||
199: !vm_map_lookup_entry(kernel_map, kernel_addr, &k_entry) ||
200: kernel_addr + size > k_entry->vme_end)
201: return(KERN_INVALID_ARGUMENT);
202:
203:
204: /*
205: * Create entry in user task
206: */
207:
208: vm_map_lock(map);
209: kr = vm_map_find_entry(map, &user_addr, size, (vm_offset_t) 0,
210: VM_OBJECT_NULL, &u_entry);
211: if (kr != KERN_SUCCESS) {
212: vm_map_unlock(map);
213: return kr;
214: }
215:
216: u_entry->object.vm_object = k_entry->object.vm_object;
217: vm_object_reference(k_entry->object.vm_object);
218: u_entry->offset = kernel_addr - k_entry->vme_start + k_entry->offset;
219: u_entry->projected_on = k_entry;
220: /*Creates coupling with kernel mapping of the buffer, and
221: also guarantees that user cannot directly manipulate
222: buffer VM entry*/
223: u_entry->protection = protection;
224: u_entry->max_protection = protection;
225: u_entry->inheritance = inheritance;
226: u_entry->wired_count = k_entry->wired_count;
227: vm_map_unlock(map);
228: *user_p = user_addr;
229:
230: /* Set up physical mappings for user pmap */
231:
232: pmap_pageable(map->pmap, user_addr, user_addr + size,
233: !k_entry->wired_count);
234: for (r_size = 0; r_size < size; r_size += PAGE_SIZE) {
235: physical_addr = pmap_extract(kernel_pmap, kernel_addr + r_size);
236: pmap_enter(map->pmap, user_addr + r_size, physical_addr,
237: protection, k_entry->wired_count);
238: }
239:
240: return(KERN_SUCCESS);
241: }
242:
243:
244: /*
245: * projected_buffer_deallocate
246: *
247: * Unmap projected buffer from task's address space.
248: * May also unmap buffer from kernel map, if buffer is not
249: * persistent and only the kernel reference remains.
250: */
251:
252: kern_return_t
1.1.1.3 ! root 253: projected_buffer_deallocate(
! 254: vm_map_t map,
! 255: vm_offset_t start,
! 256: vm_offset_t end)
1.1 root 257: {
258: vm_map_entry_t entry, k_entry;
259:
1.1.1.3 ! root 260: if (map == VM_MAP_NULL || map == kernel_map)
! 261: return KERN_INVALID_ARGUMENT;
! 262:
1.1 root 263: vm_map_lock(map);
1.1.1.3 ! root 264: if (!vm_map_lookup_entry(map, start, &entry) ||
1.1 root 265: end > entry->vme_end ||
266: /*Check corresponding kernel entry*/
267: (k_entry = entry->projected_on) == 0) {
268: vm_map_unlock(map);
269: return(KERN_INVALID_ARGUMENT);
270: }
271:
272: /*Prepare for deallocation*/
273: if (entry->vme_start < start)
1.1.1.2 root 274: _vm_map_clip_start(&map->hdr, entry, start);
1.1 root 275: if (entry->vme_end > end)
1.1.1.2 root 276: _vm_map_clip_end(&map->hdr, entry, end);
1.1 root 277: if (map->first_free == entry) /*Adjust first_free hint*/
278: map->first_free = entry->vme_prev;
279: entry->projected_on = 0; /*Needed to allow deletion*/
280: entry->wired_count = 0; /*Avoid unwire fault*/
281: vm_map_entry_delete(map, entry);
282: vm_map_unlock(map);
283:
284: /*Check if the buffer is not persistent and only the
285: kernel mapping remains, and if so delete it*/
286: vm_map_lock(kernel_map);
287: if (k_entry->projected_on == (vm_map_entry_t) -1 &&
288: k_entry->object.vm_object->ref_count == 1) {
289: if (kernel_map->first_free == k_entry)
290: kernel_map->first_free = k_entry->vme_prev;
291: k_entry->projected_on = 0; /*Allow unwire fault*/
292: vm_map_entry_delete(kernel_map, k_entry);
293: }
294: vm_map_unlock(kernel_map);
295: return(KERN_SUCCESS);
296: }
297:
298:
299: /*
300: * projected_buffer_collect
301: *
302: * Unmap all projected buffers from task's address space.
303: */
304:
305: kern_return_t
1.1.1.3 ! root 306: projected_buffer_collect(vm_map_t map)
1.1 root 307: {
308: vm_map_entry_t entry, next;
309:
310: if (map == VM_MAP_NULL || map == kernel_map)
311: return(KERN_INVALID_ARGUMENT);
312:
313: for (entry = vm_map_first_entry(map);
314: entry != vm_map_to_entry(map);
315: entry = next) {
316: next = entry->vme_next;
317: if (entry->projected_on != 0)
318: projected_buffer_deallocate(map, entry->vme_start, entry->vme_end);
319: }
320: return(KERN_SUCCESS);
321: }
322:
323:
324: /*
325: * projected_buffer_in_range
326: *
327: * Verifies whether a projected buffer exists in the address range
328: * given.
329: */
330:
331: boolean_t
1.1.1.3 ! root 332: projected_buffer_in_range(
! 333: vm_map_t map,
! 334: vm_offset_t start,
! 335: vm_offset_t end)
1.1 root 336: {
337: vm_map_entry_t entry;
338:
339: if (map == VM_MAP_NULL || map == kernel_map)
340: return(FALSE);
341:
342: /*Find first entry*/
343: if (!vm_map_lookup_entry(map, start, &entry))
344: entry = entry->vme_next;
345:
346: while (entry != vm_map_to_entry(map) && entry->projected_on == 0 &&
347: entry->vme_start <= end) {
348: entry = entry->vme_next;
349: }
350: return(entry != vm_map_to_entry(map) && entry->vme_start <= end);
351: }
352:
353:
354: /*
355: * kmem_alloc:
356: *
357: * Allocate wired-down memory in the kernel's address map
358: * or a submap. The memory is not zero-filled.
359: */
360:
361: kern_return_t
1.1.1.3 ! root 362: kmem_alloc(
! 363: vm_map_t map,
! 364: vm_offset_t *addrp,
! 365: vm_size_t size)
1.1 root 366: {
367: vm_object_t object;
368: vm_map_entry_t entry;
369: vm_offset_t addr;
1.1.1.3 ! root 370: unsigned int attempts;
1.1 root 371: kern_return_t kr;
372:
373: /*
374: * Allocate a new object. We must do this before locking
375: * the map, lest we risk deadlock with the default pager:
376: * device_read_alloc uses kmem_alloc,
377: * which tries to allocate an object,
378: * which uses kmem_alloc_wired to get memory,
379: * which blocks for pages.
380: * then the default pager needs to read a block
381: * to process a memory_object_data_write,
382: * and device_read_alloc calls kmem_alloc
383: * and deadlocks on the map lock.
384: */
385:
386: size = round_page(size);
387: object = vm_object_allocate(size);
388:
1.1.1.3 ! root 389: attempts = 0;
! 390:
! 391: retry:
1.1 root 392: vm_map_lock(map);
393: kr = vm_map_find_entry(map, &addr, size, (vm_offset_t) 0,
394: VM_OBJECT_NULL, &entry);
395: if (kr != KERN_SUCCESS) {
396: vm_map_unlock(map);
1.1.1.3 ! root 397:
! 398: if (attempts == 0) {
! 399: attempts++;
! 400: slab_collect();
! 401: goto retry;
! 402: }
! 403:
! 404: printf_once("no more room for kmem_alloc in %p\n", map);
1.1 root 405: vm_object_deallocate(object);
406: return kr;
407: }
408:
409: entry->object.vm_object = object;
410: entry->offset = 0;
411:
412: /*
413: * Since we have not given out this address yet,
414: * it is safe to unlock the map.
415: */
416: vm_map_unlock(map);
417:
418: /*
419: * Allocate wired-down memory in the kernel_object,
420: * for this entry, and enter it in the kernel pmap.
421: */
422: kmem_alloc_pages(object, 0,
423: addr, addr + size,
424: VM_PROT_DEFAULT);
425:
426: /*
427: * Return the memory, not zeroed.
428: */
429: *addrp = addr;
430: return KERN_SUCCESS;
431: }
432:
433: /*
434: * kmem_realloc:
435: *
436: * Reallocate wired-down memory in the kernel's address map
437: * or a submap. Newly allocated pages are not zeroed.
438: * This can only be used on regions allocated with kmem_alloc.
439: *
440: * If successful, the pages in the old region are mapped twice.
441: * The old region is unchanged. Use kmem_free to get rid of it.
442: */
1.1.1.3 ! root 443: kern_return_t kmem_realloc(
! 444: vm_map_t map,
! 445: vm_offset_t oldaddr,
! 446: vm_size_t oldsize,
! 447: vm_offset_t *newaddrp,
! 448: vm_size_t newsize)
1.1 root 449: {
450: vm_offset_t oldmin, oldmax;
451: vm_offset_t newaddr;
452: vm_object_t object;
453: vm_map_entry_t oldentry, newentry;
1.1.1.3 ! root 454: unsigned int attempts;
1.1 root 455: kern_return_t kr;
456:
457: oldmin = trunc_page(oldaddr);
458: oldmax = round_page(oldaddr + oldsize);
459: oldsize = oldmax - oldmin;
460: newsize = round_page(newsize);
461:
462: /*
463: * Find space for the new region.
464: */
465:
1.1.1.3 ! root 466: attempts = 0;
! 467:
! 468: retry:
1.1 root 469: vm_map_lock(map);
470: kr = vm_map_find_entry(map, &newaddr, newsize, (vm_offset_t) 0,
471: VM_OBJECT_NULL, &newentry);
472: if (kr != KERN_SUCCESS) {
473: vm_map_unlock(map);
1.1.1.3 ! root 474:
! 475: if (attempts == 0) {
! 476: attempts++;
! 477: slab_collect();
! 478: goto retry;
! 479: }
! 480:
1.1.1.2 root 481: printf_once("no more room for kmem_realloc in %p\n", map);
1.1 root 482: return kr;
483: }
484:
485: /*
486: * Find the VM object backing the old region.
487: */
488:
489: if (!vm_map_lookup_entry(map, oldmin, &oldentry))
490: panic("kmem_realloc");
491: object = oldentry->object.vm_object;
492:
493: /*
494: * Increase the size of the object and
495: * fill in the new region.
496: */
497:
498: vm_object_reference(object);
499: vm_object_lock(object);
500: if (object->size != oldsize)
501: panic("kmem_realloc");
502: object->size = newsize;
503: vm_object_unlock(object);
504:
505: newentry->object.vm_object = object;
506: newentry->offset = 0;
507:
508: /*
509: * Since we have not given out this address yet,
510: * it is safe to unlock the map. We are trusting
511: * that nobody will play with either region.
512: */
513:
514: vm_map_unlock(map);
515:
516: /*
517: * Remap the pages in the old region and
518: * allocate more pages for the new region.
519: */
520:
521: kmem_remap_pages(object, 0,
522: newaddr, newaddr + oldsize,
523: VM_PROT_DEFAULT);
524: kmem_alloc_pages(object, oldsize,
525: newaddr + oldsize, newaddr + newsize,
526: VM_PROT_DEFAULT);
527:
528: *newaddrp = newaddr;
529: return KERN_SUCCESS;
530: }
531:
532: /*
533: * kmem_alloc_wired:
534: *
535: * Allocate wired-down memory in the kernel's address map
536: * or a submap. The memory is not zero-filled.
537: *
538: * The memory is allocated in the kernel_object.
539: * It may not be copied with vm_map_copy, and
540: * it may not be reallocated with kmem_realloc.
541: */
542:
543: kern_return_t
1.1.1.3 ! root 544: kmem_alloc_wired(
! 545: vm_map_t map,
! 546: vm_offset_t *addrp,
! 547: vm_size_t size)
1.1 root 548: {
549: vm_map_entry_t entry;
550: vm_offset_t offset;
551: vm_offset_t addr;
1.1.1.3 ! root 552: unsigned int attempts;
1.1 root 553: kern_return_t kr;
554:
555: /*
556: * Use the kernel object for wired-down kernel pages.
557: * Assume that no region of the kernel object is
558: * referenced more than once. We want vm_map_find_entry
559: * to extend an existing entry if possible.
560: */
561:
562: size = round_page(size);
1.1.1.3 ! root 563: attempts = 0;
! 564:
! 565: retry:
1.1 root 566: vm_map_lock(map);
567: kr = vm_map_find_entry(map, &addr, size, (vm_offset_t) 0,
568: kernel_object, &entry);
569: if (kr != KERN_SUCCESS) {
570: vm_map_unlock(map);
1.1.1.3 ! root 571:
! 572: if (attempts == 0) {
! 573: attempts++;
! 574: slab_collect();
! 575: goto retry;
! 576: }
! 577:
! 578: printf_once("no more room for kmem_alloc_wired in %p\n", map);
1.1 root 579: return kr;
580: }
581:
582: /*
583: * Since we didn't know where the new region would
584: * start, we couldn't supply the correct offset into
585: * the kernel object. We only initialize the entry
586: * if we aren't extending an existing entry.
587: */
588:
589: offset = addr - VM_MIN_KERNEL_ADDRESS;
590:
591: if (entry->object.vm_object == VM_OBJECT_NULL) {
592: vm_object_reference(kernel_object);
593:
594: entry->object.vm_object = kernel_object;
595: entry->offset = offset;
596: }
597:
598: /*
599: * Since we have not given out this address yet,
600: * it is safe to unlock the map.
601: */
602: vm_map_unlock(map);
603:
604: /*
605: * Allocate wired-down memory in the kernel_object,
606: * for this entry, and enter it in the kernel pmap.
607: */
608: kmem_alloc_pages(kernel_object, offset,
609: addr, addr + size,
610: VM_PROT_DEFAULT);
611:
612: /*
613: * Return the memory, not zeroed.
614: */
615: *addrp = addr;
616: return KERN_SUCCESS;
617: }
618:
619: /*
620: * kmem_alloc_aligned:
621: *
622: * Like kmem_alloc_wired, except that the memory is aligned.
623: * The size should be a power-of-2.
624: */
625:
626: kern_return_t
1.1.1.3 ! root 627: kmem_alloc_aligned(
! 628: vm_map_t map,
! 629: vm_offset_t *addrp,
! 630: vm_size_t size)
1.1 root 631: {
632: vm_map_entry_t entry;
633: vm_offset_t offset;
634: vm_offset_t addr;
1.1.1.3 ! root 635: unsigned int attempts;
1.1 root 636: kern_return_t kr;
637:
638: if ((size & (size - 1)) != 0)
639: panic("kmem_alloc_aligned");
640:
641: /*
642: * Use the kernel object for wired-down kernel pages.
643: * Assume that no region of the kernel object is
644: * referenced more than once. We want vm_map_find_entry
645: * to extend an existing entry if possible.
646: */
647:
648: size = round_page(size);
1.1.1.3 ! root 649: attempts = 0;
! 650:
! 651: retry:
1.1 root 652: vm_map_lock(map);
653: kr = vm_map_find_entry(map, &addr, size, size - 1,
654: kernel_object, &entry);
655: if (kr != KERN_SUCCESS) {
656: vm_map_unlock(map);
1.1.1.3 ! root 657:
! 658: if (attempts == 0) {
! 659: attempts++;
! 660: slab_collect();
! 661: goto retry;
! 662: }
! 663:
! 664: printf_once("no more rooom for kmem_alloc_aligned in %p\n", map);
1.1 root 665: return kr;
666: }
667:
668: /*
669: * Since we didn't know where the new region would
670: * start, we couldn't supply the correct offset into
671: * the kernel object. We only initialize the entry
672: * if we aren't extending an existing entry.
673: */
674:
675: offset = addr - VM_MIN_KERNEL_ADDRESS;
676:
677: if (entry->object.vm_object == VM_OBJECT_NULL) {
678: vm_object_reference(kernel_object);
679:
680: entry->object.vm_object = kernel_object;
681: entry->offset = offset;
682: }
683:
684: /*
685: * Since we have not given out this address yet,
686: * it is safe to unlock the map.
687: */
688: vm_map_unlock(map);
689:
690: /*
691: * Allocate wired-down memory in the kernel_object,
692: * for this entry, and enter it in the kernel pmap.
693: */
694: kmem_alloc_pages(kernel_object, offset,
695: addr, addr + size,
696: VM_PROT_DEFAULT);
697:
698: /*
699: * Return the memory, not zeroed.
700: */
701: *addrp = addr;
702: return KERN_SUCCESS;
703: }
704:
705: /*
706: * kmem_alloc_pageable:
707: *
708: * Allocate pageable memory in the kernel's address map.
709: */
710:
711: kern_return_t
1.1.1.3 ! root 712: kmem_alloc_pageable(
! 713: vm_map_t map,
! 714: vm_offset_t *addrp,
! 715: vm_size_t size)
1.1 root 716: {
717: vm_offset_t addr;
718: kern_return_t kr;
719:
720: addr = vm_map_min(map);
721: kr = vm_map_enter(map, &addr, round_page(size),
722: (vm_offset_t) 0, TRUE,
723: VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
724: VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
1.1.1.2 root 725: if (kr != KERN_SUCCESS) {
726: printf_once("no more room for kmem_alloc_pageable in %p\n", map);
1.1 root 727: return kr;
1.1.1.2 root 728: }
1.1 root 729:
730: *addrp = addr;
731: return KERN_SUCCESS;
732: }
733:
734: /*
735: * kmem_free:
736: *
737: * Release a region of kernel virtual memory allocated
738: * with kmem_alloc, kmem_alloc_wired, or kmem_alloc_pageable,
739: * and return the physical pages associated with that region.
740: */
741:
742: void
1.1.1.3 ! root 743: kmem_free(
! 744: vm_map_t map,
! 745: vm_offset_t addr,
! 746: vm_size_t size)
1.1 root 747: {
748: kern_return_t kr;
749:
750: kr = vm_map_remove(map, trunc_page(addr), round_page(addr + size));
751: if (kr != KERN_SUCCESS)
752: panic("kmem_free");
753: }
754:
755: /*
756: * Allocate new wired pages in an object.
757: * The object is assumed to be mapped into the kernel map or
758: * a submap.
759: */
760: void
1.1.1.3 ! root 761: kmem_alloc_pages(
! 762: vm_object_t object,
! 763: vm_offset_t offset,
! 764: vm_offset_t start,
! 765: vm_offset_t end,
! 766: vm_prot_t protection)
1.1 root 767: {
768: /*
769: * Mark the pmap region as not pageable.
770: */
771: pmap_pageable(kernel_pmap, start, end, FALSE);
772:
773: while (start < end) {
1.1.1.3 ! root 774: vm_page_t mem;
1.1 root 775:
776: vm_object_lock(object);
777:
778: /*
779: * Allocate a page
780: */
781: while ((mem = vm_page_alloc(object, offset))
782: == VM_PAGE_NULL) {
783: vm_object_unlock(object);
784: VM_PAGE_WAIT((void (*)()) 0);
785: vm_object_lock(object);
786: }
787:
788: /*
789: * Wire it down
790: */
791: vm_page_lock_queues();
792: vm_page_wire(mem);
793: vm_page_unlock_queues();
794: vm_object_unlock(object);
795:
796: /*
797: * Enter it in the kernel pmap
798: */
799: PMAP_ENTER(kernel_pmap, start, mem,
800: protection, TRUE);
801:
802: vm_object_lock(object);
803: PAGE_WAKEUP_DONE(mem);
804: vm_object_unlock(object);
805:
806: start += PAGE_SIZE;
807: offset += PAGE_SIZE;
808: }
809: }
810:
811: /*
812: * Remap wired pages in an object into a new region.
813: * The object is assumed to be mapped into the kernel map or
814: * a submap.
815: */
816: void
1.1.1.3 ! root 817: kmem_remap_pages(
! 818: vm_object_t object,
! 819: vm_offset_t offset,
! 820: vm_offset_t start,
! 821: vm_offset_t end,
! 822: vm_prot_t protection)
1.1 root 823: {
824: /*
825: * Mark the pmap region as not pageable.
826: */
827: pmap_pageable(kernel_pmap, start, end, FALSE);
828:
829: while (start < end) {
1.1.1.3 ! root 830: vm_page_t mem;
1.1 root 831:
832: vm_object_lock(object);
833:
834: /*
835: * Find a page
836: */
837: if ((mem = vm_page_lookup(object, offset)) == VM_PAGE_NULL)
838: panic("kmem_remap_pages");
839:
840: /*
841: * Wire it down (again)
842: */
843: vm_page_lock_queues();
844: vm_page_wire(mem);
845: vm_page_unlock_queues();
846: vm_object_unlock(object);
847:
848: /*
849: * Enter it in the kernel pmap. The page isn't busy,
850: * but this shouldn't be a problem because it is wired.
851: */
852: PMAP_ENTER(kernel_pmap, start, mem,
853: protection, TRUE);
854:
855: start += PAGE_SIZE;
856: offset += PAGE_SIZE;
857: }
858: }
859:
860: /*
1.1.1.2 root 861: * kmem_submap:
1.1 root 862: *
1.1.1.2 root 863: * Initializes a map to manage a subrange
1.1 root 864: * of the kernel virtual address space.
865: *
866: * Arguments are as follows:
867: *
1.1.1.2 root 868: * map Map to initialize
1.1 root 869: * parent Map to take range from
870: * size Size of range to find
871: * min, max Returned endpoints of map
872: * pageable Can the region be paged
873: */
874:
1.1.1.2 root 875: void
1.1.1.3 ! root 876: kmem_submap(
! 877: vm_map_t map,
! 878: vm_map_t parent,
! 879: vm_offset_t *min,
! 880: vm_offset_t *max,
! 881: vm_size_t size,
! 882: boolean_t pageable)
1.1 root 883: {
884: vm_offset_t addr;
885: kern_return_t kr;
886:
887: size = round_page(size);
888:
889: /*
890: * Need reference on submap object because it is internal
891: * to the vm_system. vm_object_enter will never be called
892: * on it (usual source of reference for vm_map_enter).
893: */
894: vm_object_reference(vm_submap_object);
895:
1.1.1.3 ! root 896: addr = vm_map_min(parent);
1.1 root 897: kr = vm_map_enter(parent, &addr, size,
898: (vm_offset_t) 0, TRUE,
899: vm_submap_object, (vm_offset_t) 0, FALSE,
900: VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
901: if (kr != KERN_SUCCESS)
1.1.1.2 root 902: panic("kmem_submap");
1.1 root 903:
904: pmap_reference(vm_map_pmap(parent));
1.1.1.2 root 905: vm_map_setup(map, vm_map_pmap(parent), addr, addr + size, pageable);
1.1 root 906: kr = vm_map_submap(parent, addr, addr + size, map);
907: if (kr != KERN_SUCCESS)
1.1.1.2 root 908: panic("kmem_submap");
1.1 root 909:
910: *min = addr;
911: *max = addr + size;
912: }
913:
914: /*
915: * kmem_init:
916: *
917: * Initialize the kernel's virtual memory map, taking
918: * into account all memory allocated up to this time.
919: */
1.1.1.3 ! root 920: void kmem_init(
! 921: vm_offset_t start,
! 922: vm_offset_t end)
1.1 root 923: {
1.1.1.2 root 924: vm_map_setup(kernel_map, pmap_kernel(), VM_MIN_KERNEL_ADDRESS, end,
925: FALSE);
1.1 root 926:
927: /*
928: * Reserve virtual memory allocated up to this time.
929: */
930:
931: if (start != VM_MIN_KERNEL_ADDRESS) {
932: kern_return_t rc;
933: vm_offset_t addr = VM_MIN_KERNEL_ADDRESS;
934: rc = vm_map_enter(kernel_map,
935: &addr, start - VM_MIN_KERNEL_ADDRESS,
936: (vm_offset_t) 0, TRUE,
937: VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
938: VM_PROT_DEFAULT, VM_PROT_ALL,
939: VM_INHERIT_DEFAULT);
940: if (rc)
941: panic("%s:%d: vm_map_enter failed (%d)\n", rc);
942: }
943: }
944:
945: /*
946: * New and improved IO wiring support.
947: */
948:
949: /*
950: * kmem_io_map_copyout:
951: *
952: * Establish temporary mapping in designated map for the memory
953: * passed in. Memory format must be a page_list vm_map_copy.
954: * Mapping is READ-ONLY.
955: */
956:
957: kern_return_t
1.1.1.3 ! root 958: kmem_io_map_copyout(
! 959: vm_map_t map,
! 960: vm_offset_t *addr, /* actual addr of data */
! 961: vm_offset_t *alloc_addr, /* page aligned addr */
! 962: vm_size_t *alloc_size, /* size allocated */
! 963: vm_map_copy_t copy,
! 964: vm_size_t min_size) /* Do at least this much */
1.1 root 965: {
966: vm_offset_t myaddr, offset;
967: vm_size_t mysize, copy_size;
968: kern_return_t ret;
969: vm_page_t *page_list;
970: vm_map_copy_t new_copy;
971: int i;
972:
973: assert(copy->type == VM_MAP_COPY_PAGE_LIST);
974: assert(min_size != 0);
975:
976: /*
977: * Figure out the size in vm pages.
978: */
979: min_size += copy->offset - trunc_page(copy->offset);
980: min_size = round_page(min_size);
981: mysize = round_page(copy->offset + copy->size) -
982: trunc_page(copy->offset);
983:
984: /*
985: * If total size is larger than one page list and
986: * we don't have to do more than one page list, then
987: * only do one page list.
988: *
989: * XXX Could be much smarter about this ... like trimming length
990: * XXX if we need more than one page list but not all of them.
991: */
992:
993: copy_size = ptoa(copy->cpy_npages);
994: if (mysize > copy_size && copy_size > min_size)
995: mysize = copy_size;
996:
997: /*
998: * Allocate some address space in the map (must be kernel
999: * space).
1000: */
1001: myaddr = vm_map_min(map);
1002: ret = vm_map_enter(map, &myaddr, mysize,
1003: (vm_offset_t) 0, TRUE,
1004: VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
1005: VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
1006:
1007: if (ret != KERN_SUCCESS)
1008: return(ret);
1009:
1010: /*
1011: * Tell the pmap module that this will be wired, and
1012: * enter the mappings.
1013: */
1014: pmap_pageable(vm_map_pmap(map), myaddr, myaddr + mysize, TRUE);
1015:
1016: *addr = myaddr + (copy->offset - trunc_page(copy->offset));
1017: *alloc_addr = myaddr;
1018: *alloc_size = mysize;
1019:
1020: offset = myaddr;
1021: page_list = ©->cpy_page_list[0];
1022: while (TRUE) {
1023: for ( i = 0; i < copy->cpy_npages; i++, offset += PAGE_SIZE) {
1024: PMAP_ENTER(vm_map_pmap(map), offset, *page_list,
1025: VM_PROT_READ, TRUE);
1026: page_list++;
1027: }
1028:
1029: if (offset == (myaddr + mysize))
1030: break;
1031:
1032: /*
1033: * Onward to the next page_list. The extend_cont
1034: * leaves the current page list's pages alone;
1035: * they'll be cleaned up at discard. Reset this
1036: * copy's continuation to discard the next one.
1037: */
1038: vm_map_copy_invoke_extend_cont(copy, &new_copy, &ret);
1039:
1040: if (ret != KERN_SUCCESS) {
1041: kmem_io_map_deallocate(map, myaddr, mysize);
1042: return(ret);
1043: }
1044: copy->cpy_cont = vm_map_copy_discard_cont;
1045: copy->cpy_cont_args = (char *) new_copy;
1046: copy = new_copy;
1047: page_list = ©->cpy_page_list[0];
1048: }
1049:
1050: return(ret);
1051: }
1052:
1053: /*
1054: * kmem_io_map_deallocate:
1055: *
1056: * Get rid of the mapping established by kmem_io_map_copyout.
1057: * Assumes that addr and size have been rounded to page boundaries.
1058: * (e.g., the alloc_addr and alloc_size returned by kmem_io_map_copyout)
1059: */
1060:
1061: void
1.1.1.3 ! root 1062: kmem_io_map_deallocate(
! 1063: vm_map_t map,
! 1064: vm_offset_t addr,
! 1065: vm_size_t size)
1.1 root 1066: {
1067: /*
1068: * Remove the mappings. The pmap_remove is needed.
1069: */
1070:
1071: pmap_remove(vm_map_pmap(map), addr, addr + size);
1072: vm_map_remove(map, addr, addr + size);
1073: }
1074:
1075: /*
1076: * Routine: copyinmap
1077: * Purpose:
1078: * Like copyin, except that fromaddr is an address
1079: * in the specified VM map. This implementation
1080: * is incomplete; it handles the current user map
1081: * and the kernel map/submaps.
1082: */
1083:
1.1.1.3 ! root 1084: int copyinmap(
! 1085: vm_map_t map,
! 1086: char *fromaddr,
! 1087: char *toaddr,
! 1088: int length)
1.1 root 1089: {
1090: if (vm_map_pmap(map) == kernel_pmap) {
1091: /* assume a correct copy */
1.1.1.2 root 1092: memcpy(toaddr, fromaddr, length);
1.1 root 1093: return 0;
1094: }
1095:
1096: if (current_map() == map)
1097: return copyin( fromaddr, toaddr, length);
1098:
1099: return 1;
1100: }
1101:
1102: /*
1103: * Routine: copyoutmap
1104: * Purpose:
1105: * Like copyout, except that toaddr is an address
1106: * in the specified VM map. This implementation
1107: * is incomplete; it handles the current user map
1108: * and the kernel map/submaps.
1109: */
1110:
1.1.1.3 ! root 1111: int copyoutmap(
! 1112: vm_map_t map,
! 1113: char *fromaddr,
! 1114: char *toaddr,
! 1115: int length)
1.1 root 1116: {
1117: if (vm_map_pmap(map) == kernel_pmap) {
1118: /* assume a correct copy */
1.1.1.2 root 1119: memcpy(toaddr, fromaddr, length);
1.1 root 1120: return 0;
1121: }
1122:
1123: if (current_map() == map)
1124: return copyout(fromaddr, toaddr, length);
1125:
1126: return 1;
1127: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.