|
|
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 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: #include <kern/thread.h>
54: #include <vm/vm_fault.h>
55: #include <mach/kern_return.h>
56: #include <mach/vm_behavior.h>
57: #include <vm/vm_map.h>
58: #include <vm/vm_object.h>
59: #include <vm/vm_page.h>
60: #include <vm/pmap.h>
61:
62: #include <i386/intel_read_fault.h>
63:
64: #include <kern/macro_help.h>
65:
66: /*
67: * Expansion of vm_fault for read fault in kernel mode.
68: * Must enter the mapping as writable, since the i386
69: * (and i860 in i386 compatability mode) ignores write
70: * protection in kernel mode.
71: *
72: * Note that this routine can be called for pmap's other
73: * than the kernel_pmap, in which case it just enters
74: * a read-only mapping. (See e.g. kernel_trap().)
75: */
76: kern_return_t
77: intel_read_fault(
78: vm_map_t map,
79: vm_offset_t vaddr)
80: {
81: vm_map_version_t version; /* Map version for
82: verification */
83: vm_object_t object; /* Top-level object */
84: vm_offset_t offset; /* Top-level offset */
85: vm_prot_t prot; /* Protection for mapping */
86: vm_behavior_t behavior; /* Expected paging behavior */
87: vm_offset_t lo_offset, hi_offset;
88: vm_page_t result_page; /* Result of vm_fault_page */
89: vm_page_t top_page; /* Placeholder page */
90: boolean_t wired; /* Is map region wired? */
91: kern_return_t result;
92: register vm_page_t m;
93:
94: RetryFault:
95:
96: /*
97: * Find the backing store object and offset into it
98: * to begin search.
99: */
100: vm_map_lock_read(map);
101: result = vm_map_lookup_locked(&map, vaddr, VM_PROT_READ, &version,
102: &object, &offset, &prot, &wired,
103: &behavior, &lo_offset, &hi_offset);
104: vm_map_unlock_read(map);
105:
106: if (result != KERN_SUCCESS)
107: return (result);
108:
109: /*
110: * Make a reference to this object to prevent its
111: * disposal while we are playing with it.
112: */
113: assert(object->ref_count > 0);
114: object->ref_count++;
115: vm_object_res_reference(object);
116: vm_object_paging_begin(object);
117:
118: result = vm_fault_page(object, offset, VM_PROT_READ, FALSE,
119: THREAD_ABORTSAFE,
120: lo_offset, hi_offset, behavior,
121: &prot, &result_page, &top_page, (int *)0,
122: 0, map->no_zero_fill, FALSE);
123:
124: if (result != VM_FAULT_SUCCESS) {
125: vm_object_deallocate(object);
126:
127: switch (result) {
128: case VM_FAULT_RETRY:
129: goto RetryFault;
130: case VM_FAULT_INTERRUPTED:
131: return (KERN_SUCCESS);
132: case VM_FAULT_MEMORY_SHORTAGE:
133: VM_PAGE_WAIT();
134: goto RetryFault;
135: case VM_FAULT_FICTITIOUS_SHORTAGE:
136: vm_page_more_fictitious();
137: goto RetryFault;
138: case VM_FAULT_MEMORY_ERROR:
139: return (KERN_MEMORY_ERROR);
140: }
141: }
142:
143: m = result_page;
144:
145: /*
146: * How to clean up the result of vm_fault_page. This
147: * happens whether the mapping is entered or not.
148: */
149:
150: #define UNLOCK_AND_DEALLOCATE \
151: MACRO_BEGIN \
152: vm_fault_cleanup(m->object, top_page); \
153: vm_object_deallocate(object); \
154: MACRO_END
155:
156: /*
157: * What to do with the resulting page from vm_fault_page
158: * if it doesn't get entered into the physical map:
159: */
160:
161: #define RELEASE_PAGE(m) \
162: MACRO_BEGIN \
163: PAGE_WAKEUP_DONE(m); \
164: vm_page_lock_queues(); \
165: if (!m->active && !m->inactive) \
166: vm_page_activate(m); \
167: vm_page_unlock_queues(); \
168: MACRO_END
169:
170: /*
171: * We must verify that the maps have not changed.
172: */
173: vm_object_unlock(m->object);
174: while (!vm_map_verify(map, &version)) {
175: vm_object_t retry_object;
176: vm_offset_t retry_offset;
177: vm_prot_t retry_prot;
178:
179: vm_map_lock_read(map);
180: result = vm_map_lookup_locked(&map, vaddr, VM_PROT_READ, &version,
181: &retry_object, &retry_offset, &retry_prot,
182: &wired, &behavior, &lo_offset, &hi_offset);
183: vm_map_unlock_read(map);
184:
185: if (result != KERN_SUCCESS) {
186: vm_object_lock(m->object);
187: RELEASE_PAGE(m);
188: UNLOCK_AND_DEALLOCATE;
189: return (result);
190: }
191:
192: vm_object_unlock(retry_object);
193:
194: if (retry_object != object || retry_offset != offset) {
195: vm_object_lock(m->object);
196: RELEASE_PAGE(m);
197: UNLOCK_AND_DEALLOCATE;
198: goto RetryFault;
199: }
200: }
201:
202: /*
203: * Put the page in the physical map.
204: */
205: PMAP_ENTER(map->pmap, vaddr, m, VM_PROT_READ, wired);
206:
207: vm_object_lock(m->object);
208: vm_page_lock_queues();
209: if (!m->active && !m->inactive)
210: vm_page_activate(m);
211: m->reference = TRUE;
212: vm_page_unlock_queues();
213:
214: vm_map_verify_done(map, &version);
215: PAGE_WAKEUP_DONE(m);
216:
217: UNLOCK_AND_DEALLOCATE;
218:
219: #undef UNLOCK_AND_DEALLOCATE
220: #undef RELEASE_PAGE
221:
222: return (KERN_SUCCESS);
223: }
224:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.