]> git.saurik.com Git - apple/xnu.git/blob - osfmk/vm/device_vm.c
xnu-344.2.tar.gz
[apple/xnu.git] / osfmk / vm / device_vm.c
1 /*
2 * Copyright (c) 2000-2001 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 #include <sys/errno.h>
24 #include <kern/host.h>
25 #include <mach/mach_types.h>
26 #include <vm/vm_map.h>
27 #include <vm/vm_kern.h>
28 #include <vm/vm_pageout.h>
29 #include <mach/kern_return.h>
30 #include <mach/memory_object_types.h>
31 #include <mach/port.h>
32 #include <mach/policy.h>
33 #include <ipc/ipc_port.h>
34 #include <ipc/ipc_space.h>
35 #include <kern/thread.h>
36 #include <device/device_port.h>
37 #include <vm/vm_pageout.h>
38
39 /* Device VM COMPONENT INTERFACES */
40
41
42 /*
43 * Device PAGER
44 */
45
46
47 /* until component support available */
48
49
50
51 /* until component support available */
52 int device_pager_workaround;
53
54 typedef int device_port_t;
55
56 typedef struct device_pager {
57 int *pager; /* pager workaround pointer */
58 unsigned int pager_ikot; /* fake ip_kotype() */
59 unsigned int ref_count; /* reference count */
60 memory_object_control_t control_handle; /* mem object's cntrl handle */
61 device_port_t device_handle; /* device_handle */
62 vm_size_t size;
63 int flags;
64 } *device_pager_t;
65
66
67
68 void
69 device_pager_bootstrap(
70 void);
71
72
73 memory_object_t
74 device_pager_setup(
75 memory_object_t,
76 int,
77 vm_size_t,
78 int);
79
80 device_pager_t
81 device_pager_lookup(
82 memory_object_t);
83
84 kern_return_t
85 device_pager_init(
86 memory_object_t,
87 memory_object_control_t,
88 vm_size_t);
89
90
91 kern_return_t
92 device_pager_data_request(
93 memory_object_t,
94 memory_object_offset_t,
95 vm_size_t,
96 vm_prot_t);
97
98 kern_return_t
99 device_pager_data_return(
100 memory_object_t,
101 memory_object_offset_t,
102 vm_size_t,
103 boolean_t,
104 boolean_t);
105
106 void
107 device_pager_reference(
108 memory_object_t);
109
110 void
111 device_pager_deallocate(
112 memory_object_t);
113
114 kern_return_t
115 device_pager_data_initialize(
116 memory_object_t,
117 memory_object_offset_t,
118 vm_size_t);
119
120 kern_return_t
121 device_pager_data_unlock(
122 memory_object_t,
123 memory_object_offset_t,
124 vm_size_t,
125 vm_prot_t);
126
127 kern_return_t
128 device_pager_terminate(
129 memory_object_t);
130
131 kern_return_t
132 device_pager_synchronize(
133 memory_object_t,
134 memory_object_offset_t,
135 vm_offset_t,
136 vm_sync_t);
137
138 kern_return_t
139 device_pager_unmap(
140 memory_object_t);
141
142 device_pager_t
143 device_object_create(void);
144
145 zone_t device_pager_zone;
146
147
148 #define DEVICE_PAGER_NULL ((device_pager_t) 0)
149
150
151 #define MAX_DNODE 10000
152
153
154
155
156
157 /*
158 *
159 */
160 void
161 device_pager_bootstrap(void)
162 {
163 register vm_size_t size;
164
165 size = (vm_size_t) sizeof(struct device_pager);
166 device_pager_zone = zinit(size, (vm_size_t) MAX_DNODE*size,
167 PAGE_SIZE, "device node pager structures");
168
169 return;
170 }
171
172 /*
173 *
174 */
175 memory_object_t
176 device_pager_setup(
177 memory_object_t device,
178 int device_handle,
179 vm_size_t size,
180 int flags)
181 {
182 device_pager_t device_object;
183
184 device_object = device_object_create();
185 if (device_object == DEVICE_PAGER_NULL)
186 panic("device_pager_setup: device_object_create() failed");
187
188 device_object->device_handle = device_handle;
189 device_object->size = size;
190 device_object->flags = flags;
191
192 return((memory_object_t)device_object);
193 }
194
195 /*
196 *
197 */
198 kern_return_t
199 device_pager_populate_object(
200 memory_object_t device,
201 memory_object_offset_t offset,
202 vm_offset_t phys_addr,
203 vm_size_t size)
204 {
205 device_pager_t device_object;
206 vm_object_t vm_object;
207 kern_return_t kr;
208 upl_t upl;
209 ipc_port_t previous;
210
211 device_object = device_pager_lookup(device);
212 if(device_object == DEVICE_PAGER_NULL)
213 return KERN_FAILURE;
214
215 vm_object = (vm_object_t)memory_object_control_to_vm_object(
216 device_object->control_handle);
217 if(vm_object == NULL)
218 return KERN_FAILURE;
219
220 kr = vm_object_populate_with_private(
221 vm_object, offset, phys_addr, size);
222 if(kr != KERN_SUCCESS)
223 return kr;
224
225 if(!vm_object->phys_contiguous) {
226 int null_size = 0;
227 kr = vm_object_upl_request(vm_object,
228 (vm_object_offset_t)offset, size, &upl, NULL,
229 &null_size, (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE));
230
231 if(kr != KERN_SUCCESS)
232 panic("device_pager_populate_object: list_req failed");
233
234 upl_commit(upl, NULL);
235 upl_deallocate(upl);
236 }
237
238
239 return kr;
240 }
241
242 /*
243 *
244 */
245 device_pager_t
246 device_pager_lookup(
247 memory_object_t name)
248 {
249 device_pager_t device_object;
250
251 device_object = (device_pager_t)name;
252 assert(device_object->pager == &device_pager_workaround);
253 return (device_object);
254 }
255
256 /*
257 *
258 */
259 kern_return_t
260 device_pager_init(memory_object_t mem_obj,
261 memory_object_control_t control,
262 vm_size_t pg_size)
263 {
264 device_pager_t device_object;
265 kern_return_t kr;
266 memory_object_attr_info_data_t attributes;
267
268 vm_object_t vm_object;
269
270
271 if (control == MEMORY_OBJECT_CONTROL_NULL)
272 return KERN_INVALID_ARGUMENT;
273
274 device_object = device_pager_lookup(mem_obj);
275
276 memory_object_control_reference(control);
277 device_object->control_handle = control;
278
279
280 /* The following settings should be done through an expanded change */
281 /* attributes call */
282
283 vm_object = (vm_object_t)memory_object_control_to_vm_object(control);
284 vm_object_lock(vm_object);
285 vm_object->private = TRUE;
286 if(device_object->flags & DEVICE_PAGER_CONTIGUOUS)
287 vm_object->phys_contiguous = TRUE;
288 if(device_object->flags & DEVICE_PAGER_NOPHYSCACHE)
289 vm_object->nophyscache = TRUE;
290
291 vm_object->wimg_bits = device_object->flags & VM_WIMG_MASK;
292 vm_object_unlock(vm_object);
293
294
295 attributes.copy_strategy = MEMORY_OBJECT_COPY_DELAY;
296 /* attributes.cluster_size = (1 << (CLUSTER_SHIFT + PAGE_SHIFT));*/
297 attributes.cluster_size = (1 << (PAGE_SHIFT));
298 attributes.may_cache_object = FALSE;
299 attributes.temporary = TRUE;
300
301 kr = memory_object_change_attributes(
302 control,
303 MEMORY_OBJECT_ATTRIBUTE_INFO,
304 (memory_object_info_t) &attributes,
305 MEMORY_OBJECT_ATTR_INFO_COUNT);
306 if (kr != KERN_SUCCESS)
307 panic("device_pager_init: memory_object_change_attributes() failed");
308
309 return(KERN_SUCCESS);
310 }
311
312 /*
313 *
314 */
315 kern_return_t
316 device_pager_data_return(
317 memory_object_t mem_obj,
318 memory_object_offset_t offset,
319 vm_size_t data_cnt,
320 boolean_t dirty,
321 boolean_t kernel_copy)
322 {
323 device_pager_t device_object;
324
325 device_object = device_pager_lookup(mem_obj);
326 if (device_object == DEVICE_PAGER_NULL)
327 panic("device_pager_data_return: lookup failed");
328
329 return device_data_action(device_object->device_handle, device_object,
330 VM_PROT_READ | VM_PROT_WRITE, offset, data_cnt);
331 }
332
333 /*
334 *
335 */
336 kern_return_t
337 device_pager_data_request(
338 memory_object_t mem_obj,
339 memory_object_offset_t offset,
340 vm_size_t length,
341 vm_prot_t protection_required)
342 {
343 device_pager_t device_object;
344
345 device_object = device_pager_lookup(mem_obj);
346
347 if (device_object == DEVICE_PAGER_NULL)
348 panic("device_pager_data_request: lookup failed");
349
350 device_data_action(device_object->device_handle, device_object,
351 VM_PROT_READ, offset, length);
352 return KERN_SUCCESS;
353 }
354
355 /*
356 *
357 */
358 void
359 device_pager_reference(
360 memory_object_t mem_obj)
361 {
362 device_pager_t device_object;
363 unsigned int new_ref_count;
364
365 device_object = device_pager_lookup(mem_obj);
366 new_ref_count = hw_atomic_add(&device_object->ref_count, 1);
367 assert(new_ref_count > 1);
368 }
369
370 /*
371 *
372 */
373 void
374 device_pager_deallocate(
375 memory_object_t mem_obj)
376 {
377 device_pager_t device_object;
378
379 device_object = device_pager_lookup(mem_obj);
380
381 if (hw_atomic_sub(&device_object->ref_count, 1) == 0) {
382 if (device_object->device_handle != (device_port_t) NULL) {
383 device_close(device_object->device_handle);
384 }
385 zfree(device_pager_zone, (vm_offset_t) device_object);
386 }
387 return;
388 }
389
390 kern_return_t
391 device_pager_data_initialize(
392 memory_object_t mem_obj,
393 memory_object_offset_t offset,
394 vm_size_t data_cnt)
395 {
396 return KERN_FAILURE;
397 }
398
399 kern_return_t
400 device_pager_data_unlock(
401 memory_object_t mem_obj,
402 memory_object_offset_t offset,
403 vm_size_t size,
404 vm_prot_t desired_access)
405 {
406 return KERN_FAILURE;
407 }
408
409 device_pager_terminate(
410 memory_object_t mem_obj)
411 {
412 return KERN_SUCCESS;
413 }
414
415
416
417 /*
418 *
419 */
420 kern_return_t
421 device_pager_synchronize(
422 memory_object_t mem_obj,
423 memory_object_offset_t offset,
424 vm_offset_t length,
425 vm_sync_t sync_flags)
426 {
427 device_pager_t device_object;
428
429 device_object = device_pager_lookup(mem_obj);
430
431 memory_object_synchronize_completed(
432 device_object->control_handle, offset, length);
433
434 return KERN_SUCCESS;
435 }
436
437 /*
438 *
439 */
440 kern_return_t
441 device_pager_unmap(
442 memory_object_t mem_obj)
443 {
444 return KERN_SUCCESS;
445 }
446
447
448
449 /*
450 *
451 */
452 device_pager_t
453 device_object_create()
454 {
455 register device_pager_t device_object;
456
457 device_object = (struct device_pager *) zalloc(device_pager_zone);
458 if (device_object == DEVICE_PAGER_NULL)
459 return(DEVICE_PAGER_NULL);
460 device_object->pager = &device_pager_workaround;
461 device_object->pager_ikot = IKOT_MEMORY_OBJECT;
462 device_object->ref_count = 1;
463 device_object->control_handle = MEMORY_OBJECT_CONTROL_NULL;
464
465
466 return(device_object);
467 }
468