|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50: /*
51: */
52: /*
53: * File: vm/vm_kern.c
54: * Author: Avadis Tevanian, Jr., Michael Wayne Young
55: * Date: 1985
56: *
57: * Kernel memory management.
58: */
59:
60: #include <cpus.h>
61: #include <mach/kern_return.h>
62: #include <mach/vm_param.h>
63: #include <kern/assert.h>
64: #include <kern/lock.h>
65: #include <kern/thread.h>
66: #include <vm/vm_kern.h>
67: #include <vm/vm_map.h>
68: #include <vm/vm_object.h>
69: #include <vm/vm_page.h>
70: #include <vm/vm_pageout.h>
71: #include <kern/misc_protos.h>
72: #include <vm/cpm.h>
73:
74: #include <string.h>
75: /*
76: * Variables exported by this module.
77: */
78:
79: vm_map_t kernel_map;
80: vm_map_t kernel_pageable_map;
81:
82: /*
83: * Forward declarations for internal functions.
84: */
85: extern kern_return_t kmem_alloc_pages(
86: register vm_object_t object,
87: register vm_offset_t offset,
88: register vm_offset_t start,
89: register vm_offset_t end,
90: vm_prot_t protection);
91:
92: extern void kmem_remap_pages(
93: register vm_object_t object,
94: register vm_offset_t offset,
95: register vm_offset_t start,
96: register vm_offset_t end,
97: vm_prot_t protection);
98:
99: kern_return_t
100: kmem_alloc_contig(
101: vm_map_t map,
102: vm_offset_t *addrp,
103: vm_size_t size,
104: vm_offset_t mask,
105: int flags)
106: {
107: vm_object_t object;
108: vm_page_t m, pages;
109: kern_return_t kr;
110: vm_offset_t addr, i, offset;
111: vm_map_entry_t entry;
112:
113: if (map == VM_MAP_NULL || (flags && (flags ^ KMA_KOBJECT)))
114: return KERN_INVALID_ARGUMENT;
115:
116: if (size == 0) {
117: *addrp = 0;
118: return KERN_INVALID_ARGUMENT;
119: }
120:
121: size = round_page(size);
122: if ((flags & KMA_KOBJECT) == 0) {
123: object = vm_object_allocate(size);
124: kr = vm_map_find_space(map, &addr, size, mask, &entry);
125: }
126: else {
127: object = kernel_object;
128: kr = vm_map_find_space(map, &addr, size, mask, &entry);
129: }
130:
131: if ((flags & KMA_KOBJECT) == 0) {
132: entry->object.vm_object = object;
133: entry->offset = offset = 0;
134: } else {
135: offset = addr - VM_MIN_KERNEL_ADDRESS;
136:
137: if (entry->object.vm_object == VM_OBJECT_NULL) {
138: vm_object_reference(object);
139: entry->object.vm_object = object;
140: entry->offset = offset;
141: }
142: }
143:
144: if (kr != KERN_SUCCESS) {
145: if ((flags & KMA_KOBJECT) == 0)
146: vm_object_deallocate(object);
147: return kr;
148: }
149:
150: vm_map_unlock(map);
151:
152: kr = cpm_allocate(size, &pages, FALSE);
153:
154: if (kr != KERN_SUCCESS) {
155: vm_map_remove(map, addr, addr + size, 0);
156: *addrp = 0;
157: return kr;
158: }
159:
160: vm_object_lock(object);
161: for (i = 0; i < size; i += PAGE_SIZE) {
162: m = pages;
163: pages = NEXT_PAGE(m);
164: m->busy = FALSE;
165: vm_page_insert(m, object, offset + i);
166: }
167: vm_object_unlock(object);
168:
169: if ((kr = vm_map_wire(map, addr, addr + size, VM_PROT_DEFAULT, FALSE))
170: != KERN_SUCCESS) {
171: if (object == kernel_object) {
172: vm_object_lock(object);
173: vm_object_page_remove(object, offset, offset + size);
174: vm_object_unlock(object);
175: }
176: vm_map_remove(map, addr, addr + size, 0);
177: return kr;
178: }
179: if (object == kernel_object)
180: vm_map_simplify(map, addr);
181:
182: *addrp = addr;
183: return KERN_SUCCESS;
184: }
185:
186: /*
187: * Master entry point for allocating kernel memory.
188: * NOTE: this routine is _never_ interrupt safe.
189: *
190: * map : map to allocate into
191: * addrp : pointer to start address of new memory
192: * size : size of memory requested
193: * flags : options
194: * KMA_HERE *addrp is base address, else "anywhere"
195: * KMA_NOPAGEWAIT don't wait for pages if unavailable
196: * KMA_KOBJECT use kernel_object
197: */
198:
199: kern_return_t
200: kernel_memory_allocate(
201: register vm_map_t map,
202: register vm_offset_t *addrp,
203: register vm_size_t size,
204: register vm_offset_t mask,
205: int flags)
206: {
207: vm_object_t object = VM_OBJECT_NULL;
208: vm_map_entry_t entry;
209: vm_offset_t offset;
210: vm_offset_t addr;
211: vm_offset_t i;
212: kern_return_t kr;
213:
214: size = round_page(size);
215: if ((flags & KMA_KOBJECT) == 0) {
216: /*
217: * Allocate a new object. We must do this before locking
218: * the map, or risk deadlock with the default pager:
219: * device_read_alloc uses kmem_alloc,
220: * which tries to allocate an object,
221: * which uses kmem_alloc_wired to get memory,
222: * which blocks for pages.
223: * then the default pager needs to read a block
224: * to process a memory_object_data_write,
225: * and device_read_alloc calls kmem_alloc
226: * and deadlocks on the map lock.
227: */
228: object = vm_object_allocate(size);
229: kr = vm_map_find_space(map, &addr, size, mask, &entry);
230: }
231: else {
232: object = kernel_object;
233: kr = vm_map_find_space(map, &addr, size, mask, &entry);
234: }
235: if (kr != KERN_SUCCESS) {
236: if ((flags & KMA_KOBJECT) == 0)
237: vm_object_deallocate(object);
238: return kr;
239: }
240:
241: if ((flags & KMA_KOBJECT) == 0) {
242: entry->object.vm_object = object;
243: entry->offset = offset = 0;
244: } else {
245: offset = addr - VM_MIN_KERNEL_ADDRESS;
246:
247: if (entry->object.vm_object == VM_OBJECT_NULL) {
248: vm_object_reference(object);
249: entry->object.vm_object = object;
250: entry->offset = offset;
251: }
252: }
253:
254: /*
255: * Since we have not given out this address yet,
256: * it is safe to unlock the map.
257: */
258: vm_map_unlock(map);
259:
260: vm_object_lock(object);
261: for (i = 0; i < size; i += PAGE_SIZE) {
262: vm_page_t mem;
263:
264: while ((mem = vm_page_alloc(object, offset + i))
265: == VM_PAGE_NULL) {
266: if (flags & KMA_NOPAGEWAIT) {
267: if (object == kernel_object)
268: vm_object_page_remove(object, offset,
269: offset + i);
270: vm_object_unlock(object);
271: vm_map_remove(map, addr, addr + size, 0);
272: return KERN_RESOURCE_SHORTAGE;
273: }
274: vm_object_unlock(object);
275: VM_PAGE_WAIT();
276: vm_object_lock(object);
277: }
278: mem->busy = FALSE;
279: }
280: vm_object_unlock(object);
281:
282: if ((kr = vm_map_wire(map, addr, addr + size, VM_PROT_DEFAULT, FALSE))
283: != KERN_SUCCESS) {
284: if (object == kernel_object) {
285: vm_object_lock(object);
286: vm_object_page_remove(object, offset, offset + size);
287: vm_object_unlock(object);
288: }
289: vm_map_remove(map, addr, addr + size, 0);
290: return (kr);
291: }
292: if (object == kernel_object)
293: vm_map_simplify(map, addr);
294:
295: /*
296: * Return the memory, not zeroed.
297: */
298: #if (NCPUS > 1) && i860
299: bzero( addr, size );
300: #endif /* #if (NCPUS > 1) && i860 */
301: *addrp = addr;
302: return KERN_SUCCESS;
303: }
304:
305: /*
306: * kmem_alloc:
307: *
308: * Allocate wired-down memory in the kernel's address map
309: * or a submap. The memory is not zero-filled.
310: */
311:
312: kern_return_t
313: kmem_alloc(
314: vm_map_t map,
315: vm_offset_t *addrp,
316: vm_size_t size)
317: {
318: return kernel_memory_allocate(map, addrp, size, 0, 0);
319: }
320:
321: /*
322: * kmem_realloc:
323: *
324: * Reallocate wired-down memory in the kernel's address map
325: * or a submap. Newly allocated pages are not zeroed.
326: * This can only be used on regions allocated with kmem_alloc.
327: *
328: * If successful, the pages in the old region are mapped twice.
329: * The old region is unchanged. Use kmem_free to get rid of it.
330: */
331: kern_return_t
332: kmem_realloc(
333: vm_map_t map,
334: vm_offset_t oldaddr,
335: vm_size_t oldsize,
336: vm_offset_t *newaddrp,
337: vm_size_t newsize)
338: {
339: vm_offset_t oldmin, oldmax;
340: vm_offset_t newaddr;
341: vm_object_t object;
342: vm_map_entry_t oldentry, newentry;
343: kern_return_t kr;
344:
345: oldmin = trunc_page(oldaddr);
346: oldmax = round_page(oldaddr + oldsize);
347: oldsize = oldmax - oldmin;
348: newsize = round_page(newsize);
349:
350: /*
351: * Find space for the new region.
352: */
353:
354: kr = vm_map_find_space(map, &newaddr, newsize, (vm_offset_t) 0,
355: &newentry);
356: if (kr != KERN_SUCCESS) {
357: return kr;
358: }
359:
360: /*
361: * Find the VM object backing the old region.
362: */
363:
364: if (!vm_map_lookup_entry(map, oldmin, &oldentry))
365: panic("kmem_realloc");
366: object = oldentry->object.vm_object;
367:
368: /*
369: * Increase the size of the object and
370: * fill in the new region.
371: */
372:
373: vm_object_reference(object);
374: vm_object_lock(object);
375: if (object->size != oldsize)
376: panic("kmem_realloc");
377: object->size = newsize;
378: vm_object_unlock(object);
379:
380: newentry->object.vm_object = object;
381: newentry->offset = 0;
382: assert (newentry->wired_count == 0);
383: newentry->wired_count = 1;
384:
385: /*
386: * Since we have not given out this address yet,
387: * it is safe to unlock the map. We are trusting
388: * that nobody will play with either region.
389: */
390:
391: vm_map_unlock(map);
392:
393: /*
394: * Remap the pages in the old region and
395: * allocate more pages for the new region.
396: */
397:
398: kmem_remap_pages(object, 0,
399: newaddr, newaddr + oldsize,
400: VM_PROT_DEFAULT);
401: kmem_alloc_pages(object, oldsize,
402: newaddr + oldsize, newaddr + newsize,
403: VM_PROT_DEFAULT);
404:
405: *newaddrp = newaddr;
406: return KERN_SUCCESS;
407: }
408:
409: /*
410: * kmem_alloc_wired:
411: *
412: * Allocate wired-down memory in the kernel's address map
413: * or a submap. The memory is not zero-filled.
414: *
415: * The memory is allocated in the kernel_object.
416: * It may not be copied with vm_map_copy, and
417: * it may not be reallocated with kmem_realloc.
418: */
419:
420: kern_return_t
421: kmem_alloc_wired(
422: vm_map_t map,
423: vm_offset_t *addrp,
424: vm_size_t size)
425: {
426: return kernel_memory_allocate(map, addrp, size, 0, KMA_KOBJECT);
427: }
428:
429: /*
430: * kmem_alloc_aligned:
431: *
432: * Like kmem_alloc_wired, except that the memory is aligned.
433: * The size should be a power-of-2.
434: */
435:
436: kern_return_t
437: kmem_alloc_aligned(
438: vm_map_t map,
439: vm_offset_t *addrp,
440: vm_size_t size)
441: {
442: if ((size & (size - 1)) != 0)
443: panic("kmem_alloc_aligned: size not aligned");
444: return kernel_memory_allocate(map, addrp, size, size - 1, KMA_KOBJECT);
445: }
446:
447: /*
448: * kmem_alloc_pageable:
449: *
450: * Allocate pageable memory in the kernel's address map.
451: */
452:
453: kern_return_t
454: kmem_alloc_pageable(
455: vm_map_t map,
456: vm_offset_t *addrp,
457: vm_size_t size)
458: {
459: vm_offset_t addr;
460: kern_return_t kr;
461:
462: addr = vm_map_min(map);
463: kr = vm_map_enter(map, &addr, round_page(size),
464: (vm_offset_t) 0, TRUE,
465: VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
466: VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
467: if (kr != KERN_SUCCESS)
468: return kr;
469:
470: *addrp = addr;
471: return KERN_SUCCESS;
472: }
473:
474: /*
475: * kmem_free:
476: *
477: * Release a region of kernel virtual memory allocated
478: * with kmem_alloc, kmem_alloc_wired, or kmem_alloc_pageable,
479: * and return the physical pages associated with that region.
480: */
481:
482: void
483: kmem_free(
484: vm_map_t map,
485: vm_offset_t addr,
486: vm_size_t size)
487: {
488: kern_return_t kr;
489:
490: kr = vm_map_remove(map, trunc_page(addr),
491: round_page(addr + size), VM_MAP_REMOVE_KUNWIRE);
492: if (kr != KERN_SUCCESS)
493: panic("kmem_free");
494: }
495:
496: /*
497: * Allocate new wired pages in an object.
498: * The object is assumed to be mapped into the kernel map or
499: * a submap.
500: */
501:
502: kern_return_t
503: kmem_alloc_pages(
504: register vm_object_t object,
505: register vm_offset_t offset,
506: register vm_offset_t start,
507: register vm_offset_t end,
508: vm_prot_t protection)
509: {
510: /*
511: * Mark the pmap region as not pageable.
512: */
513: pmap_pageable(kernel_pmap, start, end, FALSE);
514:
515: while (start < end) {
516: register vm_page_t mem;
517:
518: vm_object_lock(object);
519:
520: /*
521: * Allocate a page
522: */
523: while ((mem = vm_page_alloc(object, offset))
524: == VM_PAGE_NULL) {
525: vm_object_unlock(object);
526: VM_PAGE_WAIT();
527: vm_object_lock(object);
528: }
529:
530: /*
531: * Wire it down
532: */
533: vm_page_lock_queues();
534: vm_page_wire(mem);
535: vm_page_unlock_queues();
536: vm_object_unlock(object);
537:
538: /*
539: * Enter it in the kernel pmap
540: */
541: PMAP_ENTER(kernel_pmap, start, mem,
542: protection, TRUE);
543:
544: vm_object_lock(object);
545: PAGE_WAKEUP_DONE(mem);
546: vm_object_unlock(object);
547:
548: start += PAGE_SIZE;
549: offset += PAGE_SIZE;
550: }
551: return KERN_SUCCESS;
552: }
553:
554: /*
555: * Remap wired pages in an object into a new region.
556: * The object is assumed to be mapped into the kernel map or
557: * a submap.
558: */
559: void
560: kmem_remap_pages(
561: register vm_object_t object,
562: register vm_offset_t offset,
563: register vm_offset_t start,
564: register vm_offset_t end,
565: vm_prot_t protection)
566: {
567: /*
568: * Mark the pmap region as not pageable.
569: */
570: pmap_pageable(kernel_pmap, start, end, FALSE);
571:
572: while (start < end) {
573: register vm_page_t mem;
574:
575: vm_object_lock(object);
576:
577: /*
578: * Find a page
579: */
580: if ((mem = vm_page_lookup(object, offset)) == VM_PAGE_NULL)
581: panic("kmem_remap_pages");
582:
583: /*
584: * Wire it down (again)
585: */
586: vm_page_lock_queues();
587: vm_page_wire(mem);
588: vm_page_unlock_queues();
589: vm_object_unlock(object);
590:
591: /*
592: * Enter it in the kernel pmap. The page isn't busy,
593: * but this shouldn't be a problem because it is wired.
594: */
595: PMAP_ENTER(kernel_pmap, start, mem,
596: protection, TRUE);
597:
598: start += PAGE_SIZE;
599: offset += PAGE_SIZE;
600: }
601: }
602:
603: /*
604: * kmem_suballoc:
605: *
606: * Allocates a map to manage a subrange
607: * of the kernel virtual address space.
608: *
609: * Arguments are as follows:
610: *
611: * parent Map to take range from
612: * addr Address of start of range (IN/OUT)
613: * size Size of range to find
614: * pageable Can region be paged
615: * anywhere Can region be located anywhere in map
616: * new_map Pointer to new submap
617: */
618: kern_return_t
619: kmem_suballoc(
620: vm_map_t parent,
621: vm_offset_t *addr,
622: vm_size_t size,
623: boolean_t pageable,
624: boolean_t anywhere,
625: vm_map_t *new_map)
626: {
627: vm_map_t map;
628: kern_return_t kr;
629:
630: size = round_page(size);
631:
632: /*
633: * Need reference on submap object because it is internal
634: * to the vm_system. vm_object_enter will never be called
635: * on it (usual source of reference for vm_map_enter).
636: */
637: vm_object_reference(vm_submap_object);
638:
639: if (anywhere == TRUE)
640: *addr = (vm_offset_t)vm_map_min(parent);
641: kr = vm_map_enter(parent, addr, size,
642: (vm_offset_t) 0, anywhere,
643: vm_submap_object, (vm_offset_t) 0, FALSE,
644: VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
645: if (kr != KERN_SUCCESS) {
646: vm_object_deallocate(vm_submap_object);
647: return (kr);
648: }
649:
650: pmap_reference(vm_map_pmap(parent));
651: map = vm_map_create(vm_map_pmap(parent), *addr, *addr + size, pageable);
652: if (map == VM_MAP_NULL)
653: panic("kmem_suballoc: vm_map_create failed"); /* "can't happen" */
654:
655: kr = vm_map_submap(parent, *addr, *addr + size, map, *addr);
656: if (kr != KERN_SUCCESS) {
657: /*
658: * See comment preceding vm_map_submap().
659: */
660: vm_map_remove(parent, *addr, *addr + size, VM_MAP_NO_FLAGS);
661: vm_map_deallocate(map); /* also removes ref to pmap */
662: vm_object_deallocate(vm_submap_object);
663: return (kr);
664: }
665:
666: *new_map = map;
667: return (KERN_SUCCESS);
668: }
669:
670: /*
671: * kmem_init:
672: *
673: * Initialize the kernel's virtual memory map, taking
674: * into account all memory allocated up to this time.
675: */
676: void
677: kmem_init(
678: vm_offset_t start,
679: vm_offset_t end)
680: {
681: kernel_map = vm_map_create(pmap_kernel(),
682: VM_MIN_KERNEL_ADDRESS, end,
683: FALSE);
684:
685: /*
686: * Reserve virtual memory allocated up to this time.
687: */
688:
689: if (start != VM_MIN_KERNEL_ADDRESS) {
690: vm_offset_t addr = VM_MIN_KERNEL_ADDRESS;
691: (void) vm_map_enter(kernel_map,
692: &addr, start - VM_MIN_KERNEL_ADDRESS,
693: (vm_offset_t) 0, TRUE,
694: VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
695: VM_PROT_DEFAULT, VM_PROT_ALL,
696: VM_INHERIT_DEFAULT);
697: }
698:
699: /*
700: * Account for kernel memory (text, data, bss, vm shenanigans).
701: * This may include inaccessible "holes" as determined by what
702: * the machine-dependent init code includes in mem_size.
703: */
704: vm_page_wire_count = (atop(mem_size) - (vm_page_free_count
705: + vm_page_active_count
706: + vm_page_inactive_count));
707: }
708:
709: /*
710: * kmem_io_map_copyout:
711: *
712: * Establish temporary mapping in designated map for the memory
713: * passed in. Memory format must be a page_list vm_map_copy.
714: */
715:
716: kern_return_t
717: kmem_io_map_copyout(
718: vm_map_t map,
719: vm_offset_t *addr, /* actual addr of data */
720: vm_size_t *alloc_size, /* size allocated */
721: vm_map_copy_t copy,
722: vm_size_t min_size, /* Do at least this much */
723: vm_prot_t prot) /* Protection of mapping */
724: {
725: vm_offset_t myaddr, offset;
726: vm_size_t mysize, copy_size;
727: kern_return_t ret;
728: register
729: vm_page_t *page_list;
730: vm_map_copy_t new_copy;
731: register
732: int i;
733:
734: assert(copy->type == VM_MAP_COPY_PAGE_LIST);
735: assert(min_size != 0);
736:
737: /*
738: * Figure out the size in vm pages.
739: */
740: min_size += copy->offset - trunc_page(copy->offset);
741: min_size = round_page(min_size);
742: mysize = round_page(copy->offset + copy->size) -
743: trunc_page(copy->offset);
744:
745: /*
746: * If total size is larger than one page list and
747: * we don't have to do more than one page list, then
748: * only do one page list.
749: *
750: * XXX Could be much smarter about this ... like trimming length
751: * XXX if we need more than one page list but not all of them.
752: */
753:
754: copy_size = ptoa(copy->cpy_npages);
755: if (mysize > copy_size && copy_size > min_size)
756: mysize = copy_size;
757:
758: /*
759: * Allocate some address space in the map (must be kernel
760: * space).
761: */
762: myaddr = vm_map_min(map);
763: ret = vm_map_enter(map, &myaddr, mysize,
764: (vm_offset_t) 0, TRUE,
765: VM_OBJECT_NULL, (vm_offset_t) 0, FALSE,
766: prot, prot, VM_INHERIT_DEFAULT);
767:
768: if (ret != KERN_SUCCESS)
769: return(ret);
770:
771: /*
772: * Tell the pmap module that this will be wired, and
773: * enter the mappings.
774: */
775: pmap_pageable(vm_map_pmap(map), myaddr, myaddr + mysize, TRUE);
776:
777: *addr = myaddr + (copy->offset - trunc_page(copy->offset));
778: *alloc_size = mysize;
779:
780: offset = myaddr;
781: page_list = ©->cpy_page_list[0];
782: while (TRUE) {
783: for ( i = 0; i < copy->cpy_npages; i++, offset += PAGE_SIZE) {
784: PMAP_ENTER(vm_map_pmap(map), offset, *page_list,
785: prot, TRUE);
786: page_list++;
787: }
788:
789: if (offset == (myaddr + mysize))
790: break;
791:
792: /*
793: * Onward to the next page_list. The extend_cont
794: * leaves the current page list's pages alone;
795: * they'll be cleaned up at discard. Reset this
796: * copy's continuation to discard the next one.
797: */
798: vm_map_copy_invoke_extend_cont(copy, &new_copy, &ret);
799:
800: if (ret != KERN_SUCCESS) {
801: kmem_io_map_deallocate(map, myaddr, mysize);
802: return(ret);
803: }
804: copy->cpy_cont = vm_map_copy_discard_cont;
805: copy->cpy_cont_args = (vm_map_copyin_args_t) new_copy;
806: assert(new_copy != VM_MAP_COPY_NULL);
807: assert(new_copy->type == VM_MAP_COPY_PAGE_LIST);
808: copy = new_copy;
809: page_list = ©->cpy_page_list[0];
810: }
811:
812: return(ret);
813: }
814:
815: /*
816: * kmem_io_map_deallocate:
817: *
818: * Get rid of the mapping established by kmem_io_map_copyout.
819: * Assumes that addr and size have been rounded to page boundaries.
820: */
821:
822: void
823: kmem_io_map_deallocate(
824: vm_map_t map,
825: vm_offset_t addr,
826: vm_size_t size)
827: {
828:
829: register vm_offset_t va, end;
830:
831: end = round_page(addr + size);
832: for (va = trunc_page(addr); va < end; va += PAGE_SIZE)
833: pmap_change_wiring(vm_map_pmap(map), va, FALSE);
834:
835: /*
836: * Remove the mappings. The pmap_remove is needed.
837: */
838:
839: pmap_remove(vm_map_pmap(map), addr, addr + size);
840: vm_map_remove(map, addr, addr + size, VM_MAP_REMOVE_KUNWIRE);
841: }
842:
843:
844: /*
845: * kmem_io_object_trunc:
846: *
847: * Truncate an object vm_map_copy_t.
848: * Called by the scatter/gather list network code to remove pages from
849: * the tail end of a packet. Also unwires the objects pages.
850: */
851:
852: kern_return_t
853: kmem_io_object_trunc(copy, new_size)
854: vm_map_copy_t copy; /* IN/OUT copy object */
855: register vm_size_t new_size; /* IN new object size */
856: {
857: register vm_size_t offset, old_size;
858:
859: assert(copy->type == VM_MAP_COPY_OBJECT);
860:
861: old_size = round_page(copy->size);
862: copy->size = new_size;
863: new_size = round_page(new_size);
864:
865: vm_object_lock(copy->cpy_object);
866: vm_object_page_remove(copy->cpy_object,
867: (vm_offset_t)new_size, (vm_offset_t)old_size);
868: for (offset = 0; offset < new_size; offset += PAGE_SIZE) {
869: register vm_page_t mem;
870:
871: if ((mem = vm_page_lookup(copy->cpy_object, offset)) == VM_PAGE_NULL)
872: panic("kmem_io_object_trunc: unable to find object page");
873:
874: /*
875: * Make sure these pages are marked dirty
876: */
877: mem->dirty = TRUE;
878: vm_page_lock_queues();
879: vm_page_unwire(mem);
880: vm_page_unlock_queues();
881: }
882: copy->cpy_object->size = new_size; /* adjust size of object */
883: vm_object_unlock(copy->cpy_object);
884: return(KERN_SUCCESS);
885: }
886:
887: /*
888: * kmem_io_object_deallocate:
889: *
890: * Free an vm_map_copy_t.
891: * Called by the scatter/gather list network code to free a packet.
892: */
893:
894: void
895: kmem_io_object_deallocate(
896: vm_map_copy_t copy) /* IN/OUT copy object */
897: {
898: kern_return_t ret;
899:
900: /*
901: * Clear out all the object pages (this will leave an empty object).
902: */
903: ret = kmem_io_object_trunc(copy, 0);
904: if (ret != KERN_SUCCESS)
905: panic("kmem_io_object_deallocate: unable to truncate object");
906: /*
907: * ...and discard the copy object.
908: */
909: vm_map_copy_discard(copy);
910: }
911:
912: /*
913: * Routine: copyinmap
914: * Purpose:
915: * Like copyin, except that fromaddr is an address
916: * in the specified VM map. This implementation
917: * is incomplete; it handles the current user map
918: * and the kernel map/submaps.
919: */
920: boolean_t
921: copyinmap(
922: vm_map_t map,
923: vm_offset_t fromaddr,
924: vm_offset_t toaddr,
925: vm_size_t length)
926: {
927: if (vm_map_pmap(map) == pmap_kernel()) {
928: /* assume a correct copy */
929: memcpy((void *)toaddr, (void *)fromaddr, length);
930: return FALSE;
931: }
932:
933: if (current_map() == map)
934: return copyin((char *)fromaddr, (char *)toaddr, length);
935:
936: return TRUE;
937: }
938:
939: /*
940: * Routine: copyoutmap
941: * Purpose:
942: * Like copyout, except that toaddr is an address
943: * in the specified VM map. This implementation
944: * is incomplete; it handles the current user map
945: * and the kernel map/submaps.
946: */
947: boolean_t
948: copyoutmap(
949: vm_map_t map,
950: vm_offset_t fromaddr,
951: vm_offset_t toaddr,
952: vm_size_t length)
953: {
954: if (vm_map_pmap(map) == pmap_kernel()) {
955: /* assume a correct copy */
956: memcpy((void *)toaddr, (void *)fromaddr, length);
957: return FALSE;
958: }
959:
960: if (current_map() == map)
961: return copyout((char *)fromaddr, (char *)toaddr, length);
962:
963: return TRUE;
964: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.