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