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