]> git.saurik.com Git - apple/xnu.git/blame - osfmk/vm/memory_object.c
xnu-2782.40.9.tar.gz
[apple/xnu.git] / osfmk / vm / memory_object.c
CommitLineData
1c79356b 1/*
b0d623f7 2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56/*
57 */
58/*
59 * File: vm/memory_object.c
60 * Author: Michael Wayne Young
61 *
62 * External memory management interface control functions.
63 */
64
1c79356b
A
65/*
66 * Interface dependencies:
67 */
68
69#include <mach/std_types.h> /* For pointer_t */
70#include <mach/mach_types.h>
71
0b4e3aa0 72#include <mach/mig.h>
1c79356b
A
73#include <mach/kern_return.h>
74#include <mach/memory_object.h>
75#include <mach/memory_object_default.h>
76#include <mach/memory_object_control_server.h>
0b4e3aa0 77#include <mach/host_priv_server.h>
1c79356b
A
78#include <mach/boolean.h>
79#include <mach/vm_prot.h>
80#include <mach/message.h>
81
1c79356b
A
82/*
83 * Implementation dependencies:
84 */
85#include <string.h> /* For memcpy() */
86
0b4e3aa0
A
87#include <kern/xpr.h>
88#include <kern/host.h>
89#include <kern/thread.h> /* For current_thread() */
90#include <kern/ipc_mig.h>
91#include <kern/misc_protos.h>
92
93#include <vm/vm_object.h>
94#include <vm/vm_fault.h>
1c79356b
A
95#include <vm/memory_object.h>
96#include <vm/vm_page.h>
97#include <vm/vm_pageout.h>
98#include <vm/pmap.h> /* For pmap_clear_modify */
1c79356b
A
99#include <vm/vm_kern.h> /* For kernel_map, vm_move */
100#include <vm/vm_map.h> /* For vm_map_pageable */
2d21ac55 101#include <vm/vm_purgeable_internal.h> /* Needed by some vm_page.h macros */
6d2010ae 102#include <vm/vm_shared_region.h>
1c79356b 103
1c79356b 104#include <vm/vm_external.h>
1c79356b 105
91447636
A
106#include <vm/vm_protos.h>
107
108
0b4e3aa0 109memory_object_default_t memory_manager_default = MEMORY_OBJECT_DEFAULT_NULL;
b0d623f7 110decl_lck_mtx_data(, memory_manager_default_lock)
1c79356b 111
1c79356b
A
112
113/*
114 * Routine: memory_object_should_return_page
115 *
116 * Description:
117 * Determine whether the given page should be returned,
118 * based on the page's state and on the given return policy.
119 *
120 * We should return the page if one of the following is true:
121 *
122 * 1. Page is dirty and should_return is not RETURN_NONE.
123 * 2. Page is precious and should_return is RETURN_ALL.
124 * 3. Should_return is RETURN_ANYTHING.
125 *
126 * As a side effect, m->dirty will be made consistent
127 * with pmap_is_modified(m), if should_return is not
128 * MEMORY_OBJECT_RETURN_NONE.
129 */
130
131#define memory_object_should_return_page(m, should_return) \
132 (should_return != MEMORY_OBJECT_RETURN_NONE && \
55e303ae 133 (((m)->dirty || ((m)->dirty = pmap_is_modified((m)->phys_page))) || \
1c79356b
A
134 ((m)->precious && (should_return) == MEMORY_OBJECT_RETURN_ALL) || \
135 (should_return) == MEMORY_OBJECT_RETURN_ANYTHING))
136
137typedef int memory_object_lock_result_t;
138
6d2010ae
A
139#define MEMORY_OBJECT_LOCK_RESULT_DONE 0
140#define MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK 1
141#define MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN 2
142#define MEMORY_OBJECT_LOCK_RESULT_MUST_FREE 3
1c79356b
A
143
144memory_object_lock_result_t memory_object_lock_page(
145 vm_page_t m,
146 memory_object_return_t should_return,
147 boolean_t should_flush,
148 vm_prot_t prot);
149
150/*
151 * Routine: memory_object_lock_page
152 *
153 * Description:
154 * Perform the appropriate lock operations on the
155 * given page. See the description of
156 * "memory_object_lock_request" for the meanings
157 * of the arguments.
158 *
159 * Returns an indication that the operation
160 * completed, blocked, or that the page must
161 * be cleaned.
162 */
163memory_object_lock_result_t
164memory_object_lock_page(
165 vm_page_t m,
166 memory_object_return_t should_return,
167 boolean_t should_flush,
168 vm_prot_t prot)
169{
170 XPR(XPR_MEMORY_OBJECT,
171 "m_o_lock_page, page 0x%X rtn %d flush %d prot %d\n",
b0d623f7 172 m, should_return, should_flush, prot, 0);
1c79356b 173
1c79356b 174
316670eb
A
175 if (m->busy || m->cleaning)
176 return (MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK);
b0d623f7 177
316670eb
A
178 if (m->laundry)
179 vm_pageout_steal_laundry(m, FALSE);
6d2010ae 180
1c79356b
A
181 /*
182 * Don't worry about pages for which the kernel
183 * does not have any data.
184 */
765c9de3 185 if (m->absent || m->error || m->restart) {
6d2010ae
A
186 if (m->error && should_flush && !VM_PAGE_WIRED(m)) {
187 /*
188 * dump the page, pager wants us to
189 * clean it up and there is no
190 * relevant data to return
191 */
192 return (MEMORY_OBJECT_LOCK_RESULT_MUST_FREE);
765c9de3 193 }
6d2010ae 194 return (MEMORY_OBJECT_LOCK_RESULT_DONE);
765c9de3 195 }
1c79356b
A
196 assert(!m->fictitious);
197
b0d623f7 198 if (VM_PAGE_WIRED(m)) {
6d2010ae
A
199 /*
200 * The page is wired... just clean or return the page if needed.
201 * Wired pages don't get flushed or disconnected from the pmap.
202 */
203 if (memory_object_should_return_page(m, should_return))
204 return (MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN);
1c79356b 205
6d2010ae
A
206 return (MEMORY_OBJECT_LOCK_RESULT_DONE);
207 }
1c79356b 208
6d2010ae
A
209 if (should_flush) {
210 /*
211 * must do the pmap_disconnect before determining the
212 * need to return the page... otherwise it's possible
213 * for the page to go from the clean to the dirty state
214 * after we've made our decision
215 */
316670eb
A
216 if (pmap_disconnect(m->phys_page) & VM_MEM_MODIFIED) {
217 SET_PAGE_DIRTY(m, FALSE);
218 }
6d2010ae
A
219 } else {
220 /*
221 * If we are decreasing permission, do it now;
222 * let the fault handler take care of increases
223 * (pmap_page_protect may not increase protection).
224 */
225 if (prot != VM_PROT_NO_CHANGE)
226 pmap_page_protect(m->phys_page, VM_PROT_ALL & ~prot);
1c79356b 227 }
1c79356b 228 /*
6d2010ae 229 * Handle returning dirty or precious pages
1c79356b 230 */
1c79356b 231 if (memory_object_should_return_page(m, should_return)) {
1c79356b 232 /*
6d2010ae
A
233 * we use to do a pmap_disconnect here in support
234 * of memory_object_lock_request, but that routine
235 * no longer requires this... in any event, in
236 * our world, it would turn into a big noop since
237 * we don't lock the page in any way and as soon
238 * as we drop the object lock, the page can be
239 * faulted back into an address space
240 *
241 * if (!should_flush)
242 * pmap_disconnect(m->phys_page);
1c79356b 243 */
6d2010ae 244 return (MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN);
1c79356b
A
245 }
246
247 /*
6d2010ae 248 * Handle flushing clean pages
1c79356b 249 */
6d2010ae
A
250 if (should_flush)
251 return (MEMORY_OBJECT_LOCK_RESULT_MUST_FREE);
1c79356b 252
6d2010ae
A
253 /*
254 * we use to deactivate clean pages at this point,
255 * but we do not believe that an msync should change
256 * the 'age' of a page in the cache... here is the
257 * original comment and code concerning this...
258 *
259 * XXX Make clean but not flush a paging hint,
260 * and deactivate the pages. This is a hack
261 * because it overloads flush/clean with
262 * implementation-dependent meaning. This only
263 * happens to pages that are already clean.
264 *
265 * if (vm_page_deactivate_hint && (should_return != MEMORY_OBJECT_RETURN_NONE))
266 * return (MEMORY_OBJECT_LOCK_RESULT_MUST_DEACTIVATE);
267 */
1c79356b 268
6d2010ae 269 return (MEMORY_OBJECT_LOCK_RESULT_DONE);
1c79356b 270}
0b4e3aa0 271
6d2010ae 272
1c79356b 273
1c79356b
A
274/*
275 * Routine: memory_object_lock_request [user interface]
276 *
277 * Description:
278 * Control use of the data associated with the given
279 * memory object. For each page in the given range,
280 * perform the following operations, in order:
281 * 1) restrict access to the page (disallow
282 * forms specified by "prot");
283 * 2) return data to the manager (if "should_return"
284 * is RETURN_DIRTY and the page is dirty, or
285 * "should_return" is RETURN_ALL and the page
286 * is either dirty or precious); and,
287 * 3) flush the cached copy (if "should_flush"
288 * is asserted).
289 * The set of pages is defined by a starting offset
290 * ("offset") and size ("size"). Only pages with the
291 * same page alignment as the starting offset are
292 * considered.
293 *
294 * A single acknowledgement is sent (to the "reply_to"
295 * port) when these actions are complete. If successful,
296 * the naked send right for reply_to is consumed.
297 */
298
299kern_return_t
300memory_object_lock_request(
0b4e3aa0
A
301 memory_object_control_t control,
302 memory_object_offset_t offset,
303 memory_object_size_t size,
91447636
A
304 memory_object_offset_t * resid_offset,
305 int * io_errno,
1c79356b
A
306 memory_object_return_t should_return,
307 int flags,
0b4e3aa0 308 vm_prot_t prot)
1c79356b 309{
0b4e3aa0 310 vm_object_t object;
1c79356b 311
b0d623f7 312 /*
1c79356b
A
313 * Check for bogus arguments.
314 */
0b4e3aa0 315 object = memory_object_control_to_vm_object(control);
1c79356b
A
316 if (object == VM_OBJECT_NULL)
317 return (KERN_INVALID_ARGUMENT);
318
0b4e3aa0 319 if ((prot & ~VM_PROT_ALL) != 0 && prot != VM_PROT_NO_CHANGE)
1c79356b 320 return (KERN_INVALID_ARGUMENT);
1c79356b 321
55e303ae 322 size = round_page_64(size);
1c79356b
A
323
324 /*
325 * Lock the object, and acquire a paging reference to
0b4e3aa0 326 * prevent the memory_object reference from being released.
1c79356b 327 */
1c79356b
A
328 vm_object_lock(object);
329 vm_object_paging_begin(object);
b0d623f7
A
330
331 if (flags & MEMORY_OBJECT_DATA_FLUSH_ALL) {
332 if ((should_return != MEMORY_OBJECT_RETURN_NONE) || offset || object->copy) {
333 flags &= ~MEMORY_OBJECT_DATA_FLUSH_ALL;
334 flags |= MEMORY_OBJECT_DATA_FLUSH;
335 }
336 }
1c79356b
A
337 offset -= object->paging_offset;
338
b0d623f7
A
339 if (flags & MEMORY_OBJECT_DATA_FLUSH_ALL)
340 vm_object_reap_pages(object, REAP_DATA_FLUSH);
341 else
342 (void)vm_object_update(object, offset, size, resid_offset,
343 io_errno, should_return, flags, prot);
1c79356b 344
1c79356b
A
345 vm_object_paging_end(object);
346 vm_object_unlock(object);
1c79356b
A
347
348 return (KERN_SUCCESS);
349}
350
351/*
0b4e3aa0
A
352 * memory_object_release_name: [interface]
353 *
354 * Enforces name semantic on memory_object reference count decrement
355 * This routine should not be called unless the caller holds a name
356 * reference gained through the memory_object_named_create or the
357 * memory_object_rename call.
358 * If the TERMINATE_IDLE flag is set, the call will return if the
359 * reference count is not 1. i.e. idle with the only remaining reference
360 * being the name.
361 * If the decision is made to proceed the name field flag is set to
362 * false and the reference count is decremented. If the RESPECT_CACHE
363 * flag is set and the reference count has gone to zero, the
364 * memory_object is checked to see if it is cacheable otherwise when
365 * the reference count is zero, it is simply terminated.
366 */
367
368kern_return_t
369memory_object_release_name(
370 memory_object_control_t control,
371 int flags)
372{
373 vm_object_t object;
374
375 object = memory_object_control_to_vm_object(control);
376 if (object == VM_OBJECT_NULL)
377 return (KERN_INVALID_ARGUMENT);
378
379 return vm_object_release_name(object, flags);
380}
381
382
383
384/*
385 * Routine: memory_object_destroy [user interface]
386 * Purpose:
387 * Shut down a memory object, despite the
388 * presence of address map (or other) references
389 * to the vm_object.
390 */
391kern_return_t
392memory_object_destroy(
393 memory_object_control_t control,
394 kern_return_t reason)
395{
396 vm_object_t object;
397
398 object = memory_object_control_to_vm_object(control);
399 if (object == VM_OBJECT_NULL)
400 return (KERN_INVALID_ARGUMENT);
401
402 return (vm_object_destroy(object, reason));
403}
404
405/*
406 * Routine: vm_object_sync
1c79356b
A
407 *
408 * Kernel internal function to synch out pages in a given
409 * range within an object to its memory manager. Much the
410 * same as memory_object_lock_request but page protection
411 * is not changed.
412 *
413 * If the should_flush and should_return flags are true pages
414 * are flushed, that is dirty & precious pages are written to
415 * the memory manager and then discarded. If should_return
416 * is false, only precious pages are returned to the memory
417 * manager.
418 *
419 * If should flush is false and should_return true, the memory
420 * manager's copy of the pages is updated. If should_return
421 * is also false, only the precious pages are updated. This
422 * last option is of limited utility.
423 *
424 * Returns:
425 * FALSE if no pages were returned to the pager
426 * TRUE otherwise.
427 */
428
429boolean_t
0b4e3aa0 430vm_object_sync(
1c79356b
A
431 vm_object_t object,
432 vm_object_offset_t offset,
91447636 433 vm_object_size_t size,
1c79356b 434 boolean_t should_flush,
91447636
A
435 boolean_t should_return,
436 boolean_t should_iosync)
1c79356b
A
437{
438 boolean_t rv;
91447636 439 int flags;
1c79356b 440
0b4e3aa0
A
441 XPR(XPR_VM_OBJECT,
442 "vm_o_sync, object 0x%X, offset 0x%X size 0x%x flush %d rtn %d\n",
b0d623f7 443 object, offset, size, should_flush, should_return);
1c79356b
A
444
445 /*
446 * Lock the object, and acquire a paging reference to
447 * prevent the memory_object and control ports from
448 * being destroyed.
449 */
450 vm_object_lock(object);
451 vm_object_paging_begin(object);
452
39236c6e 453 if (should_flush) {
91447636 454 flags = MEMORY_OBJECT_DATA_FLUSH;
39236c6e
A
455 /*
456 * This flush is from an msync(), not a truncate(), so the
457 * contents of the file are not affected.
458 * MEMORY_OBECT_DATA_NO_CHANGE lets vm_object_update() know
459 * that the data is not changed and that there's no need to
460 * push the old contents to a copy object.
461 */
462 flags |= MEMORY_OBJECT_DATA_NO_CHANGE;
463 } else
91447636
A
464 flags = 0;
465
466 if (should_iosync)
467 flags |= MEMORY_OBJECT_IO_SYNC;
468
469 rv = vm_object_update(object, offset, (vm_object_size_t)size, NULL, NULL,
1c79356b
A
470 (should_return) ?
471 MEMORY_OBJECT_RETURN_ALL :
472 MEMORY_OBJECT_RETURN_NONE,
91447636 473 flags,
1c79356b
A
474 VM_PROT_NO_CHANGE);
475
476
477 vm_object_paging_end(object);
478 vm_object_unlock(object);
479 return rv;
480}
481
91447636
A
482
483
6d2010ae
A
484#define LIST_REQ_PAGEOUT_PAGES(object, data_cnt, po, ro, ioerr, iosync) \
485MACRO_BEGIN \
486 \
487 int upl_flags; \
488 memory_object_t pager; \
489 \
39236c6e 490 if (object->object_slid) { \
6d2010ae
A
491 panic("Objects with slid pages not allowed\n"); \
492 } \
493 \
494 if ((pager = (object)->pager) != MEMORY_OBJECT_NULL) { \
495 vm_object_paging_begin(object); \
496 vm_object_unlock(object); \
497 \
498 if (iosync) \
499 upl_flags = UPL_MSYNC | UPL_IOSYNC; \
500 else \
501 upl_flags = UPL_MSYNC; \
502 \
503 (void) memory_object_data_return(pager, \
504 po, \
505 (memory_object_cluster_size_t)data_cnt, \
506 ro, \
507 ioerr, \
508 FALSE, \
509 FALSE, \
510 upl_flags); \
511 \
512 vm_object_lock(object); \
513 vm_object_paging_end(object); \
514 } \
515MACRO_END
516
517
91447636
A
518
519static int
520vm_object_update_extent(
521 vm_object_t object,
522 vm_object_offset_t offset,
523 vm_object_offset_t offset_end,
524 vm_object_offset_t *offset_resid,
525 int *io_errno,
526 boolean_t should_flush,
527 memory_object_return_t should_return,
528 boolean_t should_iosync,
529 vm_prot_t prot)
530{
531 vm_page_t m;
532 int retval = 0;
91447636 533 vm_object_offset_t paging_offset = 0;
b0d623f7 534 vm_object_offset_t next_offset = offset;
91447636 535 memory_object_lock_result_t page_lock_result;
6d2010ae
A
536 memory_object_cluster_size_t data_cnt = 0;
537 struct vm_page_delayed_work dw_array[DEFAULT_DELAYED_WORK_LIMIT];
538 struct vm_page_delayed_work *dwp;
539 int dw_count;
540 int dw_limit;
541
542 dwp = &dw_array[0];
543 dw_count = 0;
544 dw_limit = DELAYED_WORK_LIMIT(DEFAULT_DELAYED_WORK_LIMIT);
91447636
A
545
546 for (;
547 offset < offset_end && object->resident_page_count;
548 offset += PAGE_SIZE_64) {
549
550 /*
b0d623f7 551 * Limit the number of pages to be cleaned at once to a contiguous
fe8ab488 552 * run, or at most MAX_UPL_TRANSFER_BYTES
91447636 553 */
b0d623f7 554 if (data_cnt) {
fe8ab488 555 if ((data_cnt >= MAX_UPL_TRANSFER_BYTES) || (next_offset != offset)) {
6d2010ae
A
556
557 if (dw_count) {
558 vm_page_do_delayed_work(object, &dw_array[0], dw_count);
559 dwp = &dw_array[0];
560 dw_count = 0;
561 }
562 LIST_REQ_PAGEOUT_PAGES(object, data_cnt,
563 paging_offset, offset_resid, io_errno, should_iosync);
b0d623f7
A
564 data_cnt = 0;
565 }
91447636 566 }
91447636 567 while ((m = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
6d2010ae
A
568
569 dwp->dw_mask = 0;
570
571 page_lock_result = memory_object_lock_page(m, should_return, should_flush, prot);
572
573 if (data_cnt && page_lock_result != MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN) {
574 /*
575 * End of a run of dirty/precious pages.
576 */
577 if (dw_count) {
578 vm_page_do_delayed_work(object, &dw_array[0], dw_count);
579 dwp = &dw_array[0];
580 dw_count = 0;
581 }
582 LIST_REQ_PAGEOUT_PAGES(object, data_cnt,
583 paging_offset, offset_resid, io_errno, should_iosync);
584 /*
585 * LIST_REQ_PAGEOUT_PAGES will drop the object lock which will
586 * allow the state of page 'm' to change... we need to re-lookup
587 * the current offset
588 */
589 data_cnt = 0;
590 continue;
591 }
592
593 switch (page_lock_result) {
594
595 case MEMORY_OBJECT_LOCK_RESULT_DONE:
596 break;
597
598 case MEMORY_OBJECT_LOCK_RESULT_MUST_FREE:
599 dwp->dw_mask |= DW_vm_page_free;
600 break;
601
602 case MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK:
603 PAGE_SLEEP(object, m, THREAD_UNINT);
604 continue;
605
606 case MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN:
607 if (data_cnt == 0)
608 paging_offset = offset;
609
610 data_cnt += PAGE_SIZE;
611 next_offset = offset + PAGE_SIZE_64;
612
6d2010ae
A
613 /*
614 * wired pages shouldn't be flushed and
615 * since they aren't on any queue,
616 * no need to remove them
617 */
618 if (!VM_PAGE_WIRED(m)) {
619
620 if (should_flush) {
621 /*
622 * add additional state for the flush
623 */
6d2010ae 624 m->pageout = TRUE;
6d2010ae
A
625 }
626 /*
627 * we use to remove the page from the queues at this
628 * point, but we do not believe that an msync
629 * should cause the 'age' of a page to be changed
630 *
631 * else
632 * dwp->dw_mask |= DW_VM_PAGE_QUEUES_REMOVE;
633 */
634 }
635 retval = 1;
636 break;
637 }
638 if (dwp->dw_mask) {
639 VM_PAGE_ADD_DELAYED_WORK(dwp, m, dw_count);
640
641 if (dw_count >= dw_limit) {
642 vm_page_do_delayed_work(object, &dw_array[0], dw_count);
643 dwp = &dw_array[0];
644 dw_count = 0;
645 }
91447636
A
646 }
647 break;
648 }
649 }
650 /*
651 * We have completed the scan for applicable pages.
652 * Clean any pages that have been saved.
653 */
6d2010ae
A
654 if (dw_count)
655 vm_page_do_delayed_work(object, &dw_array[0], dw_count);
656
91447636 657 if (data_cnt) {
6d2010ae
A
658 LIST_REQ_PAGEOUT_PAGES(object, data_cnt,
659 paging_offset, offset_resid, io_errno, should_iosync);
91447636
A
660 }
661 return (retval);
662}
663
664
665
1c79356b 666/*
0b4e3aa0 667 * Routine: vm_object_update
1c79356b 668 * Description:
0b4e3aa0 669 * Work function for m_o_lock_request(), vm_o_sync().
1c79356b
A
670 *
671 * Called with object locked and paging ref taken.
672 */
673kern_return_t
0b4e3aa0 674vm_object_update(
6d2010ae
A
675 vm_object_t object,
676 vm_object_offset_t offset,
677 vm_object_size_t size,
678 vm_object_offset_t *resid_offset,
679 int *io_errno,
680 memory_object_return_t should_return,
681 int flags,
682 vm_prot_t protection)
1c79356b 683{
2d21ac55 684 vm_object_t copy_object = VM_OBJECT_NULL;
1c79356b
A
685 boolean_t data_returned = FALSE;
686 boolean_t update_cow;
91447636
A
687 boolean_t should_flush = (flags & MEMORY_OBJECT_DATA_FLUSH) ? TRUE : FALSE;
688 boolean_t should_iosync = (flags & MEMORY_OBJECT_IO_SYNC) ? TRUE : FALSE;
b0d623f7 689 vm_fault_return_t result;
91447636
A
690 int num_of_extents;
691 int n;
692#define MAX_EXTENTS 8
693#define EXTENT_SIZE (1024 * 1024 * 256)
694#define RESIDENT_LIMIT (1024 * 32)
695 struct extent {
696 vm_object_offset_t e_base;
697 vm_object_offset_t e_min;
698 vm_object_offset_t e_max;
699 } extents[MAX_EXTENTS];
1c79356b
A
700
701 /*
702 * To avoid blocking while scanning for pages, save
703 * dirty pages to be cleaned all at once.
704 *
705 * XXXO A similar strategy could be used to limit the
706 * number of times that a scan must be restarted for
707 * other reasons. Those pages that would require blocking
708 * could be temporarily collected in another list, or
709 * their offsets could be recorded in a small array.
710 */
711
712 /*
713 * XXX NOTE: May want to consider converting this to a page list
714 * XXX vm_map_copy interface. Need to understand object
715 * XXX coalescing implications before doing so.
716 */
717
718 update_cow = ((flags & MEMORY_OBJECT_DATA_FLUSH)
719 && (!(flags & MEMORY_OBJECT_DATA_NO_CHANGE) &&
720 !(flags & MEMORY_OBJECT_DATA_PURGE)))
721 || (flags & MEMORY_OBJECT_COPY_SYNC);
722
2d21ac55
A
723 if (update_cow || (flags & (MEMORY_OBJECT_DATA_PURGE | MEMORY_OBJECT_DATA_SYNC))) {
724 int collisions = 0;
725
726 while ((copy_object = object->copy) != VM_OBJECT_NULL) {
727 /*
728 * need to do a try here since we're swimming upstream
729 * against the normal lock ordering... however, we need
730 * to hold the object stable until we gain control of the
731 * copy object so we have to be careful how we approach this
732 */
733 if (vm_object_lock_try(copy_object)) {
734 /*
735 * we 'won' the lock on the copy object...
736 * no need to hold the object lock any longer...
737 * take a real reference on the copy object because
738 * we're going to call vm_fault_page on it which may
739 * under certain conditions drop the lock and the paging
740 * reference we're about to take... the reference
741 * will keep the copy object from going away if that happens
742 */
743 vm_object_unlock(object);
744 vm_object_reference_locked(copy_object);
745 break;
746 }
747 vm_object_unlock(object);
1c79356b 748
2d21ac55
A
749 collisions++;
750 mutex_pause(collisions);
751
752 vm_object_lock(object);
753 }
754 }
755 if ((copy_object != VM_OBJECT_NULL && update_cow) || (flags & MEMORY_OBJECT_DATA_SYNC)) {
91447636
A
756 vm_map_size_t i;
757 vm_map_size_t copy_size;
758 vm_map_offset_t copy_offset;
1c79356b
A
759 vm_prot_t prot;
760 vm_page_t page;
761 vm_page_t top_page;
762 kern_return_t error = 0;
2d21ac55
A
763 struct vm_object_fault_info fault_info;
764
765 if (copy_object != VM_OBJECT_NULL) {
766 /*
767 * translate offset with respect to shadow's offset
768 */
6d2010ae
A
769 copy_offset = (offset >= copy_object->vo_shadow_offset) ?
770 (vm_map_offset_t)(offset - copy_object->vo_shadow_offset) :
2d21ac55
A
771 (vm_map_offset_t) 0;
772
6d2010ae
A
773 if (copy_offset > copy_object->vo_size)
774 copy_offset = copy_object->vo_size;
2d21ac55
A
775
776 /*
777 * clip size with respect to shadow offset
778 */
6d2010ae 779 if (offset >= copy_object->vo_shadow_offset) {
2d21ac55 780 copy_size = size;
6d2010ae
A
781 } else if (size >= copy_object->vo_shadow_offset - offset) {
782 copy_size = size - (copy_object->vo_shadow_offset - offset);
2d21ac55
A
783 } else {
784 copy_size = 0;
785 }
786
6d2010ae
A
787 if (copy_offset + copy_size > copy_object->vo_size) {
788 if (copy_object->vo_size >= copy_offset) {
789 copy_size = copy_object->vo_size - copy_offset;
2d21ac55
A
790 } else {
791 copy_size = 0;
792 }
793 }
794 copy_size+=copy_offset;
1c79356b 795
1c79356b
A
796 } else {
797 copy_object = object;
798
799 copy_size = offset + size;
800 copy_offset = offset;
801 }
2d21ac55
A
802 fault_info.interruptible = THREAD_UNINT;
803 fault_info.behavior = VM_BEHAVIOR_SEQUENTIAL;
804 fault_info.user_tag = 0;
fe8ab488 805 fault_info.pmap_options = 0;
2d21ac55
A
806 fault_info.lo_offset = copy_offset;
807 fault_info.hi_offset = copy_size;
808 fault_info.no_cache = FALSE;
b0d623f7 809 fault_info.stealth = TRUE;
6d2010ae
A
810 fault_info.io_sync = FALSE;
811 fault_info.cs_bypass = FALSE;
0b4c1975 812 fault_info.mark_zf_absent = FALSE;
316670eb 813 fault_info.batch_pmap_op = FALSE;
1c79356b
A
814
815 vm_object_paging_begin(copy_object);
2d21ac55
A
816
817 for (i = copy_offset; i < copy_size; i += PAGE_SIZE) {
1c79356b 818 RETRY_COW_OF_LOCK_REQUEST:
b0d623f7
A
819 fault_info.cluster_size = (vm_size_t) (copy_size - i);
820 assert(fault_info.cluster_size == copy_size - i);
2d21ac55 821
1c79356b 822 prot = VM_PROT_WRITE|VM_PROT_READ;
39236c6e 823 page = VM_PAGE_NULL;
b0d623f7
A
824 result = vm_fault_page(copy_object, i,
825 VM_PROT_WRITE|VM_PROT_READ,
826 FALSE,
39236c6e 827 FALSE, /* page not looked up */
b0d623f7
A
828 &prot,
829 &page,
830 &top_page,
831 (int *)0,
832 &error,
833 FALSE,
834 FALSE, &fault_info);
835
836 switch (result) {
1c79356b 837 case VM_FAULT_SUCCESS:
2d21ac55 838 if (top_page) {
1c79356b
A
839 vm_fault_cleanup(
840 page->object, top_page);
1c79356b
A
841 vm_object_lock(copy_object);
842 vm_object_paging_begin(copy_object);
1c79356b 843 }
b0d623f7
A
844 if (!page->active &&
845 !page->inactive &&
846 !page->throttled) {
847 vm_page_lockspin_queues();
848 if (!page->active &&
849 !page->inactive &&
850 !page->throttled)
851 vm_page_deactivate(page);
852 vm_page_unlock_queues();
853 }
2d21ac55 854 PAGE_WAKEUP_DONE(page);
1c79356b
A
855 break;
856 case VM_FAULT_RETRY:
857 prot = VM_PROT_WRITE|VM_PROT_READ;
858 vm_object_lock(copy_object);
859 vm_object_paging_begin(copy_object);
860 goto RETRY_COW_OF_LOCK_REQUEST;
861 case VM_FAULT_INTERRUPTED:
862 prot = VM_PROT_WRITE|VM_PROT_READ;
863 vm_object_lock(copy_object);
864 vm_object_paging_begin(copy_object);
865 goto RETRY_COW_OF_LOCK_REQUEST;
866 case VM_FAULT_MEMORY_SHORTAGE:
867 VM_PAGE_WAIT();
868 prot = VM_PROT_WRITE|VM_PROT_READ;
869 vm_object_lock(copy_object);
870 vm_object_paging_begin(copy_object);
871 goto RETRY_COW_OF_LOCK_REQUEST;
b0d623f7
A
872 case VM_FAULT_SUCCESS_NO_VM_PAGE:
873 /* success but no VM page: fail */
874 vm_object_paging_end(copy_object);
875 vm_object_unlock(copy_object);
876 /*FALLTHROUGH*/
1c79356b 877 case VM_FAULT_MEMORY_ERROR:
2d21ac55
A
878 if (object != copy_object)
879 vm_object_deallocate(copy_object);
1c79356b
A
880 vm_object_lock(object);
881 goto BYPASS_COW_COPYIN;
b0d623f7
A
882 default:
883 panic("vm_object_update: unexpected error 0x%x"
884 " from vm_fault_page()\n", result);
1c79356b
A
885 }
886
887 }
888 vm_object_paging_end(copy_object);
2d21ac55
A
889 }
890 if ((flags & (MEMORY_OBJECT_DATA_SYNC | MEMORY_OBJECT_COPY_SYNC))) {
891 if (copy_object != VM_OBJECT_NULL && copy_object != object) {
1c79356b 892 vm_object_unlock(copy_object);
2d21ac55 893 vm_object_deallocate(copy_object);
1c79356b
A
894 vm_object_lock(object);
895 }
2d21ac55 896 return KERN_SUCCESS;
1c79356b 897 }
2d21ac55
A
898 if (copy_object != VM_OBJECT_NULL && copy_object != object) {
899 if ((flags & MEMORY_OBJECT_DATA_PURGE)) {
900 copy_object->shadow_severed = TRUE;
901 copy_object->shadowed = FALSE;
902 copy_object->shadow = NULL;
903 /*
904 * delete the ref the COW was holding on the target object
905 */
906 vm_object_deallocate(object);
907 }
908 vm_object_unlock(copy_object);
909 vm_object_deallocate(copy_object);
910 vm_object_lock(object);
1c79356b
A
911 }
912BYPASS_COW_COPYIN:
913
91447636
A
914 /*
915 * when we have a really large range to check relative
916 * to the number of actual resident pages, we'd like
917 * to use the resident page list to drive our checks
918 * however, the object lock will get dropped while processing
919 * the page which means the resident queue can change which
920 * means we can't walk the queue as we process the pages
921 * we also want to do the processing in offset order to allow
922 * 'runs' of pages to be collected if we're being told to
923 * flush to disk... the resident page queue is NOT ordered.
924 *
925 * a temporary solution (until we figure out how to deal with
926 * large address spaces more generically) is to pre-flight
927 * the resident page queue (if it's small enough) and develop
928 * a collection of extents (that encompass actual resident pages)
929 * to visit. This will at least allow us to deal with some of the
930 * more pathological cases in a more efficient manner. The current
931 * worst case (a single resident page at the end of an extremely large
932 * range) can take minutes to complete for ranges in the terrabyte
933 * category... since this routine is called when truncating a file,
934 * and we currently support files up to 16 Tbytes in size, this
935 * is not a theoretical problem
936 */
1c79356b 937
91447636
A
938 if ((object->resident_page_count < RESIDENT_LIMIT) &&
939 (atop_64(size) > (unsigned)(object->resident_page_count/(8 * MAX_EXTENTS)))) {
940 vm_page_t next;
941 vm_object_offset_t start;
942 vm_object_offset_t end;
943 vm_object_size_t e_mask;
944 vm_page_t m;
1c79356b 945
91447636
A
946 start = offset;
947 end = offset + size;
948 num_of_extents = 0;
949 e_mask = ~((vm_object_size_t)(EXTENT_SIZE - 1));
1c79356b 950
91447636 951 m = (vm_page_t) queue_first(&object->memq);
1c79356b 952
91447636
A
953 while (!queue_end(&object->memq, (queue_entry_t) m)) {
954 next = (vm_page_t) queue_next(&m->listq);
1c79356b 955
91447636
A
956 if ((m->offset >= start) && (m->offset < end)) {
957 /*
958 * this is a page we're interested in
959 * try to fit it into a current extent
1c79356b 960 */
91447636
A
961 for (n = 0; n < num_of_extents; n++) {
962 if ((m->offset & e_mask) == extents[n].e_base) {
963 /*
964 * use (PAGE_SIZE - 1) to determine the
965 * max offset so that we don't wrap if
966 * we're at the last page of the space
967 */
968 if (m->offset < extents[n].e_min)
969 extents[n].e_min = m->offset;
970 else if ((m->offset + (PAGE_SIZE - 1)) > extents[n].e_max)
971 extents[n].e_max = m->offset + (PAGE_SIZE - 1);
972 break;
973 }
974 }
975 if (n == num_of_extents) {
976 /*
977 * didn't find a current extent that can encompass
978 * this page
979 */
980 if (n < MAX_EXTENTS) {
981 /*
982 * if we still have room,
983 * create a new extent
984 */
985 extents[n].e_base = m->offset & e_mask;
986 extents[n].e_min = m->offset;
987 extents[n].e_max = m->offset + (PAGE_SIZE - 1);
988
989 num_of_extents++;
990 } else {
991 /*
992 * no room to create a new extent...
993 * fall back to a single extent based
994 * on the min and max page offsets
995 * we find in the range we're interested in...
996 * first, look through the extent list and
997 * develop the overall min and max for the
998 * pages we've looked at up to this point
999 */
1000 for (n = 1; n < num_of_extents; n++) {
1001 if (extents[n].e_min < extents[0].e_min)
1002 extents[0].e_min = extents[n].e_min;
1003 if (extents[n].e_max > extents[0].e_max)
1004 extents[0].e_max = extents[n].e_max;
1005 }
1006 /*
1007 * now setup to run through the remaining pages
1008 * to determine the overall min and max
1009 * offset for the specified range
1010 */
1011 extents[0].e_base = 0;
1012 e_mask = 0;
1013 num_of_extents = 1;
1014
1015 /*
1016 * by continuing, we'll reprocess the
1017 * page that forced us to abandon trying
1018 * to develop multiple extents
1019 */
1020 continue;
1021 }
1022 }
1c79356b 1023 }
91447636 1024 m = next;
1c79356b 1025 }
91447636
A
1026 } else {
1027 extents[0].e_min = offset;
1028 extents[0].e_max = offset + (size - 1);
1c79356b 1029
91447636
A
1030 num_of_extents = 1;
1031 }
1032 for (n = 0; n < num_of_extents; n++) {
1033 if (vm_object_update_extent(object, extents[n].e_min, extents[n].e_max, resid_offset, io_errno,
1034 should_flush, should_return, should_iosync, protection))
1035 data_returned = TRUE;
1c79356b 1036 }
1c79356b
A
1037 return (data_returned);
1038}
1039
91447636 1040
1c79356b
A
1041/*
1042 * Routine: memory_object_synchronize_completed [user interface]
1043 *
1044 * Tell kernel that previously synchronized data
1045 * (memory_object_synchronize) has been queue or placed on the
1046 * backing storage.
1047 *
1048 * Note: there may be multiple synchronize requests for a given
1049 * memory object outstanding but they will not overlap.
1050 */
1051
1052kern_return_t
1053memory_object_synchronize_completed(
0b4e3aa0
A
1054 memory_object_control_t control,
1055 memory_object_offset_t offset,
b0d623f7 1056 memory_object_size_t length)
1c79356b 1057{
0b4e3aa0
A
1058 vm_object_t object;
1059 msync_req_t msr;
1c79356b 1060
91447636
A
1061 object = memory_object_control_to_vm_object(control);
1062
1c79356b
A
1063 XPR(XPR_MEMORY_OBJECT,
1064 "m_o_sync_completed, object 0x%X, offset 0x%X length 0x%X\n",
b0d623f7 1065 object, offset, length, 0, 0);
1c79356b
A
1066
1067 /*
1068 * Look for bogus arguments
1069 */
1070
0b4e3aa0
A
1071 if (object == VM_OBJECT_NULL)
1072 return (KERN_INVALID_ARGUMENT);
1c79356b
A
1073
1074 vm_object_lock(object);
1075
1076/*
1077 * search for sync request structure
1078 */
1079 queue_iterate(&object->msr_q, msr, msync_req_t, msr_q) {
1080 if (msr->offset == offset && msr->length == length) {
1081 queue_remove(&object->msr_q, msr, msync_req_t, msr_q);
1082 break;
1083 }
1084 }/* queue_iterate */
1085
1086 if (queue_end(&object->msr_q, (queue_entry_t)msr)) {
1087 vm_object_unlock(object);
1c79356b
A
1088 return KERN_INVALID_ARGUMENT;
1089 }
1090
1091 msr_lock(msr);
1092 vm_object_unlock(object);
1093 msr->flag = VM_MSYNC_DONE;
1094 msr_unlock(msr);
1095 thread_wakeup((event_t) msr);
1c79356b
A
1096
1097 return KERN_SUCCESS;
1098}/* memory_object_synchronize_completed */
0b4e3aa0
A
1099
1100static kern_return_t
1101vm_object_set_attributes_common(
1c79356b
A
1102 vm_object_t object,
1103 boolean_t may_cache,
1104 memory_object_copy_strategy_t copy_strategy,
1105 boolean_t temporary,
39236c6e 1106 __unused boolean_t silent_overwrite,
1c79356b
A
1107 boolean_t advisory_pageout)
1108{
1109 boolean_t object_became_ready;
1110
1111 XPR(XPR_MEMORY_OBJECT,
1112 "m_o_set_attr_com, object 0x%X flg %x strat %d\n",
b0d623f7 1113 object, (may_cache&1)|((temporary&1)<1), copy_strategy, 0, 0);
1c79356b
A
1114
1115 if (object == VM_OBJECT_NULL)
1116 return(KERN_INVALID_ARGUMENT);
1117
1118 /*
1119 * Verify the attributes of importance
1120 */
1121
1122 switch(copy_strategy) {
1123 case MEMORY_OBJECT_COPY_NONE:
1124 case MEMORY_OBJECT_COPY_DELAY:
1125 break;
1126 default:
1c79356b
A
1127 return(KERN_INVALID_ARGUMENT);
1128 }
1129
1c79356b
A
1130 if (may_cache)
1131 may_cache = TRUE;
1132 if (temporary)
1133 temporary = TRUE;
1c79356b
A
1134
1135 vm_object_lock(object);
1136
1137 /*
1138 * Copy the attributes
1139 */
1140 assert(!object->internal);
1141 object_became_ready = !object->pager_ready;
1142 object->copy_strategy = copy_strategy;
1143 object->can_persist = may_cache;
1144 object->temporary = temporary;
39236c6e 1145// object->silent_overwrite = silent_overwrite;
1c79356b 1146 object->advisory_pageout = advisory_pageout;
1c79356b
A
1147
1148 /*
1149 * Wake up anyone waiting for the ready attribute
1150 * to become asserted.
1151 */
1152
1153 if (object_became_ready) {
1154 object->pager_ready = TRUE;
1155 vm_object_wakeup(object, VM_OBJECT_EVENT_PAGER_READY);
1156 }
1157
1158 vm_object_unlock(object);
1159
1c79356b
A
1160 return(KERN_SUCCESS);
1161}
1162
1163/*
1164 * Set the memory object attribute as provided.
1165 *
1166 * XXX This routine cannot be completed until the vm_msync, clean
1167 * in place, and cluster work is completed. See ifdef notyet
0b4e3aa0 1168 * below and note that vm_object_set_attributes_common()
1c79356b
A
1169 * may have to be expanded.
1170 */
1171kern_return_t
1172memory_object_change_attributes(
0b4e3aa0
A
1173 memory_object_control_t control,
1174 memory_object_flavor_t flavor,
1175 memory_object_info_t attributes,
1176 mach_msg_type_number_t count)
1c79356b 1177{
0b4e3aa0
A
1178 vm_object_t object;
1179 kern_return_t result = KERN_SUCCESS;
1180 boolean_t temporary;
1181 boolean_t may_cache;
1182 boolean_t invalidate;
1c79356b 1183 memory_object_copy_strategy_t copy_strategy;
0b4e3aa0 1184 boolean_t silent_overwrite;
1c79356b
A
1185 boolean_t advisory_pageout;
1186
0b4e3aa0 1187 object = memory_object_control_to_vm_object(control);
1c79356b 1188 if (object == VM_OBJECT_NULL)
0b4e3aa0 1189 return (KERN_INVALID_ARGUMENT);
1c79356b
A
1190
1191 vm_object_lock(object);
0b4e3aa0 1192
1c79356b
A
1193 temporary = object->temporary;
1194 may_cache = object->can_persist;
1195 copy_strategy = object->copy_strategy;
39236c6e
A
1196// silent_overwrite = object->silent_overwrite;
1197 silent_overwrite = FALSE;
1c79356b
A
1198 advisory_pageout = object->advisory_pageout;
1199#if notyet
1200 invalidate = object->invalidate;
1201#endif
1c79356b
A
1202 vm_object_unlock(object);
1203
1204 switch (flavor) {
1205 case OLD_MEMORY_OBJECT_BEHAVIOR_INFO:
1206 {
1207 old_memory_object_behave_info_t behave;
1208
1209 if (count != OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1210 result = KERN_INVALID_ARGUMENT;
1211 break;
1212 }
1213
1214 behave = (old_memory_object_behave_info_t) attributes;
1215
1216 temporary = behave->temporary;
1217 invalidate = behave->invalidate;
1218 copy_strategy = behave->copy_strategy;
1219
1220 break;
1221 }
1222
1223 case MEMORY_OBJECT_BEHAVIOR_INFO:
1224 {
1225 memory_object_behave_info_t behave;
1226
1227 if (count != MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1228 result = KERN_INVALID_ARGUMENT;
1229 break;
1230 }
1231
1232 behave = (memory_object_behave_info_t) attributes;
1233
1234 temporary = behave->temporary;
1235 invalidate = behave->invalidate;
1236 copy_strategy = behave->copy_strategy;
1237 silent_overwrite = behave->silent_overwrite;
1238 advisory_pageout = behave->advisory_pageout;
1239 break;
1240 }
1241
1242 case MEMORY_OBJECT_PERFORMANCE_INFO:
1243 {
1244 memory_object_perf_info_t perf;
1245
1246 if (count != MEMORY_OBJECT_PERF_INFO_COUNT) {
1247 result = KERN_INVALID_ARGUMENT;
1248 break;
1249 }
1250
1251 perf = (memory_object_perf_info_t) attributes;
1252
1253 may_cache = perf->may_cache;
1c79356b
A
1254
1255 break;
1256 }
1257
1258 case OLD_MEMORY_OBJECT_ATTRIBUTE_INFO:
1259 {
1260 old_memory_object_attr_info_t attr;
1261
1262 if (count != OLD_MEMORY_OBJECT_ATTR_INFO_COUNT) {
1263 result = KERN_INVALID_ARGUMENT;
1264 break;
1265 }
1266
1267 attr = (old_memory_object_attr_info_t) attributes;
1268
1269 may_cache = attr->may_cache;
1270 copy_strategy = attr->copy_strategy;
1c79356b
A
1271
1272 break;
1273 }
1274
1275 case MEMORY_OBJECT_ATTRIBUTE_INFO:
1276 {
1277 memory_object_attr_info_t attr;
1278
1279 if (count != MEMORY_OBJECT_ATTR_INFO_COUNT) {
1280 result = KERN_INVALID_ARGUMENT;
1281 break;
1282 }
1283
1284 attr = (memory_object_attr_info_t) attributes;
1285
1286 copy_strategy = attr->copy_strategy;
1287 may_cache = attr->may_cache_object;
1c79356b
A
1288 temporary = attr->temporary;
1289
1290 break;
1291 }
1292
1293 default:
1294 result = KERN_INVALID_ARGUMENT;
1295 break;
1296 }
1297
0b4e3aa0 1298 if (result != KERN_SUCCESS)
1c79356b 1299 return(result);
1c79356b
A
1300
1301 if (copy_strategy == MEMORY_OBJECT_COPY_TEMPORARY) {
1302 copy_strategy = MEMORY_OBJECT_COPY_DELAY;
1303 temporary = TRUE;
1304 } else {
1305 temporary = FALSE;
1306 }
1307
1308 /*
1c79356b
A
1309 * XXX may_cache may become a tri-valued variable to handle
1310 * XXX uncache if not in use.
1311 */
0b4e3aa0 1312 return (vm_object_set_attributes_common(object,
1c79356b
A
1313 may_cache,
1314 copy_strategy,
1315 temporary,
1c79356b 1316 silent_overwrite,
0b4e3aa0 1317 advisory_pageout));
1c79356b
A
1318}
1319
1320kern_return_t
1321memory_object_get_attributes(
0b4e3aa0 1322 memory_object_control_t control,
1c79356b
A
1323 memory_object_flavor_t flavor,
1324 memory_object_info_t attributes, /* pointer to OUT array */
1325 mach_msg_type_number_t *count) /* IN/OUT */
1326{
0b4e3aa0
A
1327 kern_return_t ret = KERN_SUCCESS;
1328 vm_object_t object;
1c79356b 1329
0b4e3aa0
A
1330 object = memory_object_control_to_vm_object(control);
1331 if (object == VM_OBJECT_NULL)
1332 return (KERN_INVALID_ARGUMENT);
1c79356b
A
1333
1334 vm_object_lock(object);
1335
1336 switch (flavor) {
1337 case OLD_MEMORY_OBJECT_BEHAVIOR_INFO:
1338 {
1339 old_memory_object_behave_info_t behave;
1340
1341 if (*count < OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1342 ret = KERN_INVALID_ARGUMENT;
1343 break;
1344 }
1345
1346 behave = (old_memory_object_behave_info_t) attributes;
1347 behave->copy_strategy = object->copy_strategy;
1348 behave->temporary = object->temporary;
1349#if notyet /* remove when vm_msync complies and clean in place fini */
1350 behave->invalidate = object->invalidate;
1351#else
1352 behave->invalidate = FALSE;
1353#endif
1354
1355 *count = OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT;
1356 break;
1357 }
1358
1359 case MEMORY_OBJECT_BEHAVIOR_INFO:
1360 {
1361 memory_object_behave_info_t behave;
1362
1363 if (*count < MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1364 ret = KERN_INVALID_ARGUMENT;
1365 break;
1366 }
1367
1368 behave = (memory_object_behave_info_t) attributes;
1369 behave->copy_strategy = object->copy_strategy;
1370 behave->temporary = object->temporary;
1371#if notyet /* remove when vm_msync complies and clean in place fini */
1372 behave->invalidate = object->invalidate;
1373#else
1374 behave->invalidate = FALSE;
1375#endif
1376 behave->advisory_pageout = object->advisory_pageout;
39236c6e
A
1377// behave->silent_overwrite = object->silent_overwrite;
1378 behave->silent_overwrite = FALSE;
1c79356b
A
1379 *count = MEMORY_OBJECT_BEHAVE_INFO_COUNT;
1380 break;
1381 }
1382
1383 case MEMORY_OBJECT_PERFORMANCE_INFO:
1384 {
1385 memory_object_perf_info_t perf;
1386
1387 if (*count < MEMORY_OBJECT_PERF_INFO_COUNT) {
1388 ret = KERN_INVALID_ARGUMENT;
1389 break;
1390 }
1391
1392 perf = (memory_object_perf_info_t) attributes;
2d21ac55 1393 perf->cluster_size = PAGE_SIZE;
1c79356b
A
1394 perf->may_cache = object->can_persist;
1395
1396 *count = MEMORY_OBJECT_PERF_INFO_COUNT;
1397 break;
1398 }
1399
1400 case OLD_MEMORY_OBJECT_ATTRIBUTE_INFO:
1401 {
1402 old_memory_object_attr_info_t attr;
1403
1404 if (*count < OLD_MEMORY_OBJECT_ATTR_INFO_COUNT) {
1405 ret = KERN_INVALID_ARGUMENT;
1406 break;
1407 }
1408
1409 attr = (old_memory_object_attr_info_t) attributes;
1410 attr->may_cache = object->can_persist;
1411 attr->copy_strategy = object->copy_strategy;
1412
1413 *count = OLD_MEMORY_OBJECT_ATTR_INFO_COUNT;
1414 break;
1415 }
1416
1417 case MEMORY_OBJECT_ATTRIBUTE_INFO:
1418 {
1419 memory_object_attr_info_t attr;
1420
1421 if (*count < MEMORY_OBJECT_ATTR_INFO_COUNT) {
1422 ret = KERN_INVALID_ARGUMENT;
1423 break;
1424 }
1425
1426 attr = (memory_object_attr_info_t) attributes;
1427 attr->copy_strategy = object->copy_strategy;
2d21ac55 1428 attr->cluster_size = PAGE_SIZE;
1c79356b
A
1429 attr->may_cache_object = object->can_persist;
1430 attr->temporary = object->temporary;
1431
1432 *count = MEMORY_OBJECT_ATTR_INFO_COUNT;
1433 break;
1434 }
1435
1436 default:
1437 ret = KERN_INVALID_ARGUMENT;
1438 break;
1439 }
1440
1441 vm_object_unlock(object);
1442
1c79356b
A
1443 return(ret);
1444}
1445
1c79356b 1446
55e303ae
A
1447kern_return_t
1448memory_object_iopl_request(
1449 ipc_port_t port,
1450 memory_object_offset_t offset,
91447636 1451 upl_size_t *upl_size,
55e303ae
A
1452 upl_t *upl_ptr,
1453 upl_page_info_array_t user_page_list,
1454 unsigned int *page_list_count,
1455 int *flags)
1456{
1457 vm_object_t object;
1458 kern_return_t ret;
1459 int caller_flags;
1460
1461 caller_flags = *flags;
1462
91447636
A
1463 if (caller_flags & ~UPL_VALID_FLAGS) {
1464 /*
1465 * For forward compatibility's sake,
1466 * reject any unknown flag.
1467 */
1468 return KERN_INVALID_VALUE;
1469 }
1470
55e303ae
A
1471 if (ip_kotype(port) == IKOT_NAMED_ENTRY) {
1472 vm_named_entry_t named_entry;
1473
1474 named_entry = (vm_named_entry_t)port->ip_kobject;
1475 /* a few checks to make sure user is obeying rules */
1476 if(*upl_size == 0) {
1477 if(offset >= named_entry->size)
1478 return(KERN_INVALID_RIGHT);
b0d623f7
A
1479 *upl_size = (upl_size_t)(named_entry->size - offset);
1480 if (*upl_size != named_entry->size - offset)
1481 return KERN_INVALID_ARGUMENT;
55e303ae
A
1482 }
1483 if(caller_flags & UPL_COPYOUT_FROM) {
1484 if((named_entry->protection & VM_PROT_READ)
1485 != VM_PROT_READ) {
1486 return(KERN_INVALID_RIGHT);
1487 }
1488 } else {
1489 if((named_entry->protection &
1490 (VM_PROT_READ | VM_PROT_WRITE))
1491 != (VM_PROT_READ | VM_PROT_WRITE)) {
1492 return(KERN_INVALID_RIGHT);
1493 }
1494 }
1495 if(named_entry->size < (offset + *upl_size))
1496 return(KERN_INVALID_ARGUMENT);
1497
1498 /* the callers parameter offset is defined to be the */
1499 /* offset from beginning of named entry offset in object */
1500 offset = offset + named_entry->offset;
1501
39236c6e
A
1502 if (named_entry->is_sub_map ||
1503 named_entry->is_copy)
1504 return KERN_INVALID_ARGUMENT;
55e303ae
A
1505
1506 named_entry_lock(named_entry);
1507
91447636 1508 if (named_entry->is_pager) {
55e303ae
A
1509 object = vm_object_enter(named_entry->backing.pager,
1510 named_entry->offset + named_entry->size,
1511 named_entry->internal,
1512 FALSE,
1513 FALSE);
1514 if (object == VM_OBJECT_NULL) {
1515 named_entry_unlock(named_entry);
1516 return(KERN_INVALID_OBJECT);
1517 }
91447636
A
1518
1519 /* JMM - drop reference on pager here? */
55e303ae
A
1520
1521 /* create an extra reference for the named entry */
91447636 1522 vm_object_lock(object);
55e303ae 1523 vm_object_reference_locked(object);
91447636
A
1524 named_entry->backing.object = object;
1525 named_entry->is_pager = FALSE;
55e303ae
A
1526 named_entry_unlock(named_entry);
1527
1528 /* wait for object to be ready */
1529 while (!object->pager_ready) {
1530 vm_object_wait(object,
1531 VM_OBJECT_EVENT_PAGER_READY,
1532 THREAD_UNINT);
1533 vm_object_lock(object);
1534 }
1535 vm_object_unlock(object);
91447636
A
1536 } else {
1537 /* This is the case where we are going to map */
1538 /* an already mapped object. If the object is */
1539 /* not ready it is internal. An external */
1540 /* object cannot be mapped until it is ready */
1541 /* we can therefore avoid the ready check */
1542 /* in this case. */
1543 object = named_entry->backing.object;
1544 vm_object_reference(object);
1545 named_entry_unlock(named_entry);
55e303ae 1546 }
0c530ab8 1547 } else if (ip_kotype(port) == IKOT_MEM_OBJ_CONTROL) {
55e303ae 1548 memory_object_control_t control;
0c530ab8 1549 control = (memory_object_control_t) port;
55e303ae
A
1550 if (control == NULL)
1551 return (KERN_INVALID_ARGUMENT);
1552 object = memory_object_control_to_vm_object(control);
1553 if (object == VM_OBJECT_NULL)
1554 return (KERN_INVALID_ARGUMENT);
1555 vm_object_reference(object);
0c530ab8
A
1556 } else {
1557 return KERN_INVALID_ARGUMENT;
55e303ae
A
1558 }
1559 if (object == VM_OBJECT_NULL)
1560 return (KERN_INVALID_ARGUMENT);
1561
1562 if (!object->private) {
55e303ae
A
1563 if (object->phys_contiguous) {
1564 *flags = UPL_PHYS_CONTIG;
1565 } else {
1566 *flags = 0;
1567 }
1568 } else {
1569 *flags = UPL_DEV_MEMORY | UPL_PHYS_CONTIG;
1570 }
1571
1572 ret = vm_object_iopl_request(object,
1573 offset,
1574 *upl_size,
1575 upl_ptr,
1576 user_page_list,
1577 page_list_count,
1578 caller_flags);
1579 vm_object_deallocate(object);
1580 return ret;
1581}
1582
0b4e3aa0
A
1583/*
1584 * Routine: memory_object_upl_request [interface]
1585 * Purpose:
1586 * Cause the population of a portion of a vm_object.
1587 * Depending on the nature of the request, the pages
1588 * returned may be contain valid data or be uninitialized.
1589 *
1590 */
1c79356b 1591
0b4e3aa0
A
1592kern_return_t
1593memory_object_upl_request(
1594 memory_object_control_t control,
1595 memory_object_offset_t offset,
91447636 1596 upl_size_t size,
0b4e3aa0
A
1597 upl_t *upl_ptr,
1598 upl_page_info_array_t user_page_list,
1599 unsigned int *page_list_count,
1600 int cntrl_flags)
1601{
1602 vm_object_t object;
1603
1604 object = memory_object_control_to_vm_object(control);
1605 if (object == VM_OBJECT_NULL)
b0d623f7 1606 return (KERN_TERMINATED);
0b4e3aa0
A
1607
1608 return vm_object_upl_request(object,
1609 offset,
1610 size,
1611 upl_ptr,
1612 user_page_list,
1613 page_list_count,
1614 cntrl_flags);
1615}
1616
1617/*
1618 * Routine: memory_object_super_upl_request [interface]
1619 * Purpose:
1620 * Cause the population of a portion of a vm_object
1621 * in much the same way as memory_object_upl_request.
1622 * Depending on the nature of the request, the pages
1623 * returned may be contain valid data or be uninitialized.
1624 * However, the region may be expanded up to the super
1625 * cluster size provided.
1c79356b 1626 */
0b4e3aa0 1627
1c79356b 1628kern_return_t
0b4e3aa0
A
1629memory_object_super_upl_request(
1630 memory_object_control_t control,
1631 memory_object_offset_t offset,
91447636
A
1632 upl_size_t size,
1633 upl_size_t super_cluster,
0b4e3aa0
A
1634 upl_t *upl,
1635 upl_page_info_t *user_page_list,
1636 unsigned int *page_list_count,
1637 int cntrl_flags)
1c79356b 1638{
0b4e3aa0
A
1639 vm_object_t object;
1640
1641 object = memory_object_control_to_vm_object(control);
1642 if (object == VM_OBJECT_NULL)
1643 return (KERN_INVALID_ARGUMENT);
1644
1645 return vm_object_super_upl_request(object,
1646 offset,
1647 size,
1648 super_cluster,
1649 upl,
1650 user_page_list,
1651 page_list_count,
1652 cntrl_flags);
1c79356b
A
1653}
1654
2d21ac55
A
1655kern_return_t
1656memory_object_cluster_size(memory_object_control_t control, memory_object_offset_t *start,
b0d623f7 1657 vm_size_t *length, uint32_t *io_streaming, memory_object_fault_info_t fault_info)
2d21ac55
A
1658{
1659 vm_object_t object;
1660
1661 object = memory_object_control_to_vm_object(control);
1662
1663 if (object == VM_OBJECT_NULL || object->paging_offset > *start)
1664 return (KERN_INVALID_ARGUMENT);
1665
1666 *start -= object->paging_offset;
1667
b0d623f7 1668 vm_object_cluster_size(object, (vm_object_offset_t *)start, length, (vm_object_fault_info_t)fault_info, io_streaming);
2d21ac55
A
1669
1670 *start += object->paging_offset;
1671
1672 return (KERN_SUCCESS);
1673}
1674
1675
0b4e3aa0
A
1676int vm_stat_discard_cleared_reply = 0;
1677int vm_stat_discard_cleared_unset = 0;
1678int vm_stat_discard_cleared_too_late = 0;
1679
1680
1681
1c79356b 1682/*
0b4e3aa0 1683 * Routine: host_default_memory_manager [interface]
1c79356b
A
1684 * Purpose:
1685 * set/get the default memory manager port and default cluster
1686 * size.
1687 *
1688 * If successful, consumes the supplied naked send right.
1689 */
1690kern_return_t
1691host_default_memory_manager(
0b4e3aa0
A
1692 host_priv_t host_priv,
1693 memory_object_default_t *default_manager,
2d21ac55 1694 __unused memory_object_cluster_size_t cluster_size)
1c79356b 1695{
0b4e3aa0
A
1696 memory_object_default_t current_manager;
1697 memory_object_default_t new_manager;
1698 memory_object_default_t returned_manager;
2d21ac55 1699 kern_return_t result = KERN_SUCCESS;
1c79356b
A
1700
1701 if (host_priv == HOST_PRIV_NULL)
1702 return(KERN_INVALID_HOST);
1703
1704 assert(host_priv == &realhost);
1705
1706 new_manager = *default_manager;
b0d623f7 1707 lck_mtx_lock(&memory_manager_default_lock);
1c79356b 1708 current_manager = memory_manager_default;
2d21ac55 1709 returned_manager = MEMORY_OBJECT_DEFAULT_NULL;
1c79356b 1710
0b4e3aa0 1711 if (new_manager == MEMORY_OBJECT_DEFAULT_NULL) {
1c79356b
A
1712 /*
1713 * Retrieve the current value.
1714 */
0b4e3aa0 1715 returned_manager = current_manager;
2d21ac55 1716 memory_object_default_reference(returned_manager);
1c79356b 1717 } else {
2d21ac55
A
1718
1719 /*
1720 * If this is the first non-null manager, start
1721 * up the internal pager support.
1722 */
1723 if (current_manager == MEMORY_OBJECT_DEFAULT_NULL) {
1724 result = vm_pageout_internal_start();
1725 if (result != KERN_SUCCESS)
1726 goto out;
1727 }
1728
1c79356b
A
1729 /*
1730 * Retrieve the current value,
1731 * and replace it with the supplied value.
0b4e3aa0
A
1732 * We return the old reference to the caller
1733 * but we have to take a reference on the new
1734 * one.
1c79356b 1735 */
1c79356b
A
1736 returned_manager = current_manager;
1737 memory_manager_default = new_manager;
0b4e3aa0
A
1738 memory_object_default_reference(new_manager);
1739
1c79356b
A
1740 /*
1741 * In case anyone's been waiting for a memory
1742 * manager to be established, wake them up.
1743 */
1744
1745 thread_wakeup((event_t) &memory_manager_default);
b0d623f7
A
1746
1747 /*
1748 * Now that we have a default pager for anonymous memory,
1749 * reactivate all the throttled pages (i.e. dirty pages with
1750 * no pager).
1751 */
6d2010ae
A
1752 if (current_manager == MEMORY_OBJECT_DEFAULT_NULL)
1753 {
b0d623f7
A
1754 vm_page_reactivate_all_throttled();
1755 }
1c79356b 1756 }
2d21ac55 1757 out:
b0d623f7 1758 lck_mtx_unlock(&memory_manager_default_lock);
1c79356b
A
1759
1760 *default_manager = returned_manager;
2d21ac55 1761 return(result);
1c79356b
A
1762}
1763
1764/*
1765 * Routine: memory_manager_default_reference
1766 * Purpose:
1767 * Returns a naked send right for the default
1768 * memory manager. The returned right is always
1769 * valid (not IP_NULL or IP_DEAD).
1770 */
1771
0b4e3aa0 1772__private_extern__ memory_object_default_t
2d21ac55 1773memory_manager_default_reference(void)
1c79356b 1774{
0b4e3aa0 1775 memory_object_default_t current_manager;
1c79356b 1776
b0d623f7 1777 lck_mtx_lock(&memory_manager_default_lock);
0b4e3aa0
A
1778 current_manager = memory_manager_default;
1779 while (current_manager == MEMORY_OBJECT_DEFAULT_NULL) {
9bccf70c
A
1780 wait_result_t res;
1781
b0d623f7
A
1782 res = lck_mtx_sleep(&memory_manager_default_lock,
1783 LCK_SLEEP_DEFAULT,
1784 (event_t) &memory_manager_default,
1785 THREAD_UNINT);
9bccf70c 1786 assert(res == THREAD_AWAKENED);
0b4e3aa0 1787 current_manager = memory_manager_default;
1c79356b 1788 }
0b4e3aa0 1789 memory_object_default_reference(current_manager);
b0d623f7 1790 lck_mtx_unlock(&memory_manager_default_lock);
1c79356b
A
1791
1792 return current_manager;
1793}
1794
1c79356b
A
1795/*
1796 * Routine: memory_manager_default_check
1797 *
1798 * Purpose:
1799 * Check whether a default memory manager has been set
1800 * up yet, or not. Returns KERN_SUCCESS if dmm exists,
1801 * and KERN_FAILURE if dmm does not exist.
1802 *
1803 * If there is no default memory manager, log an error,
1804 * but only the first time.
1805 *
1806 */
0b4e3aa0 1807__private_extern__ kern_return_t
1c79356b
A
1808memory_manager_default_check(void)
1809{
0b4e3aa0 1810 memory_object_default_t current;
1c79356b 1811
b0d623f7 1812 lck_mtx_lock(&memory_manager_default_lock);
1c79356b 1813 current = memory_manager_default;
0b4e3aa0 1814 if (current == MEMORY_OBJECT_DEFAULT_NULL) {
1c79356b
A
1815 static boolean_t logged; /* initialized to 0 */
1816 boolean_t complain = !logged;
1817 logged = TRUE;
b0d623f7 1818 lck_mtx_unlock(&memory_manager_default_lock);
1c79356b
A
1819 if (complain)
1820 printf("Warning: No default memory manager\n");
1821 return(KERN_FAILURE);
1822 } else {
b0d623f7 1823 lck_mtx_unlock(&memory_manager_default_lock);
1c79356b
A
1824 return(KERN_SUCCESS);
1825 }
1826}
1827
0b4e3aa0 1828__private_extern__ void
1c79356b
A
1829memory_manager_default_init(void)
1830{
0b4e3aa0 1831 memory_manager_default = MEMORY_OBJECT_DEFAULT_NULL;
b0d623f7 1832 lck_mtx_init(&memory_manager_default_lock, &vm_object_lck_grp, &vm_object_lck_attr);
1c79356b
A
1833}
1834
1835
1c79356b
A
1836
1837/* Allow manipulation of individual page state. This is actually part of */
1838/* the UPL regimen but takes place on the object rather than on a UPL */
1839
1840kern_return_t
1841memory_object_page_op(
0b4e3aa0
A
1842 memory_object_control_t control,
1843 memory_object_offset_t offset,
1844 int ops,
55e303ae 1845 ppnum_t *phys_entry,
0b4e3aa0 1846 int *flags)
1c79356b 1847{
0b4e3aa0 1848 vm_object_t object;
0b4e3aa0
A
1849
1850 object = memory_object_control_to_vm_object(control);
1851 if (object == VM_OBJECT_NULL)
1852 return (KERN_INVALID_ARGUMENT);
1c79356b 1853
0c530ab8 1854 return vm_object_page_op(object, offset, ops, phys_entry, flags);
1c79356b
A
1855}
1856
55e303ae
A
1857/*
1858 * memory_object_range_op offers performance enhancement over
1859 * memory_object_page_op for page_op functions which do not require page
1860 * level state to be returned from the call. Page_op was created to provide
1861 * a low-cost alternative to page manipulation via UPLs when only a single
1862 * page was involved. The range_op call establishes the ability in the _op
1863 * family of functions to work on multiple pages where the lack of page level
1864 * state handling allows the caller to avoid the overhead of the upl structures.
1865 */
1866
1867kern_return_t
1868memory_object_range_op(
1869 memory_object_control_t control,
1870 memory_object_offset_t offset_beg,
1871 memory_object_offset_t offset_end,
1872 int ops,
1873 int *range)
1874{
55e303ae 1875 vm_object_t object;
55e303ae
A
1876
1877 object = memory_object_control_to_vm_object(control);
1878 if (object == VM_OBJECT_NULL)
1879 return (KERN_INVALID_ARGUMENT);
1880
0c530ab8
A
1881 return vm_object_range_op(object,
1882 offset_beg,
1883 offset_end,
1884 ops,
b0d623f7 1885 (uint32_t *) range);
55e303ae
A
1886}
1887
91447636 1888
6d2010ae
A
1889void
1890memory_object_mark_used(
1891 memory_object_control_t control)
1892{
1893 vm_object_t object;
1894
1895 if (control == NULL)
1896 return;
1897
1898 object = memory_object_control_to_vm_object(control);
1899
1900 if (object != VM_OBJECT_NULL)
1901 vm_object_cache_remove(object);
1902}
1903
1904
1905void
1906memory_object_mark_unused(
1907 memory_object_control_t control,
1908 __unused boolean_t rage)
1909{
1910 vm_object_t object;
1911
1912 if (control == NULL)
1913 return;
1914
1915 object = memory_object_control_to_vm_object(control);
1916
1917 if (object != VM_OBJECT_NULL)
1918 vm_object_cache_add(object);
1919}
1920
fe8ab488
A
1921void
1922memory_object_mark_io_tracking(
1923 memory_object_control_t control)
1924{
1925 vm_object_t object;
1926
1927 if (control == NULL)
1928 return;
1929 object = memory_object_control_to_vm_object(control);
1930
1931 if (object != VM_OBJECT_NULL) {
1932 vm_object_lock(object);
1933 object->io_tracking = TRUE;
1934 vm_object_unlock(object);
1935 }
1936}
6d2010ae 1937
91447636
A
1938kern_return_t
1939memory_object_pages_resident(
1940 memory_object_control_t control,
1941 boolean_t * has_pages_resident)
1942{
1943 vm_object_t object;
1944
1945 *has_pages_resident = FALSE;
1946
1947 object = memory_object_control_to_vm_object(control);
1948 if (object == VM_OBJECT_NULL)
1949 return (KERN_INVALID_ARGUMENT);
1950
1951 if (object->resident_page_count)
1952 *has_pages_resident = TRUE;
1953
1954 return (KERN_SUCCESS);
1955}
1956
2d21ac55
A
1957kern_return_t
1958memory_object_signed(
1959 memory_object_control_t control,
1960 boolean_t is_signed)
1961{
1962 vm_object_t object;
1963
1964 object = memory_object_control_to_vm_object(control);
1965 if (object == VM_OBJECT_NULL)
1966 return KERN_INVALID_ARGUMENT;
1967
1968 vm_object_lock(object);
1969 object->code_signed = is_signed;
1970 vm_object_unlock(object);
1971
1972 return KERN_SUCCESS;
1973}
91447636 1974
39236c6e
A
1975boolean_t
1976memory_object_is_signed(
1977 memory_object_control_t control)
1978{
1979 boolean_t is_signed;
1980 vm_object_t object;
1981
1982 object = memory_object_control_to_vm_object(control);
1983 if (object == VM_OBJECT_NULL)
1984 return FALSE;
1985
1986 vm_object_lock_shared(object);
1987 is_signed = object->code_signed;
1988 vm_object_unlock(object);
1989
1990 return is_signed;
1991}
1992
6d2010ae
A
1993boolean_t
1994memory_object_is_slid(
1995 memory_object_control_t control)
1996{
1997 vm_object_t object = VM_OBJECT_NULL;
6d2010ae
A
1998
1999 object = memory_object_control_to_vm_object(control);
2000 if (object == VM_OBJECT_NULL)
2001 return FALSE;
2002
39236c6e 2003 return object->object_slid;
6d2010ae
A
2004}
2005
0b4e3aa0
A
2006static zone_t mem_obj_control_zone;
2007
2008__private_extern__ void
2009memory_object_control_bootstrap(void)
2010{
2011 int i;
2012
2013 i = (vm_size_t) sizeof (struct memory_object_control);
2014 mem_obj_control_zone = zinit (i, 8192*i, 4096, "mem_obj_control");
6d2010ae 2015 zone_change(mem_obj_control_zone, Z_CALLERACCT, FALSE);
0b4c1975 2016 zone_change(mem_obj_control_zone, Z_NOENCRYPT, TRUE);
0b4e3aa0
A
2017 return;
2018}
2019
2020__private_extern__ memory_object_control_t
2021memory_object_control_allocate(
2022 vm_object_t object)
2023{
2024 memory_object_control_t control;
2025
2026 control = (memory_object_control_t)zalloc(mem_obj_control_zone);
0c530ab8
A
2027 if (control != MEMORY_OBJECT_CONTROL_NULL) {
2028 control->moc_object = object;
2029 control->moc_ikot = IKOT_MEM_OBJ_CONTROL; /* fake ip_kotype */
2030 }
0b4e3aa0
A
2031 return (control);
2032}
2033
2034__private_extern__ void
2035memory_object_control_collapse(
2036 memory_object_control_t control,
2037 vm_object_t object)
2038{
0c530ab8
A
2039 assert((control->moc_object != VM_OBJECT_NULL) &&
2040 (control->moc_object != object));
2041 control->moc_object = object;
0b4e3aa0
A
2042}
2043
2044__private_extern__ vm_object_t
2045memory_object_control_to_vm_object(
2046 memory_object_control_t control)
2047{
0c530ab8
A
2048 if (control == MEMORY_OBJECT_CONTROL_NULL ||
2049 control->moc_ikot != IKOT_MEM_OBJ_CONTROL)
0b4e3aa0
A
2050 return VM_OBJECT_NULL;
2051
0c530ab8 2052 return (control->moc_object);
0b4e3aa0
A
2053}
2054
2055memory_object_control_t
2056convert_port_to_mo_control(
91447636 2057 __unused mach_port_t port)
0b4e3aa0
A
2058{
2059 return MEMORY_OBJECT_CONTROL_NULL;
2060}
2061
2062
2063mach_port_t
2064convert_mo_control_to_port(
91447636 2065 __unused memory_object_control_t control)
0b4e3aa0
A
2066{
2067 return MACH_PORT_NULL;
2068}
2069
2070void
2071memory_object_control_reference(
91447636 2072 __unused memory_object_control_t control)
0b4e3aa0
A
2073{
2074 return;
2075}
2076
2077/*
2078 * We only every issue one of these references, so kill it
2079 * when that gets released (should switch the real reference
2080 * counting in true port-less EMMI).
2081 */
2082void
2083memory_object_control_deallocate(
2084 memory_object_control_t control)
2085{
91447636 2086 zfree(mem_obj_control_zone, control);
0b4e3aa0
A
2087}
2088
2089void
2090memory_object_control_disable(
2091 memory_object_control_t control)
2092{
0c530ab8
A
2093 assert(control->moc_object != VM_OBJECT_NULL);
2094 control->moc_object = VM_OBJECT_NULL;
0b4e3aa0
A
2095}
2096
2097void
2098memory_object_default_reference(
2099 memory_object_default_t dmm)
2100{
2101 ipc_port_make_send(dmm);
2102}
2103
2104void
2105memory_object_default_deallocate(
2106 memory_object_default_t dmm)
2107{
2108 ipc_port_release_send(dmm);
2109}
2110
2111memory_object_t
2112convert_port_to_memory_object(
91447636 2113 __unused mach_port_t port)
0b4e3aa0
A
2114{
2115 return (MEMORY_OBJECT_NULL);
2116}
2117
2118
2119mach_port_t
2120convert_memory_object_to_port(
91447636 2121 __unused memory_object_t object)
0b4e3aa0
A
2122{
2123 return (MACH_PORT_NULL);
2124}
2125
0b4e3aa0
A
2126
2127/* Routine memory_object_reference */
2128void memory_object_reference(
2129 memory_object_t memory_object)
2130{
0c530ab8
A
2131 (memory_object->mo_pager_ops->memory_object_reference)(
2132 memory_object);
0b4e3aa0
A
2133}
2134
2135/* Routine memory_object_deallocate */
2136void memory_object_deallocate(
2137 memory_object_t memory_object)
2138{
0c530ab8
A
2139 (memory_object->mo_pager_ops->memory_object_deallocate)(
2140 memory_object);
0b4e3aa0
A
2141}
2142
2143
2144/* Routine memory_object_init */
2145kern_return_t memory_object_init
2146(
2147 memory_object_t memory_object,
2148 memory_object_control_t memory_control,
91447636 2149 memory_object_cluster_size_t memory_object_page_size
0b4e3aa0
A
2150)
2151{
0c530ab8
A
2152 return (memory_object->mo_pager_ops->memory_object_init)(
2153 memory_object,
2154 memory_control,
2155 memory_object_page_size);
0b4e3aa0
A
2156}
2157
2158/* Routine memory_object_terminate */
2159kern_return_t memory_object_terminate
2160(
2161 memory_object_t memory_object
2162)
2163{
0c530ab8
A
2164 return (memory_object->mo_pager_ops->memory_object_terminate)(
2165 memory_object);
0b4e3aa0
A
2166}
2167
2168/* Routine memory_object_data_request */
2169kern_return_t memory_object_data_request
2170(
2171 memory_object_t memory_object,
2172 memory_object_offset_t offset,
91447636 2173 memory_object_cluster_size_t length,
2d21ac55
A
2174 vm_prot_t desired_access,
2175 memory_object_fault_info_t fault_info
0b4e3aa0
A
2176)
2177{
0c530ab8
A
2178 return (memory_object->mo_pager_ops->memory_object_data_request)(
2179 memory_object,
2180 offset,
2181 length,
2d21ac55
A
2182 desired_access,
2183 fault_info);
0b4e3aa0
A
2184}
2185
2186/* Routine memory_object_data_return */
2187kern_return_t memory_object_data_return
2188(
2189 memory_object_t memory_object,
2190 memory_object_offset_t offset,
b0d623f7 2191 memory_object_cluster_size_t size,
91447636
A
2192 memory_object_offset_t *resid_offset,
2193 int *io_error,
0b4e3aa0 2194 boolean_t dirty,
91447636
A
2195 boolean_t kernel_copy,
2196 int upl_flags
0b4e3aa0
A
2197)
2198{
0c530ab8
A
2199 return (memory_object->mo_pager_ops->memory_object_data_return)(
2200 memory_object,
2201 offset,
2202 size,
2203 resid_offset,
2204 io_error,
2205 dirty,
2206 kernel_copy,
2207 upl_flags);
0b4e3aa0
A
2208}
2209
2210/* Routine memory_object_data_initialize */
2211kern_return_t memory_object_data_initialize
2212(
2213 memory_object_t memory_object,
2214 memory_object_offset_t offset,
b0d623f7 2215 memory_object_cluster_size_t size
0b4e3aa0
A
2216)
2217{
0c530ab8
A
2218 return (memory_object->mo_pager_ops->memory_object_data_initialize)(
2219 memory_object,
2220 offset,
2221 size);
0b4e3aa0
A
2222}
2223
2224/* Routine memory_object_data_unlock */
2225kern_return_t memory_object_data_unlock
2226(
2227 memory_object_t memory_object,
2228 memory_object_offset_t offset,
b0d623f7 2229 memory_object_size_t size,
0b4e3aa0
A
2230 vm_prot_t desired_access
2231)
2232{
0c530ab8
A
2233 return (memory_object->mo_pager_ops->memory_object_data_unlock)(
2234 memory_object,
2235 offset,
2236 size,
2237 desired_access);
0b4e3aa0
A
2238}
2239
2240/* Routine memory_object_synchronize */
2241kern_return_t memory_object_synchronize
2242(
2243 memory_object_t memory_object,
2244 memory_object_offset_t offset,
b0d623f7 2245 memory_object_size_t size,
0b4e3aa0
A
2246 vm_sync_t sync_flags
2247)
2248{
0c530ab8
A
2249 return (memory_object->mo_pager_ops->memory_object_synchronize)(
2250 memory_object,
2251 offset,
2252 size,
2253 sync_flags);
0b4e3aa0
A
2254}
2255
593a1d5f
A
2256
2257/*
2258 * memory_object_map() is called by VM (in vm_map_enter() and its variants)
2259 * each time a "named" VM object gets mapped directly or indirectly
2260 * (copy-on-write mapping). A "named" VM object has an extra reference held
2261 * by the pager to keep it alive until the pager decides that the
2262 * memory object (and its VM object) can be reclaimed.
2263 * VM calls memory_object_last_unmap() (in vm_object_deallocate()) when all
2264 * the mappings of that memory object have been removed.
2265 *
2266 * For a given VM object, calls to memory_object_map() and memory_object_unmap()
2267 * are serialized (through object->mapping_in_progress), to ensure that the
2268 * pager gets a consistent view of the mapping status of the memory object.
2269 *
2270 * This allows the pager to keep track of how many times a memory object
2271 * has been mapped and with which protections, to decide when it can be
2272 * reclaimed.
2273 */
2274
2275/* Routine memory_object_map */
2276kern_return_t memory_object_map
2277(
2278 memory_object_t memory_object,
2279 vm_prot_t prot
2280)
2281{
2282 return (memory_object->mo_pager_ops->memory_object_map)(
2283 memory_object,
2284 prot);
2285}
2286
2287/* Routine memory_object_last_unmap */
2288kern_return_t memory_object_last_unmap
0b4e3aa0
A
2289(
2290 memory_object_t memory_object
2291)
2292{
593a1d5f 2293 return (memory_object->mo_pager_ops->memory_object_last_unmap)(
0c530ab8 2294 memory_object);
0b4e3aa0
A
2295}
2296
6d2010ae
A
2297/* Routine memory_object_data_reclaim */
2298kern_return_t memory_object_data_reclaim
2299(
2300 memory_object_t memory_object,
2301 boolean_t reclaim_backing_store
2302)
2303{
2304 if (memory_object->mo_pager_ops->memory_object_data_reclaim == NULL)
2305 return KERN_NOT_SUPPORTED;
2306 return (memory_object->mo_pager_ops->memory_object_data_reclaim)(
2307 memory_object,
2308 reclaim_backing_store);
2309}
2310
0b4e3aa0
A
2311/* Routine memory_object_create */
2312kern_return_t memory_object_create
2313(
2314 memory_object_default_t default_memory_manager,
2315 vm_size_t new_memory_object_size,
2316 memory_object_t *new_memory_object
2317)
2318{
0b4e3aa0
A
2319 return default_pager_memory_object_create(default_memory_manager,
2320 new_memory_object_size,
2321 new_memory_object);
2322}
1c79356b 2323
91447636
A
2324upl_t
2325convert_port_to_upl(
2326 ipc_port_t port)
2327{
2328 upl_t upl;
2329
2330 ip_lock(port);
2331 if (!ip_active(port) || (ip_kotype(port) != IKOT_UPL)) {
2332 ip_unlock(port);
2333 return (upl_t)NULL;
2334 }
2335 upl = (upl_t) port->ip_kobject;
2336 ip_unlock(port);
2337 upl_lock(upl);
2338 upl->ref_count+=1;
2339 upl_unlock(upl);
2340 return upl;
2341}
2342
2343mach_port_t
2344convert_upl_to_port(
2345 __unused upl_t upl)
2346{
2347 return MACH_PORT_NULL;
2348}
2349
2350__private_extern__ void
2351upl_no_senders(
2352 __unused ipc_port_t port,
2353 __unused mach_port_mscount_t mscount)
2354{
2355 return;
2356}