1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59#include <advisory_pageout.h>
60
61
62
63
64
65#include <mach/std_types.h>
66#include <mach/mach_types.h>
67
68#include <mach/mig.h>
69#include <mach/kern_return.h>
70#include <mach/memory_object.h>
71#include <mach/memory_object_default.h>
72#include <mach/memory_object_control_server.h>
73#include <mach/host_priv_server.h>
74#include <mach/boolean.h>
75#include <mach/vm_prot.h>
76#include <mach/message.h>
77
78
79
80
81#include <string.h>
82
83#include <kern/xpr.h>
84#include <kern/host.h>
85#include <kern/thread.h>
86#include <kern/ipc_mig.h>
87#include <kern/misc_protos.h>
88
89#include <vm/vm_object.h>
90#include <vm/vm_fault.h>
91#include <vm/memory_object.h>
92#include <vm/vm_page.h>
93#include <vm/vm_pageout.h>
94#include <vm/pmap.h>
95#include <vm/vm_kern.h>
96#include <vm/vm_map.h>
97
98#if MACH_PAGEMAP
99#include <vm/vm_external.h>
100#endif
101
102#include <vm/vm_protos.h>
103
104
105memory_object_default_t memory_manager_default = MEMORY_OBJECT_DEFAULT_NULL;
106vm_size_t memory_manager_default_cluster = 0;
107decl_mutex_data(, memory_manager_default_lock)
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128#define memory_object_should_return_page(m, should_return) \
129 (should_return != MEMORY_OBJECT_RETURN_NONE && \
130 (((m)->dirty || ((m)->dirty = pmap_is_modified((m)->phys_page))) || \
131 ((m)->precious && (should_return) == MEMORY_OBJECT_RETURN_ALL) || \
132 (should_return) == MEMORY_OBJECT_RETURN_ANYTHING))
133
134typedef int memory_object_lock_result_t;
135
136#define MEMORY_OBJECT_LOCK_RESULT_DONE 0
137#define MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK 1
138#define MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN 2
139#define MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN 3
140
141memory_object_lock_result_t memory_object_lock_page(
142 vm_page_t m,
143 memory_object_return_t should_return,
144 boolean_t should_flush,
145 vm_prot_t prot);
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160memory_object_lock_result_t
161memory_object_lock_page(
162 vm_page_t m,
163 memory_object_return_t should_return,
164 boolean_t should_flush,
165 vm_prot_t prot)
166{
167 XPR(XPR_MEMORY_OBJECT,
168 "m_o_lock_page, page 0x%X rtn %d flush %d prot %d\n",
169 (integer_t)m, should_return, should_flush, prot, 0);
170
171
172
173
174
175
176
177
178 if (m->busy || m->cleaning)
179 return(MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK);
180
181
182
183
184
185
186 if (m->absent || m->error || m->restart) {
187 if(m->error && should_flush) {
188
189
190
191 if(m->wire_count == 0) {
192 VM_PAGE_FREE(m);
193 return(MEMORY_OBJECT_LOCK_RESULT_DONE);
194 }
195 } else {
196 return(MEMORY_OBJECT_LOCK_RESULT_DONE);
197 }
198 }
199
200 assert(!m->fictitious);
201
202 if (m->wire_count != 0) {
203
204
205
206
207
208
209
210
211
212
213
214
215
216 if (!should_flush &&
217 (m->page_lock == prot || prot == VM_PROT_NO_CHANGE) &&
218 ! memory_object_should_return_page(m, should_return)) {
219
220
221
222
223
224
225
226 m->unlock_request = VM_PROT_NONE;
227 PAGE_WAKEUP(m);
228
229 return(MEMORY_OBJECT_LOCK_RESULT_DONE);
230 }
231
232 return(MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK);
233 }
234
235
236
237
238
239
240 if (should_flush)
241 prot = VM_PROT_ALL;
242
243
244
245
246
247
248
249
250
251 if (prot != VM_PROT_NO_CHANGE) {
252 if ((m->page_lock ^ prot) & prot) {
253 pmap_page_protect(m->phys_page, VM_PROT_ALL & ~prot);
254 }
255#if 0
256
257
258
259 m->page_lock = prot;
260 m->lock_supplied = TRUE;
261 if (prot != VM_PROT_NONE)
262 m->unusual = TRUE;
263 else
264 m->unusual = FALSE;
265
266
267
268
269
270
271
272
273 m->unlock_request = VM_PROT_NONE;
274#endif
275 PAGE_WAKEUP(m);
276 }
277
278
279
280
281
282 if (memory_object_should_return_page(m, should_return)) {
283
284
285
286
287
288
289
290
291
292
293 vm_page_lock_queues();
294 VM_PAGE_QUEUES_REMOVE(m);
295 vm_page_unlock_queues();
296
297 if (!should_flush)
298 pmap_disconnect(m->phys_page);
299
300 if (m->dirty)
301 return(MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN);
302 else
303 return(MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN);
304 }
305
306
307
308
309
310 if (should_flush) {
311 VM_PAGE_FREE(m);
312 } else {
313
314
315
316
317
318
319
320
321 if (vm_page_deactivate_hint &&
322 (should_return != MEMORY_OBJECT_RETURN_NONE)) {
323 vm_page_lock_queues();
324 vm_page_deactivate(m);
325 vm_page_unlock_queues();
326 }
327 }
328
329 return(MEMORY_OBJECT_LOCK_RESULT_DONE);
330}
331
332#define LIST_REQ_PAGEOUT_PAGES(object, data_cnt, action, po, ro, ioerr, iosync) \
333MACRO_BEGIN \
334 \
335 register int upl_flags; \
336 \
337 vm_object_unlock(object); \
338 \
339 if (iosync) \
340 upl_flags = UPL_MSYNC | UPL_IOSYNC; \
341 else \
342 upl_flags = UPL_MSYNC; \
343 \
344 (void) memory_object_data_return(object->pager, \
345 po, \
346 data_cnt, \
347 ro, \
348 ioerr, \
349 (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN), \
350 !should_flush, \
351 upl_flags); \
352 \
353 vm_object_lock(object); \
354MACRO_END
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381kern_return_t
382memory_object_lock_request(
383 memory_object_control_t control,
384 memory_object_offset_t offset,
385 memory_object_size_t size,
386 memory_object_offset_t * resid_offset,
387 int * io_errno,
388 memory_object_return_t should_return,
389 int flags,
390 vm_prot_t prot)
391{
392 vm_object_t object;
393 __unused boolean_t should_flush;
394
395 should_flush = flags & MEMORY_OBJECT_DATA_FLUSH;
396
397 XPR(XPR_MEMORY_OBJECT,
398 "m_o_lock_request, control 0x%X off 0x%X size 0x%X flags %X prot %X\n",
399 (integer_t)control, offset, size,
400 (((should_return&1)<<1)|should_flush), prot);
401
402
403
404
405 object = memory_object_control_to_vm_object(control);
406 if (object == VM_OBJECT_NULL)
407 return (KERN_INVALID_ARGUMENT);
408
409 if ((prot & ~VM_PROT_ALL) != 0 && prot != VM_PROT_NO_CHANGE)
410 return (KERN_INVALID_ARGUMENT);
411
412 size = round_page_64(size);
413
414
415
416
417
418 vm_object_lock(object);
419 vm_object_paging_begin(object);
420 offset -= object->paging_offset;
421
422 (void)vm_object_update(object,
423 offset, size, resid_offset, io_errno, should_return, flags, prot);
424
425 vm_object_paging_end(object);
426 vm_object_unlock(object);
427
428 return (KERN_SUCCESS);
429}
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448kern_return_t
449memory_object_release_name(
450 memory_object_control_t control,
451 int flags)
452{
453 vm_object_t object;
454
455 object = memory_object_control_to_vm_object(control);
456 if (object == VM_OBJECT_NULL)
457 return (KERN_INVALID_ARGUMENT);
458
459 return vm_object_release_name(object, flags);
460}
461
462
463
464
465
466
467
468
469
470
471kern_return_t
472memory_object_destroy(
473 memory_object_control_t control,
474 kern_return_t reason)
475{
476 vm_object_t object;
477
478 object = memory_object_control_to_vm_object(control);
479 if (object == VM_OBJECT_NULL)
480 return (KERN_INVALID_ARGUMENT);
481
482 return (vm_object_destroy(object, reason));
483}
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509boolean_t
510vm_object_sync(
511 vm_object_t object,
512 vm_object_offset_t offset,
513 vm_object_size_t size,
514 boolean_t should_flush,
515 boolean_t should_return,
516 boolean_t should_iosync)
517{
518 boolean_t rv;
519 int flags;
520
521 XPR(XPR_VM_OBJECT,
522 "vm_o_sync, object 0x%X, offset 0x%X size 0x%x flush %d rtn %d\n",
523 (integer_t)object, offset, size, should_flush, should_return);
524
525
526
527
528
529
530 vm_object_lock(object);
531 vm_object_paging_begin(object);
532
533 if (should_flush)
534 flags = MEMORY_OBJECT_DATA_FLUSH;
535 else
536 flags = 0;
537
538 if (should_iosync)
539 flags |= MEMORY_OBJECT_IO_SYNC;
540
541 rv = vm_object_update(object, offset, (vm_object_size_t)size, NULL, NULL,
542 (should_return) ?
543 MEMORY_OBJECT_RETURN_ALL :
544 MEMORY_OBJECT_RETURN_NONE,
545 flags,
546 VM_PROT_NO_CHANGE);
547
548
549 vm_object_paging_end(object);
550 vm_object_unlock(object);
551 return rv;
552}
553
554
555
556
557static int
558vm_object_update_extent(
559 vm_object_t object,
560 vm_object_offset_t offset,
561 vm_object_offset_t offset_end,
562 vm_object_offset_t *offset_resid,
563 int *io_errno,
564 boolean_t should_flush,
565 memory_object_return_t should_return,
566 boolean_t should_iosync,
567 vm_prot_t prot)
568{
569 vm_page_t m;
570 int retval = 0;
571 vm_size_t data_cnt = 0;
572 vm_object_offset_t paging_offset = 0;
573 vm_object_offset_t last_offset = offset;
574 memory_object_lock_result_t page_lock_result;
575 memory_object_lock_result_t pageout_action;
576
577 pageout_action = MEMORY_OBJECT_LOCK_RESULT_DONE;
578
579 for (;
580 offset < offset_end && object->resident_page_count;
581 offset += PAGE_SIZE_64) {
582
583
584
585
586 if (data_cnt >= PAGE_SIZE * MAX_UPL_TRANSFER) {
587 LIST_REQ_PAGEOUT_PAGES(object, data_cnt,
588 pageout_action, paging_offset, offset_resid, io_errno, should_iosync);
589 data_cnt = 0;
590 }
591
592 while ((m = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
593 page_lock_result = memory_object_lock_page(m, should_return, should_flush, prot);
594
595 XPR(XPR_MEMORY_OBJECT,
596 "m_o_update: lock_page, obj 0x%X offset 0x%X result %d\n",
597 (integer_t)object, offset, page_lock_result, 0, 0);
598
599 switch (page_lock_result)
600 {
601 case MEMORY_OBJECT_LOCK_RESULT_DONE:
602
603
604
605 if (data_cnt) {
606 LIST_REQ_PAGEOUT_PAGES(object,
607 data_cnt, pageout_action,
608 paging_offset, offset_resid, io_errno, should_iosync);
609 data_cnt = 0;
610 continue;
611 }
612 break;
613
614 case MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK:
615
616
617
618
619 if (data_cnt) {
620 LIST_REQ_PAGEOUT_PAGES(object,
621 data_cnt, pageout_action,
622 paging_offset, offset_resid, io_errno, should_iosync);
623 data_cnt = 0;
624 continue;
625 }
626 PAGE_SLEEP(object, m, THREAD_UNINT);
627 continue;
628
629 case MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN:
630 case MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN:
631
632
633
634
635
636
637
638
639
640 m->busy = TRUE;
641 if (data_cnt &&
642 ((last_offset != offset) || (pageout_action != page_lock_result))) {
643 LIST_REQ_PAGEOUT_PAGES(object,
644 data_cnt, pageout_action,
645 paging_offset, offset_resid, io_errno, should_iosync);
646 data_cnt = 0;
647 }
648 m->busy = FALSE;
649
650 if (m->cleaning) {
651 PAGE_SLEEP(object, m, THREAD_UNINT);
652 continue;
653 }
654 if (data_cnt == 0) {
655 pageout_action = page_lock_result;
656 paging_offset = offset;
657 }
658 data_cnt += PAGE_SIZE;
659 last_offset = offset + PAGE_SIZE_64;
660
661 vm_page_lock_queues();
662
663
664
665 m->list_req_pending = TRUE;
666 m->cleaning = TRUE;
667
668 if (should_flush) {
669
670
671
672
673 m->busy = TRUE;
674 m->pageout = TRUE;
675 vm_page_wire(m);
676 }
677 vm_page_unlock_queues();
678
679 retval = 1;
680 break;
681 }
682 break;
683 }
684 }
685
686
687
688
689 if (data_cnt) {
690 LIST_REQ_PAGEOUT_PAGES(object,
691 data_cnt, pageout_action, paging_offset, offset_resid, io_errno, should_iosync);
692 }
693 return (retval);
694}
695
696
697
698
699
700
701
702
703
704
705kern_return_t
706vm_object_update(
707 register vm_object_t object,
708 register vm_object_offset_t offset,
709 register vm_object_size_t size,
710 register vm_object_offset_t *resid_offset,
711 int *io_errno,
712 memory_object_return_t should_return,
713 int flags,
714 vm_prot_t protection)
715{
716 vm_object_t copy_object;
717 boolean_t data_returned = FALSE;
718 boolean_t update_cow;
719 boolean_t should_flush = (flags & MEMORY_OBJECT_DATA_FLUSH) ? TRUE : FALSE;
720 boolean_t should_iosync = (flags & MEMORY_OBJECT_IO_SYNC) ? TRUE : FALSE;
721 int num_of_extents;
722 int n;
723#define MAX_EXTENTS 8
724#define EXTENT_SIZE (1024 * 1024 * 256)
725#define RESIDENT_LIMIT (1024 * 32)
726 struct extent {
727 vm_object_offset_t e_base;
728 vm_object_offset_t e_min;
729 vm_object_offset_t e_max;
730 } extents[MAX_EXTENTS];
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749 update_cow = ((flags & MEMORY_OBJECT_DATA_FLUSH)
750 && (!(flags & MEMORY_OBJECT_DATA_NO_CHANGE) &&
751 !(flags & MEMORY_OBJECT_DATA_PURGE)))
752 || (flags & MEMORY_OBJECT_COPY_SYNC);
753
754
755 if((((copy_object = object->copy) != NULL) && update_cow) ||
756 (flags & MEMORY_OBJECT_DATA_SYNC)) {
757 vm_map_size_t i;
758 vm_map_size_t copy_size;
759 vm_map_offset_t copy_offset;
760 vm_prot_t prot;
761 vm_page_t page;
762 vm_page_t top_page;
763 kern_return_t error = 0;
764
765 if(copy_object != NULL) {
766
767 copy_offset = (offset >= copy_object->shadow_offset)?
768 (vm_map_offset_t)(offset - copy_object->shadow_offset) :
769 (vm_map_offset_t) 0;
770 if(copy_offset > copy_object->size)
771 copy_offset = copy_object->size;
772
773
774 if (offset >= copy_object->shadow_offset) {
775 copy_size = size;
776 } else if (size >= copy_object->shadow_offset - offset) {
777 copy_size = size -
778 (copy_object->shadow_offset - offset);
779 } else {
780 copy_size = 0;
781 }
782
783 if (copy_offset + copy_size > copy_object->size) {
784 if (copy_object->size >= copy_offset) {
785 copy_size = copy_object->size - copy_offset;
786 } else {
787 copy_size = 0;
788 }
789 }
790
791 copy_size+=copy_offset;
792
793 vm_object_unlock(object);
794 vm_object_lock(copy_object);
795 } else {
796 copy_object = object;
797
798 copy_size = offset + size;
799 copy_offset = offset;
800 }
801
802 vm_object_paging_begin(copy_object);
803 for (i=copy_offset; i<copy_size; i+=PAGE_SIZE) {
804 RETRY_COW_OF_LOCK_REQUEST:
805 prot = VM_PROT_WRITE|VM_PROT_READ;
806 switch (vm_fault_page(copy_object, i,
807 VM_PROT_WRITE|VM_PROT_READ,
808 FALSE,
809 THREAD_UNINT,
810 copy_offset,
811 copy_offset+copy_size,
812 VM_BEHAVIOR_SEQUENTIAL,
813 &prot,
814 &page,
815 &top_page,
816 (int *)0,
817 &error,
818 FALSE,
819 FALSE, NULL, 0)) {
820
821 case VM_FAULT_SUCCESS:
822 if(top_page) {
823 vm_fault_cleanup(
824 page->object, top_page);
825 PAGE_WAKEUP_DONE(page);
826 vm_page_lock_queues();
827 if (!page->active && !page->inactive)
828 vm_page_activate(page);
829 vm_page_unlock_queues();
830 vm_object_lock(copy_object);
831 vm_object_paging_begin(copy_object);
832 } else {
833 PAGE_WAKEUP_DONE(page);
834 vm_page_lock_queues();
835 if (!page->active && !page->inactive)
836 vm_page_activate(page);
837 vm_page_unlock_queues();
838 }
839 break;
840 case VM_FAULT_RETRY:
841 prot = VM_PROT_WRITE|VM_PROT_READ;
842 vm_object_lock(copy_object);
843 vm_object_paging_begin(copy_object);
844 goto RETRY_COW_OF_LOCK_REQUEST;
845 case VM_FAULT_INTERRUPTED:
846 prot = VM_PROT_WRITE|VM_PROT_READ;
847 vm_object_lock(copy_object);
848 vm_object_paging_begin(copy_object);
849 goto RETRY_COW_OF_LOCK_REQUEST;
850 case VM_FAULT_MEMORY_SHORTAGE:
851 VM_PAGE_WAIT();
852 prot = VM_PROT_WRITE|VM_PROT_READ;
853 vm_object_lock(copy_object);
854 vm_object_paging_begin(copy_object);
855 goto RETRY_COW_OF_LOCK_REQUEST;
856 case VM_FAULT_FICTITIOUS_SHORTAGE:
857 vm_page_more_fictitious();
858 prot = VM_PROT_WRITE|VM_PROT_READ;
859 vm_object_lock(copy_object);
860 vm_object_paging_begin(copy_object);
861 goto RETRY_COW_OF_LOCK_REQUEST;
862 case VM_FAULT_MEMORY_ERROR:
863 vm_object_lock(object);
864 goto BYPASS_COW_COPYIN;
865 }
866
867 }
868 vm_object_paging_end(copy_object);
869 if(copy_object != object) {
870 vm_object_unlock(copy_object);
871 vm_object_lock(object);
872 }
873 }
874 if((flags & (MEMORY_OBJECT_DATA_SYNC | MEMORY_OBJECT_COPY_SYNC))) {
875 return KERN_SUCCESS;
876 }
877 if(((copy_object = object->copy) != NULL) &&
878 (flags & MEMORY_OBJECT_DATA_PURGE)) {
879 copy_object->shadow_severed = TRUE;
880 copy_object->shadowed = FALSE;
881 copy_object->shadow = NULL;
882
883 vm_object_deallocate(object);
884 }
885BYPASS_COW_COPYIN:
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911 if ((object->resident_page_count < RESIDENT_LIMIT) &&
912 (atop_64(size) > (unsigned)(object->resident_page_count/(8 * MAX_EXTENTS)))) {
913 vm_page_t next;
914 vm_object_offset_t start;
915 vm_object_offset_t end;
916 vm_object_size_t e_mask;
917 vm_page_t m;
918
919 start = offset;
920 end = offset + size;
921 num_of_extents = 0;
922 e_mask = ~((vm_object_size_t)(EXTENT_SIZE - 1));
923
924 m = (vm_page_t) queue_first(&object->memq);
925
926 while (!queue_end(&object->memq, (queue_entry_t) m)) {
927 next = (vm_page_t) queue_next(&m->listq);
928
929 if ((m->offset >= start) && (m->offset < end)) {
930
931
932
933
934 for (n = 0; n < num_of_extents; n++) {
935 if ((m->offset & e_mask) == extents[n].e_base) {
936
937
938
939
940
941 if (m->offset < extents[n].e_min)
942 extents[n].e_min = m->offset;
943 else if ((m->offset + (PAGE_SIZE - 1)) > extents[n].e_max)
944 extents[n].e_max = m->offset + (PAGE_SIZE - 1);
945 break;
946 }
947 }
948 if (n == num_of_extents) {
949
950
951
952
953 if (n < MAX_EXTENTS) {
954
955
956
957
958 extents[n].e_base = m->offset & e_mask;
959 extents[n].e_min = m->offset;
960 extents[n].e_max = m->offset + (PAGE_SIZE - 1);
961
962 num_of_extents++;
963 } else {
964
965
966
967
968
969
970
971
972
973 for (n = 1; n < num_of_extents; n++) {
974 if (extents[n].e_min < extents[0].e_min)
975 extents[0].e_min = extents[n].e_min;
976 if (extents[n].e_max > extents[0].e_max)
977 extents[0].e_max = extents[n].e_max;
978 }
979
980
981
982
983
984 extents[0].e_base = 0;
985 e_mask = 0;
986 num_of_extents = 1;
987
988
989
990
991
992
993 continue;
994 }
995 }
996 }
997 m = next;
998 }
999 } else {
1000 extents[0].e_min = offset;
1001 extents[0].e_max = offset + (size - 1);
1002
1003 num_of_extents = 1;
1004 }
1005 for (n = 0; n < num_of_extents; n++) {
1006 if (vm_object_update_extent(object, extents[n].e_min, extents[n].e_max, resid_offset, io_errno,
1007 should_flush, should_return, should_iosync, protection))
1008 data_returned = TRUE;
1009 }
1010 return (data_returned);
1011}
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025kern_return_t
1026memory_object_synchronize_completed(
1027 memory_object_control_t control,
1028 memory_object_offset_t offset,
1029 vm_offset_t length)
1030{
1031 vm_object_t object;
1032 msync_req_t msr;
1033
1034 object = memory_object_control_to_vm_object(control);
1035
1036 XPR(XPR_MEMORY_OBJECT,
1037 "m_o_sync_completed, object 0x%X, offset 0x%X length 0x%X\n",
1038 (integer_t)object, offset, length, 0, 0);
1039
1040
1041
1042
1043
1044 if (object == VM_OBJECT_NULL)
1045 return (KERN_INVALID_ARGUMENT);
1046
1047 vm_object_lock(object);
1048
1049
1050
1051
1052 queue_iterate(&object->msr_q, msr, msync_req_t, msr_q) {
1053 if (msr->offset == offset && msr->length == length) {
1054 queue_remove(&object->msr_q, msr, msync_req_t, msr_q);
1055 break;
1056 }
1057 }
1058
1059 if (queue_end(&object->msr_q, (queue_entry_t)msr)) {
1060 vm_object_unlock(object);
1061 return KERN_INVALID_ARGUMENT;
1062 }
1063
1064 msr_lock(msr);
1065 vm_object_unlock(object);
1066 msr->flag = VM_MSYNC_DONE;
1067 msr_unlock(msr);
1068 thread_wakeup((event_t) msr);
1069
1070 return KERN_SUCCESS;
1071}
1072
1073static kern_return_t
1074vm_object_set_attributes_common(
1075 vm_object_t object,
1076 boolean_t may_cache,
1077 memory_object_copy_strategy_t copy_strategy,
1078 boolean_t temporary,
1079 memory_object_cluster_size_t cluster_size,
1080 boolean_t silent_overwrite,
1081 boolean_t advisory_pageout)
1082{
1083 boolean_t object_became_ready;
1084
1085 XPR(XPR_MEMORY_OBJECT,
1086 "m_o_set_attr_com, object 0x%X flg %x strat %d\n",
1087 (integer_t)object, (may_cache&1)|((temporary&1)<1), copy_strategy, 0, 0);
1088
1089 if (object == VM_OBJECT_NULL)
1090 return(KERN_INVALID_ARGUMENT);
1091
1092
1093
1094
1095
1096 switch(copy_strategy) {
1097 case MEMORY_OBJECT_COPY_NONE:
1098 case MEMORY_OBJECT_COPY_DELAY:
1099 break;
1100 default:
1101 return(KERN_INVALID_ARGUMENT);
1102 }
1103
1104#if !ADVISORY_PAGEOUT
1105 if (silent_overwrite || advisory_pageout)
1106 return(KERN_INVALID_ARGUMENT);
1107
1108#endif
1109 if (may_cache)
1110 may_cache = TRUE;
1111 if (temporary)
1112 temporary = TRUE;
1113 if (cluster_size != 0) {
1114 int pages_per_cluster;
1115 pages_per_cluster = atop_32(cluster_size);
1116
1117
1118
1119
1120 if ((cluster_size & (PAGE_SIZE-1)) ||
1121 ((pages_per_cluster-1) & pages_per_cluster))
1122 return KERN_INVALID_ARGUMENT;
1123 }
1124
1125 vm_object_lock(object);
1126
1127
1128
1129
1130 assert(!object->internal);
1131 object_became_ready = !object->pager_ready;
1132 object->copy_strategy = copy_strategy;
1133 object->can_persist = may_cache;
1134 object->temporary = temporary;
1135 object->silent_overwrite = silent_overwrite;
1136 object->advisory_pageout = advisory_pageout;
1137 if (cluster_size == 0)
1138 cluster_size = PAGE_SIZE;
1139 object->cluster_size = cluster_size;
1140
1141 assert(cluster_size >= PAGE_SIZE &&
1142 cluster_size % PAGE_SIZE == 0);
1143
1144
1145
1146
1147
1148
1149 if (object_became_ready) {
1150 object->pager_ready = TRUE;
1151 vm_object_wakeup(object, VM_OBJECT_EVENT_PAGER_READY);
1152 }
1153
1154 vm_object_unlock(object);
1155
1156 return(KERN_SUCCESS);
1157}
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167kern_return_t
1168memory_object_change_attributes(
1169 memory_object_control_t control,
1170 memory_object_flavor_t flavor,
1171 memory_object_info_t attributes,
1172 mach_msg_type_number_t count)
1173{
1174 vm_object_t object;
1175 kern_return_t result = KERN_SUCCESS;
1176 boolean_t temporary;
1177 boolean_t may_cache;
1178 boolean_t invalidate;
1179 memory_object_cluster_size_t cluster_size;
1180 memory_object_copy_strategy_t copy_strategy;
1181 boolean_t silent_overwrite;
1182 boolean_t advisory_pageout;
1183
1184 object = memory_object_control_to_vm_object(control);
1185 if (object == VM_OBJECT_NULL)
1186 return (KERN_INVALID_ARGUMENT);
1187
1188 vm_object_lock(object);
1189
1190 temporary = object->temporary;
1191 may_cache = object->can_persist;
1192 copy_strategy = object->copy_strategy;
1193 silent_overwrite = object->silent_overwrite;
1194 advisory_pageout = object->advisory_pageout;
1195#if notyet
1196 invalidate = object->invalidate;
1197#endif
1198 cluster_size = object->cluster_size;
1199 vm_object_unlock(object);
1200
1201 switch (flavor) {
1202 case OLD_MEMORY_OBJECT_BEHAVIOR_INFO:
1203 {
1204 old_memory_object_behave_info_t behave;
1205
1206 if (count != OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1207 result = KERN_INVALID_ARGUMENT;
1208 break;
1209 }
1210
1211 behave = (old_memory_object_behave_info_t) attributes;
1212
1213 temporary = behave->temporary;
1214 invalidate = behave->invalidate;
1215 copy_strategy = behave->copy_strategy;
1216
1217 break;
1218 }
1219
1220 case MEMORY_OBJECT_BEHAVIOR_INFO:
1221 {
1222 memory_object_behave_info_t behave;
1223
1224 if (count != MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1225 result = KERN_INVALID_ARGUMENT;
1226 break;
1227 }
1228
1229 behave = (memory_object_behave_info_t) attributes;
1230
1231 temporary = behave->temporary;
1232 invalidate = behave->invalidate;
1233 copy_strategy = behave->copy_strategy;
1234 silent_overwrite = behave->silent_overwrite;
1235 advisory_pageout = behave->advisory_pageout;
1236 break;
1237 }
1238
1239 case MEMORY_OBJECT_PERFORMANCE_INFO:
1240 {
1241 memory_object_perf_info_t perf;
1242
1243 if (count != MEMORY_OBJECT_PERF_INFO_COUNT) {
1244 result = KERN_INVALID_ARGUMENT;
1245 break;
1246 }
1247
1248 perf = (memory_object_perf_info_t) attributes;
1249
1250 may_cache = perf->may_cache;
1251 cluster_size = round_page_32(perf->cluster_size);
1252
1253 break;
1254 }
1255
1256 case OLD_MEMORY_OBJECT_ATTRIBUTE_INFO:
1257 {
1258 old_memory_object_attr_info_t attr;
1259
1260 if (count != OLD_MEMORY_OBJECT_ATTR_INFO_COUNT) {
1261 result = KERN_INVALID_ARGUMENT;
1262 break;
1263 }
1264
1265 attr = (old_memory_object_attr_info_t) attributes;
1266
1267 may_cache = attr->may_cache;
1268 copy_strategy = attr->copy_strategy;
1269 cluster_size = page_size;
1270
1271 break;
1272 }
1273
1274 case MEMORY_OBJECT_ATTRIBUTE_INFO:
1275 {
1276 memory_object_attr_info_t attr;
1277
1278 if (count != MEMORY_OBJECT_ATTR_INFO_COUNT) {
1279 result = KERN_INVALID_ARGUMENT;
1280 break;
1281 }
1282
1283 attr = (memory_object_attr_info_t) attributes;
1284
1285 copy_strategy = attr->copy_strategy;
1286 may_cache = attr->may_cache_object;
1287 cluster_size = attr->cluster_size;
1288 temporary = attr->temporary;
1289
1290 break;
1291 }
1292
1293 default:
1294 result = KERN_INVALID_ARGUMENT;
1295 break;
1296 }
1297
1298 if (result != KERN_SUCCESS)
1299 return(result);
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
1309
1310
1311
1312 return (vm_object_set_attributes_common(object,
1313 may_cache,
1314 copy_strategy,
1315 temporary,
1316 cluster_size,
1317 silent_overwrite,
1318 advisory_pageout));
1319}
1320
1321kern_return_t
1322memory_object_get_attributes(
1323 memory_object_control_t control,
1324 memory_object_flavor_t flavor,
1325 memory_object_info_t attributes,
1326 mach_msg_type_number_t *count)
1327{
1328 kern_return_t ret = KERN_SUCCESS;
1329 vm_object_t object;
1330
1331 object = memory_object_control_to_vm_object(control);
1332 if (object == VM_OBJECT_NULL)
1333 return (KERN_INVALID_ARGUMENT);
1334
1335 vm_object_lock(object);
1336
1337 switch (flavor) {
1338 case OLD_MEMORY_OBJECT_BEHAVIOR_INFO:
1339 {
1340 old_memory_object_behave_info_t behave;
1341
1342 if (*count < OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1343 ret = KERN_INVALID_ARGUMENT;
1344 break;
1345 }
1346
1347 behave = (old_memory_object_behave_info_t) attributes;
1348 behave->copy_strategy = object->copy_strategy;
1349 behave->temporary = object->temporary;
1350#if notyet
1351 behave->invalidate = object->invalidate;
1352#else
1353 behave->invalidate = FALSE;
1354#endif
1355
1356 *count = OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT;
1357 break;
1358 }
1359
1360 case MEMORY_OBJECT_BEHAVIOR_INFO:
1361 {
1362 memory_object_behave_info_t behave;
1363
1364 if (*count < MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1365 ret = KERN_INVALID_ARGUMENT;
1366 break;
1367 }
1368
1369 behave = (memory_object_behave_info_t) attributes;
1370 behave->copy_strategy = object->copy_strategy;
1371 behave->temporary = object->temporary;
1372#if notyet
1373 behave->invalidate = object->invalidate;
1374#else
1375 behave->invalidate = FALSE;
1376#endif
1377 behave->advisory_pageout = object->advisory_pageout;
1378 behave->silent_overwrite = object->silent_overwrite;
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;
1393 perf->cluster_size = object->cluster_size;
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;
1428 attr->cluster_size = object->cluster_size;
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
1443 return(ret);
1444}
1445
1446
1447kern_return_t
1448memory_object_iopl_request(
1449 ipc_port_t port,
1450 memory_object_offset_t offset,
1451 upl_size_t *upl_size,
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
1463 if (caller_flags & ~UPL_VALID_FLAGS) {
1464
1465
1466
1467
1468 return KERN_INVALID_VALUE;
1469 }
1470
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
1476 if(*upl_size == 0) {
1477 if(offset >= named_entry->size)
1478 return(KERN_INVALID_RIGHT);
1479 *upl_size = named_entry->size - offset;
1480 }
1481 if(caller_flags & UPL_COPYOUT_FROM) {
1482 if((named_entry->protection & VM_PROT_READ)
1483 != VM_PROT_READ) {
1484 return(KERN_INVALID_RIGHT);
1485 }
1486 } else {
1487 if((named_entry->protection &
1488 (VM_PROT_READ | VM_PROT_WRITE))
1489 != (VM_PROT_READ | VM_PROT_WRITE)) {
1490 return(KERN_INVALID_RIGHT);
1491 }
1492 }
1493 if(named_entry->size < (offset + *upl_size))
1494 return(KERN_INVALID_ARGUMENT);
1495
1496
1497
1498 offset = offset + named_entry->offset;
1499
1500 if(named_entry->is_sub_map)
1501 return (KERN_INVALID_ARGUMENT);
1502
1503 named_entry_lock(named_entry);
1504
1505 if (named_entry->is_pager) {
1506 object = vm_object_enter(named_entry->backing.pager,
1507 named_entry->offset + named_entry->size,
1508 named_entry->internal,
1509 FALSE,
1510 FALSE);
1511 if (object == VM_OBJECT_NULL) {
1512 named_entry_unlock(named_entry);
1513 return(KERN_INVALID_OBJECT);
1514 }
1515
1516
1517
1518
1519 vm_object_lock(object);
1520 vm_object_reference_locked(object);
1521 named_entry->backing.object = object;
1522 named_entry->is_pager = FALSE;
1523 named_entry_unlock(named_entry);
1524
1525
1526 while (!object->pager_ready) {
1527 vm_object_wait(object,
1528 VM_OBJECT_EVENT_PAGER_READY,
1529 THREAD_UNINT);
1530 vm_object_lock(object);
1531 }
1532 vm_object_unlock(object);
1533 } else {
1534
1535
1536
1537
1538
1539
1540 object = named_entry->backing.object;
1541 vm_object_reference(object);
1542 named_entry_unlock(named_entry);
1543 }
1544 } else {
1545 memory_object_control_t control;
1546 control = (memory_object_control_t)port->ip_kobject;
1547 if (control == NULL)
1548 return (KERN_INVALID_ARGUMENT);
1549 object = memory_object_control_to_vm_object(control);
1550 if (object == VM_OBJECT_NULL)
1551 return (KERN_INVALID_ARGUMENT);
1552 vm_object_reference(object);
1553 }
1554 if (object == VM_OBJECT_NULL)
1555 return (KERN_INVALID_ARGUMENT);
1556
1557 if (!object->private) {
1558 if (*upl_size > (MAX_UPL_TRANSFER*PAGE_SIZE))
1559 *upl_size = (MAX_UPL_TRANSFER*PAGE_SIZE);
1560 if (object->phys_contiguous) {
1561 *flags = UPL_PHYS_CONTIG;
1562 } else {
1563 *flags = 0;
1564 }
1565 } else {
1566 *flags = UPL_DEV_MEMORY | UPL_PHYS_CONTIG;
1567 }
1568
1569 ret = vm_object_iopl_request(object,
1570 offset,
1571 *upl_size,
1572 upl_ptr,
1573 user_page_list,
1574 page_list_count,
1575 caller_flags);
1576 vm_object_deallocate(object);
1577 return ret;
1578}
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589kern_return_t
1590memory_object_upl_request(
1591 memory_object_control_t control,
1592 memory_object_offset_t offset,
1593 upl_size_t size,
1594 upl_t *upl_ptr,
1595 upl_page_info_array_t user_page_list,
1596 unsigned int *page_list_count,
1597 int cntrl_flags)
1598{
1599 vm_object_t object;
1600
1601 object = memory_object_control_to_vm_object(control);
1602 if (object == VM_OBJECT_NULL)
1603 return (KERN_INVALID_ARGUMENT);
1604
1605 return vm_object_upl_request(object,
1606 offset,
1607 size,
1608 upl_ptr,
1609 user_page_list,
1610 page_list_count,
1611 cntrl_flags);
1612}
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625kern_return_t
1626memory_object_super_upl_request(
1627 memory_object_control_t control,
1628 memory_object_offset_t offset,
1629 upl_size_t size,
1630 upl_size_t super_cluster,
1631 upl_t *upl,
1632 upl_page_info_t *user_page_list,
1633 unsigned int *page_list_count,
1634 int cntrl_flags)
1635{
1636 vm_object_t object;
1637
1638 object = memory_object_control_to_vm_object(control);
1639 if (object == VM_OBJECT_NULL)
1640 return (KERN_INVALID_ARGUMENT);
1641
1642 return vm_object_super_upl_request(object,
1643 offset,
1644 size,
1645 super_cluster,
1646 upl,
1647 user_page_list,
1648 page_list_count,
1649 cntrl_flags);
1650}
1651
1652int vm_stat_discard_cleared_reply = 0;
1653int vm_stat_discard_cleared_unset = 0;
1654int vm_stat_discard_cleared_too_late = 0;
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666kern_return_t
1667host_default_memory_manager(
1668 host_priv_t host_priv,
1669 memory_object_default_t *default_manager,
1670 memory_object_cluster_size_t cluster_size)
1671{
1672 memory_object_default_t current_manager;
1673 memory_object_default_t new_manager;
1674 memory_object_default_t returned_manager;
1675
1676 if (host_priv == HOST_PRIV_NULL)
1677 return(KERN_INVALID_HOST);
1678
1679 assert(host_priv == &realhost);
1680
1681 new_manager = *default_manager;
1682 mutex_lock(&memory_manager_default_lock);
1683 current_manager = memory_manager_default;
1684
1685 if (new_manager == MEMORY_OBJECT_DEFAULT_NULL) {
1686
1687
1688
1689 memory_object_default_reference(current_manager);
1690 returned_manager = current_manager;
1691 } else {
1692
1693
1694
1695
1696
1697
1698
1699
1700 returned_manager = current_manager;
1701 memory_manager_default = new_manager;
1702 memory_object_default_reference(new_manager);
1703
1704 if (cluster_size % PAGE_SIZE != 0) {
1705#if 0
1706 mutex_unlock(&memory_manager_default_lock);
1707 return KERN_INVALID_ARGUMENT;
1708#else
1709 cluster_size = round_page_32(cluster_size);
1710#endif
1711 }
1712 memory_manager_default_cluster = cluster_size;
1713
1714
1715
1716
1717
1718
1719 thread_wakeup((event_t) &memory_manager_default);
1720 }
1721
1722 mutex_unlock(&memory_manager_default_lock);
1723
1724 *default_manager = returned_manager;
1725 return(KERN_SUCCESS);
1726}
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736__private_extern__ memory_object_default_t
1737memory_manager_default_reference(
1738 memory_object_cluster_size_t *cluster_size)
1739{
1740 memory_object_default_t current_manager;
1741
1742 mutex_lock(&memory_manager_default_lock);
1743 current_manager = memory_manager_default;
1744 while (current_manager == MEMORY_OBJECT_DEFAULT_NULL) {
1745 wait_result_t res;
1746
1747 res = thread_sleep_mutex((event_t) &memory_manager_default,
1748 &memory_manager_default_lock,
1749 THREAD_UNINT);
1750 assert(res == THREAD_AWAKENED);
1751 current_manager = memory_manager_default;
1752 }
1753 memory_object_default_reference(current_manager);
1754 *cluster_size = memory_manager_default_cluster;
1755 mutex_unlock(&memory_manager_default_lock);
1756
1757 return current_manager;
1758}
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772__private_extern__ kern_return_t
1773memory_manager_default_check(void)
1774{
1775 memory_object_default_t current;
1776
1777 mutex_lock(&memory_manager_default_lock);
1778 current = memory_manager_default;
1779 if (current == MEMORY_OBJECT_DEFAULT_NULL) {
1780 static boolean_t logged;
1781 boolean_t complain = !logged;
1782 logged = TRUE;
1783 mutex_unlock(&memory_manager_default_lock);
1784 if (complain)
1785 printf("Warning: No default memory manager\n");
1786 return(KERN_FAILURE);
1787 } else {
1788 mutex_unlock(&memory_manager_default_lock);
1789 return(KERN_SUCCESS);
1790 }
1791}
1792
1793__private_extern__ void
1794memory_manager_default_init(void)
1795{
1796 memory_manager_default = MEMORY_OBJECT_DEFAULT_NULL;
1797 mutex_init(&memory_manager_default_lock, 0);
1798}
1799
1800
1801
1802
1803
1804
1805kern_return_t
1806memory_object_page_op(
1807 memory_object_control_t control,
1808 memory_object_offset_t offset,
1809 int ops,
1810 ppnum_t *phys_entry,
1811 int *flags)
1812{
1813 vm_object_t object;
1814 vm_page_t dst_page;
1815
1816
1817 object = memory_object_control_to_vm_object(control);
1818 if (object == VM_OBJECT_NULL)
1819 return (KERN_INVALID_ARGUMENT);
1820
1821 vm_object_lock(object);
1822
1823 if(ops & UPL_POP_PHYSICAL) {
1824 if(object->phys_contiguous) {
1825 if (phys_entry) {
1826 *phys_entry = (ppnum_t)
1827 (object->shadow_offset >> 12);
1828 }
1829 vm_object_unlock(object);
1830 return KERN_SUCCESS;
1831 } else {
1832 vm_object_unlock(object);
1833 return KERN_INVALID_OBJECT;
1834 }
1835 }
1836 if(object->phys_contiguous) {
1837 vm_object_unlock(object);
1838 return KERN_INVALID_OBJECT;
1839 }
1840
1841 while(TRUE) {
1842 if((dst_page = vm_page_lookup(object,offset)) == VM_PAGE_NULL) {
1843 vm_object_unlock(object);
1844 return KERN_FAILURE;
1845 }
1846
1847
1848 if((dst_page->busy || dst_page->cleaning) &&
1849 (((ops & UPL_POP_SET) &&
1850 (ops & UPL_POP_BUSY)) || (ops & UPL_POP_DUMP))) {
1851
1852
1853 PAGE_SLEEP(object, dst_page, THREAD_UNINT);
1854 continue;
1855 }
1856
1857 if (ops & UPL_POP_DUMP) {
1858 vm_page_lock_queues();
1859
1860 if (dst_page->no_isync == FALSE)
1861 pmap_disconnect(dst_page->phys_page);
1862 vm_page_free(dst_page);
1863
1864 vm_page_unlock_queues();
1865 break;
1866 }
1867
1868 if (flags) {
1869 *flags = 0;
1870
1871
1872
1873
1874 if(dst_page->dirty) *flags |= UPL_POP_DIRTY;
1875 if(dst_page->pageout) *flags |= UPL_POP_PAGEOUT;
1876 if(dst_page->precious) *flags |= UPL_POP_PRECIOUS;
1877 if(dst_page->absent) *flags |= UPL_POP_ABSENT;
1878 if(dst_page->busy) *flags |= UPL_POP_BUSY;
1879 }
1880
1881
1882
1883 if(ops & UPL_POP_SET) {
1884
1885
1886
1887
1888
1889
1890
1891 assert(dst_page->busy || (ops & UPL_POP_BUSY));
1892 if (ops & UPL_POP_DIRTY) dst_page->dirty = TRUE;
1893 if (ops & UPL_POP_PAGEOUT) dst_page->pageout = TRUE;
1894 if (ops & UPL_POP_PRECIOUS) dst_page->precious = TRUE;
1895 if (ops & UPL_POP_ABSENT) dst_page->absent = TRUE;
1896 if (ops & UPL_POP_BUSY) dst_page->busy = TRUE;
1897 }
1898
1899 if(ops & UPL_POP_CLR) {
1900 assert(dst_page->busy);
1901 if (ops & UPL_POP_DIRTY) dst_page->dirty = FALSE;
1902 if (ops & UPL_POP_PAGEOUT) dst_page->pageout = FALSE;
1903 if (ops & UPL_POP_PRECIOUS) dst_page->precious = FALSE;
1904 if (ops & UPL_POP_ABSENT) dst_page->absent = FALSE;
1905 if (ops & UPL_POP_BUSY) {
1906 dst_page->busy = FALSE;
1907 PAGE_WAKEUP(dst_page);
1908 }
1909 }
1910
1911 if (dst_page->encrypted) {
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921 if ((ops & UPL_POP_SET) && (ops & UPL_POP_BUSY) &&
1922 dst_page->busy) {
1923
1924
1925
1926
1927
1928 vm_page_decrypt(dst_page, 0);
1929 } else {
1930
1931
1932
1933
1934
1935
1936
1937
1938 assert(!phys_entry);
1939 }
1940 }
1941
1942 if (phys_entry) {
1943
1944
1945
1946
1947
1948
1949 assert(dst_page->busy);
1950 assert(!dst_page->encrypted);
1951 *phys_entry = dst_page->phys_page;
1952 }
1953
1954 break;
1955 }
1956
1957 vm_object_unlock(object);
1958 return KERN_SUCCESS;
1959
1960}
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972kern_return_t
1973memory_object_range_op(
1974 memory_object_control_t control,
1975 memory_object_offset_t offset_beg,
1976 memory_object_offset_t offset_end,
1977 int ops,
1978 int *range)
1979{
1980 memory_object_offset_t offset;
1981 vm_object_t object;
1982 vm_page_t dst_page;
1983
1984 object = memory_object_control_to_vm_object(control);
1985 if (object == VM_OBJECT_NULL)
1986 return (KERN_INVALID_ARGUMENT);
1987
1988 if (object->resident_page_count == 0) {
1989 if (range) {
1990 if (ops & UPL_ROP_PRESENT)
1991 *range = 0;
1992 else
1993 *range = offset_end - offset_beg;
1994 }
1995 return KERN_SUCCESS;
1996 }
1997 vm_object_lock(object);
1998
1999 if (object->phys_contiguous) {
2000 vm_object_unlock(object);
2001 return KERN_INVALID_OBJECT;
2002 }
2003
2004 offset = offset_beg;
2005
2006 while (offset < offset_end) {
2007 dst_page = vm_page_lookup(object, offset);
2008 if (dst_page != VM_PAGE_NULL) {
2009 if (ops & UPL_ROP_DUMP) {
2010 if (dst_page->busy || dst_page->cleaning) {
2011
2012
2013
2014
2015 PAGE_SLEEP(object,
2016 dst_page, THREAD_UNINT);
2017
2018
2019
2020
2021
2022
2023 continue;
2024 }
2025 vm_page_lock_queues();
2026
2027 if (dst_page->no_isync == FALSE)
2028 pmap_disconnect(dst_page->phys_page);
2029 vm_page_free(dst_page);
2030
2031 vm_page_unlock_queues();
2032 } else if (ops & UPL_ROP_ABSENT)
2033 break;
2034 } else if (ops & UPL_ROP_PRESENT)
2035 break;
2036
2037 offset += PAGE_SIZE;
2038 }
2039 vm_object_unlock(object);
2040
2041 if (range)
2042 *range = offset - offset_beg;
2043
2044 return KERN_SUCCESS;
2045}
2046
2047
2048kern_return_t
2049memory_object_pages_resident(
2050 memory_object_control_t control,
2051 boolean_t * has_pages_resident)
2052{
2053 vm_object_t object;
2054
2055 *has_pages_resident = FALSE;
2056
2057 object = memory_object_control_to_vm_object(control);
2058 if (object == VM_OBJECT_NULL)
2059 return (KERN_INVALID_ARGUMENT);
2060
2061 if (object->resident_page_count)
2062 *has_pages_resident = TRUE;
2063
2064 return (KERN_SUCCESS);
2065}
2066
2067
2068static zone_t mem_obj_control_zone;
2069
2070__private_extern__ void
2071memory_object_control_bootstrap(void)
2072{
2073 int i;
2074
2075 i = (vm_size_t) sizeof (struct memory_object_control);
2076 mem_obj_control_zone = zinit (i, 8192*i, 4096, "mem_obj_control");
2077 return;
2078}
2079
2080__private_extern__ memory_object_control_t
2081memory_object_control_allocate(
2082 vm_object_t object)
2083{
2084 memory_object_control_t control;
2085
2086 control = (memory_object_control_t)zalloc(mem_obj_control_zone);
2087 if (control != MEMORY_OBJECT_CONTROL_NULL)
2088 control->object = object;
2089 return (control);
2090}
2091
2092__private_extern__ void
2093memory_object_control_collapse(
2094 memory_object_control_t control,
2095 vm_object_t object)
2096{
2097 assert((control->object != VM_OBJECT_NULL) &&
2098 (control->object != object));
2099 control->object = object;
2100}
2101
2102__private_extern__ vm_object_t
2103memory_object_control_to_vm_object(
2104 memory_object_control_t control)
2105{
2106 if (control == MEMORY_OBJECT_CONTROL_NULL)
2107 return VM_OBJECT_NULL;
2108
2109 return (control->object);
2110}
2111
2112memory_object_control_t
2113convert_port_to_mo_control(
2114 __unused mach_port_t port)
2115{
2116 return MEMORY_OBJECT_CONTROL_NULL;
2117}
2118
2119
2120mach_port_t
2121convert_mo_control_to_port(
2122 __unused memory_object_control_t control)
2123{
2124 return MACH_PORT_NULL;
2125}
2126
2127void
2128memory_object_control_reference(
2129 __unused memory_object_control_t control)
2130{
2131 return;
2132}
2133
2134
2135
2136
2137
2138
2139void
2140memory_object_control_deallocate(
2141 memory_object_control_t control)
2142{
2143 zfree(mem_obj_control_zone, control);
2144}
2145
2146void
2147memory_object_control_disable(
2148 memory_object_control_t control)
2149{
2150 assert(control->object != VM_OBJECT_NULL);
2151 control->object = VM_OBJECT_NULL;
2152}
2153
2154void
2155memory_object_default_reference(
2156 memory_object_default_t dmm)
2157{
2158 ipc_port_make_send(dmm);
2159}
2160
2161void
2162memory_object_default_deallocate(
2163 memory_object_default_t dmm)
2164{
2165 ipc_port_release_send(dmm);
2166}
2167
2168memory_object_t
2169convert_port_to_memory_object(
2170 __unused mach_port_t port)
2171{
2172 return (MEMORY_OBJECT_NULL);
2173}
2174
2175
2176mach_port_t
2177convert_memory_object_to_port(
2178 __unused memory_object_t object)
2179{
2180 return (MACH_PORT_NULL);
2181}
2182
2183
2184
2185void memory_object_reference(
2186 memory_object_t memory_object)
2187{
2188
2189#ifdef MACH_BSD
2190 if (memory_object->pager == &vnode_pager_workaround) {
2191 vnode_pager_reference(memory_object);
2192 } else if (memory_object->pager == &device_pager_workaround) {
2193 device_pager_reference(memory_object);
2194 } else
2195#endif
2196 dp_memory_object_reference(memory_object);
2197}
2198
2199
2200void memory_object_deallocate(
2201 memory_object_t memory_object)
2202{
2203
2204#ifdef MACH_BSD
2205 if (memory_object->pager == &vnode_pager_workaround) {
2206 vnode_pager_deallocate(memory_object);
2207 } else if (memory_object->pager == &device_pager_workaround) {
2208 device_pager_deallocate(memory_object);
2209 } else
2210#endif
2211 dp_memory_object_deallocate(memory_object);
2212}
2213
2214
2215
2216kern_return_t memory_object_init
2217(
2218 memory_object_t memory_object,
2219 memory_object_control_t memory_control,
2220 memory_object_cluster_size_t memory_object_page_size
2221)
2222{
2223#ifdef MACH_BSD
2224 if (memory_object->pager == &vnode_pager_workaround) {
2225 return vnode_pager_init(memory_object,
2226 memory_control,
2227 memory_object_page_size);
2228 } else if (memory_object->pager == &device_pager_workaround) {
2229 return device_pager_init(memory_object,
2230 memory_control,
2231 memory_object_page_size);
2232 } else
2233#endif
2234 return dp_memory_object_init(memory_object,
2235 memory_control,
2236 memory_object_page_size);
2237}
2238
2239
2240kern_return_t memory_object_terminate
2241(
2242 memory_object_t memory_object
2243)
2244{
2245#ifdef MACH_BSD
2246 if (memory_object->pager == &vnode_pager_workaround) {
2247 return vnode_pager_terminate(memory_object);
2248 } else if (memory_object->pager == &device_pager_workaround) {
2249 return device_pager_terminate(memory_object);
2250 } else
2251#endif
2252 return dp_memory_object_terminate(memory_object);
2253}
2254
2255
2256kern_return_t memory_object_data_request
2257(
2258 memory_object_t memory_object,
2259 memory_object_offset_t offset,
2260 memory_object_cluster_size_t length,
2261 vm_prot_t desired_access
2262)
2263{
2264#ifdef MACH_BSD
2265 if (memory_object->pager == &vnode_pager_workaround) {
2266 return vnode_pager_data_request(memory_object,
2267 offset,
2268 length,
2269 desired_access);
2270 } else if (memory_object->pager == &device_pager_workaround) {
2271 return device_pager_data_request(memory_object,
2272 offset,
2273 length,
2274 desired_access);
2275 } else
2276#endif
2277 return dp_memory_object_data_request(memory_object,
2278 offset,
2279 length,
2280 desired_access);
2281}
2282
2283
2284kern_return_t memory_object_data_return
2285(
2286 memory_object_t memory_object,
2287 memory_object_offset_t offset,
2288 vm_size_t size,
2289 memory_object_offset_t *resid_offset,
2290 int *io_error,
2291 boolean_t dirty,
2292 boolean_t kernel_copy,
2293 int upl_flags
2294)
2295{
2296#ifdef MACH_BSD
2297 if (memory_object->pager == &vnode_pager_workaround) {
2298 return vnode_pager_data_return(memory_object,
2299 offset,
2300 size,
2301 resid_offset,
2302 io_error,
2303 dirty,
2304 kernel_copy,
2305 upl_flags);
2306 } else if (memory_object->pager == &device_pager_workaround) {
2307
2308 return device_pager_data_return(memory_object,
2309 offset,
2310 size,
2311 dirty,
2312 kernel_copy,
2313 upl_flags);
2314 }
2315 else
2316#endif
2317 {
2318 return dp_memory_object_data_return(memory_object,
2319 offset,
2320 size,
2321 NULL,
2322 NULL,
2323 dirty,
2324 kernel_copy,
2325 upl_flags);
2326 }
2327}
2328
2329
2330kern_return_t memory_object_data_initialize
2331(
2332 memory_object_t memory_object,
2333 memory_object_offset_t offset,
2334 vm_size_t size
2335)
2336{
2337#ifdef MACH_BSD
2338 if (memory_object->pager == &vnode_pager_workaround) {
2339 return vnode_pager_data_initialize(memory_object,
2340 offset,
2341 size);
2342 } else if (memory_object->pager == &device_pager_workaround) {
2343 return device_pager_data_initialize(memory_object,
2344 offset,
2345 size);
2346 } else
2347#endif
2348 return dp_memory_object_data_initialize(memory_object,
2349 offset,
2350 size);
2351}
2352
2353
2354kern_return_t memory_object_data_unlock
2355(
2356 memory_object_t memory_object,
2357 memory_object_offset_t offset,
2358 vm_size_t size,
2359 vm_prot_t desired_access
2360)
2361{
2362#ifdef MACH_BSD
2363 if (memory_object->pager == &vnode_pager_workaround) {
2364 return vnode_pager_data_unlock(memory_object,
2365 offset,
2366 size,
2367 desired_access);
2368 } else if (memory_object->pager == &device_pager_workaround) {
2369 return device_pager_data_unlock(memory_object,
2370 offset,
2371 size,
2372 desired_access);
2373 } else
2374#endif
2375 return dp_memory_object_data_unlock(memory_object,
2376 offset,
2377 size,
2378 desired_access);
2379}
2380
2381
2382kern_return_t memory_object_synchronize
2383(
2384 memory_object_t memory_object,
2385 memory_object_offset_t offset,
2386 vm_size_t size,
2387 vm_sync_t sync_flags
2388)
2389{
2390#ifdef MACH_BSD
2391 if (memory_object->pager == &vnode_pager_workaround) {
2392 return vnode_pager_synchronize(memory_object,
2393 offset,
2394 size,
2395 sync_flags);
2396 } else if (memory_object->pager == &device_pager_workaround) {
2397 return device_pager_synchronize(memory_object,
2398 offset,
2399 size,
2400 sync_flags);
2401 } else
2402#endif
2403 return dp_memory_object_synchronize(memory_object,
2404 offset,
2405 size,
2406 sync_flags);
2407}
2408
2409
2410kern_return_t memory_object_unmap
2411(
2412 memory_object_t memory_object
2413)
2414{
2415#ifdef MACH_BSD
2416 if (memory_object->pager == &vnode_pager_workaround) {
2417 return vnode_pager_unmap(memory_object);
2418 } else if (memory_object->pager == &device_pager_workaround) {
2419 return device_pager_unmap(memory_object);
2420 } else
2421#endif
2422 return dp_memory_object_unmap(memory_object);
2423}
2424
2425
2426kern_return_t memory_object_create
2427(
2428 memory_object_default_t default_memory_manager,
2429 vm_size_t new_memory_object_size,
2430 memory_object_t *new_memory_object
2431)
2432{
2433 return default_pager_memory_object_create(default_memory_manager,
2434 new_memory_object_size,
2435 new_memory_object);
2436}
2437
2438upl_t
2439convert_port_to_upl(
2440 ipc_port_t port)
2441{
2442 upl_t upl;
2443
2444 ip_lock(port);
2445 if (!ip_active(port) || (ip_kotype(port) != IKOT_UPL)) {
2446 ip_unlock(port);
2447 return (upl_t)NULL;
2448 }
2449 upl = (upl_t) port->ip_kobject;
2450 ip_unlock(port);
2451 upl_lock(upl);
2452 upl->ref_count+=1;
2453 upl_unlock(upl);
2454 return upl;
2455}
2456
2457mach_port_t
2458convert_upl_to_port(
2459 __unused upl_t upl)
2460{
2461 return MACH_PORT_NULL;
2462}
2463
2464__private_extern__ void
2465upl_no_senders(
2466 __unused ipc_port_t port,
2467 __unused mach_port_mscount_t mscount)
2468{
2469 return;
2470}
2471