]> git.saurik.com Git - apple/xnu.git/blob - osfmk/vm/vm_fourk_pager.c
xnu-3247.10.11.tar.gz
[apple/xnu.git] / osfmk / vm / vm_fourk_pager.c
1 /*
2 * Copyright (c) 2014 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <sys/errno.h>
30
31 #include <mach/mach_types.h>
32 #include <mach/mach_traps.h>
33 #include <mach/host_priv.h>
34 #include <mach/kern_return.h>
35 #include <mach/memory_object_control.h>
36 #include <mach/memory_object_types.h>
37 #include <mach/port.h>
38 #include <mach/policy.h>
39 #include <mach/upl.h>
40 #include <mach/thread_act.h>
41 #include <mach/mach_vm.h>
42
43 #include <kern/host.h>
44 #include <kern/kalloc.h>
45 #include <kern/page_decrypt.h>
46 #include <kern/queue.h>
47 #include <kern/thread.h>
48
49 #include <ipc/ipc_port.h>
50 #include <ipc/ipc_space.h>
51
52 #include <default_pager/default_pager_types.h>
53 #include <default_pager/default_pager_object_server.h>
54
55 #include <vm/vm_fault.h>
56 #include <vm/vm_map.h>
57 #include <vm/vm_pageout.h>
58 #include <vm/memory_object.h>
59 #include <vm/vm_pageout.h>
60 #include <vm/vm_protos.h>
61
62
63 /*
64 * 4K MEMORY PAGER
65 *
66 * This external memory manager (EMM) handles memory mappings that are
67 * 4K-aligned but not page-aligned and can therefore not be mapped directly.
68 *
69 * It mostly handles page-in requests (from memory_object_data_request()) by
70 * getting the data needed to fill in each 4K-chunk. That can require
71 * getting data from one or two pages from its backing VM object
72 * (a file or a "apple-protected" pager backed by an encrypted file), and
73 * copies the data to another page so that it is aligned as expected by
74 * the mapping.
75 *
76 * Returned pages can never be dirtied and must always be mapped copy-on-write,
77 * so the memory manager does not need to handle page-out requests (from
78 * memory_object_data_return()).
79 *
80 */
81
82 /* forward declarations */
83 void fourk_pager_reference(memory_object_t mem_obj);
84 void fourk_pager_deallocate(memory_object_t mem_obj);
85 kern_return_t fourk_pager_init(memory_object_t mem_obj,
86 memory_object_control_t control,
87 memory_object_cluster_size_t pg_size);
88 kern_return_t fourk_pager_terminate(memory_object_t mem_obj);
89 kern_return_t fourk_pager_data_request(memory_object_t mem_obj,
90 memory_object_offset_t offset,
91 memory_object_cluster_size_t length,
92 vm_prot_t protection_required,
93 memory_object_fault_info_t fault_info);
94 kern_return_t fourk_pager_data_return(memory_object_t mem_obj,
95 memory_object_offset_t offset,
96 memory_object_cluster_size_t data_cnt,
97 memory_object_offset_t *resid_offset,
98 int *io_error,
99 boolean_t dirty,
100 boolean_t kernel_copy,
101 int upl_flags);
102 kern_return_t fourk_pager_data_initialize(memory_object_t mem_obj,
103 memory_object_offset_t offset,
104 memory_object_cluster_size_t data_cnt);
105 kern_return_t fourk_pager_data_unlock(memory_object_t mem_obj,
106 memory_object_offset_t offset,
107 memory_object_size_t size,
108 vm_prot_t desired_access);
109 kern_return_t fourk_pager_synchronize(memory_object_t mem_obj,
110 memory_object_offset_t offset,
111 memory_object_size_t length,
112 vm_sync_t sync_flags);
113 kern_return_t fourk_pager_map(memory_object_t mem_obj,
114 vm_prot_t prot);
115 kern_return_t fourk_pager_last_unmap(memory_object_t mem_obj);
116
117 /*
118 * Vector of VM operations for this EMM.
119 * These routines are invoked by VM via the memory_object_*() interfaces.
120 */
121 const struct memory_object_pager_ops fourk_pager_ops = {
122 fourk_pager_reference,
123 fourk_pager_deallocate,
124 fourk_pager_init,
125 fourk_pager_terminate,
126 fourk_pager_data_request,
127 fourk_pager_data_return,
128 fourk_pager_data_initialize,
129 fourk_pager_data_unlock,
130 fourk_pager_synchronize,
131 fourk_pager_map,
132 fourk_pager_last_unmap,
133 NULL, /* data_reclaim */
134 "fourk_pager"
135 };
136
137 /*
138 * The "fourk_pager" describes a memory object backed by
139 * the "4K" EMM.
140 */
141 #define FOURK_PAGER_SLOTS 4 /* 16K / 4K */
142 typedef struct fourk_pager_backing {
143 vm_object_t backing_object;
144 vm_object_offset_t backing_offset;
145 } *fourk_pager_backing_t;
146 typedef struct fourk_pager {
147 struct ipc_object_header pager_header; /* fake ip_kotype() */
148 memory_object_pager_ops_t pager_ops; /* == &fourk_pager_ops */
149 memory_object_control_t pager_control; /* mem object control handle */
150 queue_chain_t pager_queue; /* next & prev pagers */
151 unsigned int ref_count; /* reference count */
152 int is_ready; /* is this pager ready ? */
153 int is_mapped; /* is this mem_obj mapped ? */
154 struct fourk_pager_backing slots[FOURK_PAGER_SLOTS]; /* backing for each
155 4K-chunk */
156 } *fourk_pager_t;
157 #define FOURK_PAGER_NULL ((fourk_pager_t) NULL)
158 #define pager_ikot pager_header.io_bits
159
160 /*
161 * List of memory objects managed by this EMM.
162 * The list is protected by the "fourk_pager_lock" lock.
163 */
164 int fourk_pager_count = 0; /* number of pagers */
165 int fourk_pager_count_mapped = 0; /* number of unmapped pagers */
166 queue_head_t fourk_pager_queue;
167 decl_lck_mtx_data(,fourk_pager_lock)
168
169 /*
170 * Maximum number of unmapped pagers we're willing to keep around.
171 */
172 int fourk_pager_cache_limit = 0;
173
174 /*
175 * Statistics & counters.
176 */
177 int fourk_pager_count_max = 0;
178 int fourk_pager_count_unmapped_max = 0;
179 int fourk_pager_num_trim_max = 0;
180 int fourk_pager_num_trim_total = 0;
181
182
183 lck_grp_t fourk_pager_lck_grp;
184 lck_grp_attr_t fourk_pager_lck_grp_attr;
185 lck_attr_t fourk_pager_lck_attr;
186
187
188 /* internal prototypes */
189 fourk_pager_t fourk_pager_lookup(memory_object_t mem_obj);
190 void fourk_pager_dequeue(fourk_pager_t pager);
191 void fourk_pager_deallocate_internal(fourk_pager_t pager,
192 boolean_t locked);
193 void fourk_pager_terminate_internal(fourk_pager_t pager);
194 void fourk_pager_trim(void);
195
196
197 #if DEBUG
198 int fourk_pagerdebug = 0;
199 #define PAGER_ALL 0xffffffff
200 #define PAGER_INIT 0x00000001
201 #define PAGER_PAGEIN 0x00000002
202
203 #define PAGER_DEBUG(LEVEL, A) \
204 MACRO_BEGIN \
205 if ((fourk_pagerdebug & LEVEL)==LEVEL) { \
206 printf A; \
207 } \
208 MACRO_END
209 #else
210 #define PAGER_DEBUG(LEVEL, A)
211 #endif
212
213
214 void
215 fourk_pager_bootstrap(void)
216 {
217 lck_grp_attr_setdefault(&fourk_pager_lck_grp_attr);
218 lck_grp_init(&fourk_pager_lck_grp, "4K-pager", &fourk_pager_lck_grp_attr);
219 lck_attr_setdefault(&fourk_pager_lck_attr);
220 lck_mtx_init(&fourk_pager_lock, &fourk_pager_lck_grp, &fourk_pager_lck_attr);
221 queue_init(&fourk_pager_queue);
222 }
223
224 /*
225 * fourk_pager_init()
226 *
227 * Initialize the memory object and makes it ready to be used and mapped.
228 */
229 kern_return_t
230 fourk_pager_init(
231 memory_object_t mem_obj,
232 memory_object_control_t control,
233 #if !DEBUG
234 __unused
235 #endif
236 memory_object_cluster_size_t pg_size)
237 {
238 fourk_pager_t pager;
239 kern_return_t kr;
240 memory_object_attr_info_data_t attributes;
241
242 PAGER_DEBUG(PAGER_ALL,
243 ("fourk_pager_init: %p, %p, %x\n",
244 mem_obj, control, pg_size));
245
246 if (control == MEMORY_OBJECT_CONTROL_NULL)
247 return KERN_INVALID_ARGUMENT;
248
249 pager = fourk_pager_lookup(mem_obj);
250
251 memory_object_control_reference(control);
252
253 pager->pager_control = control;
254
255 attributes.copy_strategy = MEMORY_OBJECT_COPY_DELAY;
256 /* attributes.cluster_size = (1 << (CLUSTER_SHIFT + PAGE_SHIFT));*/
257 attributes.cluster_size = (1 << (PAGE_SHIFT));
258 attributes.may_cache_object = FALSE;
259 attributes.temporary = TRUE;
260
261 kr = memory_object_change_attributes(
262 control,
263 MEMORY_OBJECT_ATTRIBUTE_INFO,
264 (memory_object_info_t) &attributes,
265 MEMORY_OBJECT_ATTR_INFO_COUNT);
266 if (kr != KERN_SUCCESS)
267 panic("fourk_pager_init: "
268 "memory_object_change_attributes() failed");
269
270 return KERN_SUCCESS;
271 }
272
273 /*
274 * fourk_pager_data_return()
275 *
276 * Handles page-out requests from VM. This should never happen since
277 * the pages provided by this EMM are not supposed to be dirty or dirtied
278 * and VM should simply discard the contents and reclaim the pages if it
279 * needs to.
280 */
281 kern_return_t
282 fourk_pager_data_return(
283 __unused memory_object_t mem_obj,
284 __unused memory_object_offset_t offset,
285 __unused memory_object_cluster_size_t data_cnt,
286 __unused memory_object_offset_t *resid_offset,
287 __unused int *io_error,
288 __unused boolean_t dirty,
289 __unused boolean_t kernel_copy,
290 __unused int upl_flags)
291 {
292 panic("fourk_pager_data_return: should never get called");
293 return KERN_FAILURE;
294 }
295
296 kern_return_t
297 fourk_pager_data_initialize(
298 __unused memory_object_t mem_obj,
299 __unused memory_object_offset_t offset,
300 __unused memory_object_cluster_size_t data_cnt)
301 {
302 panic("fourk_pager_data_initialize: should never get called");
303 return KERN_FAILURE;
304 }
305
306 kern_return_t
307 fourk_pager_data_unlock(
308 __unused memory_object_t mem_obj,
309 __unused memory_object_offset_t offset,
310 __unused memory_object_size_t size,
311 __unused vm_prot_t desired_access)
312 {
313 return KERN_FAILURE;
314 }
315
316 /*
317 * fourk_pager_reference()
318 *
319 * Get a reference on this memory object.
320 * For external usage only. Assumes that the initial reference count is not 0,
321 * i.e one should not "revive" a dead pager this way.
322 */
323 void
324 fourk_pager_reference(
325 memory_object_t mem_obj)
326 {
327 fourk_pager_t pager;
328
329 pager = fourk_pager_lookup(mem_obj);
330
331 lck_mtx_lock(&fourk_pager_lock);
332 assert(pager->ref_count > 0);
333 pager->ref_count++;
334 lck_mtx_unlock(&fourk_pager_lock);
335 }
336
337
338 /*
339 * fourk_pager_dequeue:
340 *
341 * Removes a pager from the list of pagers.
342 *
343 * The caller must hold "fourk_pager_lock".
344 */
345 void
346 fourk_pager_dequeue(
347 fourk_pager_t pager)
348 {
349 assert(!pager->is_mapped);
350
351 queue_remove(&fourk_pager_queue,
352 pager,
353 fourk_pager_t,
354 pager_queue);
355 pager->pager_queue.next = NULL;
356 pager->pager_queue.prev = NULL;
357
358 fourk_pager_count--;
359 }
360
361 /*
362 * fourk_pager_terminate_internal:
363 *
364 * Trigger the asynchronous termination of the memory object associated
365 * with this pager.
366 * When the memory object is terminated, there will be one more call
367 * to memory_object_deallocate() (i.e. fourk_pager_deallocate())
368 * to finish the clean up.
369 *
370 * "fourk_pager_lock" should not be held by the caller.
371 * We don't need the lock because the pager has already been removed from
372 * the pagers' list and is now ours exclusively.
373 */
374 void
375 fourk_pager_terminate_internal(
376 fourk_pager_t pager)
377 {
378 int i;
379
380 assert(pager->is_ready);
381 assert(!pager->is_mapped);
382
383 for (i = 0; i < FOURK_PAGER_SLOTS; i++) {
384 if (pager->slots[i].backing_object != VM_OBJECT_NULL &&
385 pager->slots[i].backing_object != (vm_object_t) -1) {
386 vm_object_deallocate(pager->slots[i].backing_object);
387 pager->slots[i].backing_object = (vm_object_t) -1;
388 pager->slots[i].backing_offset = (vm_object_offset_t) -1;
389 }
390 }
391
392 /* trigger the destruction of the memory object */
393 memory_object_destroy(pager->pager_control, 0);
394 }
395
396 /*
397 * fourk_pager_deallocate_internal()
398 *
399 * Release a reference on this pager and free it when the last
400 * reference goes away.
401 * Can be called with fourk_pager_lock held or not but always returns
402 * with it unlocked.
403 */
404 void
405 fourk_pager_deallocate_internal(
406 fourk_pager_t pager,
407 boolean_t locked)
408 {
409 boolean_t needs_trimming;
410 int count_unmapped;
411
412 if (! locked) {
413 lck_mtx_lock(&fourk_pager_lock);
414 }
415
416 count_unmapped = (fourk_pager_count -
417 fourk_pager_count_mapped);
418 if (count_unmapped > fourk_pager_cache_limit) {
419 /* we have too many unmapped pagers: trim some */
420 needs_trimming = TRUE;
421 } else {
422 needs_trimming = FALSE;
423 }
424
425 /* drop a reference on this pager */
426 pager->ref_count--;
427
428 if (pager->ref_count == 1) {
429 /*
430 * Only the "named" reference is left, which means that
431 * no one is really holding on to this pager anymore.
432 * Terminate it.
433 */
434 fourk_pager_dequeue(pager);
435 /* the pager is all ours: no need for the lock now */
436 lck_mtx_unlock(&fourk_pager_lock);
437 fourk_pager_terminate_internal(pager);
438 } else if (pager->ref_count == 0) {
439 /*
440 * Dropped the existence reference; the memory object has
441 * been terminated. Do some final cleanup and release the
442 * pager structure.
443 */
444 lck_mtx_unlock(&fourk_pager_lock);
445 if (pager->pager_control != MEMORY_OBJECT_CONTROL_NULL) {
446 memory_object_control_deallocate(pager->pager_control);
447 pager->pager_control = MEMORY_OBJECT_CONTROL_NULL;
448 }
449 kfree(pager, sizeof (*pager));
450 pager = FOURK_PAGER_NULL;
451 } else {
452 /* there are still plenty of references: keep going... */
453 lck_mtx_unlock(&fourk_pager_lock);
454 }
455
456 if (needs_trimming) {
457 fourk_pager_trim();
458 }
459 /* caution: lock is not held on return... */
460 }
461
462 /*
463 * fourk_pager_deallocate()
464 *
465 * Release a reference on this pager and free it when the last
466 * reference goes away.
467 */
468 void
469 fourk_pager_deallocate(
470 memory_object_t mem_obj)
471 {
472 fourk_pager_t pager;
473
474 PAGER_DEBUG(PAGER_ALL, ("fourk_pager_deallocate: %p\n", mem_obj));
475 pager = fourk_pager_lookup(mem_obj);
476 fourk_pager_deallocate_internal(pager, FALSE);
477 }
478
479 /*
480 *
481 */
482 kern_return_t
483 fourk_pager_terminate(
484 #if !DEBUG
485 __unused
486 #endif
487 memory_object_t mem_obj)
488 {
489 PAGER_DEBUG(PAGER_ALL, ("fourk_pager_terminate: %p\n", mem_obj));
490
491 return KERN_SUCCESS;
492 }
493
494 /*
495 *
496 */
497 kern_return_t
498 fourk_pager_synchronize(
499 memory_object_t mem_obj,
500 memory_object_offset_t offset,
501 memory_object_size_t length,
502 __unused vm_sync_t sync_flags)
503 {
504 fourk_pager_t pager;
505
506 PAGER_DEBUG(PAGER_ALL, ("fourk_pager_synchronize: %p\n", mem_obj));
507
508 pager = fourk_pager_lookup(mem_obj);
509
510 memory_object_synchronize_completed(pager->pager_control,
511 offset, length);
512
513 return KERN_SUCCESS;
514 }
515
516 /*
517 * fourk_pager_map()
518 *
519 * This allows VM to let us, the EMM, know that this memory object
520 * is currently mapped one or more times. This is called by VM each time
521 * the memory object gets mapped and we take one extra reference on the
522 * memory object to account for all its mappings.
523 */
524 kern_return_t
525 fourk_pager_map(
526 memory_object_t mem_obj,
527 __unused vm_prot_t prot)
528 {
529 fourk_pager_t pager;
530
531 PAGER_DEBUG(PAGER_ALL, ("fourk_pager_map: %p\n", mem_obj));
532
533 pager = fourk_pager_lookup(mem_obj);
534
535 lck_mtx_lock(&fourk_pager_lock);
536 assert(pager->is_ready);
537 assert(pager->ref_count > 0); /* pager is alive */
538 if (pager->is_mapped == FALSE) {
539 /*
540 * First mapping of this pager: take an extra reference
541 * that will remain until all the mappings of this pager
542 * are removed.
543 */
544 pager->is_mapped = TRUE;
545 pager->ref_count++;
546 fourk_pager_count_mapped++;
547 }
548 lck_mtx_unlock(&fourk_pager_lock);
549
550 return KERN_SUCCESS;
551 }
552
553 /*
554 * fourk_pager_last_unmap()
555 *
556 * This is called by VM when this memory object is no longer mapped anywhere.
557 */
558 kern_return_t
559 fourk_pager_last_unmap(
560 memory_object_t mem_obj)
561 {
562 fourk_pager_t pager;
563 int count_unmapped;
564
565 PAGER_DEBUG(PAGER_ALL,
566 ("fourk_pager_last_unmap: %p\n", mem_obj));
567
568 pager = fourk_pager_lookup(mem_obj);
569
570 lck_mtx_lock(&fourk_pager_lock);
571 if (pager->is_mapped) {
572 /*
573 * All the mappings are gone, so let go of the one extra
574 * reference that represents all the mappings of this pager.
575 */
576 fourk_pager_count_mapped--;
577 count_unmapped = (fourk_pager_count -
578 fourk_pager_count_mapped);
579 if (count_unmapped > fourk_pager_count_unmapped_max) {
580 fourk_pager_count_unmapped_max = count_unmapped;
581 }
582 pager->is_mapped = FALSE;
583 fourk_pager_deallocate_internal(pager, TRUE);
584 /* caution: deallocate_internal() released the lock ! */
585 } else {
586 lck_mtx_unlock(&fourk_pager_lock);
587 }
588
589 return KERN_SUCCESS;
590 }
591
592
593 /*
594 *
595 */
596 fourk_pager_t
597 fourk_pager_lookup(
598 memory_object_t mem_obj)
599 {
600 fourk_pager_t pager;
601
602 pager = (fourk_pager_t) mem_obj;
603 assert(pager->pager_ops == &fourk_pager_ops);
604 assert(pager->ref_count > 0);
605 return pager;
606 }
607
608 void
609 fourk_pager_trim(void)
610 {
611 fourk_pager_t pager, prev_pager;
612 queue_head_t trim_queue;
613 int num_trim;
614 int count_unmapped;
615
616 lck_mtx_lock(&fourk_pager_lock);
617
618 /*
619 * We have too many pagers, try and trim some unused ones,
620 * starting with the oldest pager at the end of the queue.
621 */
622 queue_init(&trim_queue);
623 num_trim = 0;
624
625 for (pager = (fourk_pager_t)
626 queue_last(&fourk_pager_queue);
627 !queue_end(&fourk_pager_queue,
628 (queue_entry_t) pager);
629 pager = prev_pager) {
630 /* get prev elt before we dequeue */
631 prev_pager = (fourk_pager_t)
632 queue_prev(&pager->pager_queue);
633
634 if (pager->ref_count == 2 &&
635 pager->is_ready &&
636 !pager->is_mapped) {
637 /* this pager can be trimmed */
638 num_trim++;
639 /* remove this pager from the main list ... */
640 fourk_pager_dequeue(pager);
641 /* ... and add it to our trim queue */
642 queue_enter_first(&trim_queue,
643 pager,
644 fourk_pager_t,
645 pager_queue);
646
647 count_unmapped = (fourk_pager_count -
648 fourk_pager_count_mapped);
649 if (count_unmapped <= fourk_pager_cache_limit) {
650 /* we have enough pagers to trim */
651 break;
652 }
653 }
654 }
655 if (num_trim > fourk_pager_num_trim_max) {
656 fourk_pager_num_trim_max = num_trim;
657 }
658 fourk_pager_num_trim_total += num_trim;
659
660 lck_mtx_unlock(&fourk_pager_lock);
661
662 /* terminate the trimmed pagers */
663 while (!queue_empty(&trim_queue)) {
664 queue_remove_first(&trim_queue,
665 pager,
666 fourk_pager_t,
667 pager_queue);
668 pager->pager_queue.next = NULL;
669 pager->pager_queue.prev = NULL;
670 assert(pager->ref_count == 2);
671 /*
672 * We can't call deallocate_internal() because the pager
673 * has already been dequeued, but we still need to remove
674 * a reference.
675 */
676 pager->ref_count--;
677 fourk_pager_terminate_internal(pager);
678 }
679 }
680
681
682
683
684
685
686 vm_object_t
687 fourk_pager_to_vm_object(
688 memory_object_t mem_obj)
689 {
690 fourk_pager_t pager;
691 vm_object_t object;
692
693 pager = fourk_pager_lookup(mem_obj);
694 if (pager == NULL) {
695 return VM_OBJECT_NULL;
696 }
697
698 assert(pager->ref_count > 0);
699 assert(pager->pager_control != MEMORY_OBJECT_CONTROL_NULL);
700 object = memory_object_control_to_vm_object(pager->pager_control);
701 assert(object != VM_OBJECT_NULL);
702 return object;
703 }
704
705 memory_object_t
706 fourk_pager_create(void)
707 {
708 fourk_pager_t pager;
709 memory_object_control_t control;
710 kern_return_t kr;
711 int i;
712
713 #if 00
714 if (PAGE_SIZE_64 == FOURK_PAGE_SIZE) {
715 panic("fourk_pager_create: page size is 4K !?");
716 }
717 #endif
718
719 pager = (fourk_pager_t) kalloc(sizeof (*pager));
720 if (pager == FOURK_PAGER_NULL) {
721 return MEMORY_OBJECT_NULL;
722 }
723 bzero(pager, sizeof (*pager));
724
725 /*
726 * The vm_map call takes both named entry ports and raw memory
727 * objects in the same parameter. We need to make sure that
728 * vm_map does not see this object as a named entry port. So,
729 * we reserve the first word in the object for a fake ip_kotype
730 * setting - that will tell vm_map to use it as a memory object.
731 */
732 pager->pager_ops = &fourk_pager_ops;
733 pager->pager_ikot = IKOT_MEMORY_OBJECT;
734 pager->pager_control = MEMORY_OBJECT_CONTROL_NULL;
735 pager->ref_count = 2; /* existence + setup reference */
736 pager->is_ready = FALSE;/* not ready until it has a "name" */
737 pager->is_mapped = FALSE;
738
739 for (i = 0; i < FOURK_PAGER_SLOTS; i++) {
740 pager->slots[i].backing_object = (vm_object_t) -1;
741 pager->slots[i].backing_offset = (vm_object_offset_t) -1;
742 }
743
744 lck_mtx_lock(&fourk_pager_lock);
745
746 /* enter new pager at the head of our list of pagers */
747 queue_enter_first(&fourk_pager_queue,
748 pager,
749 fourk_pager_t,
750 pager_queue);
751 fourk_pager_count++;
752 if (fourk_pager_count > fourk_pager_count_max) {
753 fourk_pager_count_max = fourk_pager_count;
754 }
755 lck_mtx_unlock(&fourk_pager_lock);
756
757 kr = memory_object_create_named((memory_object_t) pager,
758 0,
759 &control);
760 assert(kr == KERN_SUCCESS);
761
762 lck_mtx_lock(&fourk_pager_lock);
763 /* the new pager is now ready to be used */
764 pager->is_ready = TRUE;
765 lck_mtx_unlock(&fourk_pager_lock);
766
767 /* wakeup anyone waiting for this pager to be ready */
768 thread_wakeup(&pager->is_ready);
769
770 return (memory_object_t) pager;
771 }
772
773 /*
774 * fourk_pager_data_request()
775 *
776 * Handles page-in requests from VM.
777 */
778 int fourk_pager_data_request_debug = 0;
779 kern_return_t
780 fourk_pager_data_request(
781 memory_object_t mem_obj,
782 memory_object_offset_t offset,
783 memory_object_cluster_size_t length,
784 #if !DEBUG
785 __unused
786 #endif
787 vm_prot_t protection_required,
788 memory_object_fault_info_t mo_fault_info)
789 {
790 fourk_pager_t pager;
791 memory_object_control_t mo_control;
792 upl_t upl;
793 int upl_flags;
794 upl_size_t upl_size;
795 upl_page_info_t *upl_pl;
796 unsigned int pl_count;
797 vm_object_t dst_object;
798 kern_return_t kr, retval;
799 vm_map_offset_t kernel_mapping;
800 vm_offset_t src_vaddr, dst_vaddr;
801 vm_offset_t cur_offset;
802 int sub_page;
803 int sub_page_idx, sub_page_cnt;
804
805 pager = fourk_pager_lookup(mem_obj);
806 assert(pager->is_ready);
807 assert(pager->ref_count > 1); /* pager is alive and mapped */
808
809 PAGER_DEBUG(PAGER_PAGEIN, ("fourk_pager_data_request: %p, %llx, %x, %x, pager %p\n", mem_obj, offset, length, protection_required, pager));
810
811 retval = KERN_SUCCESS;
812 kernel_mapping = 0;
813
814 offset = memory_object_trunc_page(offset);
815
816 /*
817 * Gather in a UPL all the VM pages requested by VM.
818 */
819 mo_control = pager->pager_control;
820
821 upl_size = length;
822 upl_flags =
823 UPL_RET_ONLY_ABSENT |
824 UPL_SET_LITE |
825 UPL_NO_SYNC |
826 UPL_CLEAN_IN_PLACE | /* triggers UPL_CLEAR_DIRTY */
827 UPL_SET_INTERNAL;
828 pl_count = 0;
829 kr = memory_object_upl_request(mo_control,
830 offset, upl_size,
831 &upl, NULL, NULL, upl_flags);
832 if (kr != KERN_SUCCESS) {
833 retval = kr;
834 goto done;
835 }
836 dst_object = mo_control->moc_object;
837 assert(dst_object != VM_OBJECT_NULL);
838
839 #if __x86_64__ || __arm__ || __arm64__
840 /* use the 1-to-1 mapping of physical memory */
841 #else /* __x86_64__ || __arm__ || __arm64__ */
842 /*
843 * Reserve 2 virtual pages in the kernel address space to map the
844 * source and destination physical pages when it's their turn to
845 * be processed.
846 */
847 vm_map_entry_t map_entry;
848
849 vm_object_reference(kernel_object); /* ref. for mapping */
850 kr = vm_map_find_space(kernel_map,
851 &kernel_mapping,
852 2 * PAGE_SIZE_64,
853 0,
854 0,
855 &map_entry);
856 if (kr != KERN_SUCCESS) {
857 vm_object_deallocate(kernel_object);
858 retval = kr;
859 goto done;
860 }
861 map_entry->object.vm_object = kernel_object;
862 map_entry->offset = kernel_mapping;
863 vm_map_unlock(kernel_map);
864 src_vaddr = CAST_DOWN(vm_offset_t, kernel_mapping);
865 dst_vaddr = CAST_DOWN(vm_offset_t, kernel_mapping + PAGE_SIZE_64);
866 #endif /* __x86_64__ || __arm__ || __arm64__ */
867
868 /*
869 * Fill in the contents of the pages requested by VM.
870 */
871 upl_pl = UPL_GET_INTERNAL_PAGE_LIST(upl);
872 pl_count = length / PAGE_SIZE;
873 for (cur_offset = 0;
874 retval == KERN_SUCCESS && cur_offset < length;
875 cur_offset += PAGE_SIZE) {
876 ppnum_t dst_pnum;
877 int num_subpg_signed, num_subpg_validated;
878 int num_subpg_tainted, num_subpg_nx;
879
880 if (!upl_page_present(upl_pl, (int)(cur_offset / PAGE_SIZE))) {
881 /* this page is not in the UPL: skip it */
882 continue;
883 }
884
885 /*
886 * Establish an explicit pmap mapping of the destination
887 * physical page.
888 * We can't do a regular VM mapping because the VM page
889 * is "busy".
890 */
891 dst_pnum = (ppnum_t)
892 upl_phys_page(upl_pl, (int)(cur_offset / PAGE_SIZE));
893 assert(dst_pnum != 0);
894 #if __x86_64__
895 dst_vaddr = (vm_map_offset_t)
896 PHYSMAP_PTOV((pmap_paddr_t)dst_pnum << PAGE_SHIFT);
897 #else
898 pmap_enter(kernel_pmap,
899 dst_vaddr,
900 dst_pnum,
901 VM_PROT_READ | VM_PROT_WRITE,
902 VM_PROT_NONE,
903 0,
904 TRUE);
905 #endif
906
907 /* retrieve appropriate data for each 4K-page in this page */
908 if (PAGE_SHIFT == FOURK_PAGE_SHIFT &&
909 page_shift_user32 == SIXTEENK_PAGE_SHIFT) {
910 /*
911 * Find the slot for the requested 4KB page in
912 * the 16K page...
913 */
914 assert(PAGE_SHIFT == FOURK_PAGE_SHIFT);
915 assert(page_shift_user32 == SIXTEENK_PAGE_SHIFT);
916 sub_page_idx = ((offset & SIXTEENK_PAGE_MASK) /
917 PAGE_SIZE);
918 /*
919 * ... and provide only that one 4KB page.
920 */
921 sub_page_cnt = 1;
922 } else {
923 /*
924 * Iterate over all slots, i.e. retrieve all four 4KB
925 * pages in the requested 16KB page.
926 */
927 assert(PAGE_SHIFT == SIXTEENK_PAGE_SHIFT);
928 sub_page_idx = 0;
929 sub_page_cnt = FOURK_PAGER_SLOTS;
930 }
931
932 num_subpg_signed = 0;
933 num_subpg_validated = 0;
934 num_subpg_tainted = 0;
935 num_subpg_nx = 0;
936
937 /* retrieve appropriate data for each 4K-page in this page */
938 for (sub_page = sub_page_idx;
939 sub_page < sub_page_idx + sub_page_cnt;
940 sub_page++) {
941 vm_object_t src_object;
942 memory_object_offset_t src_offset;
943 vm_offset_t offset_in_src_page;
944 kern_return_t error_code;
945 vm_page_t src_page;
946 vm_page_t top_page;
947 vm_prot_t prot;
948 int interruptible;
949 struct vm_object_fault_info fault_info;
950 boolean_t subpg_validated;
951 unsigned subpg_tainted;
952
953
954 if (offset < SIXTEENK_PAGE_SIZE) {
955 /*
956 * The 1st 16K-page can cover multiple
957 * sub-mappings, as described in the
958 * pager->slots[] array.
959 */
960 src_object =
961 pager->slots[sub_page].backing_object;
962 src_offset =
963 pager->slots[sub_page].backing_offset;
964 } else {
965 fourk_pager_backing_t slot;
966
967 /*
968 * Beyond the 1st 16K-page in the pager is
969 * an extension of the last "sub page" in
970 * the pager->slots[] array.
971 */
972 slot = &pager->slots[FOURK_PAGER_SLOTS-1];
973 src_object = slot->backing_object;
974 src_offset = slot->backing_offset;
975 src_offset += FOURK_PAGE_SIZE;
976 src_offset +=
977 (vm_map_trunc_page(offset,
978 SIXTEENK_PAGE_MASK)
979 - SIXTEENK_PAGE_SIZE);
980 src_offset += sub_page * FOURK_PAGE_SIZE;
981 }
982 offset_in_src_page = src_offset & PAGE_MASK_64;
983 src_offset = vm_object_trunc_page(src_offset);
984
985 if (src_object == VM_OBJECT_NULL ||
986 src_object == (vm_object_t) -1) {
987 /* zero-fill */
988 bzero((char *)(dst_vaddr +
989 ((sub_page-sub_page_idx)
990 * FOURK_PAGE_SIZE)),
991 FOURK_PAGE_SIZE);
992 if (fourk_pager_data_request_debug) {
993 printf("fourk_pager_data_request"
994 "(%p,0x%llx+0x%lx+0x%04x): "
995 "ZERO\n",
996 pager,
997 offset,
998 cur_offset,
999 ((sub_page - sub_page_idx)
1000 * FOURK_PAGE_SIZE));
1001 }
1002 continue;
1003 }
1004
1005 /* fault in the source page from src_object */
1006 retry_src_fault:
1007 src_page = VM_PAGE_NULL;
1008 top_page = VM_PAGE_NULL;
1009 fault_info = *((struct vm_object_fault_info *)
1010 (uintptr_t)mo_fault_info);
1011 fault_info.stealth = TRUE;
1012 fault_info.io_sync = FALSE;
1013 fault_info.mark_zf_absent = FALSE;
1014 fault_info.batch_pmap_op = FALSE;
1015 interruptible = fault_info.interruptible;
1016 prot = VM_PROT_READ;
1017 error_code = 0;
1018
1019 vm_object_lock(src_object);
1020 vm_object_paging_begin(src_object);
1021 kr = vm_fault_page(src_object,
1022 src_offset,
1023 VM_PROT_READ,
1024 FALSE,
1025 FALSE, /* src_page not looked up */
1026 &prot,
1027 &src_page,
1028 &top_page,
1029 NULL,
1030 &error_code,
1031 FALSE,
1032 FALSE,
1033 &fault_info);
1034 switch (kr) {
1035 case VM_FAULT_SUCCESS:
1036 break;
1037 case VM_FAULT_RETRY:
1038 goto retry_src_fault;
1039 case VM_FAULT_MEMORY_SHORTAGE:
1040 if (vm_page_wait(interruptible)) {
1041 goto retry_src_fault;
1042 }
1043 /* fall thru */
1044 case VM_FAULT_INTERRUPTED:
1045 retval = MACH_SEND_INTERRUPTED;
1046 goto src_fault_done;
1047 case VM_FAULT_SUCCESS_NO_VM_PAGE:
1048 /* success but no VM page: fail */
1049 vm_object_paging_end(src_object);
1050 vm_object_unlock(src_object);
1051 /*FALLTHROUGH*/
1052 case VM_FAULT_MEMORY_ERROR:
1053 /* the page is not there! */
1054 if (error_code) {
1055 retval = error_code;
1056 } else {
1057 retval = KERN_MEMORY_ERROR;
1058 }
1059 goto src_fault_done;
1060 default:
1061 panic("fourk_pager_data_request: "
1062 "vm_fault_page() unexpected error 0x%x\n",
1063 kr);
1064 }
1065 assert(src_page != VM_PAGE_NULL);
1066 assert(src_page->busy);
1067
1068 if (!src_page->active &&
1069 !src_page->inactive &&
1070 !src_page->speculative &&
1071 !src_page->throttled &&
1072 !VM_PAGE_WIRED(src_page)) {
1073 vm_page_lockspin_queues();
1074 if (!src_page->active &&
1075 !src_page->inactive &&
1076 !src_page->speculative &&
1077 !src_page->throttled &&
1078 !VM_PAGE_WIRED(src_page)) {
1079 vm_page_deactivate(src_page);
1080 }
1081 vm_page_unlock_queues();
1082 }
1083
1084 #if __x86_64__
1085 src_vaddr = (vm_map_offset_t)
1086 PHYSMAP_PTOV((pmap_paddr_t)src_page->phys_page
1087 << PAGE_SHIFT);
1088 #else
1089 /*
1090 * Establish an explicit mapping of the source
1091 * physical page.
1092 */
1093 pmap_enter(kernel_pmap,
1094 src_vaddr,
1095 src_page->phys_page,
1096 VM_PROT_READ,
1097 VM_PROT_NONE,
1098 0,
1099 TRUE);
1100 #endif
1101
1102 /*
1103 * Validate the 4K page we want from
1104 * this source page...
1105 */
1106 subpg_validated = FALSE;
1107 subpg_tainted = 0;
1108 if (src_page->object->code_signed) {
1109 vm_page_validate_cs_mapped_chunk(
1110 src_page,
1111 (const void *) src_vaddr,
1112 offset_in_src_page,
1113 &subpg_validated,
1114 &subpg_tainted);
1115 num_subpg_signed++;
1116 if (subpg_validated) {
1117 num_subpg_validated++;
1118 }
1119 if (subpg_tainted & CS_VALIDATE_TAINTED) {
1120 num_subpg_tainted++;
1121 }
1122 if (subpg_tainted & CS_VALIDATE_NX) {
1123 /* subpg should not be executable */
1124 if (sub_page_cnt > 1) {
1125 /*
1126 * The destination page has
1127 * more than 1 subpage and its
1128 * other subpages might need
1129 * EXEC, so we do not propagate
1130 * CS_VALIDATE_NX to the
1131 * destination page...
1132 */
1133 } else {
1134 num_subpg_nx++;
1135 }
1136 }
1137 }
1138
1139 /*
1140 * Copy the relevant portion of the source page
1141 * into the appropriate part of the destination page.
1142 */
1143 bcopy((const char *)(src_vaddr + offset_in_src_page),
1144 (char *)(dst_vaddr +
1145 ((sub_page - sub_page_idx) *
1146 FOURK_PAGE_SIZE)),
1147 FOURK_PAGE_SIZE);
1148 if (fourk_pager_data_request_debug) {
1149 printf("fourk_data_request"
1150 "(%p,0x%llx+0x%lx+0x%04x): "
1151 "backed by [%p:0x%llx]: "
1152 "[0x%016llx 0x%016llx] "
1153 "code_signed=%d "
1154 "cs_valid=%d cs_tainted=%d cs_nx=%d\n",
1155 pager,
1156 offset, cur_offset,
1157 (sub_page-sub_page_idx)*FOURK_PAGE_SIZE,
1158 src_page->object,
1159 src_page->offset + offset_in_src_page,
1160 *(uint64_t *)(dst_vaddr +
1161 ((sub_page-sub_page_idx) *
1162 FOURK_PAGE_SIZE)),
1163 *(uint64_t *)(dst_vaddr +
1164 ((sub_page-sub_page_idx) *
1165 FOURK_PAGE_SIZE) +
1166 8),
1167 src_page->object->code_signed,
1168 subpg_validated,
1169 !!(subpg_tainted & CS_VALIDATE_TAINTED),
1170 !!(subpg_tainted & CS_VALIDATE_NX));
1171 }
1172
1173 #if __x86_64__ || __arm__ || __arm64__
1174 /* we used the 1-to-1 mapping of physical memory */
1175 src_vaddr = 0;
1176 #else /* __x86_64__ || __arm__ || __arm64__ */
1177 /*
1178 * Remove the pmap mapping of the source page
1179 * in the kernel.
1180 */
1181 pmap_remove(kernel_pmap,
1182 (addr64_t) src_vaddr,
1183 (addr64_t) src_vaddr + PAGE_SIZE_64);
1184 #endif /* __x86_64__ || __arm__ || __arm64__ */
1185
1186 src_fault_done:
1187 /*
1188 * Cleanup the result of vm_fault_page().
1189 */
1190 if (src_page) {
1191 vm_object_t src_page_object;
1192
1193 src_page_object = src_page->object;
1194 PAGE_WAKEUP_DONE(src_page);
1195 src_page = VM_PAGE_NULL;
1196 vm_object_paging_end(src_page_object);
1197 vm_object_unlock(src_page_object);
1198 if (top_page) {
1199 vm_object_t top_object;
1200
1201 top_object = top_page->object;
1202 vm_object_lock(top_object);
1203 VM_PAGE_FREE(top_page);
1204 top_page = VM_PAGE_NULL;
1205 vm_object_paging_end(top_object);
1206 vm_object_unlock(top_object);
1207 }
1208 }
1209 }
1210 if (num_subpg_signed > 0) {
1211 /* some code-signing involved with this 16K page */
1212 if (num_subpg_tainted > 0) {
1213 /* a tainted subpage taints entire 16K page */
1214 UPL_SET_CS_TAINTED(upl_pl,
1215 cur_offset / PAGE_SIZE,
1216 TRUE);
1217 /* also mark as "validated" for consisteny */
1218 UPL_SET_CS_VALIDATED(upl_pl,
1219 cur_offset / PAGE_SIZE,
1220 TRUE);
1221 } else if (num_subpg_validated == num_subpg_signed) {
1222 /*
1223 * All the code-signed 4K subpages of this
1224 * 16K page are validated: our 16K page is
1225 * considered validated.
1226 */
1227 UPL_SET_CS_VALIDATED(upl_pl,
1228 cur_offset / PAGE_SIZE,
1229 TRUE);
1230 }
1231 if (num_subpg_nx > 0) {
1232 UPL_SET_CS_NX(upl_pl,
1233 cur_offset / PAGE_SIZE,
1234 TRUE);
1235 }
1236 }
1237 }
1238
1239 done:
1240 if (upl != NULL) {
1241 /* clean up the UPL */
1242
1243 /*
1244 * The pages are currently dirty because we've just been
1245 * writing on them, but as far as we're concerned, they're
1246 * clean since they contain their "original" contents as
1247 * provided by us, the pager.
1248 * Tell the UPL to mark them "clean".
1249 */
1250 upl_clear_dirty(upl, TRUE);
1251
1252 /* abort or commit the UPL */
1253 if (retval != KERN_SUCCESS) {
1254 upl_abort(upl, 0);
1255 if (retval == KERN_ABORTED) {
1256 wait_result_t wait_result;
1257
1258 /*
1259 * We aborted the fault and did not provide
1260 * any contents for the requested pages but
1261 * the pages themselves are not invalid, so
1262 * let's return success and let the caller
1263 * retry the fault, in case it might succeed
1264 * later (when the decryption code is up and
1265 * running in the kernel, for example).
1266 */
1267 retval = KERN_SUCCESS;
1268 /*
1269 * Wait a little bit first to avoid using
1270 * too much CPU time retrying and failing
1271 * the same fault over and over again.
1272 */
1273 wait_result = assert_wait_timeout(
1274 (event_t) fourk_pager_data_request,
1275 THREAD_UNINT,
1276 10000, /* 10ms */
1277 NSEC_PER_USEC);
1278 assert(wait_result == THREAD_WAITING);
1279 wait_result = thread_block(THREAD_CONTINUE_NULL);
1280 assert(wait_result == THREAD_TIMED_OUT);
1281 }
1282 } else {
1283 boolean_t empty;
1284 upl_commit_range(upl, 0, upl->size,
1285 UPL_COMMIT_CS_VALIDATED | UPL_COMMIT_WRITTEN_BY_KERNEL,
1286 upl_pl, pl_count, &empty);
1287 }
1288
1289 /* and deallocate the UPL */
1290 upl_deallocate(upl);
1291 upl = NULL;
1292 }
1293 if (kernel_mapping != 0) {
1294 /* clean up the mapping of the source and destination pages */
1295 kr = vm_map_remove(kernel_map,
1296 kernel_mapping,
1297 kernel_mapping + (2 * PAGE_SIZE_64),
1298 VM_MAP_NO_FLAGS);
1299 assert(kr == KERN_SUCCESS);
1300 kernel_mapping = 0;
1301 src_vaddr = 0;
1302 dst_vaddr = 0;
1303 }
1304
1305 return retval;
1306 }
1307
1308
1309
1310 kern_return_t
1311 fourk_pager_populate(
1312 memory_object_t mem_obj,
1313 boolean_t overwrite,
1314 int index,
1315 vm_object_t new_backing_object,
1316 vm_object_offset_t new_backing_offset,
1317 vm_object_t *old_backing_object,
1318 vm_object_offset_t *old_backing_offset)
1319 {
1320 fourk_pager_t pager;
1321
1322 pager = fourk_pager_lookup(mem_obj);
1323 if (pager == NULL) {
1324 return KERN_INVALID_ARGUMENT;
1325 }
1326
1327 assert(pager->ref_count > 0);
1328 assert(pager->pager_control != MEMORY_OBJECT_CONTROL_NULL);
1329
1330 if (index < 0 || index > FOURK_PAGER_SLOTS) {
1331 return KERN_INVALID_ARGUMENT;
1332 }
1333
1334 if (!overwrite &&
1335 (pager->slots[index].backing_object != (vm_object_t) -1 ||
1336 pager->slots[index].backing_offset != (vm_object_offset_t) -1)) {
1337 return KERN_INVALID_ADDRESS;
1338 }
1339
1340 *old_backing_object = pager->slots[index].backing_object;
1341 *old_backing_offset = pager->slots[index].backing_offset;
1342
1343 pager->slots[index].backing_object = new_backing_object;
1344 pager->slots[index].backing_offset = new_backing_offset;
1345
1346 return KERN_SUCCESS;
1347 }
1348