|
|
1.1 root 1: /*
2: * Copyright (c) 1991 Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * The Mach Operating System project at Carnegie-Mellon University.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
1.1.1.4 ! root 36: * from: @(#)vm_fault.c 7.6 (Berkeley) 5/7/91
! 37: * vm_fault.c,v 1.6.2.1 1993/07/25 21:25:21 cgd Exp
1.1 root 38: *
39: *
40: * Copyright (c) 1987, 1990 Carnegie-Mellon University.
41: * All rights reserved.
42: *
43: * Authors: Avadis Tevanian, Jr., Michael Wayne Young
44: *
45: * Permission to use, copy, modify and distribute this software and
46: * its documentation is hereby granted, provided that both the copyright
47: * notice and this permission notice appear in all copies of the
48: * software, derivative works or modified versions, and any portions
49: * thereof, and that both notices appear in supporting documentation.
50: *
51: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
52: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
53: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
54: *
55: * Carnegie Mellon requests users of this software to return to
56: *
57: * Software Distribution Coordinator or [email protected]
58: * School of Computer Science
59: * Carnegie Mellon University
60: * Pittsburgh PA 15213-3890
61: *
62: * any improvements or extensions that they make and grant Carnegie the
63: * rights to redistribute these changes.
64: */
65:
66: /*
67: * Page fault handling module.
68: */
69:
70: #include "param.h"
71:
72: #include "vm.h"
73: #include "vm_page.h"
74: #include "vm_pageout.h"
75:
76: /*
77: * vm_fault:
78: *
79: * Handle a page fault occuring at the given address,
80: * requiring the given permissions, in the map specified.
81: * If successful, the page is inserted into the
82: * associated physical map.
83: *
84: * NOTE: the given address should be truncated to the
85: * proper page address.
86: *
87: * KERN_SUCCESS is returned if the page fault is handled; otherwise,
88: * a standard error specifying why the fault is fatal is returned.
89: *
90: *
91: * The map in question must be referenced, and remains so.
92: * Caller may hold no locks.
93: */
1.1.1.4 ! root 94: int
1.1 root 95: vm_fault(map, vaddr, fault_type, change_wiring)
96: vm_map_t map;
97: vm_offset_t vaddr;
98: vm_prot_t fault_type;
99: boolean_t change_wiring;
100: {
101: vm_object_t first_object;
102: vm_offset_t first_offset;
103: vm_map_entry_t entry;
104: register vm_object_t object;
105: register vm_offset_t offset;
106: register vm_page_t m;
107: vm_page_t first_m;
108: vm_prot_t prot;
109: int result;
110: boolean_t wired;
111: boolean_t su;
112: boolean_t lookup_still_valid;
113: boolean_t page_exists;
114: vm_page_t old_m;
115: vm_object_t next_object;
116:
117: vm_stat.faults++; /* needs lock XXX */
118: /*
119: * Recovery actions
120: */
121: #define FREE_PAGE(m) { \
122: PAGE_WAKEUP(m); \
123: vm_page_lock_queues(); \
124: vm_page_free(m); \
125: vm_page_unlock_queues(); \
126: }
127:
128: #define RELEASE_PAGE(m) { \
129: PAGE_WAKEUP(m); \
130: vm_page_lock_queues(); \
131: vm_page_activate(m); \
132: vm_page_unlock_queues(); \
133: }
134:
135: #define UNLOCK_MAP { \
136: if (lookup_still_valid) { \
137: vm_map_lookup_done(map, entry); \
138: lookup_still_valid = FALSE; \
139: } \
140: }
141:
142: #define UNLOCK_THINGS { \
143: object->paging_in_progress--; \
144: vm_object_unlock(object); \
145: if (object != first_object) { \
146: vm_object_lock(first_object); \
147: FREE_PAGE(first_m); \
148: first_object->paging_in_progress--; \
149: vm_object_unlock(first_object); \
150: } \
151: UNLOCK_MAP; \
152: }
153:
154: #define UNLOCK_AND_DEALLOCATE { \
155: UNLOCK_THINGS; \
156: vm_object_deallocate(first_object); \
157: }
158:
159: RetryFault: ;
160:
161: /*
162: * Find the backing store object and offset into
163: * it to begin the search.
164: */
165:
166: if ((result = vm_map_lookup(&map, vaddr, fault_type, &entry,
167: &first_object, &first_offset,
168: &prot, &wired, &su)) != KERN_SUCCESS) {
169: return(result);
170: }
171: lookup_still_valid = TRUE;
172:
173: if (wired)
174: fault_type = prot;
175:
176: first_m = NULL;
177:
178: /*
179: * Make a reference to this object to
180: * prevent its disposal while we are messing with
181: * it. Once we have the reference, the map is free
182: * to be diddled. Since objects reference their
183: * shadows (and copies), they will stay around as well.
184: */
185:
186: vm_object_lock(first_object);
187:
188: first_object->ref_count++;
189: first_object->paging_in_progress++;
190:
191: /*
192: * INVARIANTS (through entire routine):
193: *
194: * 1) At all times, we must either have the object
195: * lock or a busy page in some object to prevent
196: * some other thread from trying to bring in
197: * the same page.
198: *
199: * Note that we cannot hold any locks during the
200: * pager access or when waiting for memory, so
201: * we use a busy page then.
202: *
203: * Note also that we aren't as concerned about
204: * more than one thead attempting to pager_data_unlock
205: * the same page at once, so we don't hold the page
206: * as busy then, but do record the highest unlock
207: * value so far. [Unlock requests may also be delivered
208: * out of order.]
209: *
210: * 2) Once we have a busy page, we must remove it from
211: * the pageout queues, so that the pageout daemon
212: * will not grab it away.
213: *
214: * 3) To prevent another thread from racing us down the
215: * shadow chain and entering a new page in the top
216: * object before we do, we must keep a busy page in
217: * the top object while following the shadow chain.
218: *
219: * 4) We must increment paging_in_progress on any object
220: * for which we have a busy page, to prevent
221: * vm_object_collapse from removing the busy page
222: * without our noticing.
223: */
224:
225: /*
226: * Search for the page at object/offset.
227: */
228:
229: object = first_object;
230: offset = first_offset;
231:
232: /*
233: * See whether this page is resident
234: */
235:
236: while (TRUE) {
237: m = vm_page_lookup(object, offset);
238: if (m != NULL) {
239: /*
240: * If the page is being brought in,
241: * wait for it and then retry.
242: */
243: if (m->busy) {
244: #ifdef DOTHREADS
245: int wait_result;
246:
247: PAGE_ASSERT_WAIT(m, !change_wiring);
248: UNLOCK_THINGS;
249: thread_block();
250: wait_result = current_thread()->wait_result;
251: vm_object_deallocate(first_object);
252: if (wait_result != THREAD_AWAKENED)
253: return(KERN_SUCCESS);
254: goto RetryFault;
255: #else
256: PAGE_ASSERT_WAIT(m, !change_wiring);
257: UNLOCK_THINGS;
1.1.1.2 root 258: thread_wakeup(&vm_pages_needed); /* XXX! */
1.1 root 259: thread_block();
260: vm_object_deallocate(first_object);
261: goto RetryFault;
262: #endif
263: }
264:
265: if (m->absent)
266: panic("vm_fault: absent");
267:
268: /*
269: * If the desired access to this page has
270: * been locked out, request that it be unlocked.
271: */
272:
273: if (fault_type & m->page_lock) {
274: #ifdef DOTHREADS
275: int wait_result;
276:
277: if ((fault_type & m->unlock_request) != fault_type)
278: panic("vm_fault: pager_data_unlock");
279:
280: PAGE_ASSERT_WAIT(m, !change_wiring);
281: UNLOCK_THINGS;
282: thread_block();
283: wait_result = current_thread()->wait_result;
284: vm_object_deallocate(first_object);
285: if (wait_result != THREAD_AWAKENED)
286: return(KERN_SUCCESS);
287: goto RetryFault;
288: #else
289: if ((fault_type & m->unlock_request) != fault_type)
290: panic("vm_fault: pager_data_unlock");
291:
292: PAGE_ASSERT_WAIT(m, !change_wiring);
293: UNLOCK_THINGS;
1.1.1.2 root 294: thread_wakeup(&vm_pages_needed); /* XXX */
1.1 root 295: thread_block();
296: vm_object_deallocate(first_object);
297: goto RetryFault;
298: #endif
299: }
300:
301: /*
302: * Remove the page from the pageout daemon's
303: * reach while we play with it.
304: */
305:
306: vm_page_lock_queues();
307: if (m->inactive) {
308: queue_remove(&vm_page_queue_inactive, m,
309: vm_page_t, pageq);
310: m->inactive = FALSE;
311: vm_page_inactive_count--;
312: vm_stat.reactivations++;
313: }
314:
315: if (m->active) {
316: queue_remove(&vm_page_queue_active, m,
317: vm_page_t, pageq);
318: m->active = FALSE;
319: vm_page_active_count--;
320: }
321: vm_page_unlock_queues();
322:
323: /*
324: * Mark page busy for other threads.
325: */
326: m->busy = TRUE;
327: m->absent = FALSE;
328: break;
329: }
330:
331: if (((object->pager != NULL) &&
332: (!change_wiring || wired))
333: || (object == first_object)) {
334:
335: /*
336: * Allocate a new page for this object/offset
337: * pair.
338: */
339:
340: m = vm_page_alloc(object, offset);
341:
342: if (m == NULL) {
343: UNLOCK_AND_DEALLOCATE;
344: VM_WAIT;
345: goto RetryFault;
346: }
347: }
348:
349: if ((object->pager != NULL) &&
350: (!change_wiring || wired)) {
351: int rv;
352:
353: /*
354: * Now that we have a busy page, we can
355: * release the object lock.
356: */
357: vm_object_unlock(object);
358:
359: /*
360: * Call the pager to retrieve the data, if any,
361: * after releasing the lock on the map.
362: */
363: UNLOCK_MAP;
364:
365: rv = vm_pager_get(object->pager, m, TRUE);
366: if (rv == VM_PAGER_OK) {
367: /*
368: * Found the page.
369: * Leave it busy while we play with it.
370: */
371: vm_object_lock(object);
372:
373: /*
374: * Relookup in case pager changed page.
375: * Pager is responsible for disposition
376: * of old page if moved.
377: */
378: m = vm_page_lookup(object, offset);
379:
380: vm_stat.pageins++;
381: m->fake = FALSE;
382: pmap_clear_modify(VM_PAGE_TO_PHYS(m));
383: break;
384: }
385:
386: /*
387: * Remove the bogus page (which does not
388: * exist at this object/offset); before
389: * doing so, we must get back our object
390: * lock to preserve our invariant.
391: *
392: * Also wake up any other thread that may want
393: * to bring in this page.
394: *
395: * If this is the top-level object, we must
396: * leave the busy page to prevent another
397: * thread from rushing past us, and inserting
398: * the page in that object at the same time
399: * that we are.
400: */
401:
402: vm_object_lock(object);
403: /*
404: * Data outside the range of the pager; an error
405: */
406: if (rv == VM_PAGER_BAD) {
407: FREE_PAGE(m);
408: UNLOCK_AND_DEALLOCATE;
409: return(KERN_PROTECTION_FAILURE); /* XXX */
410: }
411: if (object != first_object) {
412: FREE_PAGE(m);
413: /*
414: * XXX - we cannot just fall out at this
415: * point, m has been freed and is invalid!
416: */
417: }
418: }
419:
420: /*
421: * We get here if the object has no pager (or unwiring)
422: * or the pager doesn't have the page.
423: */
424: if (object == first_object)
425: first_m = m;
426:
427: /*
428: * Move on to the next object. Lock the next
429: * object before unlocking the current one.
430: */
431:
432: offset += object->shadow_offset;
433: next_object = object->shadow;
434: if (next_object == NULL) {
435: /*
436: * If there's no object left, fill the page
437: * in the top object with zeros.
438: */
439: if (object != first_object) {
440: object->paging_in_progress--;
441: vm_object_unlock(object);
442:
443: object = first_object;
444: offset = first_offset;
445: m = first_m;
446: vm_object_lock(object);
447: }
448: first_m = NULL;
449:
450: vm_page_zero_fill(m);
451: vm_stat.zero_fill_count++;
452: m->fake = FALSE;
453: m->absent = FALSE;
454: break;
455: }
456: else {
457: vm_object_lock(next_object);
458: if (object != first_object)
459: object->paging_in_progress--;
460: vm_object_unlock(object);
461: object = next_object;
462: object->paging_in_progress++;
463: }
464: }
465:
466: if (m->absent || m->active || m->inactive || !m->busy)
467: panic("vm_fault: absent or active or inactive or not busy after main loop");
468:
469: /*
470: * PAGE HAS BEEN FOUND.
471: * [Loop invariant still holds -- the object lock
472: * is held.]
473: */
474:
475: old_m = m; /* save page that would be copied */
476:
477: /*
478: * If the page is being written, but isn't
479: * already owned by the top-level object,
480: * we have to copy it into a new page owned
481: * by the top-level object.
482: */
483:
484: if (object != first_object) {
485: /*
486: * We only really need to copy if we
487: * want to write it.
488: */
489:
490: if (fault_type & VM_PROT_WRITE) {
491:
492: /*
493: * If we try to collapse first_object at this
494: * point, we may deadlock when we try to get
495: * the lock on an intermediate object (since we
496: * have the bottom object locked). We can't
497: * unlock the bottom object, because the page
498: * we found may move (by collapse) if we do.
499: *
500: * Instead, we first copy the page. Then, when
501: * we have no more use for the bottom object,
502: * we unlock it and try to collapse.
503: *
504: * Note that we copy the page even if we didn't
505: * need to... that's the breaks.
506: */
507:
508: /*
509: * We already have an empty page in
510: * first_object - use it.
511: */
512:
513: vm_page_copy(m, first_m);
514: first_m->fake = FALSE;
515: first_m->absent = FALSE;
516:
517: /*
518: * If another map is truly sharing this
519: * page with us, we have to flush all
520: * uses of the original page, since we
521: * can't distinguish those which want the
522: * original from those which need the
523: * new copy.
524: *
525: * XXX If we know that only one map has
526: * access to this page, then we could
527: * avoid the pmap_page_protect() call.
528: */
529:
530: vm_page_lock_queues();
1.1.1.3 root 531: vm_page_activate(m);
1.1.1.4 ! root 532: vm_page_deactivate(m);
1.1 root 533: pmap_page_protect(VM_PAGE_TO_PHYS(m), VM_PROT_NONE);
534: vm_page_unlock_queues();
535:
536: /*
537: * We no longer need the old page or object.
538: */
539: PAGE_WAKEUP(m);
540: object->paging_in_progress--;
541: vm_object_unlock(object);
542:
543: /*
544: * Only use the new page below...
545: */
546:
547: vm_stat.cow_faults++;
548: m = first_m;
549: object = first_object;
550: offset = first_offset;
551:
552: /*
553: * Now that we've gotten the copy out of the
554: * way, let's try to collapse the top object.
555: */
556: vm_object_lock(object);
557: /*
558: * But we have to play ugly games with
559: * paging_in_progress to do that...
560: */
561: object->paging_in_progress--;
562: vm_object_collapse(object);
563: object->paging_in_progress++;
564: }
565: else {
566: prot &= (~VM_PROT_WRITE);
567: m->copy_on_write = TRUE;
568: }
569: }
570:
571: if (m->active || m->inactive)
572: panic("vm_fault: active or inactive before copy object handling");
573:
574: /*
575: * If the page is being written, but hasn't been
576: * copied to the copy-object, we have to copy it there.
577: */
578: RetryCopy:
579: if (first_object->copy != NULL) {
580: vm_object_t copy_object = first_object->copy;
581: vm_offset_t copy_offset;
582: vm_page_t copy_m;
583:
584: /*
585: * We only need to copy if we want to write it.
586: */
587: if ((fault_type & VM_PROT_WRITE) == 0) {
588: prot &= ~VM_PROT_WRITE;
589: m->copy_on_write = TRUE;
590: }
591: else {
592: /*
593: * Try to get the lock on the copy_object.
594: */
595: if (!vm_object_lock_try(copy_object)) {
596: vm_object_unlock(object);
597: /* should spin a bit here... */
598: vm_object_lock(object);
599: goto RetryCopy;
600: }
601:
602: /*
603: * Make another reference to the copy-object,
604: * to keep it from disappearing during the
605: * copy.
606: */
607: copy_object->ref_count++;
608:
609: /*
610: * Does the page exist in the copy?
611: */
612: copy_offset = first_offset
613: - copy_object->shadow_offset;
614: copy_m = vm_page_lookup(copy_object, copy_offset);
615: if (page_exists = (copy_m != NULL)) {
616: if (copy_m->busy) {
617: #ifdef DOTHREADS
618: int wait_result;
619:
620: /*
621: * If the page is being brought
622: * in, wait for it and then retry.
623: */
624: PAGE_ASSERT_WAIT(copy_m, !change_wiring);
625: RELEASE_PAGE(m);
626: copy_object->ref_count--;
627: vm_object_unlock(copy_object);
628: UNLOCK_THINGS;
629: thread_block();
630: wait_result = current_thread()->wait_result;
631: vm_object_deallocate(first_object);
632: if (wait_result != THREAD_AWAKENED)
633: return(KERN_SUCCESS);
634: goto RetryFault;
635: #else
636: /*
637: * If the page is being brought
638: * in, wait for it and then retry.
639: */
640: PAGE_ASSERT_WAIT(copy_m, !change_wiring);
641: RELEASE_PAGE(m);
642: copy_object->ref_count--;
643: vm_object_unlock(copy_object);
644: UNLOCK_THINGS;
1.1.1.2 root 645: thread_wakeup(&vm_pages_needed); /* XXX */
1.1 root 646: thread_block();
647: vm_object_deallocate(first_object);
648: goto RetryFault;
649: #endif
650: }
651: }
652:
653: /*
654: * If the page is not in memory (in the object)
655: * and the object has a pager, we have to check
656: * if the pager has the data in secondary
657: * storage.
658: */
659: if (!page_exists) {
660:
661: /*
662: * If we don't allocate a (blank) page
663: * here... another thread could try
664: * to page it in, allocate a page, and
665: * then block on the busy page in its
666: * shadow (first_object). Then we'd
667: * trip over the busy page after we
668: * found that the copy_object's pager
669: * doesn't have the page...
670: */
671: copy_m = vm_page_alloc(copy_object,
672: copy_offset);
673: if (copy_m == NULL) {
674: /*
675: * Wait for a page, then retry.
676: */
677: RELEASE_PAGE(m);
678: copy_object->ref_count--;
679: vm_object_unlock(copy_object);
680: UNLOCK_AND_DEALLOCATE;
681: VM_WAIT;
682: goto RetryFault;
683: }
684:
685: if (copy_object->pager != NULL) {
686: vm_object_unlock(object);
687: vm_object_unlock(copy_object);
688: UNLOCK_MAP;
689:
690: page_exists = vm_pager_has_page(
691: copy_object->pager,
692: (copy_offset + copy_object->paging_offset));
693:
694: vm_object_lock(copy_object);
695:
696: /*
697: * Since the map is unlocked, someone
698: * else could have copied this object
699: * and put a different copy_object
700: * between the two. Or, the last
701: * reference to the copy-object (other
702: * than the one we have) may have
703: * disappeared - if that has happened,
704: * we don't need to make the copy.
705: */
706: if (copy_object->shadow != object ||
707: copy_object->ref_count == 1) {
708: /*
709: * Gaah... start over!
710: */
711: FREE_PAGE(copy_m);
712: vm_object_unlock(copy_object);
713: vm_object_deallocate(copy_object);
714: /* may block */
715: vm_object_lock(object);
716: goto RetryCopy;
717: }
718: vm_object_lock(object);
719:
720: if (page_exists) {
721: /*
722: * We didn't need the page
723: */
724: FREE_PAGE(copy_m);
725: }
726: }
727: }
728: if (!page_exists) {
729: /*
730: * Must copy page into copy-object.
731: */
732: vm_page_copy(m, copy_m);
733: copy_m->fake = FALSE;
734: copy_m->absent = FALSE;
735:
736: /*
737: * Things to remember:
738: * 1. The copied page must be marked 'dirty'
739: * so it will be paged out to the copy
740: * object.
741: * 2. If the old page was in use by any users
742: * of the copy-object, it must be removed
743: * from all pmaps. (We can't know which
744: * pmaps use it.)
745: */
746: vm_page_lock_queues();
747: pmap_page_protect(VM_PAGE_TO_PHYS(old_m),
748: VM_PROT_NONE);
749: copy_m->clean = FALSE;
750: vm_page_activate(copy_m); /* XXX */
751: vm_page_unlock_queues();
752:
753: PAGE_WAKEUP(copy_m);
754: }
755: /*
756: * The reference count on copy_object must be
757: * at least 2: one for our extra reference,
758: * and at least one from the outside world
759: * (we checked that when we last locked
760: * copy_object).
761: */
762: copy_object->ref_count--;
763: vm_object_unlock(copy_object);
764: m->copy_on_write = FALSE;
765: }
766: }
767:
768: if (m->active || m->inactive)
769: panic("vm_fault: active or inactive before retrying lookup");
770:
771: /*
772: * We must verify that the maps have not changed
773: * since our last lookup.
774: */
775:
776: if (!lookup_still_valid) {
777: vm_object_t retry_object;
778: vm_offset_t retry_offset;
779: vm_prot_t retry_prot;
780:
781: /*
782: * Since map entries may be pageable, make sure we can
783: * take a page fault on them.
784: */
785: vm_object_unlock(object);
786:
787: /*
788: * To avoid trying to write_lock the map while another
789: * thread has it read_locked (in vm_map_pageable), we
790: * do not try for write permission. If the page is
791: * still writable, we will get write permission. If it
792: * is not, or has been marked needs_copy, we enter the
793: * mapping without write permission, and will merely
794: * take another fault.
795: */
796: result = vm_map_lookup(&map, vaddr,
797: fault_type & ~VM_PROT_WRITE, &entry,
798: &retry_object, &retry_offset, &retry_prot,
799: &wired, &su);
800:
801: vm_object_lock(object);
802:
803: /*
804: * If we don't need the page any longer, put it on the
805: * active list (the easiest thing to do here). If no
806: * one needs it, pageout will grab it eventually.
807: */
808:
809: if (result != KERN_SUCCESS) {
810: RELEASE_PAGE(m);
811: UNLOCK_AND_DEALLOCATE;
812: return(result);
813: }
814:
815: lookup_still_valid = TRUE;
816:
817: if ((retry_object != first_object) ||
818: (retry_offset != first_offset)) {
819: RELEASE_PAGE(m);
820: UNLOCK_AND_DEALLOCATE;
821: goto RetryFault;
822: }
823:
824: /*
825: * Check whether the protection has changed or the object
826: * has been copied while we left the map unlocked.
827: * Changing from read to write permission is OK - we leave
828: * the page write-protected, and catch the write fault.
829: * Changing from write to read permission means that we
830: * can't mark the page write-enabled after all.
831: */
832: prot &= retry_prot;
833: if (m->copy_on_write)
834: prot &= ~VM_PROT_WRITE;
835: }
836:
837: /*
838: * (the various bits we're fiddling with here are locked by
839: * the object's lock)
840: */
841:
842: /* XXX This distorts the meaning of the copy_on_write bit */
843:
844: if (prot & VM_PROT_WRITE)
845: m->copy_on_write = FALSE;
846:
847: /*
848: * It's critically important that a wired-down page be faulted
849: * only once in each map for which it is wired.
850: */
851:
852: if (m->active || m->inactive)
853: panic("vm_fault: active or inactive before pmap_enter");
854:
855: vm_object_unlock(object);
856:
857: /*
858: * Put this page into the physical map.
859: * We had to do the unlock above because pmap_enter
860: * may cause other faults. We don't put the
861: * page back on the active queue until later so
862: * that the page-out daemon won't find us (yet).
863: */
864:
865: pmap_enter(map->pmap, vaddr, VM_PAGE_TO_PHYS(m),
866: prot & ~(m->page_lock), wired);
867:
868: /*
869: * If the page is not wired down, then put it where the
870: * pageout daemon can find it.
871: */
872: vm_object_lock(object);
873: vm_page_lock_queues();
874: if (change_wiring) {
875: if (wired)
876: vm_page_wire(m);
877: else
878: vm_page_unwire(m);
879: }
880: else
881: vm_page_activate(m);
882: vm_page_unlock_queues();
883:
884: /*
885: * Unlock everything, and return
886: */
887:
888: PAGE_WAKEUP(m);
889: UNLOCK_AND_DEALLOCATE;
890:
891: return(KERN_SUCCESS);
892: }
893:
894: /*
895: * vm_fault_wire:
896: *
897: * Wire down a range of virtual addresses in a map.
898: */
1.1.1.4 ! root 899: void
! 900: vm_fault_wire(map, start, end)
1.1 root 901: vm_map_t map;
902: vm_offset_t start, end;
903: {
904:
905: register vm_offset_t va;
906: register pmap_t pmap;
907:
908: pmap = vm_map_pmap(map);
909:
910: /*
911: * Inform the physical mapping system that the
912: * range of addresses may not fault, so that
913: * page tables and such can be locked down as well.
914: */
915:
916: pmap_pageable(pmap, start, end, FALSE);
917:
918: /*
919: * We simulate a fault to get the page and enter it
920: * in the physical map.
921: */
922:
923: for (va = start; va < end; va += PAGE_SIZE) {
924: (void) vm_fault(map, va, VM_PROT_NONE, TRUE);
925: }
926: }
927:
928:
929: /*
930: * vm_fault_unwire:
931: *
932: * Unwire a range of virtual addresses in a map.
933: */
1.1.1.4 ! root 934: void
! 935: vm_fault_unwire(map, start, end)
1.1 root 936: vm_map_t map;
937: vm_offset_t start, end;
938: {
939:
940: register vm_offset_t va, pa;
941: register pmap_t pmap;
942:
943: pmap = vm_map_pmap(map);
944:
945: /*
946: * Since the pages are wired down, we must be able to
947: * get their mappings from the physical map system.
948: */
949:
950: vm_page_lock_queues();
951:
952: for (va = start; va < end; va += PAGE_SIZE) {
953: pa = pmap_extract(pmap, va);
954: if (pa == (vm_offset_t) 0) {
955: panic("unwire: page not in pmap");
956: }
957: pmap_change_wiring(pmap, va, FALSE);
958: vm_page_unwire(PHYS_TO_VM_PAGE(pa));
959: }
960: vm_page_unlock_queues();
961:
962: /*
963: * Inform the physical mapping system that the range
964: * of addresses may fault, so that page tables and
965: * such may be unwired themselves.
966: */
967:
968: pmap_pageable(pmap, start, end, TRUE);
969:
970: }
971:
972: /*
973: * Routine:
974: * vm_fault_copy_entry
975: * Function:
976: * Copy all of the pages from a wired-down map entry to another.
977: *
978: * In/out conditions:
979: * The source and destination maps must be locked for write.
980: * The source map entry must be wired down (or be a sharing map
981: * entry corresponding to a main map entry that is wired down).
982: */
983:
1.1.1.4 ! root 984: void
! 985: vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry)
1.1 root 986: vm_map_t dst_map;
987: vm_map_t src_map;
988: vm_map_entry_t dst_entry;
989: vm_map_entry_t src_entry;
990: {
991:
992: vm_object_t dst_object;
993: vm_object_t src_object;
994: vm_offset_t dst_offset;
995: vm_offset_t src_offset;
996: vm_prot_t prot;
997: vm_offset_t vaddr;
998: vm_page_t dst_m;
999: vm_page_t src_m;
1000:
1001: #ifdef lint
1002: src_map++;
1003: #endif lint
1004:
1005: src_object = src_entry->object.vm_object;
1006: src_offset = src_entry->offset;
1007:
1008: /*
1009: * Create the top-level object for the destination entry.
1010: * (Doesn't actually shadow anything - we copy the pages
1011: * directly.)
1012: */
1013: dst_object = vm_object_allocate(
1014: (vm_size_t) (dst_entry->end - dst_entry->start));
1015:
1016: dst_entry->object.vm_object = dst_object;
1017: dst_entry->offset = 0;
1018:
1019: prot = dst_entry->max_protection;
1020:
1021: /*
1022: * Loop through all of the pages in the entry's range, copying
1023: * each one from the source object (it should be there) to the
1024: * destination object.
1025: */
1026: for (vaddr = dst_entry->start, dst_offset = 0;
1027: vaddr < dst_entry->end;
1028: vaddr += PAGE_SIZE, dst_offset += PAGE_SIZE) {
1029:
1030: /*
1031: * Allocate a page in the destination object
1032: */
1033: vm_object_lock(dst_object);
1034: do {
1035: dst_m = vm_page_alloc(dst_object, dst_offset);
1036: if (dst_m == NULL) {
1037: vm_object_unlock(dst_object);
1038: VM_WAIT;
1039: vm_object_lock(dst_object);
1040: }
1041: } while (dst_m == NULL);
1042:
1043: /*
1044: * Find the page in the source object, and copy it in.
1045: * (Because the source is wired down, the page will be
1046: * in memory.)
1047: */
1048: vm_object_lock(src_object);
1049: src_m = vm_page_lookup(src_object, dst_offset + src_offset);
1050: if (src_m == NULL)
1051: panic("vm_fault_copy_wired: page missing");
1052:
1053: vm_page_copy(src_m, dst_m);
1054:
1055: /*
1056: * Enter it in the pmap...
1057: */
1058: vm_object_unlock(src_object);
1059: vm_object_unlock(dst_object);
1060:
1061: pmap_enter(dst_map->pmap, vaddr, VM_PAGE_TO_PHYS(dst_m),
1062: prot, FALSE);
1063:
1064: /*
1065: * Mark it no longer busy, and put it on the active list.
1066: */
1067: vm_object_lock(dst_object);
1068: vm_page_lock_queues();
1069: vm_page_activate(dst_m);
1070: vm_page_unlock_queues();
1071: PAGE_WAKEUP(dst_m);
1072: vm_object_unlock(dst_object);
1073: }
1074:
1075: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.