|
|
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_alloc_wired:
435: *
436: * Allocate wired-down memory in the kernel's address map
437: * or a submap. The memory is not zero-filled.
438: *
439: * The memory is allocated in the kernel_object.
1.1.1.4 ! root 440: * It may not be copied with vm_map_copy.
1.1 root 441: */
442:
443: kern_return_t
1.1.1.3 root 444: kmem_alloc_wired(
445: vm_map_t map,
446: vm_offset_t *addrp,
447: vm_size_t size)
1.1 root 448: {
449: vm_map_entry_t entry;
450: vm_offset_t offset;
451: vm_offset_t addr;
1.1.1.3 root 452: unsigned int attempts;
1.1 root 453: kern_return_t kr;
454:
455: /*
456: * Use the kernel object for wired-down kernel pages.
457: * Assume that no region of the kernel object is
458: * referenced more than once. We want vm_map_find_entry
459: * to extend an existing entry if possible.
460: */
461:
462: size = round_page(size);
1.1.1.3 root 463: attempts = 0;
464:
465: retry:
1.1 root 466: vm_map_lock(map);
467: kr = vm_map_find_entry(map, &addr, size, (vm_offset_t) 0,
468: kernel_object, &entry);
469: if (kr != KERN_SUCCESS) {
470: vm_map_unlock(map);
1.1.1.3 root 471:
472: if (attempts == 0) {
473: attempts++;
474: slab_collect();
475: goto retry;
476: }
477:
478: printf_once("no more room for kmem_alloc_wired in %p\n", map);
1.1 root 479: return kr;
480: }
481:
482: /*
483: * Since we didn't know where the new region would
484: * start, we couldn't supply the correct offset into
485: * the kernel object. We only initialize the entry
486: * if we aren't extending an existing entry.
487: */
488:
489: offset = addr - VM_MIN_KERNEL_ADDRESS;
490:
491: if (entry->object.vm_object == VM_OBJECT_NULL) {
492: vm_object_reference(kernel_object);
493:
494: entry->object.vm_object = kernel_object;
495: entry->offset = offset;
496: }
497:
498: /*
499: * Since we have not given out this address yet,
500: * it is safe to unlock the map.
501: */
502: vm_map_unlock(map);
503:
504: /*
505: * Allocate wired-down memory in the kernel_object,
506: * for this entry, and enter it in the kernel pmap.
507: */
508: kmem_alloc_pages(kernel_object, offset,
509: addr, addr + size,
510: VM_PROT_DEFAULT);
511:
512: /*
513: * Return the memory, not zeroed.
514: */
515: *addrp = addr;
516: return KERN_SUCCESS;
517: }
518:
519: /*
520: * kmem_alloc_aligned:
521: *
522: * Like kmem_alloc_wired, except that the memory is aligned.
523: * The size should be a power-of-2.
524: */
525:
526: kern_return_t
1.1.1.3 root 527: kmem_alloc_aligned(
528: vm_map_t map,
529: vm_offset_t *addrp,
530: vm_size_t size)
1.1 root 531: {
532: vm_map_entry_t entry;
533: vm_offset_t offset;
534: vm_offset_t addr;
1.1.1.3 root 535: unsigned int attempts;
1.1 root 536: kern_return_t kr;
537:
538: if ((size & (size - 1)) != 0)
539: panic("kmem_alloc_aligned");
540:
541: /*
542: * Use the kernel object for wired-down kernel pages.
543: * Assume that no region of the kernel object is
544: * referenced more than once. We want vm_map_find_entry
545: * to extend an existing entry if possible.
546: */
547:
548: size = round_page(size);
1.1.1.3 root 549: attempts = 0;
550:
551: retry:
1.1 root 552: vm_map_lock(map);
553: kr = vm_map_find_entry(map, &addr, size, size - 1,
554: kernel_object, &entry);
555: if (kr != KERN_SUCCESS) {
556: vm_map_unlock(map);
1.1.1.3 root 557:
558: if (attempts == 0) {
559: attempts++;
560: slab_collect();
561: goto retry;
562: }
563:
1.1.1.4 ! root 564: printf_once("no more room for kmem_alloc_aligned in %p\n", map);
1.1 root 565: return kr;
566: }
567:
568: /*
569: * Since we didn't know where the new region would
570: * start, we couldn't supply the correct offset into
571: * the kernel object. We only initialize the entry
572: * if we aren't extending an existing entry.
573: */
574:
575: offset = addr - VM_MIN_KERNEL_ADDRESS;
576:
577: if (entry->object.vm_object == VM_OBJECT_NULL) {
578: vm_object_reference(kernel_object);
579:
580: entry->object.vm_object = kernel_object;
581: entry->offset = offset;
582: }
583:
584: /*
585: * Since we have not given out this address yet,
586: * it is safe to unlock the map.
587: */
588: vm_map_unlock(map);
589:
590: /*
591: * Allocate wired-down memory in the kernel_object,
592: * for this entry, and enter it in the kernel pmap.
593: */
594: kmem_alloc_pages(kernel_object, offset,
595: addr, addr + size,
596: VM_PROT_DEFAULT);
597:
598: /*
599: * Return the memory, not zeroed.
600: */
601: *addrp = addr;
602: return KERN_SUCCESS;
603: }
604:
605: /*
606: * kmem_alloc_pageable:
607: *
608: * Allocate pageable memory in the kernel's address map.
609: */
610:
611: kern_return_t
1.1.1.3 root 612: kmem_alloc_pageable(
613: vm_map_t map,
614: vm_offset_t *addrp,
615: vm_size_t size)
1.1 root 616: {
617: vm_offset_t addr;
618: kern_return_t kr;
619:
620: addr = vm_map_min(map);
621: kr = vm_map_enter(map, &addr, round_page(size),
622: (vm_offset_t) 0, TRUE,
623: VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
624: VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
1.1.1.2 root 625: if (kr != KERN_SUCCESS) {
626: printf_once("no more room for kmem_alloc_pageable in %p\n", map);
1.1 root 627: return kr;
1.1.1.2 root 628: }
1.1 root 629:
630: *addrp = 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:
642: void
1.1.1.3 root 643: kmem_free(
644: vm_map_t map,
645: vm_offset_t addr,
646: vm_size_t size)
1.1 root 647: {
648: kern_return_t kr;
649:
650: kr = vm_map_remove(map, trunc_page(addr), round_page(addr + size));
651: if (kr != KERN_SUCCESS)
652: panic("kmem_free");
653: }
654:
655: /*
656: * Allocate new wired pages in an object.
657: * The object is assumed to be mapped into the kernel map or
658: * a submap.
659: */
660: void
1.1.1.3 root 661: kmem_alloc_pages(
662: vm_object_t object,
663: vm_offset_t offset,
664: vm_offset_t start,
665: vm_offset_t end,
666: vm_prot_t protection)
1.1 root 667: {
668: /*
669: * Mark the pmap region as not pageable.
670: */
671: pmap_pageable(kernel_pmap, start, end, FALSE);
672:
673: while (start < end) {
1.1.1.3 root 674: vm_page_t mem;
1.1 root 675:
676: vm_object_lock(object);
677:
678: /*
679: * Allocate a page
680: */
681: while ((mem = vm_page_alloc(object, offset))
682: == VM_PAGE_NULL) {
683: vm_object_unlock(object);
684: VM_PAGE_WAIT((void (*)()) 0);
685: vm_object_lock(object);
686: }
687:
688: /*
689: * Wire it down
690: */
691: vm_page_lock_queues();
692: vm_page_wire(mem);
693: vm_page_unlock_queues();
694: vm_object_unlock(object);
695:
696: /*
697: * Enter it in the kernel pmap
698: */
699: PMAP_ENTER(kernel_pmap, start, mem,
700: protection, TRUE);
701:
702: vm_object_lock(object);
703: PAGE_WAKEUP_DONE(mem);
704: vm_object_unlock(object);
705:
706: start += PAGE_SIZE;
707: offset += PAGE_SIZE;
708: }
709: }
710:
711: /*
712: * Remap wired pages in an object into a new region.
713: * The object is assumed to be mapped into the kernel map or
714: * a submap.
715: */
716: void
1.1.1.3 root 717: kmem_remap_pages(
718: vm_object_t object,
719: vm_offset_t offset,
720: vm_offset_t start,
721: vm_offset_t end,
722: vm_prot_t protection)
1.1 root 723: {
724: /*
725: * Mark the pmap region as not pageable.
726: */
727: pmap_pageable(kernel_pmap, start, end, FALSE);
728:
729: while (start < end) {
1.1.1.3 root 730: vm_page_t mem;
1.1 root 731:
732: vm_object_lock(object);
733:
734: /*
735: * Find a page
736: */
737: if ((mem = vm_page_lookup(object, offset)) == VM_PAGE_NULL)
738: panic("kmem_remap_pages");
739:
740: /*
741: * Wire it down (again)
742: */
743: vm_page_lock_queues();
744: vm_page_wire(mem);
745: vm_page_unlock_queues();
746: vm_object_unlock(object);
747:
748: /*
749: * Enter it in the kernel pmap. The page isn't busy,
750: * but this shouldn't be a problem because it is wired.
751: */
752: PMAP_ENTER(kernel_pmap, start, mem,
753: protection, TRUE);
754:
755: start += PAGE_SIZE;
756: offset += PAGE_SIZE;
757: }
758: }
759:
760: /*
1.1.1.2 root 761: * kmem_submap:
1.1 root 762: *
1.1.1.2 root 763: * Initializes a map to manage a subrange
1.1 root 764: * of the kernel virtual address space.
765: *
766: * Arguments are as follows:
767: *
1.1.1.2 root 768: * map Map to initialize
1.1 root 769: * parent Map to take range from
770: * size Size of range to find
771: * min, max Returned endpoints of map
772: * pageable Can the region be paged
773: */
774:
1.1.1.2 root 775: void
1.1.1.3 root 776: kmem_submap(
777: vm_map_t map,
778: vm_map_t parent,
779: vm_offset_t *min,
780: vm_offset_t *max,
781: vm_size_t size,
782: boolean_t pageable)
1.1 root 783: {
784: vm_offset_t addr;
785: kern_return_t kr;
786:
787: size = round_page(size);
788:
789: /*
790: * Need reference on submap object because it is internal
791: * to the vm_system. vm_object_enter will never be called
792: * on it (usual source of reference for vm_map_enter).
793: */
794: vm_object_reference(vm_submap_object);
795:
1.1.1.3 root 796: addr = vm_map_min(parent);
1.1 root 797: kr = vm_map_enter(parent, &addr, size,
798: (vm_offset_t) 0, TRUE,
799: vm_submap_object, (vm_offset_t) 0, FALSE,
800: VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
801: if (kr != KERN_SUCCESS)
1.1.1.2 root 802: panic("kmem_submap");
1.1 root 803:
804: pmap_reference(vm_map_pmap(parent));
1.1.1.2 root 805: vm_map_setup(map, vm_map_pmap(parent), addr, addr + size, pageable);
1.1 root 806: kr = vm_map_submap(parent, addr, addr + size, map);
807: if (kr != KERN_SUCCESS)
1.1.1.2 root 808: panic("kmem_submap");
1.1 root 809:
810: *min = addr;
811: *max = addr + size;
812: }
813:
814: /*
815: * kmem_init:
816: *
817: * Initialize the kernel's virtual memory map, taking
818: * into account all memory allocated up to this time.
819: */
1.1.1.3 root 820: void kmem_init(
821: vm_offset_t start,
822: vm_offset_t end)
1.1 root 823: {
1.1.1.2 root 824: vm_map_setup(kernel_map, pmap_kernel(), VM_MIN_KERNEL_ADDRESS, end,
825: FALSE);
1.1 root 826:
827: /*
828: * Reserve virtual memory allocated up to this time.
829: */
830: if (start != VM_MIN_KERNEL_ADDRESS) {
831: kern_return_t rc;
832: vm_offset_t addr = VM_MIN_KERNEL_ADDRESS;
833: rc = vm_map_enter(kernel_map,
834: &addr, start - VM_MIN_KERNEL_ADDRESS,
835: (vm_offset_t) 0, TRUE,
836: VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
837: VM_PROT_DEFAULT, VM_PROT_ALL,
838: VM_INHERIT_DEFAULT);
839: if (rc)
1.1.1.4 ! root 840: panic("vm_map_enter failed (%d)\n", rc);
1.1 root 841: }
842: }
843:
844: /*
845: * New and improved IO wiring support.
846: */
847:
848: /*
849: * kmem_io_map_copyout:
850: *
851: * Establish temporary mapping in designated map for the memory
852: * passed in. Memory format must be a page_list vm_map_copy.
853: * Mapping is READ-ONLY.
854: */
855:
856: kern_return_t
1.1.1.3 root 857: kmem_io_map_copyout(
858: vm_map_t map,
859: vm_offset_t *addr, /* actual addr of data */
860: vm_offset_t *alloc_addr, /* page aligned addr */
861: vm_size_t *alloc_size, /* size allocated */
862: vm_map_copy_t copy,
863: vm_size_t min_size) /* Do at least this much */
1.1 root 864: {
865: vm_offset_t myaddr, offset;
866: vm_size_t mysize, copy_size;
867: kern_return_t ret;
868: vm_page_t *page_list;
869: vm_map_copy_t new_copy;
870: int i;
871:
872: assert(copy->type == VM_MAP_COPY_PAGE_LIST);
873: assert(min_size != 0);
874:
875: /*
876: * Figure out the size in vm pages.
877: */
878: min_size += copy->offset - trunc_page(copy->offset);
879: min_size = round_page(min_size);
880: mysize = round_page(copy->offset + copy->size) -
881: trunc_page(copy->offset);
882:
883: /*
884: * If total size is larger than one page list and
885: * we don't have to do more than one page list, then
886: * only do one page list.
887: *
888: * XXX Could be much smarter about this ... like trimming length
889: * XXX if we need more than one page list but not all of them.
890: */
891:
892: copy_size = ptoa(copy->cpy_npages);
893: if (mysize > copy_size && copy_size > min_size)
894: mysize = copy_size;
895:
896: /*
897: * Allocate some address space in the map (must be kernel
898: * space).
899: */
900: myaddr = vm_map_min(map);
901: ret = vm_map_enter(map, &myaddr, mysize,
902: (vm_offset_t) 0, TRUE,
903: VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
904: VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
905:
906: if (ret != KERN_SUCCESS)
907: return(ret);
908:
909: /*
910: * Tell the pmap module that this will be wired, and
911: * enter the mappings.
912: */
913: pmap_pageable(vm_map_pmap(map), myaddr, myaddr + mysize, TRUE);
914:
915: *addr = myaddr + (copy->offset - trunc_page(copy->offset));
916: *alloc_addr = myaddr;
917: *alloc_size = mysize;
918:
919: offset = myaddr;
920: page_list = ©->cpy_page_list[0];
921: while (TRUE) {
922: for ( i = 0; i < copy->cpy_npages; i++, offset += PAGE_SIZE) {
923: PMAP_ENTER(vm_map_pmap(map), offset, *page_list,
924: VM_PROT_READ, TRUE);
925: page_list++;
926: }
927:
928: if (offset == (myaddr + mysize))
929: break;
930:
931: /*
932: * Onward to the next page_list. The extend_cont
933: * leaves the current page list's pages alone;
934: * they'll be cleaned up at discard. Reset this
935: * copy's continuation to discard the next one.
936: */
937: vm_map_copy_invoke_extend_cont(copy, &new_copy, &ret);
938:
939: if (ret != KERN_SUCCESS) {
940: kmem_io_map_deallocate(map, myaddr, mysize);
941: return(ret);
942: }
943: copy->cpy_cont = vm_map_copy_discard_cont;
944: copy->cpy_cont_args = (char *) new_copy;
945: copy = new_copy;
946: page_list = ©->cpy_page_list[0];
947: }
948:
949: return(ret);
950: }
951:
952: /*
953: * kmem_io_map_deallocate:
954: *
955: * Get rid of the mapping established by kmem_io_map_copyout.
956: * Assumes that addr and size have been rounded to page boundaries.
957: * (e.g., the alloc_addr and alloc_size returned by kmem_io_map_copyout)
958: */
959:
960: void
1.1.1.3 root 961: kmem_io_map_deallocate(
962: vm_map_t map,
963: vm_offset_t addr,
964: vm_size_t size)
1.1 root 965: {
966: /*
967: * Remove the mappings. The pmap_remove is needed.
968: */
969:
970: pmap_remove(vm_map_pmap(map), addr, addr + size);
971: vm_map_remove(map, addr, addr + size);
972: }
973:
974: /*
975: * Routine: copyinmap
976: * Purpose:
977: * Like copyin, except that fromaddr is an address
978: * in the specified VM map. This implementation
979: * is incomplete; it handles the current user map
980: * and the kernel map/submaps.
981: */
982:
1.1.1.3 root 983: int copyinmap(
984: vm_map_t map,
985: char *fromaddr,
986: char *toaddr,
987: int length)
1.1 root 988: {
989: if (vm_map_pmap(map) == kernel_pmap) {
990: /* assume a correct copy */
1.1.1.2 root 991: memcpy(toaddr, fromaddr, length);
1.1 root 992: return 0;
993: }
994:
995: if (current_map() == map)
996: return copyin( fromaddr, toaddr, length);
997:
998: return 1;
999: }
1000:
1001: /*
1002: * Routine: copyoutmap
1003: * Purpose:
1004: * Like copyout, except that toaddr is an address
1005: * in the specified VM map. This implementation
1006: * is incomplete; it handles the current user map
1007: * and the kernel map/submaps.
1008: */
1009:
1.1.1.3 root 1010: int copyoutmap(
1011: vm_map_t map,
1012: char *fromaddr,
1013: char *toaddr,
1014: int length)
1.1 root 1015: {
1016: if (vm_map_pmap(map) == kernel_pmap) {
1017: /* assume a correct copy */
1.1.1.2 root 1018: memcpy(toaddr, fromaddr, length);
1.1 root 1019: return 0;
1020: }
1021:
1022: if (current_map() == map)
1023: return copyout(fromaddr, toaddr, length);
1024:
1025: return 1;
1026: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.