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