2 * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
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.
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.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
60 * Author: Avadis Tevanian, Jr., Michael Wayne Young
62 * Resident memory management module.
66 #include <libkern/OSAtomic.h>
67 #include <libkern/OSDebug.h>
69 #include <mach/clock_types.h>
70 #include <mach/vm_prot.h>
71 #include <mach/vm_statistics.h>
73 #include <kern/counters.h>
74 #include <kern/sched_prim.h>
75 #include <kern/policy_internal.h>
76 #include <kern/task.h>
77 #include <kern/thread.h>
78 #include <kern/kalloc.h>
79 #include <kern/zalloc.h>
81 #include <kern/ledger.h>
83 #include <vm/vm_init.h>
84 #include <vm/vm_map.h>
85 #include <vm/vm_page.h>
86 #include <vm/vm_pageout.h>
87 #include <vm/vm_kern.h> /* kernel_memory_allocate() */
88 #include <kern/misc_protos.h>
89 #include <zone_debug.h>
90 #include <mach_debug/zone_info.h>
92 #include <pexpert/pexpert.h>
93 #include <san/kasan.h>
95 #include <vm/vm_protos.h>
96 #include <vm/memory_object.h>
97 #include <vm/vm_purgeable_internal.h>
98 #include <vm/vm_compressor.h>
100 #if CONFIG_PHANTOM_CACHE
101 #include <vm/vm_phantom_cache.h>
104 #include <IOKit/IOHibernatePrivate.h>
106 #include <sys/kdebug.h>
109 char vm_page_inactive_states
[VM_PAGE_Q_STATE_ARRAY_SIZE
];
110 char vm_page_pageable_states
[VM_PAGE_Q_STATE_ARRAY_SIZE
];
111 char vm_page_non_speculative_pageable_states
[VM_PAGE_Q_STATE_ARRAY_SIZE
];
112 char vm_page_active_or_inactive_states
[VM_PAGE_Q_STATE_ARRAY_SIZE
];
114 #if CONFIG_SECLUDED_MEMORY
115 struct vm_page_secluded_data vm_page_secluded
;
116 #endif /* CONFIG_SECLUDED_MEMORY */
118 boolean_t hibernate_cleaning_in_progress
= FALSE
;
119 boolean_t vm_page_free_verify
= TRUE
;
121 uint32_t vm_lopage_free_count
= 0;
122 uint32_t vm_lopage_free_limit
= 0;
123 uint32_t vm_lopage_lowater
= 0;
124 boolean_t vm_lopage_refill
= FALSE
;
125 boolean_t vm_lopage_needed
= FALSE
;
127 lck_mtx_ext_t vm_page_queue_lock_ext
;
128 lck_mtx_ext_t vm_page_queue_free_lock_ext
;
129 lck_mtx_ext_t vm_purgeable_queue_lock_ext
;
131 int speculative_age_index
= 0;
132 int speculative_steal_index
= 0;
133 struct vm_speculative_age_q vm_page_queue_speculative
[VM_PAGE_MAX_SPECULATIVE_AGE_Q
+ 1];
136 __private_extern__
void vm_page_init_lck_grp(void);
138 static void vm_page_free_prepare(vm_page_t page
);
139 static vm_page_t
vm_page_grab_fictitious_common(ppnum_t phys_addr
);
141 static void vm_tag_init(void);
143 uint64_t vm_min_kernel_and_kext_address
= VM_MIN_KERNEL_AND_KEXT_ADDRESS
;
144 uint32_t vm_packed_from_vm_pages_array_mask
= VM_PACKED_FROM_VM_PAGES_ARRAY
;
145 uint32_t vm_packed_pointer_shift
= VM_PACKED_POINTER_SHIFT
;
148 * Associated with page of user-allocatable memory is a
153 * These variables record the values returned by vm_page_bootstrap,
154 * for debugging purposes. The implementation of pmap_steal_memory
155 * and pmap_startup here also uses them internally.
158 vm_offset_t virtual_space_start
;
159 vm_offset_t virtual_space_end
;
160 uint32_t vm_page_pages
;
163 * The vm_page_lookup() routine, which provides for fast
164 * (virtual memory object, offset) to page lookup, employs
165 * the following hash table. The vm_page_{insert,remove}
166 * routines install and remove associations in the table.
167 * [This table is often called the virtual-to-physical,
171 vm_page_packed_t page_list
;
172 #if MACH_PAGE_HASH_STATS
173 int cur_count
; /* current count */
174 int hi_count
; /* high water mark */
175 #endif /* MACH_PAGE_HASH_STATS */
179 #define BUCKETS_PER_LOCK 16
181 vm_page_bucket_t
*vm_page_buckets
; /* Array of buckets */
182 unsigned int vm_page_bucket_count
= 0; /* How big is array? */
183 unsigned int vm_page_hash_mask
; /* Mask for hash function */
184 unsigned int vm_page_hash_shift
; /* Shift for hash function */
185 uint32_t vm_page_bucket_hash
; /* Basic bucket hash */
186 unsigned int vm_page_bucket_lock_count
= 0; /* How big is array of locks? */
188 #ifndef VM_TAG_ACTIVE_UPDATE
189 #error VM_TAG_ACTIVE_UPDATE
191 #ifndef VM_MAX_TAG_ZONES
192 #error VM_MAX_TAG_ZONES
195 boolean_t vm_tag_active_update
= VM_TAG_ACTIVE_UPDATE
;
196 lck_spin_t
*vm_page_bucket_locks
;
197 lck_spin_t vm_objects_wired_lock
;
198 lck_spin_t vm_allocation_sites_lock
;
200 vm_allocation_site_t vm_allocation_sites_static
[VM_KERN_MEMORY_FIRST_DYNAMIC
+ 1];
201 vm_allocation_site_t
* vm_allocation_sites
[VM_MAX_TAG_VALUE
];
203 vm_allocation_zone_total_t
** vm_allocation_zone_totals
;
204 #endif /* VM_MAX_TAG_ZONES */
206 vm_tag_t vm_allocation_tag_highest
;
208 #if VM_PAGE_BUCKETS_CHECK
209 boolean_t vm_page_buckets_check_ready
= FALSE
;
210 #if VM_PAGE_FAKE_BUCKETS
211 vm_page_bucket_t
*vm_page_fake_buckets
; /* decoy buckets */
212 vm_map_offset_t vm_page_fake_buckets_start
, vm_page_fake_buckets_end
;
213 #endif /* VM_PAGE_FAKE_BUCKETS */
214 #endif /* VM_PAGE_BUCKETS_CHECK */
218 #if MACH_PAGE_HASH_STATS
219 /* This routine is only for debug. It is intended to be called by
220 * hand by a developer using a kernel debugger. This routine prints
221 * out vm_page_hash table statistics to the kernel debug console.
231 for (i
= 0; i
< vm_page_bucket_count
; i
++) {
232 if (vm_page_buckets
[i
].hi_count
) {
234 highsum
+= vm_page_buckets
[i
].hi_count
;
235 if (vm_page_buckets
[i
].hi_count
> maxdepth
)
236 maxdepth
= vm_page_buckets
[i
].hi_count
;
239 printf("Total number of buckets: %d\n", vm_page_bucket_count
);
240 printf("Number used buckets: %d = %d%%\n",
241 numbuckets
, 100*numbuckets
/vm_page_bucket_count
);
242 printf("Number unused buckets: %d = %d%%\n",
243 vm_page_bucket_count
- numbuckets
,
244 100*(vm_page_bucket_count
-numbuckets
)/vm_page_bucket_count
);
245 printf("Sum of bucket max depth: %d\n", highsum
);
246 printf("Average bucket depth: %d.%2d\n",
247 highsum
/vm_page_bucket_count
,
248 highsum%vm_page_bucket_count
);
249 printf("Maximum bucket depth: %d\n", maxdepth
);
251 #endif /* MACH_PAGE_HASH_STATS */
254 * The virtual page size is currently implemented as a runtime
255 * variable, but is constant once initialized using vm_set_page_size.
256 * This initialization must be done in the machine-dependent
257 * bootstrap sequence, before calling other machine-independent
260 * All references to the virtual page size outside this
261 * module must use the PAGE_SIZE, PAGE_MASK and PAGE_SHIFT
264 #if defined(__arm__) || defined(__arm64__)
269 vm_size_t page_size
= PAGE_SIZE
;
270 vm_size_t page_mask
= PAGE_MASK
;
271 int page_shift
= PAGE_SHIFT
;
275 * Resident page structures are initialized from
276 * a template (see vm_page_alloc).
278 * When adding a new field to the virtual memory
279 * object structure, be sure to add initialization
280 * (see vm_page_bootstrap).
282 struct vm_page vm_page_template
;
284 vm_page_t vm_pages
= VM_PAGE_NULL
;
285 vm_page_t vm_page_array_beginning_addr
;
286 vm_page_t vm_page_array_ending_addr
;
287 vm_page_t vm_page_array_boundary
;
289 unsigned int vm_pages_count
= 0;
290 ppnum_t vm_page_lowest
= 0;
293 * Resident pages that represent real memory
294 * are allocated from a set of free lists,
297 unsigned int vm_colors
;
298 unsigned int vm_color_mask
; /* mask is == (vm_colors-1) */
299 unsigned int vm_cache_geometry_colors
= 0; /* set by hw dependent code during startup */
300 unsigned int vm_free_magazine_refill_limit
= 0;
303 struct vm_page_queue_free_head
{
304 vm_page_queue_head_t qhead
;
305 } __attribute__((aligned(VM_PACKED_POINTER_ALIGNMENT
)));
307 struct vm_page_queue_free_head vm_page_queue_free
[MAX_COLORS
];
310 unsigned int vm_page_free_wanted
;
311 unsigned int vm_page_free_wanted_privileged
;
312 #if CONFIG_SECLUDED_MEMORY
313 unsigned int vm_page_free_wanted_secluded
;
314 #endif /* CONFIG_SECLUDED_MEMORY */
315 unsigned int vm_page_free_count
;
318 * Occasionally, the virtual memory system uses
319 * resident page structures that do not refer to
320 * real pages, for example to leave a page with
321 * important state information in the VP table.
323 * These page structures are allocated the way
324 * most other kernel structures are.
326 zone_t vm_page_array_zone
;
328 vm_locks_array_t vm_page_locks
;
329 decl_lck_mtx_data(,vm_page_alloc_lock
)
330 lck_mtx_ext_t vm_page_alloc_lock_ext
;
332 unsigned int io_throttle_zero_fill
;
334 unsigned int vm_page_local_q_count
= 0;
335 unsigned int vm_page_local_q_soft_limit
= 250;
336 unsigned int vm_page_local_q_hard_limit
= 500;
337 struct vplq
*vm_page_local_q
= NULL
;
339 /* N.B. Guard and fictitious pages must not
340 * be assigned a zero phys_page value.
343 * Fictitious pages don't have a physical address,
344 * but we must initialize phys_page to something.
345 * For debugging, this should be a strange value
346 * that the pmap module can recognize in assertions.
348 const ppnum_t vm_page_fictitious_addr
= (ppnum_t
) -1;
351 * Guard pages are not accessible so they don't
352 * need a physical address, but we need to enter
354 * Let's make it recognizable and make sure that
355 * we don't use a real physical page with that
358 const ppnum_t vm_page_guard_addr
= (ppnum_t
) -2;
361 * Resident page structures are also chained on
362 * queues that are used by the page replacement
363 * system (pageout daemon). These queues are
364 * defined here, but are shared by the pageout
365 * module. The inactive queue is broken into
366 * file backed and anonymous for convenience as the
367 * pageout daemon often assignes a higher
368 * importance to anonymous pages (less likely to pick)
370 vm_page_queue_head_t vm_page_queue_active
__attribute__((aligned(VM_PACKED_POINTER_ALIGNMENT
)));
371 vm_page_queue_head_t vm_page_queue_inactive
__attribute__((aligned(VM_PACKED_POINTER_ALIGNMENT
)));
372 #if CONFIG_SECLUDED_MEMORY
373 vm_page_queue_head_t vm_page_queue_secluded
__attribute__((aligned(VM_PACKED_POINTER_ALIGNMENT
)));
374 #endif /* CONFIG_SECLUDED_MEMORY */
375 vm_page_queue_head_t vm_page_queue_anonymous
__attribute__((aligned(VM_PACKED_POINTER_ALIGNMENT
))); /* inactive memory queue for anonymous pages */
376 vm_page_queue_head_t vm_page_queue_throttled
__attribute__((aligned(VM_PACKED_POINTER_ALIGNMENT
)));
378 queue_head_t vm_objects_wired
;
380 #if CONFIG_BACKGROUND_QUEUE
381 vm_page_queue_head_t vm_page_queue_background
__attribute__((aligned(VM_PACKED_POINTER_ALIGNMENT
)));
382 uint32_t vm_page_background_target
;
383 uint32_t vm_page_background_count
;
384 uint64_t vm_page_background_promoted_count
;
386 uint32_t vm_page_background_internal_count
;
387 uint32_t vm_page_background_external_count
;
389 uint32_t vm_page_background_mode
;
390 uint32_t vm_page_background_exclude_external
;
393 unsigned int vm_page_active_count
;
394 unsigned int vm_page_inactive_count
;
395 #if CONFIG_SECLUDED_MEMORY
396 unsigned int vm_page_secluded_count
;
397 unsigned int vm_page_secluded_count_free
;
398 unsigned int vm_page_secluded_count_inuse
;
399 #endif /* CONFIG_SECLUDED_MEMORY */
400 unsigned int vm_page_anonymous_count
;
401 unsigned int vm_page_throttled_count
;
402 unsigned int vm_page_speculative_count
;
404 unsigned int vm_page_wire_count
;
405 unsigned int vm_page_wire_count_on_boot
= 0;
406 unsigned int vm_page_stolen_count
;
407 unsigned int vm_page_wire_count_initial
;
408 unsigned int vm_page_pages_initial
;
409 unsigned int vm_page_gobble_count
= 0;
411 #define VM_PAGE_WIRE_COUNT_WARNING 0
412 #define VM_PAGE_GOBBLE_COUNT_WARNING 0
414 unsigned int vm_page_purgeable_count
= 0; /* # of pages purgeable now */
415 unsigned int vm_page_purgeable_wired_count
= 0; /* # of purgeable pages that are wired now */
416 uint64_t vm_page_purged_count
= 0; /* total count of purged pages */
418 unsigned int vm_page_xpmapped_external_count
= 0;
419 unsigned int vm_page_external_count
= 0;
420 unsigned int vm_page_internal_count
= 0;
421 unsigned int vm_page_pageable_external_count
= 0;
422 unsigned int vm_page_pageable_internal_count
= 0;
424 #if DEVELOPMENT || DEBUG
425 unsigned int vm_page_speculative_recreated
= 0;
426 unsigned int vm_page_speculative_created
= 0;
427 unsigned int vm_page_speculative_used
= 0;
430 vm_page_queue_head_t vm_page_queue_cleaned
__attribute__((aligned(VM_PACKED_POINTER_ALIGNMENT
)));
432 unsigned int vm_page_cleaned_count
= 0;
433 unsigned int vm_pageout_enqueued_cleaned
= 0;
435 uint64_t max_valid_dma_address
= 0xffffffffffffffffULL
;
436 ppnum_t max_valid_low_ppnum
= 0xffffffff;
440 * Several page replacement parameters are also
441 * shared with this module, so that page allocation
442 * (done here in vm_page_alloc) can trigger the
445 unsigned int vm_page_free_target
= 0;
446 unsigned int vm_page_free_min
= 0;
447 unsigned int vm_page_throttle_limit
= 0;
448 unsigned int vm_page_inactive_target
= 0;
449 #if CONFIG_SECLUDED_MEMORY
450 unsigned int vm_page_secluded_target
= 0;
451 #endif /* CONFIG_SECLUDED_MEMORY */
452 unsigned int vm_page_anonymous_min
= 0;
453 unsigned int vm_page_inactive_min
= 0;
454 unsigned int vm_page_free_reserved
= 0;
455 unsigned int vm_page_throttle_count
= 0;
459 * The VM system has a couple of heuristics for deciding
460 * that pages are "uninteresting" and should be placed
461 * on the inactive queue as likely candidates for replacement.
462 * These variables let the heuristics be controlled at run-time
463 * to make experimentation easier.
466 boolean_t vm_page_deactivate_hint
= TRUE
;
468 struct vm_page_stats_reusable vm_page_stats_reusable
;
473 * Sets the page size, perhaps based upon the memory
474 * size. Must be called before any use of page-size
475 * dependent functions.
477 * Sets page_shift and page_mask from page_size.
480 vm_set_page_size(void)
482 page_size
= PAGE_SIZE
;
483 page_mask
= PAGE_MASK
;
484 page_shift
= PAGE_SHIFT
;
486 if ((page_mask
& page_size
) != 0)
487 panic("vm_set_page_size: page size not a power of two");
489 for (page_shift
= 0; ; page_shift
++)
490 if ((1U << page_shift
) == page_size
)
494 #if defined (__x86_64__)
496 #define MAX_CLUMP_SIZE 16
497 #define DEFAULT_CLUMP_SIZE 4
499 unsigned int vm_clump_size
, vm_clump_mask
, vm_clump_shift
, vm_clump_promote_threshold
;
501 #if DEVELOPMENT || DEBUG
502 unsigned long vm_clump_stats
[MAX_CLUMP_SIZE
+1];
503 unsigned long vm_clump_allocs
, vm_clump_inserts
, vm_clump_inrange
, vm_clump_promotes
;
505 static inline void vm_clump_update_stats(unsigned int c
) {
506 assert(c
<=vm_clump_size
);
507 if(c
>0 && c
<=vm_clump_size
) vm_clump_stats
[c
]+=c
;
510 #endif /* if DEVELOPMENT || DEBUG */
512 /* Called once to setup the VM clump knobs */
514 vm_page_setup_clump( void )
516 unsigned int override
, n
;
518 vm_clump_size
= DEFAULT_CLUMP_SIZE
;
519 if ( PE_parse_boot_argn("clump_size", &override
, sizeof (override
)) ) vm_clump_size
= override
;
521 if(vm_clump_size
> MAX_CLUMP_SIZE
) panic("vm_page_setup_clump:: clump_size is too large!");
522 if(vm_clump_size
< 1) panic("vm_page_setup_clump:: clump_size must be >= 1");
523 if((vm_clump_size
& (vm_clump_size
-1)) != 0) panic("vm_page_setup_clump:: clump_size must be a power of 2");
525 vm_clump_promote_threshold
= vm_clump_size
;
526 vm_clump_mask
= vm_clump_size
- 1;
527 for(vm_clump_shift
=0, n
=vm_clump_size
; n
>1; n
>>=1, vm_clump_shift
++);
529 #if DEVELOPMENT || DEBUG
530 bzero(vm_clump_stats
, sizeof(vm_clump_stats
));
531 vm_clump_allocs
= vm_clump_inserts
= vm_clump_inrange
= vm_clump_promotes
= 0;
532 #endif /* if DEVELOPMENT || DEBUG */
535 #endif /* #if defined (__x86_64__) */
537 #define COLOR_GROUPS_TO_STEAL 4
539 /* Called once during statup, once the cache geometry is known.
542 vm_page_set_colors( void )
544 unsigned int n
, override
;
546 #if defined (__x86_64__)
547 /* adjust #colors because we need to color outside the clump boundary */
548 vm_cache_geometry_colors
>>= vm_clump_shift
;
550 if ( PE_parse_boot_argn("colors", &override
, sizeof (override
)) ) /* colors specified as a boot-arg? */
552 else if ( vm_cache_geometry_colors
) /* do we know what the cache geometry is? */
553 n
= vm_cache_geometry_colors
;
554 else n
= DEFAULT_COLORS
; /* use default if all else fails */
558 if ( n
> MAX_COLORS
)
561 /* the count must be a power of 2 */
562 if ( ( n
& (n
- 1)) != 0 )
563 n
= DEFAULT_COLORS
; /* use default if all else fails */
566 vm_color_mask
= n
- 1;
568 vm_free_magazine_refill_limit
= vm_colors
* COLOR_GROUPS_TO_STEAL
;
570 #if defined (__x86_64__)
571 /* adjust for reduction in colors due to clumping and multiple cores */
573 vm_free_magazine_refill_limit
*= (vm_clump_size
* real_ncpus
);
578 lck_grp_t vm_page_lck_grp_free
;
579 lck_grp_t vm_page_lck_grp_queue
;
580 lck_grp_t vm_page_lck_grp_local
;
581 lck_grp_t vm_page_lck_grp_purge
;
582 lck_grp_t vm_page_lck_grp_alloc
;
583 lck_grp_t vm_page_lck_grp_bucket
;
584 lck_grp_attr_t vm_page_lck_grp_attr
;
585 lck_attr_t vm_page_lck_attr
;
588 __private_extern__
void
589 vm_page_init_lck_grp(void)
592 * initialze the vm_page lock world
594 lck_grp_attr_setdefault(&vm_page_lck_grp_attr
);
595 lck_grp_init(&vm_page_lck_grp_free
, "vm_page_free", &vm_page_lck_grp_attr
);
596 lck_grp_init(&vm_page_lck_grp_queue
, "vm_page_queue", &vm_page_lck_grp_attr
);
597 lck_grp_init(&vm_page_lck_grp_local
, "vm_page_queue_local", &vm_page_lck_grp_attr
);
598 lck_grp_init(&vm_page_lck_grp_purge
, "vm_page_purge", &vm_page_lck_grp_attr
);
599 lck_grp_init(&vm_page_lck_grp_alloc
, "vm_page_alloc", &vm_page_lck_grp_attr
);
600 lck_grp_init(&vm_page_lck_grp_bucket
, "vm_page_bucket", &vm_page_lck_grp_attr
);
601 lck_attr_setdefault(&vm_page_lck_attr
);
602 lck_mtx_init_ext(&vm_page_alloc_lock
, &vm_page_alloc_lock_ext
, &vm_page_lck_grp_alloc
, &vm_page_lck_attr
);
604 vm_compressor_init_locks();
608 vm_page_init_local_q()
610 unsigned int num_cpus
;
612 struct vplq
*t_local_q
;
614 num_cpus
= ml_get_max_cpus();
617 * no point in this for a uni-processor system
621 /* KASAN breaks the expectation of a size-aligned object by adding a
622 * rezone, so explicitly align. */
623 t_local_q
= (struct vplq
*)kalloc(num_cpus
* sizeof(struct vplq
) + VM_PACKED_POINTER_ALIGNMENT
);
624 t_local_q
= (void *)(((uintptr_t)t_local_q
+ (VM_PACKED_POINTER_ALIGNMENT
-1)) & ~(VM_PACKED_POINTER_ALIGNMENT
-1));
626 t_local_q
= (struct vplq
*)kalloc(num_cpus
* sizeof(struct vplq
));
629 for (i
= 0; i
< num_cpus
; i
++) {
632 lq
= &t_local_q
[i
].vpl_un
.vpl
;
633 VPL_LOCK_INIT(lq
, &vm_page_lck_grp_local
, &vm_page_lck_attr
);
634 vm_page_queue_init(&lq
->vpl_queue
);
636 lq
->vpl_internal_count
= 0;
637 lq
->vpl_external_count
= 0;
639 vm_page_local_q_count
= num_cpus
;
641 vm_page_local_q
= (struct vplq
*)t_local_q
;
646 * vm_init_before_launchd
648 * This should be called right before launchd is loaded.
651 vm_init_before_launchd()
653 vm_page_wire_count_on_boot
= vm_page_wire_count
;
660 * Initializes the resident memory module.
662 * Allocates memory for the page cells, and
663 * for the object/offset-to-page hash table headers.
664 * Each page cell is initialized and placed on the free list.
665 * Returns the range of available kernel virtual memory.
680 * Initialize the vm_page template.
683 m
= &vm_page_template
;
684 bzero(m
, sizeof (*m
));
686 #if CONFIG_BACKGROUND_QUEUE
687 m
->vm_page_backgroundq
.next
= 0;
688 m
->vm_page_backgroundq
.prev
= 0;
689 m
->vm_page_in_background
= FALSE
;
690 m
->vm_page_on_backgroundq
= FALSE
;
693 VM_PAGE_ZERO_PAGEQ_ENTRY(m
);
698 m
->vm_page_object
= 0; /* reset later */
699 m
->offset
= (vm_object_offset_t
) -1; /* reset later */
702 m
->vm_page_q_state
= VM_PAGE_NOT_ON_Q
;
704 m
->reference
= FALSE
;
707 m
->__unused_pageq_bits
= 0;
709 #if !defined(__arm__) && !defined(__arm64__)
710 VM_PAGE_SET_PHYS_PAGE(m
, 0); /* reset later */
716 m
->fictitious
= FALSE
;
719 m
->free_when_done
= FALSE
;
725 m
->clustered
= FALSE
;
726 m
->overwriting
= FALSE
;
729 m
->cs_validated
= FALSE
;
730 m
->cs_tainted
= FALSE
;
736 m
->written_by_kernel
= FALSE
;
737 m
->__unused_object_bits
= 0;
740 * Initialize the page queues.
742 vm_page_init_lck_grp();
744 lck_mtx_init_ext(&vm_page_queue_free_lock
, &vm_page_queue_free_lock_ext
, &vm_page_lck_grp_free
, &vm_page_lck_attr
);
745 lck_mtx_init_ext(&vm_page_queue_lock
, &vm_page_queue_lock_ext
, &vm_page_lck_grp_queue
, &vm_page_lck_attr
);
746 lck_mtx_init_ext(&vm_purgeable_queue_lock
, &vm_purgeable_queue_lock_ext
, &vm_page_lck_grp_purge
, &vm_page_lck_attr
);
748 for (i
= 0; i
< PURGEABLE_Q_TYPE_MAX
; i
++) {
751 purgeable_queues
[i
].token_q_head
= 0;
752 purgeable_queues
[i
].token_q_tail
= 0;
753 for (group
= 0; group
< NUM_VOLATILE_GROUPS
; group
++)
754 queue_init(&purgeable_queues
[i
].objq
[group
]);
756 purgeable_queues
[i
].type
= i
;
757 purgeable_queues
[i
].new_pages
= 0;
759 purgeable_queues
[i
].debug_count_tokens
= 0;
760 purgeable_queues
[i
].debug_count_objects
= 0;
763 purgeable_nonvolatile_count
= 0;
764 queue_init(&purgeable_nonvolatile_queue
);
766 for (i
= 0; i
< MAX_COLORS
; i
++ )
767 vm_page_queue_init(&vm_page_queue_free
[i
].qhead
);
769 vm_page_queue_init(&vm_lopage_queue_free
);
770 vm_page_queue_init(&vm_page_queue_active
);
771 vm_page_queue_init(&vm_page_queue_inactive
);
772 #if CONFIG_SECLUDED_MEMORY
773 vm_page_queue_init(&vm_page_queue_secluded
);
774 #endif /* CONFIG_SECLUDED_MEMORY */
775 vm_page_queue_init(&vm_page_queue_cleaned
);
776 vm_page_queue_init(&vm_page_queue_throttled
);
777 vm_page_queue_init(&vm_page_queue_anonymous
);
778 queue_init(&vm_objects_wired
);
780 for ( i
= 0; i
<= VM_PAGE_MAX_SPECULATIVE_AGE_Q
; i
++ ) {
781 vm_page_queue_init(&vm_page_queue_speculative
[i
].age_q
);
783 vm_page_queue_speculative
[i
].age_ts
.tv_sec
= 0;
784 vm_page_queue_speculative
[i
].age_ts
.tv_nsec
= 0;
786 #if CONFIG_BACKGROUND_QUEUE
787 vm_page_queue_init(&vm_page_queue_background
);
789 vm_page_background_count
= 0;
790 vm_page_background_internal_count
= 0;
791 vm_page_background_external_count
= 0;
792 vm_page_background_promoted_count
= 0;
794 vm_page_background_target
= (unsigned int)(atop_64(max_mem
) / 25);
796 if (vm_page_background_target
> VM_PAGE_BACKGROUND_TARGET_MAX
)
797 vm_page_background_target
= VM_PAGE_BACKGROUND_TARGET_MAX
;
799 vm_page_background_mode
= VM_PAGE_BG_LEVEL_1
;
800 vm_page_background_exclude_external
= 0;
802 PE_parse_boot_argn("vm_page_bg_mode", &vm_page_background_mode
, sizeof(vm_page_background_mode
));
803 PE_parse_boot_argn("vm_page_bg_exclude_external", &vm_page_background_exclude_external
, sizeof(vm_page_background_exclude_external
));
804 PE_parse_boot_argn("vm_page_bg_target", &vm_page_background_target
, sizeof(vm_page_background_target
));
806 if (vm_page_background_mode
> VM_PAGE_BG_LEVEL_1
)
807 vm_page_background_mode
= VM_PAGE_BG_LEVEL_1
;
809 vm_page_free_wanted
= 0;
810 vm_page_free_wanted_privileged
= 0;
811 #if CONFIG_SECLUDED_MEMORY
812 vm_page_free_wanted_secluded
= 0;
813 #endif /* CONFIG_SECLUDED_MEMORY */
815 #if defined (__x86_64__)
816 /* this must be called before vm_page_set_colors() */
817 vm_page_setup_clump();
820 vm_page_set_colors();
822 bzero(vm_page_inactive_states
, sizeof(vm_page_inactive_states
));
823 vm_page_inactive_states
[VM_PAGE_ON_INACTIVE_INTERNAL_Q
] = 1;
824 vm_page_inactive_states
[VM_PAGE_ON_INACTIVE_EXTERNAL_Q
] = 1;
825 vm_page_inactive_states
[VM_PAGE_ON_INACTIVE_CLEANED_Q
] = 1;
827 bzero(vm_page_pageable_states
, sizeof(vm_page_pageable_states
));
828 vm_page_pageable_states
[VM_PAGE_ON_INACTIVE_INTERNAL_Q
] = 1;
829 vm_page_pageable_states
[VM_PAGE_ON_INACTIVE_EXTERNAL_Q
] = 1;
830 vm_page_pageable_states
[VM_PAGE_ON_INACTIVE_CLEANED_Q
] = 1;
831 vm_page_pageable_states
[VM_PAGE_ON_ACTIVE_Q
] = 1;
832 vm_page_pageable_states
[VM_PAGE_ON_SPECULATIVE_Q
] = 1;
833 vm_page_pageable_states
[VM_PAGE_ON_THROTTLED_Q
] = 1;
834 #if CONFIG_SECLUDED_MEMORY
835 vm_page_pageable_states
[VM_PAGE_ON_SECLUDED_Q
] = 1;
836 #endif /* CONFIG_SECLUDED_MEMORY */
838 bzero(vm_page_non_speculative_pageable_states
, sizeof(vm_page_non_speculative_pageable_states
));
839 vm_page_non_speculative_pageable_states
[VM_PAGE_ON_INACTIVE_INTERNAL_Q
] = 1;
840 vm_page_non_speculative_pageable_states
[VM_PAGE_ON_INACTIVE_EXTERNAL_Q
] = 1;
841 vm_page_non_speculative_pageable_states
[VM_PAGE_ON_INACTIVE_CLEANED_Q
] = 1;
842 vm_page_non_speculative_pageable_states
[VM_PAGE_ON_ACTIVE_Q
] = 1;
843 vm_page_non_speculative_pageable_states
[VM_PAGE_ON_THROTTLED_Q
] = 1;
844 #if CONFIG_SECLUDED_MEMORY
845 vm_page_non_speculative_pageable_states
[VM_PAGE_ON_SECLUDED_Q
] = 1;
846 #endif /* CONFIG_SECLUDED_MEMORY */
848 bzero(vm_page_active_or_inactive_states
, sizeof(vm_page_active_or_inactive_states
));
849 vm_page_active_or_inactive_states
[VM_PAGE_ON_INACTIVE_INTERNAL_Q
] = 1;
850 vm_page_active_or_inactive_states
[VM_PAGE_ON_INACTIVE_EXTERNAL_Q
] = 1;
851 vm_page_active_or_inactive_states
[VM_PAGE_ON_INACTIVE_CLEANED_Q
] = 1;
852 vm_page_active_or_inactive_states
[VM_PAGE_ON_ACTIVE_Q
] = 1;
853 #if CONFIG_SECLUDED_MEMORY
854 vm_page_active_or_inactive_states
[VM_PAGE_ON_SECLUDED_Q
] = 1;
855 #endif /* CONFIG_SECLUDED_MEMORY */
857 for (i
= 0; i
< VM_KERN_MEMORY_FIRST_DYNAMIC
; i
++)
859 vm_allocation_sites_static
[i
].refcount
= 2;
860 vm_allocation_sites_static
[i
].tag
= i
;
861 vm_allocation_sites
[i
] = &vm_allocation_sites_static
[i
];
863 vm_allocation_sites_static
[VM_KERN_MEMORY_FIRST_DYNAMIC
].refcount
= 2;
864 vm_allocation_sites_static
[VM_KERN_MEMORY_FIRST_DYNAMIC
].tag
= VM_KERN_MEMORY_ANY
;
865 vm_allocation_sites
[VM_KERN_MEMORY_ANY
] = &vm_allocation_sites_static
[VM_KERN_MEMORY_FIRST_DYNAMIC
];
868 * Steal memory for the map and zone subsystems.
873 kernel_debug_string_early("vm_map_steal_memory");
874 vm_map_steal_memory();
877 * Allocate (and initialize) the virtual-to-physical
878 * table hash buckets.
880 * The number of buckets should be a power of two to
881 * get a good hash function. The following computation
882 * chooses the first power of two that is greater
883 * than the number of physical pages in the system.
886 if (vm_page_bucket_count
== 0) {
887 unsigned int npages
= pmap_free_pages();
889 vm_page_bucket_count
= 1;
890 while (vm_page_bucket_count
< npages
)
891 vm_page_bucket_count
<<= 1;
893 vm_page_bucket_lock_count
= (vm_page_bucket_count
+ BUCKETS_PER_LOCK
- 1) / BUCKETS_PER_LOCK
;
895 vm_page_hash_mask
= vm_page_bucket_count
- 1;
898 * Calculate object shift value for hashing algorithm:
899 * O = log2(sizeof(struct vm_object))
900 * B = log2(vm_page_bucket_count)
901 * hash shifts the object left by
904 size
= vm_page_bucket_count
;
905 for (log1
= 0; size
> 1; log1
++)
907 size
= sizeof(struct vm_object
);
908 for (log2
= 0; size
> 1; log2
++)
910 vm_page_hash_shift
= log1
/2 - log2
+ 1;
912 vm_page_bucket_hash
= 1 << ((log1
+ 1) >> 1); /* Get (ceiling of sqrt of table size) */
913 vm_page_bucket_hash
|= 1 << ((log1
+ 1) >> 2); /* Get (ceiling of quadroot of table size) */
914 vm_page_bucket_hash
|= 1; /* Set bit and add 1 - always must be 1 to insure unique series */
916 if (vm_page_hash_mask
& vm_page_bucket_count
)
917 printf("vm_page_bootstrap: WARNING -- strange page hash\n");
919 #if VM_PAGE_BUCKETS_CHECK
920 #if VM_PAGE_FAKE_BUCKETS
922 * Allocate a decoy set of page buckets, to detect
923 * any stomping there.
925 vm_page_fake_buckets
= (vm_page_bucket_t
*)
926 pmap_steal_memory(vm_page_bucket_count
*
927 sizeof(vm_page_bucket_t
));
928 vm_page_fake_buckets_start
= (vm_map_offset_t
) vm_page_fake_buckets
;
929 vm_page_fake_buckets_end
=
930 vm_map_round_page((vm_page_fake_buckets_start
+
931 (vm_page_bucket_count
*
932 sizeof (vm_page_bucket_t
))),
935 for (cp
= (char *)vm_page_fake_buckets_start
;
936 cp
< (char *)vm_page_fake_buckets_end
;
940 #endif /* VM_PAGE_FAKE_BUCKETS */
941 #endif /* VM_PAGE_BUCKETS_CHECK */
943 kernel_debug_string_early("vm_page_buckets");
944 vm_page_buckets
= (vm_page_bucket_t
*)
945 pmap_steal_memory(vm_page_bucket_count
*
946 sizeof(vm_page_bucket_t
));
948 kernel_debug_string_early("vm_page_bucket_locks");
949 vm_page_bucket_locks
= (lck_spin_t
*)
950 pmap_steal_memory(vm_page_bucket_lock_count
*
953 for (i
= 0; i
< vm_page_bucket_count
; i
++) {
954 vm_page_bucket_t
*bucket
= &vm_page_buckets
[i
];
956 bucket
->page_list
= VM_PAGE_PACK_PTR(VM_PAGE_NULL
);
957 #if MACH_PAGE_HASH_STATS
958 bucket
->cur_count
= 0;
959 bucket
->hi_count
= 0;
960 #endif /* MACH_PAGE_HASH_STATS */
963 for (i
= 0; i
< vm_page_bucket_lock_count
; i
++)
964 lck_spin_init(&vm_page_bucket_locks
[i
], &vm_page_lck_grp_bucket
, &vm_page_lck_attr
);
966 lck_spin_init(&vm_objects_wired_lock
, &vm_page_lck_grp_bucket
, &vm_page_lck_attr
);
967 lck_spin_init(&vm_allocation_sites_lock
, &vm_page_lck_grp_bucket
, &vm_page_lck_attr
);
970 #if VM_PAGE_BUCKETS_CHECK
971 vm_page_buckets_check_ready
= TRUE
;
972 #endif /* VM_PAGE_BUCKETS_CHECK */
975 * Machine-dependent code allocates the resident page table.
976 * It uses vm_page_init to initialize the page frames.
977 * The code also returns to us the virtual space available
978 * to the kernel. We don't trust the pmap module
979 * to get the alignment right.
982 kernel_debug_string_early("pmap_startup");
983 pmap_startup(&virtual_space_start
, &virtual_space_end
);
984 virtual_space_start
= round_page(virtual_space_start
);
985 virtual_space_end
= trunc_page(virtual_space_end
);
987 *startp
= virtual_space_start
;
988 *endp
= virtual_space_end
;
991 * Compute the initial "wire" count.
992 * Up until now, the pages which have been set aside are not under
993 * the VM system's control, so although they aren't explicitly
994 * wired, they nonetheless can't be moved. At this moment,
995 * all VM managed pages are "free", courtesy of pmap_startup.
997 assert((unsigned int) atop_64(max_mem
) == atop_64(max_mem
));
998 vm_page_wire_count
= ((unsigned int) atop_64(max_mem
)) - vm_page_free_count
- vm_lopage_free_count
; /* initial value */
999 #if CONFIG_SECLUDED_MEMORY
1000 vm_page_wire_count
-= vm_page_secluded_count
;
1002 vm_page_wire_count_initial
= vm_page_wire_count
;
1003 vm_page_pages_initial
= vm_page_pages
;
1005 printf("vm_page_bootstrap: %d free pages and %d wired pages\n",
1006 vm_page_free_count
, vm_page_wire_count
);
1008 kernel_debug_string_early("vm_page_bootstrap complete");
1009 simple_lock_init(&vm_paging_lock
, 0);
1012 #ifndef MACHINE_PAGES
1014 * We implement pmap_steal_memory and pmap_startup with the help
1015 * of two simpler functions, pmap_virtual_space and pmap_next_page.
1023 vm_offset_t addr
, vaddr
;
1027 * We round the size to a round multiple.
1030 size
= (size
+ sizeof (void *) - 1) &~ (sizeof (void *) - 1);
1033 * If this is the first call to pmap_steal_memory,
1034 * we have to initialize ourself.
1037 if (virtual_space_start
== virtual_space_end
) {
1038 pmap_virtual_space(&virtual_space_start
, &virtual_space_end
);
1041 * The initial values must be aligned properly, and
1042 * we don't trust the pmap module to do it right.
1045 virtual_space_start
= round_page(virtual_space_start
);
1046 virtual_space_end
= trunc_page(virtual_space_end
);
1050 * Allocate virtual memory for this request.
1053 addr
= virtual_space_start
;
1054 virtual_space_start
+= size
;
1056 //kprintf("pmap_steal_memory: %08lX - %08lX; size=%08lX\n", (long)addr, (long)virtual_space_start, (long)size); /* (TEST/DEBUG) */
1059 * Allocate and map physical pages to back new virtual pages.
1062 for (vaddr
= round_page(addr
);
1063 vaddr
< addr
+ size
;
1064 vaddr
+= PAGE_SIZE
) {
1066 if (!pmap_next_page_hi(&phys_page
))
1067 panic("pmap_steal_memory() size: 0x%llx\n", (uint64_t)size
);
1070 * XXX Logically, these mappings should be wired,
1071 * but some pmap modules barf if they are.
1073 #if defined(__LP64__)
1075 /* ARM64_TODO: verify that we really don't need this */
1077 pmap_pre_expand(kernel_pmap
, vaddr
);
1081 kr
= pmap_enter(kernel_pmap
, vaddr
, phys_page
,
1082 VM_PROT_READ
|VM_PROT_WRITE
, VM_PROT_NONE
,
1083 VM_WIMG_USE_DEFAULT
, FALSE
);
1085 if (kr
!= KERN_SUCCESS
) {
1086 panic("pmap_steal_memory() pmap_enter failed, vaddr=%#lx, phys_page=%u",
1087 (unsigned long)vaddr
, phys_page
);
1091 * Account for newly stolen memory
1093 vm_page_wire_count
++;
1094 vm_page_stolen_count
++;
1098 kasan_notify_address(round_page(addr
), size
);
1100 return (void *) addr
;
1103 #if CONFIG_SECLUDED_MEMORY
1104 /* boot-args to control secluded memory */
1105 unsigned int secluded_mem_mb
= 0; /* # of MBs of RAM to seclude */
1106 int secluded_for_iokit
= 1; /* IOKit can use secluded memory */
1107 int secluded_for_apps
= 1; /* apps can use secluded memory */
1108 int secluded_for_filecache
= 2; /* filecache can use seclude memory */
1110 int secluded_for_fbdp
= 0;
1112 #endif /* CONFIG_SECLUDED_MEMORY */
1115 #if defined(__arm__) || defined(__arm64__)
1116 extern void patch_low_glo_vm_page_info(void *, void *, uint32_t);
1117 unsigned int vm_first_phys_ppnum
= 0;
1121 void vm_page_release_startup(vm_page_t mem
);
1124 vm_offset_t
*startp
,
1127 unsigned int i
, npages
, pages_initialized
, fill
, fillval
;
1131 #if defined(__LP64__)
1133 * make sure we are aligned on a 64 byte boundary
1134 * for VM_PAGE_PACK_PTR (it clips off the low-order
1135 * 6 bits of the pointer)
1137 if (virtual_space_start
!= virtual_space_end
)
1138 virtual_space_start
= round_page(virtual_space_start
);
1142 * We calculate how many page frames we will have
1143 * and then allocate the page structures in one chunk.
1146 tmpaddr
= (addr64_t
)pmap_free_pages() * (addr64_t
)PAGE_SIZE
; /* Get the amount of memory left */
1147 tmpaddr
= tmpaddr
+ (addr64_t
)(round_page(virtual_space_start
) - virtual_space_start
); /* Account for any slop */
1148 npages
= (unsigned int)(tmpaddr
/ (addr64_t
)(PAGE_SIZE
+ sizeof(*vm_pages
))); /* Figure size of all vm_page_ts, including enough to hold the vm_page_ts */
1150 vm_pages
= (vm_page_t
) pmap_steal_memory(npages
* sizeof *vm_pages
);
1153 * Initialize the page frames.
1155 kernel_debug_string_early("Initialize the page frames");
1157 vm_page_array_beginning_addr
= &vm_pages
[0];
1158 vm_page_array_ending_addr
= &vm_pages
[npages
];
1160 for (i
= 0, pages_initialized
= 0; i
< npages
; i
++) {
1161 if (!pmap_next_page(&phys_page
))
1163 #if defined(__arm__) || defined(__arm64__)
1164 if (pages_initialized
== 0) {
1165 vm_first_phys_ppnum
= phys_page
;
1166 patch_low_glo_vm_page_info((void *)vm_page_array_beginning_addr
, (void *)vm_page_array_ending_addr
, vm_first_phys_ppnum
);
1168 assert((i
+ vm_first_phys_ppnum
) == phys_page
);
1170 if (pages_initialized
== 0 || phys_page
< vm_page_lowest
)
1171 vm_page_lowest
= phys_page
;
1173 vm_page_init(&vm_pages
[i
], phys_page
, FALSE
);
1175 pages_initialized
++;
1177 vm_pages_count
= pages_initialized
;
1178 vm_page_array_boundary
= &vm_pages
[pages_initialized
];
1180 #if defined(__LP64__)
1182 if ((vm_page_t
)(VM_PAGE_UNPACK_PTR(VM_PAGE_PACK_PTR(&vm_pages
[0]))) != &vm_pages
[0])
1183 panic("VM_PAGE_PACK_PTR failed on &vm_pages[0] - %p", (void *)&vm_pages
[0]);
1185 if ((vm_page_t
)(VM_PAGE_UNPACK_PTR(VM_PAGE_PACK_PTR(&vm_pages
[vm_pages_count
-1]))) != &vm_pages
[vm_pages_count
-1])
1186 panic("VM_PAGE_PACK_PTR failed on &vm_pages[vm_pages_count-1] - %p", (void *)&vm_pages
[vm_pages_count
-1]);
1188 kernel_debug_string_early("page fill/release");
1190 * Check if we want to initialize pages to a known value
1192 fill
= 0; /* Assume no fill */
1193 if (PE_parse_boot_argn("fill", &fillval
, sizeof (fillval
))) fill
= 1; /* Set fill */
1195 /* This slows down booting the DEBUG kernel, particularly on
1196 * large memory systems, but is worthwhile in deterministically
1197 * trapping uninitialized memory usage.
1201 fillval
= 0xDEB8F177;
1205 kprintf("Filling vm_pages with pattern: 0x%x\n", fillval
);
1207 #if CONFIG_SECLUDED_MEMORY
1208 /* default: no secluded mem */
1209 secluded_mem_mb
= 0;
1210 if (max_mem
> 1*1024*1024*1024) {
1211 /* default to 90MB for devices with > 1GB of RAM */
1212 secluded_mem_mb
= 90;
1214 /* override with value from device tree, if provided */
1215 PE_get_default("kern.secluded_mem_mb",
1216 &secluded_mem_mb
, sizeof(secluded_mem_mb
));
1217 /* override with value from boot-args, if provided */
1218 PE_parse_boot_argn("secluded_mem_mb",
1220 sizeof (secluded_mem_mb
));
1222 vm_page_secluded_target
= (unsigned int)
1223 ((secluded_mem_mb
* 1024ULL * 1024ULL) / PAGE_SIZE
);
1224 PE_parse_boot_argn("secluded_for_iokit",
1225 &secluded_for_iokit
,
1226 sizeof (secluded_for_iokit
));
1227 PE_parse_boot_argn("secluded_for_apps",
1229 sizeof (secluded_for_apps
));
1230 PE_parse_boot_argn("secluded_for_filecache",
1231 &secluded_for_filecache
,
1232 sizeof (secluded_for_filecache
));
1234 PE_parse_boot_argn("secluded_for_fbdp",
1236 sizeof (secluded_for_fbdp
));
1238 #endif /* CONFIG_SECLUDED_MEMORY */
1240 // -debug code remove
1241 if (2 == vm_himemory_mode
) {
1242 // free low -> high so high is preferred
1243 for (i
= 1; i
<= pages_initialized
; i
++) {
1244 if(fill
) fillPage(VM_PAGE_GET_PHYS_PAGE(&vm_pages
[i
- 1]), fillval
); /* Fill the page with a know value if requested at boot */
1245 vm_page_release_startup(&vm_pages
[i
- 1]);
1249 // debug code remove-
1252 * Release pages in reverse order so that physical pages
1253 * initially get allocated in ascending addresses. This keeps
1254 * the devices (which must address physical memory) happy if
1255 * they require several consecutive pages.
1257 for (i
= pages_initialized
; i
> 0; i
--) {
1258 if(fill
) fillPage(VM_PAGE_GET_PHYS_PAGE(&vm_pages
[i
- 1]), fillval
); /* Fill the page with a know value if requested at boot */
1259 vm_page_release_startup(&vm_pages
[i
- 1]);
1262 VM_CHECK_MEMORYSTATUS
;
1266 vm_page_t xx
, xxo
, xxl
;
1269 j
= 0; /* (BRINGUP) */
1272 for( i
= 0; i
< vm_colors
; i
++ ) {
1273 queue_iterate(&vm_page_queue_free
[i
].qhead
,
1276 pageq
) { /* BRINGUP */
1277 j
++; /* (BRINGUP) */
1278 if(j
> vm_page_free_count
) { /* (BRINGUP) */
1279 panic("pmap_startup: too many pages, xx = %08X, xxl = %08X\n", xx
, xxl
);
1282 l
= vm_page_free_count
- j
; /* (BRINGUP) */
1283 k
= 0; /* (BRINGUP) */
1285 if(((j
- 1) & 0xFFFF) == 0) kprintf("checking number %d of %d\n", j
, vm_page_free_count
);
1287 for(xxo
= xx
->pageq
.next
; xxo
!= &vm_page_queue_free
[i
].qhead
; xxo
= xxo
->pageq
.next
) { /* (BRINGUP) */
1289 if(k
> l
) panic("pmap_startup: too many in secondary check %d %d\n", k
, l
);
1290 if((xx
->phys_page
& 0xFFFFFFFF) == (xxo
->phys_page
& 0xFFFFFFFF)) { /* (BRINGUP) */
1291 panic("pmap_startup: duplicate physaddr, xx = %08X, xxo = %08X\n", xx
, xxo
);
1299 if(j
!= vm_page_free_count
) { /* (BRINGUP) */
1300 panic("pmap_startup: vm_page_free_count does not match, calc = %d, vm_page_free_count = %08X\n", j
, vm_page_free_count
);
1307 * We have to re-align virtual_space_start,
1308 * because pmap_steal_memory has been using it.
1311 virtual_space_start
= round_page(virtual_space_start
);
1313 *startp
= virtual_space_start
;
1314 *endp
= virtual_space_end
;
1316 #endif /* MACHINE_PAGES */
1319 * Routine: vm_page_module_init
1321 * Second initialization pass, to be done after
1322 * the basic VM system is ready.
1325 vm_page_module_init(void)
1327 uint64_t vm_page_zone_pages
, vm_page_array_zone_data_size
;
1328 vm_size_t vm_page_with_ppnum_size
;
1330 vm_page_array_zone
= zinit((vm_size_t
) sizeof(struct vm_page
),
1331 0, PAGE_SIZE
, "vm pages array");
1333 zone_change(vm_page_array_zone
, Z_CALLERACCT
, FALSE
);
1334 zone_change(vm_page_array_zone
, Z_EXPAND
, FALSE
);
1335 zone_change(vm_page_array_zone
, Z_EXHAUST
, TRUE
);
1336 zone_change(vm_page_array_zone
, Z_FOREIGN
, TRUE
);
1337 zone_change(vm_page_array_zone
, Z_GZALLOC_EXEMPT
, TRUE
);
1339 * Adjust zone statistics to account for the real pages allocated
1340 * in vm_page_create(). [Q: is this really what we want?]
1342 vm_page_array_zone
->count
+= vm_page_pages
;
1343 vm_page_array_zone
->sum_count
+= vm_page_pages
;
1344 vm_page_array_zone_data_size
= vm_page_pages
* vm_page_array_zone
->elem_size
;
1345 vm_page_array_zone
->cur_size
+= vm_page_array_zone_data_size
;
1346 vm_page_zone_pages
= ((round_page(vm_page_array_zone_data_size
)) / PAGE_SIZE
);
1347 OSAddAtomic64(vm_page_zone_pages
, &(vm_page_array_zone
->page_count
));
1348 /* since zone accounts for these, take them out of stolen */
1349 VM_PAGE_MOVE_STOLEN(vm_page_zone_pages
);
1351 vm_page_with_ppnum_size
= (sizeof(struct vm_page_with_ppnum
) + (VM_PACKED_POINTER_ALIGNMENT
-1)) & ~(VM_PACKED_POINTER_ALIGNMENT
- 1);
1353 vm_page_zone
= zinit(vm_page_with_ppnum_size
,
1354 0, PAGE_SIZE
, "vm pages");
1356 zone_change(vm_page_zone
, Z_CALLERACCT
, FALSE
);
1357 zone_change(vm_page_zone
, Z_EXPAND
, FALSE
);
1358 zone_change(vm_page_zone
, Z_EXHAUST
, TRUE
);
1359 zone_change(vm_page_zone
, Z_FOREIGN
, TRUE
);
1360 zone_change(vm_page_zone
, Z_GZALLOC_EXEMPT
, TRUE
);
1361 zone_change(vm_page_zone
, Z_ALIGNMENT_REQUIRED
, TRUE
);
1365 * Routine: vm_page_create
1367 * After the VM system is up, machine-dependent code
1368 * may stumble across more physical memory. For example,
1369 * memory that it was reserving for a frame buffer.
1370 * vm_page_create turns this memory into available pages.
1381 for (phys_page
= start
;
1384 while ((m
= (vm_page_t
) vm_page_grab_fictitious_common(phys_page
))
1386 vm_page_more_fictitious();
1388 m
->fictitious
= FALSE
;
1389 pmap_clear_noencrypt(phys_page
);
1392 vm_page_release(m
, FALSE
);
1399 * Distributes the object/offset key pair among hash buckets.
1401 * NOTE: The bucket count must be a power of 2
1403 #define vm_page_hash(object, offset) (\
1404 ( (natural_t)((uintptr_t)object * vm_page_bucket_hash) + ((uint32_t)atop_64(offset) ^ vm_page_bucket_hash))\
1405 & vm_page_hash_mask)
1409 * vm_page_insert: [ internal use only ]
1411 * Inserts the given mem entry into the object/object-page
1412 * table and object list.
1414 * The object must be locked.
1420 vm_object_offset_t offset
)
1422 vm_page_insert_internal(mem
, object
, offset
, VM_KERN_MEMORY_NONE
, FALSE
, TRUE
, FALSE
, FALSE
, NULL
);
1426 vm_page_insert_wired(
1429 vm_object_offset_t offset
,
1432 vm_page_insert_internal(mem
, object
, offset
, tag
, FALSE
, TRUE
, FALSE
, FALSE
, NULL
);
1436 vm_page_insert_internal(
1439 vm_object_offset_t offset
,
1441 boolean_t queues_lock_held
,
1442 boolean_t insert_in_hash
,
1443 boolean_t batch_pmap_op
,
1444 boolean_t batch_accounting
,
1445 uint64_t *delayed_ledger_update
)
1447 vm_page_bucket_t
*bucket
;
1448 lck_spin_t
*bucket_lock
;
1453 "vm_page_insert, object 0x%X offset 0x%X page 0x%X\n",
1454 object
, offset
, mem
, 0,0);
1457 * we may not hold the page queue lock
1458 * so this check isn't safe to make
1463 assert(page_aligned(offset
));
1465 assert(!VM_PAGE_WIRED(mem
) || mem
->private || mem
->fictitious
|| (tag
!= VM_KERN_MEMORY_NONE
));
1467 /* the vm_submap_object is only a placeholder for submaps */
1468 assert(object
!= vm_submap_object
);
1470 vm_object_lock_assert_exclusive(object
);
1471 LCK_MTX_ASSERT(&vm_page_queue_lock
,
1472 queues_lock_held
? LCK_MTX_ASSERT_OWNED
1473 : LCK_MTX_ASSERT_NOTOWNED
);
1475 if (queues_lock_held
== FALSE
)
1476 assert(!VM_PAGE_PAGEABLE(mem
));
1478 if (insert_in_hash
== TRUE
) {
1479 #if DEBUG || VM_PAGE_CHECK_BUCKETS
1480 if (mem
->tabled
|| mem
->vm_page_object
)
1481 panic("vm_page_insert: page %p for (obj=%p,off=0x%llx) "
1482 "already in (obj=%p,off=0x%llx)",
1483 mem
, object
, offset
, VM_PAGE_OBJECT(mem
), mem
->offset
);
1485 if (object
->internal
&& (offset
>= object
->vo_size
)) {
1486 panic("vm_page_insert_internal: (page=%p,obj=%p,off=0x%llx,size=0x%llx) inserted at offset past object bounds",
1487 mem
, object
, offset
, object
->vo_size
);
1490 assert(vm_page_lookup(object
, offset
) == VM_PAGE_NULL
);
1493 * Record the object/offset pair in this page
1496 mem
->vm_page_object
= VM_PAGE_PACK_OBJECT(object
);
1497 mem
->offset
= offset
;
1499 #if CONFIG_SECLUDED_MEMORY
1500 if (object
->eligible_for_secluded
) {
1501 vm_page_secluded
.eligible_for_secluded
++;
1503 #endif /* CONFIG_SECLUDED_MEMORY */
1506 * Insert it into the object_object/offset hash table
1508 hash_id
= vm_page_hash(object
, offset
);
1509 bucket
= &vm_page_buckets
[hash_id
];
1510 bucket_lock
= &vm_page_bucket_locks
[hash_id
/ BUCKETS_PER_LOCK
];
1512 lck_spin_lock(bucket_lock
);
1514 mem
->next_m
= bucket
->page_list
;
1515 bucket
->page_list
= VM_PAGE_PACK_PTR(mem
);
1516 assert(mem
== (vm_page_t
)(VM_PAGE_UNPACK_PTR(bucket
->page_list
)));
1518 #if MACH_PAGE_HASH_STATS
1519 if (++bucket
->cur_count
> bucket
->hi_count
)
1520 bucket
->hi_count
= bucket
->cur_count
;
1521 #endif /* MACH_PAGE_HASH_STATS */
1523 lck_spin_unlock(bucket_lock
);
1527 unsigned int cache_attr
;
1529 cache_attr
= object
->wimg_bits
& VM_WIMG_MASK
;
1531 if (cache_attr
!= VM_WIMG_USE_DEFAULT
) {
1532 PMAP_SET_CACHE_ATTR(mem
, object
, cache_attr
, batch_pmap_op
);
1536 * Now link into the object's list of backed pages.
1538 vm_page_queue_enter(&object
->memq
, mem
, vm_page_t
, listq
);
1539 object
->memq_hint
= mem
;
1543 * Show that the object has one more resident page.
1546 object
->resident_page_count
++;
1547 if (VM_PAGE_WIRED(mem
)) {
1548 assert(mem
->wire_count
> 0);
1549 VM_OBJECT_WIRED_PAGE_UPDATE_START(object
);
1550 VM_OBJECT_WIRED_PAGE_ADD(object
, mem
);
1551 VM_OBJECT_WIRED_PAGE_UPDATE_END(object
, tag
);
1553 assert(object
->resident_page_count
>= object
->wired_page_count
);
1555 if (batch_accounting
== FALSE
) {
1556 if (object
->internal
) {
1557 OSAddAtomic(1, &vm_page_internal_count
);
1559 OSAddAtomic(1, &vm_page_external_count
);
1564 * It wouldn't make sense to insert a "reusable" page in
1565 * an object (the page would have been marked "reusable" only
1566 * at the time of a madvise(MADV_FREE_REUSABLE) if it was already
1567 * in the object at that time).
1568 * But a page could be inserted in a "all_reusable" object, if
1569 * something faults it in (a vm_read() from another task or a
1570 * "use-after-free" issue in user space, for example). It can
1571 * also happen if we're relocating a page from that object to
1572 * a different physical page during a physically-contiguous
1575 assert(!mem
->reusable
);
1576 if (object
->all_reusable
) {
1577 OSAddAtomic(+1, &vm_page_stats_reusable
.reusable_count
);
1580 if (object
->purgable
== VM_PURGABLE_DENY
) {
1583 owner
= object
->vo_purgeable_owner
;
1586 (object
->purgable
== VM_PURGABLE_NONVOLATILE
||
1587 VM_PAGE_WIRED(mem
))) {
1589 if (delayed_ledger_update
)
1590 *delayed_ledger_update
+= PAGE_SIZE
;
1592 /* more non-volatile bytes */
1593 ledger_credit(owner
->ledger
,
1594 task_ledgers
.purgeable_nonvolatile
,
1596 /* more footprint */
1597 ledger_credit(owner
->ledger
,
1598 task_ledgers
.phys_footprint
,
1603 (object
->purgable
== VM_PURGABLE_VOLATILE
||
1604 object
->purgable
== VM_PURGABLE_EMPTY
)) {
1605 assert(! VM_PAGE_WIRED(mem
));
1606 /* more volatile bytes */
1607 ledger_credit(owner
->ledger
,
1608 task_ledgers
.purgeable_volatile
,
1612 if (object
->purgable
== VM_PURGABLE_VOLATILE
) {
1613 if (VM_PAGE_WIRED(mem
)) {
1614 OSAddAtomic(+1, &vm_page_purgeable_wired_count
);
1616 OSAddAtomic(+1, &vm_page_purgeable_count
);
1618 } else if (object
->purgable
== VM_PURGABLE_EMPTY
&&
1619 mem
->vm_page_q_state
== VM_PAGE_ON_THROTTLED_Q
) {
1621 * This page belongs to a purged VM object but hasn't
1622 * been purged (because it was "busy").
1623 * It's in the "throttled" queue and hence not
1624 * visible to vm_pageout_scan(). Move it to a pageable
1625 * queue, so that it can eventually be reclaimed, instead
1626 * of lingering in the "empty" object.
1628 if (queues_lock_held
== FALSE
)
1629 vm_page_lockspin_queues();
1630 vm_page_deactivate(mem
);
1631 if (queues_lock_held
== FALSE
)
1632 vm_page_unlock_queues();
1635 #if VM_OBJECT_TRACKING_OP_MODIFIED
1636 if (vm_object_tracking_inited
&&
1638 object
->resident_page_count
== 0 &&
1639 object
->pager
== NULL
&&
1640 object
->shadow
!= NULL
&&
1641 object
->shadow
->copy
== object
) {
1642 void *bt
[VM_OBJECT_TRACKING_BTDEPTH
];
1645 numsaved
=OSBacktrace(bt
, VM_OBJECT_TRACKING_BTDEPTH
);
1646 btlog_add_entry(vm_object_tracking_btlog
,
1648 VM_OBJECT_TRACKING_OP_MODIFIED
,
1652 #endif /* VM_OBJECT_TRACKING_OP_MODIFIED */
1658 * Exactly like vm_page_insert, except that we first
1659 * remove any existing page at the given offset in object.
1661 * The object must be locked.
1667 vm_object_offset_t offset
)
1669 vm_page_bucket_t
*bucket
;
1670 vm_page_t found_m
= VM_PAGE_NULL
;
1671 lck_spin_t
*bucket_lock
;
1676 * we don't hold the page queue lock
1677 * so this check isn't safe to make
1681 vm_object_lock_assert_exclusive(object
);
1682 #if DEBUG || VM_PAGE_CHECK_BUCKETS
1683 if (mem
->tabled
|| mem
->vm_page_object
)
1684 panic("vm_page_replace: page %p for (obj=%p,off=0x%llx) "
1685 "already in (obj=%p,off=0x%llx)",
1686 mem
, object
, offset
, VM_PAGE_OBJECT(mem
), mem
->offset
);
1688 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_NOTOWNED
);
1690 assert(!VM_PAGE_PAGEABLE(mem
));
1693 * Record the object/offset pair in this page
1695 mem
->vm_page_object
= VM_PAGE_PACK_OBJECT(object
);
1696 mem
->offset
= offset
;
1699 * Insert it into the object_object/offset hash table,
1700 * replacing any page that might have been there.
1703 hash_id
= vm_page_hash(object
, offset
);
1704 bucket
= &vm_page_buckets
[hash_id
];
1705 bucket_lock
= &vm_page_bucket_locks
[hash_id
/ BUCKETS_PER_LOCK
];
1707 lck_spin_lock(bucket_lock
);
1709 if (bucket
->page_list
) {
1710 vm_page_packed_t
*mp
= &bucket
->page_list
;
1711 vm_page_t m
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(*mp
));
1715 * compare packed object pointers
1717 if (m
->vm_page_object
== mem
->vm_page_object
&& m
->offset
== offset
) {
1719 * Remove old page from hash list
1723 m
->next_m
= VM_PAGE_PACK_PTR(NULL
);
1729 } while ((m
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(*mp
))));
1731 mem
->next_m
= bucket
->page_list
;
1733 mem
->next_m
= VM_PAGE_PACK_PTR(NULL
);
1736 * insert new page at head of hash list
1738 bucket
->page_list
= VM_PAGE_PACK_PTR(mem
);
1741 lck_spin_unlock(bucket_lock
);
1745 * there was already a page at the specified
1746 * offset for this object... remove it from
1747 * the object and free it back to the free list
1749 vm_page_free_unlocked(found_m
, FALSE
);
1751 vm_page_insert_internal(mem
, object
, offset
, VM_KERN_MEMORY_NONE
, FALSE
, FALSE
, FALSE
, FALSE
, NULL
);
1755 * vm_page_remove: [ internal use only ]
1757 * Removes the given mem entry from the object/offset-page
1758 * table and the object page list.
1760 * The object must be locked.
1766 boolean_t remove_from_hash
)
1768 vm_page_bucket_t
*bucket
;
1770 lck_spin_t
*bucket_lock
;
1773 vm_object_t m_object
;
1775 m_object
= VM_PAGE_OBJECT(mem
);
1778 "vm_page_remove, object 0x%X offset 0x%X page 0x%X\n",
1779 m_object
, mem
->offset
,
1782 vm_object_lock_assert_exclusive(m_object
);
1783 assert(mem
->tabled
);
1784 assert(!mem
->cleaning
);
1785 assert(!mem
->laundry
);
1787 if (VM_PAGE_PAGEABLE(mem
)) {
1788 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
1792 * we don't hold the page queue lock
1793 * so this check isn't safe to make
1797 if (remove_from_hash
== TRUE
) {
1799 * Remove from the object_object/offset hash table
1801 hash_id
= vm_page_hash(m_object
, mem
->offset
);
1802 bucket
= &vm_page_buckets
[hash_id
];
1803 bucket_lock
= &vm_page_bucket_locks
[hash_id
/ BUCKETS_PER_LOCK
];
1805 lck_spin_lock(bucket_lock
);
1807 if ((this = (vm_page_t
)(VM_PAGE_UNPACK_PTR(bucket
->page_list
))) == mem
) {
1808 /* optimize for common case */
1810 bucket
->page_list
= mem
->next_m
;
1812 vm_page_packed_t
*prev
;
1814 for (prev
= &this->next_m
;
1815 (this = (vm_page_t
)(VM_PAGE_UNPACK_PTR(*prev
))) != mem
;
1816 prev
= &this->next_m
)
1818 *prev
= this->next_m
;
1820 #if MACH_PAGE_HASH_STATS
1821 bucket
->cur_count
--;
1822 #endif /* MACH_PAGE_HASH_STATS */
1823 mem
->hashed
= FALSE
;
1824 this->next_m
= VM_PAGE_PACK_PTR(NULL
);
1825 lck_spin_unlock(bucket_lock
);
1828 * Now remove from the object's list of backed pages.
1831 vm_page_remove_internal(mem
);
1834 * And show that the object has one fewer resident
1838 assert(m_object
->resident_page_count
> 0);
1839 m_object
->resident_page_count
--;
1841 if (m_object
->internal
) {
1843 assert(vm_page_internal_count
);
1846 OSAddAtomic(-1, &vm_page_internal_count
);
1848 assert(vm_page_external_count
);
1849 OSAddAtomic(-1, &vm_page_external_count
);
1851 if (mem
->xpmapped
) {
1852 assert(vm_page_xpmapped_external_count
);
1853 OSAddAtomic(-1, &vm_page_xpmapped_external_count
);
1856 if (!m_object
->internal
&& (m_object
->objq
.next
|| m_object
->objq
.prev
)) {
1857 if (m_object
->resident_page_count
== 0)
1858 vm_object_cache_remove(m_object
);
1861 if (VM_PAGE_WIRED(mem
)) {
1862 assert(mem
->wire_count
> 0);
1863 VM_OBJECT_WIRED_PAGE_UPDATE_START(m_object
);
1864 VM_OBJECT_WIRED_PAGE_REMOVE(m_object
, mem
);
1865 VM_OBJECT_WIRED_PAGE_UPDATE_END(m_object
, m_object
->wire_tag
);
1867 assert(m_object
->resident_page_count
>=
1868 m_object
->wired_page_count
);
1869 if (mem
->reusable
) {
1870 assert(m_object
->reusable_page_count
> 0);
1871 m_object
->reusable_page_count
--;
1872 assert(m_object
->reusable_page_count
<=
1873 m_object
->resident_page_count
);
1874 mem
->reusable
= FALSE
;
1875 OSAddAtomic(-1, &vm_page_stats_reusable
.reusable_count
);
1876 vm_page_stats_reusable
.reused_remove
++;
1877 } else if (m_object
->all_reusable
) {
1878 OSAddAtomic(-1, &vm_page_stats_reusable
.reusable_count
);
1879 vm_page_stats_reusable
.reused_remove
++;
1882 if (m_object
->purgable
== VM_PURGABLE_DENY
) {
1885 owner
= m_object
->vo_purgeable_owner
;
1888 (m_object
->purgable
== VM_PURGABLE_NONVOLATILE
||
1889 VM_PAGE_WIRED(mem
))) {
1890 /* less non-volatile bytes */
1891 ledger_debit(owner
->ledger
,
1892 task_ledgers
.purgeable_nonvolatile
,
1894 /* less footprint */
1895 ledger_debit(owner
->ledger
,
1896 task_ledgers
.phys_footprint
,
1899 (m_object
->purgable
== VM_PURGABLE_VOLATILE
||
1900 m_object
->purgable
== VM_PURGABLE_EMPTY
)) {
1901 assert(! VM_PAGE_WIRED(mem
));
1902 /* less volatile bytes */
1903 ledger_debit(owner
->ledger
,
1904 task_ledgers
.purgeable_volatile
,
1907 if (m_object
->purgable
== VM_PURGABLE_VOLATILE
) {
1908 if (VM_PAGE_WIRED(mem
)) {
1909 assert(vm_page_purgeable_wired_count
> 0);
1910 OSAddAtomic(-1, &vm_page_purgeable_wired_count
);
1912 assert(vm_page_purgeable_count
> 0);
1913 OSAddAtomic(-1, &vm_page_purgeable_count
);
1917 if (m_object
->set_cache_attr
== TRUE
)
1918 pmap_set_cache_attributes(VM_PAGE_GET_PHYS_PAGE(mem
), 0);
1920 mem
->tabled
= FALSE
;
1921 mem
->vm_page_object
= 0;
1922 mem
->offset
= (vm_object_offset_t
) -1;
1929 * Returns the page associated with the object/offset
1930 * pair specified; if none is found, VM_PAGE_NULL is returned.
1932 * The object must be locked. No side effects.
1935 #define VM_PAGE_HASH_LOOKUP_THRESHOLD 10
1937 #if DEBUG_VM_PAGE_LOOKUP
1941 uint64_t vpl_empty_obj
;
1942 uint64_t vpl_bucket_NULL
;
1943 uint64_t vpl_hit_hint
;
1944 uint64_t vpl_hit_hint_next
;
1945 uint64_t vpl_hit_hint_prev
;
1951 uint64_t vpl_fast_elapsed
;
1952 uint64_t vpl_slow_elapsed
;
1953 } vm_page_lookup_stats
__attribute__((aligned(8)));
1957 #define KDP_VM_PAGE_WALK_MAX 1000
1962 vm_object_offset_t offset
)
1965 int num_traversed
= 0;
1968 panic("panic: kdp_vm_page_lookup done outside of kernel debugger");
1971 vm_page_queue_iterate(&object
->memq
, cur_page
, vm_page_t
, listq
) {
1972 if (cur_page
->offset
== offset
) {
1977 if (num_traversed
>= KDP_VM_PAGE_WALK_MAX
) {
1978 return VM_PAGE_NULL
;
1982 return VM_PAGE_NULL
;
1988 vm_object_offset_t offset
)
1991 vm_page_bucket_t
*bucket
;
1992 vm_page_queue_entry_t qe
;
1993 lck_spin_t
*bucket_lock
= NULL
;
1995 #if DEBUG_VM_PAGE_LOOKUP
1996 uint64_t start
, elapsed
;
1998 OSAddAtomic64(1, &vm_page_lookup_stats
.vpl_total
);
2000 vm_object_lock_assert_held(object
);
2002 if (object
->resident_page_count
== 0) {
2003 #if DEBUG_VM_PAGE_LOOKUP
2004 OSAddAtomic64(1, &vm_page_lookup_stats
.vpl_empty_obj
);
2006 return (VM_PAGE_NULL
);
2009 mem
= object
->memq_hint
;
2011 if (mem
!= VM_PAGE_NULL
) {
2012 assert(VM_PAGE_OBJECT(mem
) == object
);
2014 if (mem
->offset
== offset
) {
2015 #if DEBUG_VM_PAGE_LOOKUP
2016 OSAddAtomic64(1, &vm_page_lookup_stats
.vpl_hit_hint
);
2020 qe
= (vm_page_queue_entry_t
)vm_page_queue_next(&mem
->listq
);
2022 if (! vm_page_queue_end(&object
->memq
, qe
)) {
2023 vm_page_t next_page
;
2025 next_page
= (vm_page_t
)((uintptr_t)qe
);
2026 assert(VM_PAGE_OBJECT(next_page
) == object
);
2028 if (next_page
->offset
== offset
) {
2029 object
->memq_hint
= next_page
; /* new hint */
2030 #if DEBUG_VM_PAGE_LOOKUP
2031 OSAddAtomic64(1, &vm_page_lookup_stats
.vpl_hit_hint_next
);
2036 qe
= (vm_page_queue_entry_t
)vm_page_queue_prev(&mem
->listq
);
2038 if (! vm_page_queue_end(&object
->memq
, qe
)) {
2039 vm_page_t prev_page
;
2041 prev_page
= (vm_page_t
)((uintptr_t)qe
);
2042 assert(VM_PAGE_OBJECT(prev_page
) == object
);
2044 if (prev_page
->offset
== offset
) {
2045 object
->memq_hint
= prev_page
; /* new hint */
2046 #if DEBUG_VM_PAGE_LOOKUP
2047 OSAddAtomic64(1, &vm_page_lookup_stats
.vpl_hit_hint_prev
);
2054 * Search the hash table for this object/offset pair
2056 hash_id
= vm_page_hash(object
, offset
);
2057 bucket
= &vm_page_buckets
[hash_id
];
2060 * since we hold the object lock, we are guaranteed that no
2061 * new pages can be inserted into this object... this in turn
2062 * guarantess that the page we're looking for can't exist
2063 * if the bucket it hashes to is currently NULL even when looked
2064 * at outside the scope of the hash bucket lock... this is a
2065 * really cheap optimiztion to avoid taking the lock
2067 if (!bucket
->page_list
) {
2068 #if DEBUG_VM_PAGE_LOOKUP
2069 OSAddAtomic64(1, &vm_page_lookup_stats
.vpl_bucket_NULL
);
2071 return (VM_PAGE_NULL
);
2074 #if DEBUG_VM_PAGE_LOOKUP
2075 start
= mach_absolute_time();
2077 if (object
->resident_page_count
<= VM_PAGE_HASH_LOOKUP_THRESHOLD
) {
2079 * on average, it's roughly 3 times faster to run a short memq list
2080 * than to take the spin lock and go through the hash list
2082 mem
= (vm_page_t
)vm_page_queue_first(&object
->memq
);
2084 while (!vm_page_queue_end(&object
->memq
, (vm_page_queue_entry_t
)mem
)) {
2086 if (mem
->offset
== offset
)
2089 mem
= (vm_page_t
)vm_page_queue_next(&mem
->listq
);
2091 if (vm_page_queue_end(&object
->memq
, (vm_page_queue_entry_t
)mem
))
2094 vm_page_object_t packed_object
;
2096 packed_object
= VM_PAGE_PACK_OBJECT(object
);
2098 bucket_lock
= &vm_page_bucket_locks
[hash_id
/ BUCKETS_PER_LOCK
];
2100 lck_spin_lock(bucket_lock
);
2102 for (mem
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(bucket
->page_list
));
2103 mem
!= VM_PAGE_NULL
;
2104 mem
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(mem
->next_m
))) {
2107 * we don't hold the page queue lock
2108 * so this check isn't safe to make
2112 if ((mem
->vm_page_object
== packed_object
) && (mem
->offset
== offset
))
2115 lck_spin_unlock(bucket_lock
);
2118 #if DEBUG_VM_PAGE_LOOKUP
2119 elapsed
= mach_absolute_time() - start
;
2122 OSAddAtomic64(1, &vm_page_lookup_stats
.vpl_slow
);
2123 OSAddAtomic64(elapsed
, &vm_page_lookup_stats
.vpl_slow_elapsed
);
2125 OSAddAtomic64(1, &vm_page_lookup_stats
.vpl_fast
);
2126 OSAddAtomic64(elapsed
, &vm_page_lookup_stats
.vpl_fast_elapsed
);
2128 if (mem
!= VM_PAGE_NULL
)
2129 OSAddAtomic64(1, &vm_page_lookup_stats
.vpl_hit
);
2131 OSAddAtomic64(1, &vm_page_lookup_stats
.vpl_miss
);
2133 if (mem
!= VM_PAGE_NULL
) {
2134 assert(VM_PAGE_OBJECT(mem
) == object
);
2136 object
->memq_hint
= mem
;
2145 * Move the given memory entry from its
2146 * current object to the specified target object/offset.
2148 * The object must be locked.
2153 vm_object_t new_object
,
2154 vm_object_offset_t new_offset
)
2156 boolean_t internal_to_external
, external_to_internal
;
2158 vm_object_t m_object
;
2160 m_object
= VM_PAGE_OBJECT(mem
);
2162 assert(m_object
!= new_object
);
2166 "vm_page_rename, new object 0x%X, offset 0x%X page 0x%X\n",
2167 new_object
, new_offset
,
2171 * Changes to mem->object require the page lock because
2172 * the pageout daemon uses that lock to get the object.
2174 vm_page_lockspin_queues();
2176 internal_to_external
= FALSE
;
2177 external_to_internal
= FALSE
;
2179 if (mem
->vm_page_q_state
== VM_PAGE_ON_ACTIVE_LOCAL_Q
) {
2181 * it's much easier to get the vm_page_pageable_xxx accounting correct
2182 * if we first move the page to the active queue... it's going to end
2183 * up there anyway, and we don't do vm_page_rename's frequently enough
2184 * for this to matter.
2186 vm_page_queues_remove(mem
, FALSE
);
2187 vm_page_activate(mem
);
2189 if (VM_PAGE_PAGEABLE(mem
)) {
2190 if (m_object
->internal
&& !new_object
->internal
) {
2191 internal_to_external
= TRUE
;
2193 if (!m_object
->internal
&& new_object
->internal
) {
2194 external_to_internal
= TRUE
;
2198 tag
= m_object
->wire_tag
;
2199 vm_page_remove(mem
, TRUE
);
2200 vm_page_insert_internal(mem
, new_object
, new_offset
, tag
, TRUE
, TRUE
, FALSE
, FALSE
, NULL
);
2202 if (internal_to_external
) {
2203 vm_page_pageable_internal_count
--;
2204 vm_page_pageable_external_count
++;
2205 } else if (external_to_internal
) {
2206 vm_page_pageable_external_count
--;
2207 vm_page_pageable_internal_count
++;
2210 vm_page_unlock_queues();
2216 * Initialize the fields in a new page.
2217 * This takes a structure with random values and initializes it
2218 * so that it can be given to vm_page_release or vm_page_insert.
2229 if ((phys_page
!= vm_page_fictitious_addr
) && (phys_page
!= vm_page_guard_addr
)) {
2230 if (!(pmap_valid_page(phys_page
))) {
2231 panic("vm_page_init: non-DRAM phys_page 0x%x\n", phys_page
);
2235 *mem
= vm_page_template
;
2237 VM_PAGE_SET_PHYS_PAGE(mem
, phys_page
);
2240 * we're leaving this turned off for now... currently pages
2241 * come off the free list and are either immediately dirtied/referenced
2242 * due to zero-fill or COW faults, or are used to read or write files...
2243 * in the file I/O case, the UPL mechanism takes care of clearing
2244 * the state of the HW ref/mod bits in a somewhat fragile way.
2245 * Since we may change the way this works in the future (to toughen it up),
2246 * I'm leaving this as a reminder of where these bits could get cleared
2250 * make sure both the h/w referenced and modified bits are
2251 * clear at this point... we are especially dependent on
2252 * not finding a 'stale' h/w modified in a number of spots
2253 * once this page goes back into use
2255 pmap_clear_refmod(phys_page
, VM_MEM_MODIFIED
| VM_MEM_REFERENCED
);
2257 mem
->lopage
= lopage
;
2261 * vm_page_grab_fictitious:
2263 * Remove a fictitious page from the free list.
2264 * Returns VM_PAGE_NULL if there are no free pages.
2266 int c_vm_page_grab_fictitious
= 0;
2267 int c_vm_page_grab_fictitious_failed
= 0;
2268 int c_vm_page_release_fictitious
= 0;
2269 int c_vm_page_more_fictitious
= 0;
2272 vm_page_grab_fictitious_common(
2277 if ((m
= (vm_page_t
)zget(vm_page_zone
))) {
2279 vm_page_init(m
, phys_addr
, FALSE
);
2280 m
->fictitious
= TRUE
;
2282 c_vm_page_grab_fictitious
++;
2284 c_vm_page_grab_fictitious_failed
++;
2290 vm_page_grab_fictitious(void)
2292 return vm_page_grab_fictitious_common(vm_page_fictitious_addr
);
2299 vm_page_grab_guard(void)
2302 page
= vm_page_grab_fictitious_common(vm_page_guard_addr
);
2303 if (page
) OSAddAtomic(1, &vm_guard_count
);
2309 * vm_page_release_fictitious:
2311 * Release a fictitious page to the zone pool
2314 vm_page_release_fictitious(
2317 assert((m
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
) || (m
->vm_page_q_state
== VM_PAGE_IS_WIRED
));
2318 assert(m
->fictitious
);
2319 assert(VM_PAGE_GET_PHYS_PAGE(m
) == vm_page_fictitious_addr
||
2320 VM_PAGE_GET_PHYS_PAGE(m
) == vm_page_guard_addr
);
2323 if (VM_PAGE_GET_PHYS_PAGE(m
) == vm_page_guard_addr
) OSAddAtomic(-1, &vm_guard_count
);
2325 c_vm_page_release_fictitious
++;
2327 zfree(vm_page_zone
, m
);
2331 * vm_page_more_fictitious:
2333 * Add more fictitious pages to the zone.
2334 * Allowed to block. This routine is way intimate
2335 * with the zones code, for several reasons:
2336 * 1. we need to carve some page structures out of physical
2337 * memory before zones work, so they _cannot_ come from
2339 * 2. the zone needs to be collectable in order to prevent
2340 * growth without bound. These structures are used by
2341 * the device pager (by the hundreds and thousands), as
2342 * private pages for pageout, and as blocking pages for
2343 * pagein. Temporary bursts in demand should not result in
2344 * permanent allocation of a resource.
2345 * 3. To smooth allocation humps, we allocate single pages
2346 * with kernel_memory_allocate(), and cram them into the
2350 void vm_page_more_fictitious(void)
2353 kern_return_t retval
;
2355 c_vm_page_more_fictitious
++;
2358 * Allocate a single page from the zone_map. Do not wait if no physical
2359 * pages are immediately available, and do not zero the space. We need
2360 * our own blocking lock here to prevent having multiple,
2361 * simultaneous requests from piling up on the zone_map lock. Exactly
2362 * one (of our) threads should be potentially waiting on the map lock.
2363 * If winner is not vm-privileged, then the page allocation will fail,
2364 * and it will temporarily block here in the vm_page_wait().
2366 lck_mtx_lock(&vm_page_alloc_lock
);
2368 * If another thread allocated space, just bail out now.
2370 if (zone_free_count(vm_page_zone
) > 5) {
2372 * The number "5" is a small number that is larger than the
2373 * number of fictitious pages that any single caller will
2374 * attempt to allocate. Otherwise, a thread will attempt to
2375 * acquire a fictitious page (vm_page_grab_fictitious), fail,
2376 * release all of the resources and locks already acquired,
2377 * and then call this routine. This routine finds the pages
2378 * that the caller released, so fails to allocate new space.
2379 * The process repeats infinitely. The largest known number
2380 * of fictitious pages required in this manner is 2. 5 is
2381 * simply a somewhat larger number.
2383 lck_mtx_unlock(&vm_page_alloc_lock
);
2387 retval
= kernel_memory_allocate(zone_map
,
2388 &addr
, PAGE_SIZE
, 0,
2389 KMA_KOBJECT
|KMA_NOPAGEWAIT
, VM_KERN_MEMORY_ZONE
);
2390 if (retval
!= KERN_SUCCESS
) {
2392 * No page was available. Drop the
2393 * lock to give another thread a chance at it, and
2394 * wait for the pageout daemon to make progress.
2396 lck_mtx_unlock(&vm_page_alloc_lock
);
2397 vm_page_wait(THREAD_UNINT
);
2401 zcram(vm_page_zone
, addr
, PAGE_SIZE
);
2403 lck_mtx_unlock(&vm_page_alloc_lock
);
2410 * Return true if it is not likely that a non-vm_privileged thread
2411 * can get memory without blocking. Advisory only, since the
2412 * situation may change under us.
2417 /* No locking, at worst we will fib. */
2418 return( vm_page_free_count
<= vm_page_free_reserved
);
2422 #if CONFIG_BACKGROUND_QUEUE
2425 vm_page_update_background_state(vm_page_t mem
)
2427 if (vm_page_background_mode
== VM_PAGE_BG_DISABLED
)
2430 if (mem
->vm_page_in_background
== FALSE
)
2433 #if BACKGROUNDQ_BASED_ON_QOS
2434 if (proc_get_effective_thread_policy(current_thread(), TASK_POLICY_QOS
) <= THREAD_QOS_LEGACY
)
2439 my_task
= current_task();
2442 if (proc_get_effective_task_policy(my_task
, TASK_POLICY_DARWIN_BG
))
2446 vm_page_lockspin_queues();
2448 mem
->vm_page_in_background
= FALSE
;
2449 vm_page_background_promoted_count
++;
2451 vm_page_remove_from_backgroundq(mem
);
2453 vm_page_unlock_queues();
2458 vm_page_assign_background_state(vm_page_t mem
)
2460 if (vm_page_background_mode
== VM_PAGE_BG_DISABLED
)
2463 #if BACKGROUNDQ_BASED_ON_QOS
2464 if (proc_get_effective_thread_policy(current_thread(), TASK_POLICY_QOS
) <= THREAD_QOS_LEGACY
)
2465 mem
->vm_page_in_background
= TRUE
;
2467 mem
->vm_page_in_background
= FALSE
;
2471 my_task
= current_task();
2474 mem
->vm_page_in_background
= proc_get_effective_task_policy(my_task
, TASK_POLICY_DARWIN_BG
);
2480 vm_page_remove_from_backgroundq(
2483 vm_object_t m_object
;
2485 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
2487 if (mem
->vm_page_on_backgroundq
) {
2488 vm_page_queue_remove(&vm_page_queue_background
, mem
, vm_page_t
, vm_page_backgroundq
);
2490 mem
->vm_page_backgroundq
.next
= 0;
2491 mem
->vm_page_backgroundq
.prev
= 0;
2492 mem
->vm_page_on_backgroundq
= FALSE
;
2494 vm_page_background_count
--;
2496 m_object
= VM_PAGE_OBJECT(mem
);
2498 if (m_object
->internal
)
2499 vm_page_background_internal_count
--;
2501 vm_page_background_external_count
--;
2503 assert(VM_PAGE_UNPACK_PTR(mem
->vm_page_backgroundq
.next
) == (uintptr_t)NULL
&&
2504 VM_PAGE_UNPACK_PTR(mem
->vm_page_backgroundq
.prev
) == (uintptr_t)NULL
);
2510 vm_page_add_to_backgroundq(
2514 vm_object_t m_object
;
2516 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
2518 if (vm_page_background_mode
== VM_PAGE_BG_DISABLED
)
2521 if (mem
->vm_page_on_backgroundq
== FALSE
) {
2523 m_object
= VM_PAGE_OBJECT(mem
);
2525 if (vm_page_background_exclude_external
&& !m_object
->internal
)
2529 vm_page_queue_enter_first(&vm_page_queue_background
, mem
, vm_page_t
, vm_page_backgroundq
);
2531 vm_page_queue_enter(&vm_page_queue_background
, mem
, vm_page_t
, vm_page_backgroundq
);
2532 mem
->vm_page_on_backgroundq
= TRUE
;
2534 vm_page_background_count
++;
2536 if (m_object
->internal
)
2537 vm_page_background_internal_count
++;
2539 vm_page_background_external_count
++;
2546 * this is an interface to support bring-up of drivers
2547 * on platforms with physical memory > 4G...
2549 int vm_himemory_mode
= 2;
2553 * this interface exists to support hardware controllers
2554 * incapable of generating DMAs with more than 32 bits
2555 * of address on platforms with physical memory > 4G...
2557 unsigned int vm_lopages_allocated_q
= 0;
2558 unsigned int vm_lopages_allocated_cpm_success
= 0;
2559 unsigned int vm_lopages_allocated_cpm_failed
= 0;
2560 vm_page_queue_head_t vm_lopage_queue_free
__attribute__((aligned(VM_PACKED_POINTER_ALIGNMENT
)));
2563 vm_page_grablo(void)
2567 if (vm_lopage_needed
== FALSE
)
2568 return (vm_page_grab());
2570 lck_mtx_lock_spin(&vm_page_queue_free_lock
);
2572 if ( !vm_page_queue_empty(&vm_lopage_queue_free
)) {
2573 vm_page_queue_remove_first(&vm_lopage_queue_free
,
2577 assert(vm_lopage_free_count
);
2578 assert(mem
->vm_page_q_state
== VM_PAGE_ON_FREE_LOPAGE_Q
);
2579 mem
->vm_page_q_state
= VM_PAGE_NOT_ON_Q
;
2581 vm_lopage_free_count
--;
2582 vm_lopages_allocated_q
++;
2584 if (vm_lopage_free_count
< vm_lopage_lowater
)
2585 vm_lopage_refill
= TRUE
;
2587 lck_mtx_unlock(&vm_page_queue_free_lock
);
2589 #if CONFIG_BACKGROUND_QUEUE
2590 vm_page_assign_background_state(mem
);
2593 lck_mtx_unlock(&vm_page_queue_free_lock
);
2595 if (cpm_allocate(PAGE_SIZE
, &mem
, atop(0xffffffff), 0, FALSE
, KMA_LOMEM
) != KERN_SUCCESS
) {
2597 lck_mtx_lock_spin(&vm_page_queue_free_lock
);
2598 vm_lopages_allocated_cpm_failed
++;
2599 lck_mtx_unlock(&vm_page_queue_free_lock
);
2601 return (VM_PAGE_NULL
);
2603 assert(mem
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
);
2607 vm_page_lockspin_queues();
2609 mem
->gobbled
= FALSE
;
2610 vm_page_gobble_count
--;
2611 vm_page_wire_count
--;
2613 vm_lopages_allocated_cpm_success
++;
2614 vm_page_unlock_queues();
2617 assert(!mem
->pmapped
);
2618 assert(!mem
->wpmapped
);
2619 assert(!pmap_is_noencrypt(VM_PAGE_GET_PHYS_PAGE(mem
)));
2621 VM_PAGE_ZERO_PAGEQ_ENTRY(mem
);
2630 * first try to grab a page from the per-cpu free list...
2631 * this must be done while pre-emption is disabled... if
2632 * a page is available, we're done...
2633 * if no page is available, grab the vm_page_queue_free_lock
2634 * and see if current number of free pages would allow us
2635 * to grab at least 1... if not, return VM_PAGE_NULL as before...
2636 * if there are pages available, disable preemption and
2637 * recheck the state of the per-cpu free list... we could
2638 * have been preempted and moved to a different cpu, or
2639 * some other thread could have re-filled it... if still
2640 * empty, figure out how many pages we can steal from the
2641 * global free queue and move to the per-cpu queue...
2642 * return 1 of these pages when done... only wakeup the
2643 * pageout_scan thread if we moved pages from the global
2644 * list... no need for the wakeup if we've satisfied the
2645 * request from the per-cpu queue.
2648 #if CONFIG_SECLUDED_MEMORY
2649 vm_page_t
vm_page_grab_secluded(void);
2650 #endif /* CONFIG_SECLUDED_MEMORY */
2655 return vm_page_grab_options(0);
2659 boolean_t hibernate_rebuild_needed
= FALSE
;
2660 #endif /* HIBERNATION */
2663 vm_page_grab_options(
2668 disable_preemption();
2670 if ((mem
= PROCESSOR_DATA(current_processor(), free_pages
))) {
2671 return_page_from_cpu_list
:
2672 assert(mem
->vm_page_q_state
== VM_PAGE_ON_FREE_LOCAL_Q
);
2675 if (hibernate_rebuild_needed
) {
2676 panic("%s:%d should not modify cpu->free_pages while hibernating", __FUNCTION__
, __LINE__
);
2678 #endif /* HIBERNATION */
2679 PROCESSOR_DATA(current_processor(), page_grab_count
) += 1;
2680 PROCESSOR_DATA(current_processor(), free_pages
) = mem
->snext
;
2682 enable_preemption();
2683 VM_PAGE_ZERO_PAGEQ_ENTRY(mem
);
2684 mem
->vm_page_q_state
= VM_PAGE_NOT_ON_Q
;
2686 assert(mem
->listq
.next
== 0 && mem
->listq
.prev
== 0);
2687 assert(mem
->tabled
== FALSE
);
2688 assert(mem
->vm_page_object
== 0);
2689 assert(!mem
->laundry
);
2690 assert(pmap_verify_free(VM_PAGE_GET_PHYS_PAGE(mem
)));
2692 assert(!mem
->pmapped
);
2693 assert(!mem
->wpmapped
);
2694 assert(!pmap_is_noencrypt(VM_PAGE_GET_PHYS_PAGE(mem
)));
2696 #if CONFIG_BACKGROUND_QUEUE
2697 vm_page_assign_background_state(mem
);
2701 enable_preemption();
2705 * Optionally produce warnings if the wire or gobble
2706 * counts exceed some threshold.
2708 #if VM_PAGE_WIRE_COUNT_WARNING
2709 if (vm_page_wire_count
>= VM_PAGE_WIRE_COUNT_WARNING
) {
2710 printf("mk: vm_page_grab(): high wired page count of %d\n",
2711 vm_page_wire_count
);
2714 #if VM_PAGE_GOBBLE_COUNT_WARNING
2715 if (vm_page_gobble_count
>= VM_PAGE_GOBBLE_COUNT_WARNING
) {
2716 printf("mk: vm_page_grab(): high gobbled page count of %d\n",
2717 vm_page_gobble_count
);
2721 lck_mtx_lock_spin(&vm_page_queue_free_lock
);
2724 * Only let privileged threads (involved in pageout)
2725 * dip into the reserved pool.
2727 if ((vm_page_free_count
< vm_page_free_reserved
) &&
2728 !(current_thread()->options
& TH_OPT_VMPRIV
)) {
2729 /* no page for us in the free queue... */
2730 lck_mtx_unlock(&vm_page_queue_free_lock
);
2733 #if CONFIG_SECLUDED_MEMORY
2734 /* ... but can we try and grab from the secluded queue? */
2735 if (vm_page_secluded_count
> 0 &&
2736 ((grab_options
& VM_PAGE_GRAB_SECLUDED
) ||
2737 task_can_use_secluded_mem(current_task()))) {
2738 mem
= vm_page_grab_secluded();
2739 if (grab_options
& VM_PAGE_GRAB_SECLUDED
) {
2740 vm_page_secluded
.grab_for_iokit
++;
2742 vm_page_secluded
.grab_for_iokit_success
++;
2746 VM_CHECK_MEMORYSTATUS
;
2750 #else /* CONFIG_SECLUDED_MEMORY */
2751 (void) grab_options
;
2752 #endif /* CONFIG_SECLUDED_MEMORY */
2757 unsigned int pages_to_steal
;
2759 unsigned int clump_end
, sub_count
;
2761 while ( vm_page_free_count
== 0 ) {
2763 lck_mtx_unlock(&vm_page_queue_free_lock
);
2765 * must be a privileged thread to be
2766 * in this state since a non-privileged
2767 * thread would have bailed if we were
2768 * under the vm_page_free_reserved mark
2771 lck_mtx_lock_spin(&vm_page_queue_free_lock
);
2774 disable_preemption();
2776 if ((mem
= PROCESSOR_DATA(current_processor(), free_pages
))) {
2777 lck_mtx_unlock(&vm_page_queue_free_lock
);
2780 * we got preempted and moved to another processor
2781 * or we got preempted and someone else ran and filled the cache
2783 goto return_page_from_cpu_list
;
2785 if (vm_page_free_count
<= vm_page_free_reserved
)
2788 if (vm_free_magazine_refill_limit
<= (vm_page_free_count
- vm_page_free_reserved
))
2789 pages_to_steal
= vm_free_magazine_refill_limit
;
2791 pages_to_steal
= (vm_page_free_count
- vm_page_free_reserved
);
2793 color
= PROCESSOR_DATA(current_processor(), start_color
);
2796 vm_page_free_count
-= pages_to_steal
;
2797 clump_end
= sub_count
= 0;
2799 while (pages_to_steal
--) {
2801 while (vm_page_queue_empty(&vm_page_queue_free
[color
].qhead
))
2802 color
= (color
+ 1) & vm_color_mask
;
2803 #if defined(__x86_64__)
2804 vm_page_queue_remove_first_with_clump(&vm_page_queue_free
[color
].qhead
,
2810 vm_page_queue_remove_first(&vm_page_queue_free
[color
].qhead
,
2816 assert(mem
->vm_page_q_state
== VM_PAGE_ON_FREE_Q
);
2818 VM_PAGE_ZERO_PAGEQ_ENTRY(mem
);
2820 #if defined(__arm__) || defined(__arm64__)
2821 color
= (color
+ 1) & vm_color_mask
;
2824 #if DEVELOPMENT || DEBUG
2828 vm_clump_update_stats(sub_count
);
2830 color
= (color
+ 1) & vm_color_mask
;
2833 if (clump_end
) color
= (color
+ 1) & vm_color_mask
;
2835 #endif /* if DEVELOPMENT || DEBUG */
2837 #endif /* if defined(__arm__) || defined(__arm64__) */
2845 assert(mem
->listq
.next
== 0 && mem
->listq
.prev
== 0);
2846 assert(mem
->tabled
== FALSE
);
2847 assert(mem
->vm_page_object
== 0);
2848 assert(!mem
->laundry
);
2850 mem
->vm_page_q_state
= VM_PAGE_ON_FREE_LOCAL_Q
;
2852 assert(pmap_verify_free(VM_PAGE_GET_PHYS_PAGE(mem
)));
2854 assert(!mem
->pmapped
);
2855 assert(!mem
->wpmapped
);
2856 assert(!pmap_is_noencrypt(VM_PAGE_GET_PHYS_PAGE(mem
)));
2858 #if defined (__x86_64__) && (DEVELOPMENT || DEBUG)
2859 vm_clump_update_stats(sub_count
);
2861 lck_mtx_unlock(&vm_page_queue_free_lock
);
2864 if (hibernate_rebuild_needed
) {
2865 panic("%s:%d should not modify cpu->free_pages while hibernating", __FUNCTION__
, __LINE__
);
2867 #endif /* HIBERNATION */
2868 PROCESSOR_DATA(current_processor(), free_pages
) = head
->snext
;
2869 PROCESSOR_DATA(current_processor(), start_color
) = color
;
2872 * satisfy this request
2874 PROCESSOR_DATA(current_processor(), page_grab_count
) += 1;
2876 assert(mem
->vm_page_q_state
== VM_PAGE_ON_FREE_LOCAL_Q
);
2878 VM_PAGE_ZERO_PAGEQ_ENTRY(mem
);
2879 mem
->vm_page_q_state
= VM_PAGE_NOT_ON_Q
;
2881 enable_preemption();
2884 * Decide if we should poke the pageout daemon.
2885 * We do this if the free count is less than the low
2886 * water mark, or if the free count is less than the high
2887 * water mark (but above the low water mark) and the inactive
2888 * count is less than its target.
2890 * We don't have the counts locked ... if they change a little,
2891 * it doesn't really matter.
2893 if ((vm_page_free_count
< vm_page_free_min
) ||
2894 ((vm_page_free_count
< vm_page_free_target
) &&
2895 ((vm_page_inactive_count
+ vm_page_speculative_count
) < vm_page_inactive_min
)))
2896 thread_wakeup((event_t
) &vm_page_free_wanted
);
2898 VM_CHECK_MEMORYSTATUS
;
2901 // dbgLog(VM_PAGE_GET_PHYS_PAGE(mem), vm_page_free_count, vm_page_wire_count, 4); /* (TEST/DEBUG) */
2903 #if CONFIG_BACKGROUND_QUEUE
2904 vm_page_assign_background_state(mem
);
2910 #if CONFIG_SECLUDED_MEMORY
2912 vm_page_grab_secluded(void)
2918 if (vm_page_secluded_count
== 0) {
2919 /* no secluded pages to grab... */
2920 return VM_PAGE_NULL
;
2923 /* secluded queue is protected by the VM page queue lock */
2924 vm_page_lock_queues();
2926 if (vm_page_secluded_count
== 0) {
2927 /* no secluded pages to grab... */
2928 vm_page_unlock_queues();
2929 return VM_PAGE_NULL
;
2933 /* can we grab from the secluded queue? */
2934 if (vm_page_secluded_count
> vm_page_secluded_target
||
2935 (vm_page_secluded_count
> 0 &&
2936 task_can_use_secluded_mem(current_task()))) {
2939 /* can't grab from secluded queue... */
2940 vm_page_unlock_queues();
2941 return VM_PAGE_NULL
;
2945 /* we can grab a page from secluded queue! */
2946 assert((vm_page_secluded_count_free
+
2947 vm_page_secluded_count_inuse
) ==
2948 vm_page_secluded_count
);
2949 if (current_task()->task_can_use_secluded_mem
) {
2950 assert(num_tasks_can_use_secluded_mem
> 0);
2952 assert(!vm_page_queue_empty(&vm_page_queue_secluded
));
2953 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
2954 mem
= (vm_page_t
)vm_page_queue_first(&vm_page_queue_secluded
);
2955 assert(mem
->vm_page_q_state
== VM_PAGE_ON_SECLUDED_Q
);
2956 vm_page_queues_remove(mem
, TRUE
);
2958 object
= VM_PAGE_OBJECT(mem
);
2960 assert(!mem
->fictitious
);
2961 assert(!VM_PAGE_WIRED(mem
));
2962 if (object
== VM_OBJECT_NULL
) {
2963 /* free for grab! */
2964 vm_page_unlock_queues();
2965 vm_page_secluded
.grab_success_free
++;
2968 assert(mem
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
);
2969 assert(VM_PAGE_OBJECT(mem
) == VM_OBJECT_NULL
);
2970 assert(mem
->pageq
.next
== 0);
2971 assert(mem
->pageq
.prev
== 0);
2972 assert(mem
->listq
.next
== 0);
2973 assert(mem
->listq
.prev
== 0);
2974 #if CONFIG_BACKGROUND_QUEUE
2975 assert(mem
->vm_page_on_backgroundq
== 0);
2976 assert(mem
->vm_page_backgroundq
.next
== 0);
2977 assert(mem
->vm_page_backgroundq
.prev
== 0);
2978 #endif /* CONFIG_BACKGROUND_QUEUE */
2982 assert(!object
->internal
);
2983 // vm_page_pageable_external_count--;
2985 if (!vm_object_lock_try(object
)) {
2986 // printf("SECLUDED: page %p: object %p locked\n", mem, object);
2987 vm_page_secluded
.grab_failure_locked
++;
2988 reactivate_secluded_page
:
2989 vm_page_activate(mem
);
2990 vm_page_unlock_queues();
2991 return VM_PAGE_NULL
;
2996 /* can't steal page in this state... */
2997 vm_object_unlock(object
);
2998 vm_page_secluded
.grab_failure_state
++;
2999 goto reactivate_secluded_page
;
3003 refmod_state
= pmap_disconnect(VM_PAGE_GET_PHYS_PAGE(mem
));
3004 if (refmod_state
& VM_MEM_REFERENCED
) {
3005 mem
->reference
= TRUE
;
3007 if (refmod_state
& VM_MEM_MODIFIED
) {
3008 SET_PAGE_DIRTY(mem
, FALSE
);
3010 if (mem
->dirty
|| mem
->precious
) {
3011 /* can't grab a dirty page; re-activate */
3012 // printf("SECLUDED: dirty page %p\n", mem);
3013 PAGE_WAKEUP_DONE(mem
);
3014 vm_page_secluded
.grab_failure_dirty
++;
3015 vm_object_unlock(object
);
3016 goto reactivate_secluded_page
;
3018 if (mem
->reference
) {
3019 /* it's been used but we do need to grab a page... */
3022 vm_page_unlock_queues();
3024 /* finish what vm_page_free() would have done... */
3025 vm_page_free_prepare_object(mem
, TRUE
);
3026 vm_object_unlock(object
);
3027 object
= VM_OBJECT_NULL
;
3028 if (vm_page_free_verify
) {
3029 assert(pmap_verify_free(VM_PAGE_GET_PHYS_PAGE(mem
)));
3031 pmap_clear_noencrypt(VM_PAGE_GET_PHYS_PAGE(mem
));
3032 vm_page_secluded
.grab_success_other
++;
3035 assert(mem
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
);
3036 assert(VM_PAGE_OBJECT(mem
) == VM_OBJECT_NULL
);
3037 assert(mem
->pageq
.next
== 0);
3038 assert(mem
->pageq
.prev
== 0);
3039 assert(mem
->listq
.next
== 0);
3040 assert(mem
->listq
.prev
== 0);
3041 #if CONFIG_BACKGROUND_QUEUE
3042 assert(mem
->vm_page_on_backgroundq
== 0);
3043 assert(mem
->vm_page_backgroundq
.next
== 0);
3044 assert(mem
->vm_page_backgroundq
.prev
== 0);
3045 #endif /* CONFIG_BACKGROUND_QUEUE */
3049 #endif /* CONFIG_SECLUDED_MEMORY */
3054 * Return a page to the free list.
3060 boolean_t page_queues_locked
)
3063 int need_wakeup
= 0;
3064 int need_priv_wakeup
= 0;
3065 #if CONFIG_SECLUDED_MEMORY
3066 int need_secluded_wakeup
= 0;
3067 #endif /* CONFIG_SECLUDED_MEMORY */
3069 if (page_queues_locked
) {
3070 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
3072 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_NOTOWNED
);
3075 assert(!mem
->private && !mem
->fictitious
);
3076 if (vm_page_free_verify
) {
3077 assert(pmap_verify_free(VM_PAGE_GET_PHYS_PAGE(mem
)));
3079 // dbgLog(VM_PAGE_GET_PHYS_PAGE(mem), vm_page_free_count, vm_page_wire_count, 5); /* (TEST/DEBUG) */
3081 pmap_clear_noencrypt(VM_PAGE_GET_PHYS_PAGE(mem
));
3083 lck_mtx_lock_spin(&vm_page_queue_free_lock
);
3085 assert(mem
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
);
3087 assert(!mem
->laundry
);
3088 assert(mem
->vm_page_object
== 0);
3089 assert(mem
->pageq
.next
== 0 && mem
->pageq
.prev
== 0);
3090 assert(mem
->listq
.next
== 0 && mem
->listq
.prev
== 0);
3091 #if CONFIG_BACKGROUND_QUEUE
3092 assert(mem
->vm_page_backgroundq
.next
== 0 &&
3093 mem
->vm_page_backgroundq
.prev
== 0 &&
3094 mem
->vm_page_on_backgroundq
== FALSE
);
3096 if ((mem
->lopage
== TRUE
|| vm_lopage_refill
== TRUE
) &&
3097 vm_lopage_free_count
< vm_lopage_free_limit
&&
3098 VM_PAGE_GET_PHYS_PAGE(mem
) < max_valid_low_ppnum
) {
3100 * this exists to support hardware controllers
3101 * incapable of generating DMAs with more than 32 bits
3102 * of address on platforms with physical memory > 4G...
3104 vm_page_queue_enter_first(&vm_lopage_queue_free
,
3108 vm_lopage_free_count
++;
3110 if (vm_lopage_free_count
>= vm_lopage_free_limit
)
3111 vm_lopage_refill
= FALSE
;
3113 mem
->vm_page_q_state
= VM_PAGE_ON_FREE_LOPAGE_Q
;
3115 #if CONFIG_SECLUDED_MEMORY
3116 } else if (vm_page_free_count
> vm_page_free_reserved
&&
3117 vm_page_secluded_count
< vm_page_secluded_target
&&
3118 num_tasks_can_use_secluded_mem
== 0) {
3120 * XXX FBDP TODO: also avoid refilling secluded queue
3121 * when some IOKit objects are already grabbing from it...
3123 if (!page_queues_locked
) {
3124 if (!vm_page_trylock_queues()) {
3125 /* take locks in right order */
3126 lck_mtx_unlock(&vm_page_queue_free_lock
);
3127 vm_page_lock_queues();
3128 lck_mtx_lock_spin(&vm_page_queue_free_lock
);
3131 mem
->lopage
= FALSE
;
3132 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
3133 vm_page_queue_enter_first(&vm_page_queue_secluded
,
3137 mem
->vm_page_q_state
= VM_PAGE_ON_SECLUDED_Q
;
3138 vm_page_secluded_count
++;
3139 vm_page_secluded_count_free
++;
3140 if (!page_queues_locked
) {
3141 vm_page_unlock_queues();
3143 LCK_MTX_ASSERT(&vm_page_queue_free_lock
, LCK_MTX_ASSERT_OWNED
);
3144 if (vm_page_free_wanted_secluded
> 0) {
3145 vm_page_free_wanted_secluded
--;
3146 need_secluded_wakeup
= 1;
3148 #endif /* CONFIG_SECLUDED_MEMORY */
3150 mem
->lopage
= FALSE
;
3151 mem
->vm_page_q_state
= VM_PAGE_ON_FREE_Q
;
3153 color
= VM_PAGE_GET_COLOR(mem
);
3154 #if defined(__x86_64__)
3155 vm_page_queue_enter_clump(&vm_page_queue_free
[color
].qhead
,
3160 vm_page_queue_enter(&vm_page_queue_free
[color
].qhead
,
3165 vm_page_free_count
++;
3167 * Check if we should wake up someone waiting for page.
3168 * But don't bother waking them unless they can allocate.
3170 * We wakeup only one thread, to prevent starvation.
3171 * Because the scheduling system handles wait queues FIFO,
3172 * if we wakeup all waiting threads, one greedy thread
3173 * can starve multiple niceguy threads. When the threads
3174 * all wakeup, the greedy threads runs first, grabs the page,
3175 * and waits for another page. It will be the first to run
3176 * when the next page is freed.
3178 * However, there is a slight danger here.
3179 * The thread we wake might not use the free page.
3180 * Then the other threads could wait indefinitely
3181 * while the page goes unused. To forestall this,
3182 * the pageout daemon will keep making free pages
3183 * as long as vm_page_free_wanted is non-zero.
3186 assert(vm_page_free_count
> 0);
3187 if (vm_page_free_wanted_privileged
> 0) {
3188 vm_page_free_wanted_privileged
--;
3189 need_priv_wakeup
= 1;
3190 #if CONFIG_SECLUDED_MEMORY
3191 } else if (vm_page_free_wanted_secluded
> 0 &&
3192 vm_page_free_count
> vm_page_free_reserved
) {
3193 vm_page_free_wanted_secluded
--;
3194 need_secluded_wakeup
= 1;
3195 #endif /* CONFIG_SECLUDED_MEMORY */
3196 } else if (vm_page_free_wanted
> 0 &&
3197 vm_page_free_count
> vm_page_free_reserved
) {
3198 vm_page_free_wanted
--;
3202 lck_mtx_unlock(&vm_page_queue_free_lock
);
3204 if (need_priv_wakeup
)
3205 thread_wakeup_one((event_t
) &vm_page_free_wanted_privileged
);
3206 #if CONFIG_SECLUDED_MEMORY
3207 else if (need_secluded_wakeup
)
3208 thread_wakeup_one((event_t
) &vm_page_free_wanted_secluded
);
3209 #endif /* CONFIG_SECLUDED_MEMORY */
3210 else if (need_wakeup
)
3211 thread_wakeup_one((event_t
) &vm_page_free_count
);
3213 VM_CHECK_MEMORYSTATUS
;
3217 * This version of vm_page_release() is used only at startup
3218 * when we are single-threaded and pages are being released
3219 * for the first time. Hence, no locking or unnecessary checks are made.
3220 * Note: VM_CHECK_MEMORYSTATUS invoked by the caller.
3223 vm_page_release_startup(
3226 vm_page_queue_t queue_free
;
3228 if (vm_lopage_free_count
< vm_lopage_free_limit
&&
3229 VM_PAGE_GET_PHYS_PAGE(mem
) < max_valid_low_ppnum
) {
3231 mem
->vm_page_q_state
= VM_PAGE_ON_FREE_LOPAGE_Q
;
3232 vm_lopage_free_count
++;
3233 queue_free
= &vm_lopage_queue_free
;
3234 #if CONFIG_SECLUDED_MEMORY
3235 } else if (vm_page_secluded_count
< vm_page_secluded_target
) {
3236 mem
->lopage
= FALSE
;
3237 mem
->vm_page_q_state
= VM_PAGE_ON_SECLUDED_Q
;
3238 vm_page_secluded_count
++;
3239 vm_page_secluded_count_free
++;
3240 queue_free
= &vm_page_queue_secluded
;
3241 #endif /* CONFIG_SECLUDED_MEMORY */
3243 mem
->lopage
= FALSE
;
3244 mem
->vm_page_q_state
= VM_PAGE_ON_FREE_Q
;
3245 vm_page_free_count
++;
3246 queue_free
= &vm_page_queue_free
[VM_PAGE_GET_COLOR(mem
)].qhead
;
3248 if (mem
->vm_page_q_state
== VM_PAGE_ON_FREE_Q
) {
3249 #if defined(__x86_64__)
3250 vm_page_queue_enter_clump(queue_free
, mem
, vm_page_t
, pageq
);
3252 vm_page_queue_enter(queue_free
, mem
, vm_page_t
, pageq
);
3255 vm_page_queue_enter_first(queue_free
, mem
, vm_page_t
, pageq
);
3261 * Wait for a page to become available.
3262 * If there are plenty of free pages, then we don't sleep.
3265 * TRUE: There may be another page, try again
3266 * FALSE: We were interrupted out of our wait, don't try again
3274 * We can't use vm_page_free_reserved to make this
3275 * determination. Consider: some thread might
3276 * need to allocate two pages. The first allocation
3277 * succeeds, the second fails. After the first page is freed,
3278 * a call to vm_page_wait must really block.
3280 kern_return_t wait_result
;
3281 int need_wakeup
= 0;
3282 int is_privileged
= current_thread()->options
& TH_OPT_VMPRIV
;
3284 lck_mtx_lock_spin(&vm_page_queue_free_lock
);
3286 if (is_privileged
&& vm_page_free_count
) {
3287 lck_mtx_unlock(&vm_page_queue_free_lock
);
3291 if (vm_page_free_count
>= vm_page_free_target
) {
3292 lck_mtx_unlock(&vm_page_queue_free_lock
);
3296 if (is_privileged
) {
3297 if (vm_page_free_wanted_privileged
++ == 0)
3299 wait_result
= assert_wait((event_t
)&vm_page_free_wanted_privileged
, interruptible
);
3300 #if CONFIG_SECLUDED_MEMORY
3301 } else if (secluded_for_apps
&&
3302 task_can_use_secluded_mem(current_task())) {
3304 /* XXX FBDP: need pageq lock for this... */
3305 /* XXX FBDP: might wait even if pages available, */
3306 /* XXX FBDP: hopefully not for too long... */
3307 if (vm_page_secluded_count
> 0) {
3308 lck_mtx_unlock(&vm_page_queue_free_lock
);
3312 if (vm_page_free_wanted_secluded
++ == 0) {
3315 wait_result
= assert_wait(
3316 (event_t
)&vm_page_free_wanted_secluded
,
3318 #endif /* CONFIG_SECLUDED_MEMORY */
3320 if (vm_page_free_wanted
++ == 0)
3322 wait_result
= assert_wait((event_t
)&vm_page_free_count
,
3325 lck_mtx_unlock(&vm_page_queue_free_lock
);
3326 counter(c_vm_page_wait_block
++);
3329 thread_wakeup((event_t
)&vm_page_free_wanted
);
3331 if (wait_result
== THREAD_WAITING
) {
3332 VM_DEBUG_EVENT(vm_page_wait_block
, VM_PAGE_WAIT_BLOCK
, DBG_FUNC_START
,
3333 vm_page_free_wanted_privileged
,
3334 vm_page_free_wanted
,
3335 #if CONFIG_SECLUDED_MEMORY
3336 vm_page_free_wanted_secluded
,
3337 #else /* CONFIG_SECLUDED_MEMORY */
3339 #endif /* CONFIG_SECLUDED_MEMORY */
3341 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
3342 VM_DEBUG_EVENT(vm_page_wait_block
,
3343 VM_PAGE_WAIT_BLOCK
, DBG_FUNC_END
, 0, 0, 0, 0);
3346 return (wait_result
== THREAD_AWAKENED
);
3352 * Allocate and return a memory cell associated
3353 * with this VM object/offset pair.
3355 * Object must be locked.
3361 vm_object_offset_t offset
)
3366 vm_object_lock_assert_exclusive(object
);
3368 #if CONFIG_SECLUDED_MEMORY
3369 if (object
->can_grab_secluded
) {
3370 grab_options
|= VM_PAGE_GRAB_SECLUDED
;
3372 #endif /* CONFIG_SECLUDED_MEMORY */
3373 mem
= vm_page_grab_options(grab_options
);
3374 if (mem
== VM_PAGE_NULL
)
3375 return VM_PAGE_NULL
;
3377 vm_page_insert(mem
, object
, offset
);
3383 * vm_page_alloc_guard:
3385 * Allocate a fictitious page which will be used
3386 * as a guard page. The page will be inserted into
3387 * the object and returned to the caller.
3391 vm_page_alloc_guard(
3393 vm_object_offset_t offset
)
3397 vm_object_lock_assert_exclusive(object
);
3398 mem
= vm_page_grab_guard();
3399 if (mem
== VM_PAGE_NULL
)
3400 return VM_PAGE_NULL
;
3402 vm_page_insert(mem
, object
, offset
);
3408 counter(unsigned int c_laundry_pages_freed
= 0;)
3411 * vm_page_free_prepare:
3413 * Removes page from any queue it may be on
3414 * and disassociates it from its VM object.
3416 * Object and page queues must be locked prior to entry.
3419 vm_page_free_prepare(
3422 vm_page_free_prepare_queues(mem
);
3423 vm_page_free_prepare_object(mem
, TRUE
);
3428 vm_page_free_prepare_queues(
3431 vm_object_t m_object
;
3435 assert(mem
->vm_page_q_state
!= VM_PAGE_ON_FREE_Q
);
3436 assert(!mem
->cleaning
);
3437 m_object
= VM_PAGE_OBJECT(mem
);
3439 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
3441 vm_object_lock_assert_exclusive(m_object
);
3445 * We may have to free a page while it's being laundered
3446 * if we lost its pager (due to a forced unmount, for example).
3447 * We need to call vm_pageout_steal_laundry() before removing
3448 * the page from its VM object, so that we can remove it
3449 * from its pageout queue and adjust the laundry accounting
3451 vm_pageout_steal_laundry(mem
, TRUE
);
3452 counter(++c_laundry_pages_freed
);
3455 vm_page_queues_remove(mem
, TRUE
);
3457 if (VM_PAGE_WIRED(mem
)) {
3458 assert(mem
->wire_count
> 0);
3462 VM_OBJECT_WIRED_PAGE_UPDATE_START(m_object
);
3463 VM_OBJECT_WIRED_PAGE_REMOVE(m_object
, mem
);
3464 VM_OBJECT_WIRED_PAGE_UPDATE_END(m_object
, m_object
->wire_tag
);
3466 assert(m_object
->resident_page_count
>=
3467 m_object
->wired_page_count
);
3469 if (m_object
->purgable
== VM_PURGABLE_VOLATILE
) {
3470 OSAddAtomic(+1, &vm_page_purgeable_count
);
3471 assert(vm_page_purgeable_wired_count
> 0);
3472 OSAddAtomic(-1, &vm_page_purgeable_wired_count
);
3474 if ((m_object
->purgable
== VM_PURGABLE_VOLATILE
||
3475 m_object
->purgable
== VM_PURGABLE_EMPTY
) &&
3476 m_object
->vo_purgeable_owner
!= TASK_NULL
) {
3479 owner
= m_object
->vo_purgeable_owner
;
3481 * While wired, this page was accounted
3482 * as "non-volatile" but it should now
3483 * be accounted as "volatile".
3485 /* one less "non-volatile"... */
3486 ledger_debit(owner
->ledger
,
3487 task_ledgers
.purgeable_nonvolatile
,
3489 /* ... and "phys_footprint" */
3490 ledger_debit(owner
->ledger
,
3491 task_ledgers
.phys_footprint
,
3493 /* one more "volatile" */
3494 ledger_credit(owner
->ledger
,
3495 task_ledgers
.purgeable_volatile
,
3499 if (!mem
->private && !mem
->fictitious
)
3500 vm_page_wire_count
--;
3502 mem
->vm_page_q_state
= VM_PAGE_NOT_ON_Q
;
3503 mem
->wire_count
= 0;
3504 assert(!mem
->gobbled
);
3505 } else if (mem
->gobbled
) {
3506 if (!mem
->private && !mem
->fictitious
)
3507 vm_page_wire_count
--;
3508 vm_page_gobble_count
--;
3514 vm_page_free_prepare_object(
3516 boolean_t remove_from_hash
)
3519 vm_page_remove(mem
, remove_from_hash
); /* clears tabled, object, offset */
3521 PAGE_WAKEUP(mem
); /* clears wanted */
3524 mem
->private = FALSE
;
3525 mem
->fictitious
= TRUE
;
3526 VM_PAGE_SET_PHYS_PAGE(mem
, vm_page_fictitious_addr
);
3528 if ( !mem
->fictitious
) {
3529 assert(mem
->pageq
.next
== 0);
3530 assert(mem
->pageq
.prev
== 0);
3531 assert(mem
->listq
.next
== 0);
3532 assert(mem
->listq
.prev
== 0);
3533 #if CONFIG_BACKGROUND_QUEUE
3534 assert(mem
->vm_page_backgroundq
.next
== 0);
3535 assert(mem
->vm_page_backgroundq
.prev
== 0);
3536 #endif /* CONFIG_BACKGROUND_QUEUE */
3537 assert(mem
->next_m
== 0);
3538 vm_page_init(mem
, VM_PAGE_GET_PHYS_PAGE(mem
), mem
->lopage
);
3546 * Returns the given page to the free list,
3547 * disassociating it with any VM object.
3549 * Object and page queues must be locked prior to entry.
3555 vm_page_free_prepare(mem
);
3557 if (mem
->fictitious
) {
3558 vm_page_release_fictitious(mem
);
3560 vm_page_release(mem
,
3561 TRUE
); /* page queues are locked */
3567 vm_page_free_unlocked(
3569 boolean_t remove_from_hash
)
3571 vm_page_lockspin_queues();
3572 vm_page_free_prepare_queues(mem
);
3573 vm_page_unlock_queues();
3575 vm_page_free_prepare_object(mem
, remove_from_hash
);
3577 if (mem
->fictitious
) {
3578 vm_page_release_fictitious(mem
);
3580 vm_page_release(mem
, FALSE
); /* page queues are not locked */
3586 * Free a list of pages. The list can be up to several hundred pages,
3587 * as blocked up by vm_pageout_scan().
3588 * The big win is not having to take the free list lock once
3591 * The VM page queues lock (vm_page_queue_lock) should NOT be held.
3592 * The VM page free queues lock (vm_page_queue_free_lock) should NOT be held.
3597 boolean_t prepare_object
)
3601 vm_page_t local_freeq
;
3604 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_NOTOWNED
);
3605 LCK_MTX_ASSERT(&vm_page_queue_free_lock
, LCK_MTX_ASSERT_NOTOWNED
);
3610 local_freeq
= VM_PAGE_NULL
;
3614 * break up the processing into smaller chunks so
3615 * that we can 'pipeline' the pages onto the
3616 * free list w/o introducing too much
3617 * contention on the global free queue lock
3619 while (mem
&& pg_count
< 64) {
3621 assert((mem
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
) ||
3622 (mem
->vm_page_q_state
== VM_PAGE_IS_WIRED
));
3623 #if CONFIG_BACKGROUND_QUEUE
3624 assert(mem
->vm_page_backgroundq
.next
== 0 &&
3625 mem
->vm_page_backgroundq
.prev
== 0 &&
3626 mem
->vm_page_on_backgroundq
== FALSE
);
3630 assert(mem
->pageq
.prev
== 0);
3632 if (vm_page_free_verify
&& !mem
->fictitious
&& !mem
->private) {
3633 assert(pmap_verify_free(VM_PAGE_GET_PHYS_PAGE(mem
)));
3635 if (prepare_object
== TRUE
)
3636 vm_page_free_prepare_object(mem
, TRUE
);
3638 if (!mem
->fictitious
) {
3641 if ((mem
->lopage
== TRUE
|| vm_lopage_refill
== TRUE
) &&
3642 vm_lopage_free_count
< vm_lopage_free_limit
&&
3643 VM_PAGE_GET_PHYS_PAGE(mem
) < max_valid_low_ppnum
) {
3644 vm_page_release(mem
, FALSE
); /* page queues are not locked */
3645 #if CONFIG_SECLUDED_MEMORY
3646 } else if (vm_page_secluded_count
< vm_page_secluded_target
&&
3647 num_tasks_can_use_secluded_mem
== 0) {
3648 vm_page_release(mem
,
3649 FALSE
); /* page queues are not locked */
3650 #endif /* CONFIG_SECLUDED_MEMORY */
3653 * IMPORTANT: we can't set the page "free" here
3654 * because that would make the page eligible for
3655 * a physically-contiguous allocation (see
3656 * vm_page_find_contiguous()) right away (we don't
3657 * hold the vm_page_queue_free lock). That would
3658 * cause trouble because the page is not actually
3659 * in the free queue yet...
3661 mem
->snext
= local_freeq
;
3665 pmap_clear_noencrypt(VM_PAGE_GET_PHYS_PAGE(mem
));
3668 assert(VM_PAGE_GET_PHYS_PAGE(mem
) == vm_page_fictitious_addr
||
3669 VM_PAGE_GET_PHYS_PAGE(mem
) == vm_page_guard_addr
);
3670 vm_page_release_fictitious(mem
);
3676 if ( (mem
= local_freeq
) ) {
3677 unsigned int avail_free_count
;
3678 unsigned int need_wakeup
= 0;
3679 unsigned int need_priv_wakeup
= 0;
3680 #if CONFIG_SECLUDED_MEMORY
3681 unsigned int need_wakeup_secluded
= 0;
3682 #endif /* CONFIG_SECLUDED_MEMORY */
3684 lck_mtx_lock_spin(&vm_page_queue_free_lock
);
3691 assert(mem
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
);
3693 mem
->lopage
= FALSE
;
3694 mem
->vm_page_q_state
= VM_PAGE_ON_FREE_Q
;
3696 color
= VM_PAGE_GET_COLOR(mem
);
3697 #if defined(__x86_64__)
3698 vm_page_queue_enter_clump(&vm_page_queue_free
[color
].qhead
,
3703 vm_page_queue_enter(&vm_page_queue_free
[color
].qhead
,
3710 vm_page_free_count
+= pg_count
;
3711 avail_free_count
= vm_page_free_count
;
3713 if (vm_page_free_wanted_privileged
> 0 && avail_free_count
> 0) {
3715 if (avail_free_count
< vm_page_free_wanted_privileged
) {
3716 need_priv_wakeup
= avail_free_count
;
3717 vm_page_free_wanted_privileged
-= avail_free_count
;
3718 avail_free_count
= 0;
3720 need_priv_wakeup
= vm_page_free_wanted_privileged
;
3721 avail_free_count
-= vm_page_free_wanted_privileged
;
3722 vm_page_free_wanted_privileged
= 0;
3725 #if CONFIG_SECLUDED_MEMORY
3726 if (vm_page_free_wanted_secluded
> 0 &&
3727 avail_free_count
> vm_page_free_reserved
) {
3728 unsigned int available_pages
;
3729 available_pages
= (avail_free_count
-
3730 vm_page_free_reserved
);
3731 if (available_pages
<
3732 vm_page_free_wanted_secluded
) {
3733 need_wakeup_secluded
= available_pages
;
3734 vm_page_free_wanted_secluded
-=
3736 avail_free_count
-= available_pages
;
3738 need_wakeup_secluded
=
3739 vm_page_free_wanted_secluded
;
3741 vm_page_free_wanted_secluded
;
3742 vm_page_free_wanted_secluded
= 0;
3745 #endif /* CONFIG_SECLUDED_MEMORY */
3746 if (vm_page_free_wanted
> 0 && avail_free_count
> vm_page_free_reserved
) {
3747 unsigned int available_pages
;
3749 available_pages
= avail_free_count
- vm_page_free_reserved
;
3751 if (available_pages
>= vm_page_free_wanted
) {
3752 need_wakeup
= vm_page_free_wanted
;
3753 vm_page_free_wanted
= 0;
3755 need_wakeup
= available_pages
;
3756 vm_page_free_wanted
-= available_pages
;
3759 lck_mtx_unlock(&vm_page_queue_free_lock
);
3761 if (need_priv_wakeup
!= 0) {
3763 * There shouldn't be that many VM-privileged threads,
3764 * so let's wake them all up, even if we don't quite
3765 * have enough pages to satisfy them all.
3767 thread_wakeup((event_t
)&vm_page_free_wanted_privileged
);
3769 #if CONFIG_SECLUDED_MEMORY
3770 if (need_wakeup_secluded
!= 0 &&
3771 vm_page_free_wanted_secluded
== 0) {
3772 thread_wakeup((event_t
)
3773 &vm_page_free_wanted_secluded
);
3776 need_wakeup_secluded
!= 0;
3777 need_wakeup_secluded
--) {
3780 &vm_page_free_wanted_secluded
);
3783 #endif /* CONFIG_SECLUDED_MEMORY */
3784 if (need_wakeup
!= 0 && vm_page_free_wanted
== 0) {
3786 * We don't expect to have any more waiters
3787 * after this, so let's wake them all up at
3790 thread_wakeup((event_t
) &vm_page_free_count
);
3791 } else for (; need_wakeup
!= 0; need_wakeup
--) {
3793 * Wake up one waiter per page we just released.
3795 thread_wakeup_one((event_t
) &vm_page_free_count
);
3798 VM_CHECK_MEMORYSTATUS
;
3807 * Mark this page as wired down by yet
3808 * another map, removing it from paging queues
3811 * The page's object and the page queues must be locked.
3819 boolean_t check_memorystatus
)
3821 vm_object_t m_object
;
3823 m_object
= VM_PAGE_OBJECT(mem
);
3825 // dbgLog(current_thread(), mem->offset, m_object, 1); /* (TEST/DEBUG) */
3829 vm_object_lock_assert_exclusive(m_object
);
3832 * In theory, the page should be in an object before it
3833 * gets wired, since we need to hold the object lock
3834 * to update some fields in the page structure.
3835 * However, some code (i386 pmap, for example) might want
3836 * to wire a page before it gets inserted into an object.
3837 * That's somewhat OK, as long as nobody else can get to
3838 * that page and update it at the same time.
3841 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
3842 if ( !VM_PAGE_WIRED(mem
)) {
3845 vm_pageout_steal_laundry(mem
, TRUE
);
3847 vm_page_queues_remove(mem
, TRUE
);
3849 assert(mem
->wire_count
== 0);
3850 mem
->vm_page_q_state
= VM_PAGE_IS_WIRED
;
3854 VM_OBJECT_WIRED_PAGE_UPDATE_START(m_object
);
3855 VM_OBJECT_WIRED_PAGE_ADD(m_object
, mem
);
3856 VM_OBJECT_WIRED_PAGE_UPDATE_END(m_object
, tag
);
3858 assert(m_object
->resident_page_count
>=
3859 m_object
->wired_page_count
);
3860 if (m_object
->purgable
== VM_PURGABLE_VOLATILE
) {
3861 assert(vm_page_purgeable_count
> 0);
3862 OSAddAtomic(-1, &vm_page_purgeable_count
);
3863 OSAddAtomic(1, &vm_page_purgeable_wired_count
);
3865 if ((m_object
->purgable
== VM_PURGABLE_VOLATILE
||
3866 m_object
->purgable
== VM_PURGABLE_EMPTY
) &&
3867 m_object
->vo_purgeable_owner
!= TASK_NULL
) {
3870 owner
= m_object
->vo_purgeable_owner
;
3871 /* less volatile bytes */
3872 ledger_debit(owner
->ledger
,
3873 task_ledgers
.purgeable_volatile
,
3875 /* more not-quite-volatile bytes */
3876 ledger_credit(owner
->ledger
,
3877 task_ledgers
.purgeable_nonvolatile
,
3879 /* more footprint */
3880 ledger_credit(owner
->ledger
,
3881 task_ledgers
.phys_footprint
,
3884 if (m_object
->all_reusable
) {
3886 * Wired pages are not counted as "re-usable"
3887 * in "all_reusable" VM objects, so nothing
3890 } else if (mem
->reusable
) {
3892 * This page is not "re-usable" when it's
3893 * wired, so adjust its state and the
3896 vm_object_reuse_pages(m_object
,
3898 mem
->offset
+PAGE_SIZE_64
,
3902 assert(!mem
->reusable
);
3904 if (!mem
->private && !mem
->fictitious
&& !mem
->gobbled
)
3905 vm_page_wire_count
++;
3907 vm_page_gobble_count
--;
3908 mem
->gobbled
= FALSE
;
3910 if (check_memorystatus
== TRUE
) {
3911 VM_CHECK_MEMORYSTATUS
;
3914 assert(!mem
->gobbled
);
3915 assert(mem
->vm_page_q_state
== VM_PAGE_IS_WIRED
);
3917 if (__improbable(mem
->wire_count
== 0)) {
3918 panic("vm_page_wire(%p): wire_count overflow", mem
);
3926 * Release one wiring of this page, potentially
3927 * enabling it to be paged again.
3929 * The page's object and the page queues must be locked.
3936 vm_object_t m_object
;
3938 m_object
= VM_PAGE_OBJECT(mem
);
3940 // dbgLog(current_thread(), mem->offset, m_object, 0); /* (TEST/DEBUG) */
3943 assert(VM_PAGE_WIRED(mem
));
3944 assert(mem
->wire_count
> 0);
3945 assert(!mem
->gobbled
);
3946 assert(m_object
!= VM_OBJECT_NULL
);
3947 vm_object_lock_assert_exclusive(m_object
);
3948 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
3949 if (--mem
->wire_count
== 0) {
3951 mem
->vm_page_q_state
= VM_PAGE_NOT_ON_Q
;
3953 VM_OBJECT_WIRED_PAGE_UPDATE_START(m_object
);
3954 VM_OBJECT_WIRED_PAGE_REMOVE(m_object
, mem
);
3955 VM_OBJECT_WIRED_PAGE_UPDATE_END(m_object
, m_object
->wire_tag
);
3956 if (!mem
->private && !mem
->fictitious
) {
3957 vm_page_wire_count
--;
3960 assert(m_object
->resident_page_count
>=
3961 m_object
->wired_page_count
);
3962 if (m_object
->purgable
== VM_PURGABLE_VOLATILE
) {
3963 OSAddAtomic(+1, &vm_page_purgeable_count
);
3964 assert(vm_page_purgeable_wired_count
> 0);
3965 OSAddAtomic(-1, &vm_page_purgeable_wired_count
);
3967 if ((m_object
->purgable
== VM_PURGABLE_VOLATILE
||
3968 m_object
->purgable
== VM_PURGABLE_EMPTY
) &&
3969 m_object
->vo_purgeable_owner
!= TASK_NULL
) {
3972 owner
= m_object
->vo_purgeable_owner
;
3973 /* more volatile bytes */
3974 ledger_credit(owner
->ledger
,
3975 task_ledgers
.purgeable_volatile
,
3977 /* less not-quite-volatile bytes */
3978 ledger_debit(owner
->ledger
,
3979 task_ledgers
.purgeable_nonvolatile
,
3981 /* less footprint */
3982 ledger_debit(owner
->ledger
,
3983 task_ledgers
.phys_footprint
,
3986 assert(m_object
!= kernel_object
);
3987 assert(mem
->pageq
.next
== 0 && mem
->pageq
.prev
== 0);
3989 if (queueit
== TRUE
) {
3990 if (m_object
->purgable
== VM_PURGABLE_EMPTY
) {
3991 vm_page_deactivate(mem
);
3993 vm_page_activate(mem
);
3997 VM_CHECK_MEMORYSTATUS
;
4004 * vm_page_deactivate:
4006 * Returns the given page to the inactive list,
4007 * indicating that no physical maps have access
4008 * to this page. [Used by the physical mapping system.]
4010 * The page queues must be locked.
4016 vm_page_deactivate_internal(m
, TRUE
);
4021 vm_page_deactivate_internal(
4023 boolean_t clear_hw_reference
)
4025 vm_object_t m_object
;
4027 m_object
= VM_PAGE_OBJECT(m
);
4030 assert(m_object
!= kernel_object
);
4031 assert(VM_PAGE_GET_PHYS_PAGE(m
) != vm_page_guard_addr
);
4033 // dbgLog(VM_PAGE_GET_PHYS_PAGE(m), vm_page_free_count, vm_page_wire_count, 6); /* (TEST/DEBUG) */
4034 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
4036 * This page is no longer very interesting. If it was
4037 * interesting (active or inactive/referenced), then we
4038 * clear the reference bit and (re)enter it in the
4039 * inactive queue. Note wired pages should not have
4040 * their reference bit cleared.
4042 assert ( !(m
->absent
&& !m
->unusual
));
4044 if (m
->gobbled
) { /* can this happen? */
4045 assert( !VM_PAGE_WIRED(m
));
4047 if (!m
->private && !m
->fictitious
)
4048 vm_page_wire_count
--;
4049 vm_page_gobble_count
--;
4053 * if this page is currently on the pageout queue, we can't do the
4054 * vm_page_queues_remove (which doesn't handle the pageout queue case)
4055 * and we can't remove it manually since we would need the object lock
4056 * (which is not required here) to decrement the activity_in_progress
4057 * reference which is held on the object while the page is in the pageout queue...
4058 * just let the normal laundry processing proceed
4060 if (m
->laundry
|| m
->private || m
->fictitious
||
4061 (m
->vm_page_q_state
== VM_PAGE_USED_BY_COMPRESSOR
) ||
4062 (m
->vm_page_q_state
== VM_PAGE_ON_PAGEOUT_Q
) ||
4066 if (!m
->absent
&& clear_hw_reference
== TRUE
)
4067 pmap_clear_reference(VM_PAGE_GET_PHYS_PAGE(m
));
4069 m
->reference
= FALSE
;
4070 m
->no_cache
= FALSE
;
4072 if ( !VM_PAGE_INACTIVE(m
)) {
4073 vm_page_queues_remove(m
, FALSE
);
4075 if (!VM_DYNAMIC_PAGING_ENABLED() &&
4076 m
->dirty
&& m_object
->internal
&&
4077 (m_object
->purgable
== VM_PURGABLE_DENY
||
4078 m_object
->purgable
== VM_PURGABLE_NONVOLATILE
||
4079 m_object
->purgable
== VM_PURGABLE_VOLATILE
)) {
4080 vm_page_check_pageable_safe(m
);
4081 vm_page_queue_enter(&vm_page_queue_throttled
, m
, vm_page_t
, pageq
);
4082 m
->vm_page_q_state
= VM_PAGE_ON_THROTTLED_Q
;
4083 vm_page_throttled_count
++;
4085 if (m_object
->named
&& m_object
->ref_count
== 1) {
4086 vm_page_speculate(m
, FALSE
);
4087 #if DEVELOPMENT || DEBUG
4088 vm_page_speculative_recreated
++;
4091 vm_page_enqueue_inactive(m
, FALSE
);
4098 * vm_page_enqueue_cleaned
4100 * Put the page on the cleaned queue, mark it cleaned, etc.
4101 * Being on the cleaned queue (and having m->clean_queue set)
4102 * does ** NOT ** guarantee that the page is clean!
4104 * Call with the queues lock held.
4107 void vm_page_enqueue_cleaned(vm_page_t m
)
4109 vm_object_t m_object
;
4111 m_object
= VM_PAGE_OBJECT(m
);
4113 assert(VM_PAGE_GET_PHYS_PAGE(m
) != vm_page_guard_addr
);
4114 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
4115 assert( !(m
->absent
&& !m
->unusual
));
4117 if (VM_PAGE_WIRED(m
)) {
4122 if (!m
->private && !m
->fictitious
)
4123 vm_page_wire_count
--;
4124 vm_page_gobble_count
--;
4128 * if this page is currently on the pageout queue, we can't do the
4129 * vm_page_queues_remove (which doesn't handle the pageout queue case)
4130 * and we can't remove it manually since we would need the object lock
4131 * (which is not required here) to decrement the activity_in_progress
4132 * reference which is held on the object while the page is in the pageout queue...
4133 * just let the normal laundry processing proceed
4135 if (m
->laundry
|| m
->private || m
->fictitious
||
4136 (m
->vm_page_q_state
== VM_PAGE_ON_INACTIVE_CLEANED_Q
) ||
4137 (m
->vm_page_q_state
== VM_PAGE_ON_PAGEOUT_Q
)) {
4140 vm_page_queues_remove(m
, FALSE
);
4142 vm_page_check_pageable_safe(m
);
4143 vm_page_queue_enter(&vm_page_queue_cleaned
, m
, vm_page_t
, pageq
);
4144 m
->vm_page_q_state
= VM_PAGE_ON_INACTIVE_CLEANED_Q
;
4145 vm_page_cleaned_count
++;
4147 vm_page_inactive_count
++;
4148 if (m_object
->internal
) {
4149 vm_page_pageable_internal_count
++;
4151 vm_page_pageable_external_count
++;
4153 #if CONFIG_BACKGROUND_QUEUE
4154 if (m
->vm_page_in_background
)
4155 vm_page_add_to_backgroundq(m
, TRUE
);
4157 vm_pageout_enqueued_cleaned
++;
4163 * Put the specified page on the active list (if appropriate).
4165 * The page queues must be locked.
4172 vm_object_t m_object
;
4174 m_object
= VM_PAGE_OBJECT(m
);
4177 #ifdef FIXME_4778297
4178 assert(m_object
!= kernel_object
);
4180 assert(VM_PAGE_GET_PHYS_PAGE(m
) != vm_page_guard_addr
);
4181 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
4182 assert( !(m
->absent
&& !m
->unusual
));
4185 assert( !VM_PAGE_WIRED(m
));
4186 if (!m
->private && !m
->fictitious
)
4187 vm_page_wire_count
--;
4188 vm_page_gobble_count
--;
4192 * if this page is currently on the pageout queue, we can't do the
4193 * vm_page_queues_remove (which doesn't handle the pageout queue case)
4194 * and we can't remove it manually since we would need the object lock
4195 * (which is not required here) to decrement the activity_in_progress
4196 * reference which is held on the object while the page is in the pageout queue...
4197 * just let the normal laundry processing proceed
4199 if (m
->laundry
|| m
->private || m
->fictitious
||
4200 (m
->vm_page_q_state
== VM_PAGE_USED_BY_COMPRESSOR
) ||
4201 (m
->vm_page_q_state
== VM_PAGE_ON_PAGEOUT_Q
))
4205 if (m
->vm_page_q_state
== VM_PAGE_ON_ACTIVE_Q
)
4206 panic("vm_page_activate: already active");
4209 if (m
->vm_page_q_state
== VM_PAGE_ON_SPECULATIVE_Q
) {
4210 DTRACE_VM2(pgrec
, int, 1, (uint64_t *), NULL
);
4211 DTRACE_VM2(pgfrec
, int, 1, (uint64_t *), NULL
);
4214 vm_page_queues_remove(m
, FALSE
);
4216 if ( !VM_PAGE_WIRED(m
)) {
4217 vm_page_check_pageable_safe(m
);
4218 if (!VM_DYNAMIC_PAGING_ENABLED() &&
4219 m
->dirty
&& m_object
->internal
&&
4220 (m_object
->purgable
== VM_PURGABLE_DENY
||
4221 m_object
->purgable
== VM_PURGABLE_NONVOLATILE
||
4222 m_object
->purgable
== VM_PURGABLE_VOLATILE
)) {
4223 vm_page_queue_enter(&vm_page_queue_throttled
, m
, vm_page_t
, pageq
);
4224 m
->vm_page_q_state
= VM_PAGE_ON_THROTTLED_Q
;
4225 vm_page_throttled_count
++;
4227 #if CONFIG_SECLUDED_MEMORY
4228 if (secluded_for_filecache
&&
4229 vm_page_secluded_target
!= 0 &&
4230 num_tasks_can_use_secluded_mem
== 0 &&
4231 m_object
->eligible_for_secluded
) {
4232 vm_page_queue_enter(&vm_page_queue_secluded
, m
,
4234 m
->vm_page_q_state
= VM_PAGE_ON_SECLUDED_Q
;
4235 vm_page_secluded_count
++;
4236 vm_page_secluded_count_inuse
++;
4237 assert(!m_object
->internal
);
4238 // vm_page_pageable_external_count++;
4240 #endif /* CONFIG_SECLUDED_MEMORY */
4241 vm_page_enqueue_active(m
, FALSE
);
4243 m
->reference
= TRUE
;
4244 m
->no_cache
= FALSE
;
4251 * vm_page_speculate:
4253 * Put the specified page on the speculative list (if appropriate).
4255 * The page queues must be locked.
4262 struct vm_speculative_age_q
*aq
;
4263 vm_object_t m_object
;
4265 m_object
= VM_PAGE_OBJECT(m
);
4268 vm_page_check_pageable_safe(m
);
4270 assert(VM_PAGE_GET_PHYS_PAGE(m
) != vm_page_guard_addr
);
4271 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
4272 assert( !(m
->absent
&& !m
->unusual
));
4273 assert(m_object
->internal
== FALSE
);
4276 * if this page is currently on the pageout queue, we can't do the
4277 * vm_page_queues_remove (which doesn't handle the pageout queue case)
4278 * and we can't remove it manually since we would need the object lock
4279 * (which is not required here) to decrement the activity_in_progress
4280 * reference which is held on the object while the page is in the pageout queue...
4281 * just let the normal laundry processing proceed
4283 if (m
->laundry
|| m
->private || m
->fictitious
||
4284 (m
->vm_page_q_state
== VM_PAGE_USED_BY_COMPRESSOR
) ||
4285 (m
->vm_page_q_state
== VM_PAGE_ON_PAGEOUT_Q
))
4288 vm_page_queues_remove(m
, FALSE
);
4290 if ( !VM_PAGE_WIRED(m
)) {
4295 clock_get_system_nanotime(&sec
, &nsec
);
4296 ts
.tv_sec
= (unsigned int) sec
;
4299 if (vm_page_speculative_count
== 0) {
4301 speculative_age_index
= VM_PAGE_MIN_SPECULATIVE_AGE_Q
;
4302 speculative_steal_index
= VM_PAGE_MIN_SPECULATIVE_AGE_Q
;
4304 aq
= &vm_page_queue_speculative
[speculative_age_index
];
4307 * set the timer to begin a new group
4309 aq
->age_ts
.tv_sec
= vm_page_speculative_q_age_ms
/ 1000;
4310 aq
->age_ts
.tv_nsec
= (vm_page_speculative_q_age_ms
% 1000) * 1000 * NSEC_PER_USEC
;
4312 ADD_MACH_TIMESPEC(&aq
->age_ts
, &ts
);
4314 aq
= &vm_page_queue_speculative
[speculative_age_index
];
4316 if (CMP_MACH_TIMESPEC(&ts
, &aq
->age_ts
) >= 0) {
4318 speculative_age_index
++;
4320 if (speculative_age_index
> VM_PAGE_MAX_SPECULATIVE_AGE_Q
)
4321 speculative_age_index
= VM_PAGE_MIN_SPECULATIVE_AGE_Q
;
4322 if (speculative_age_index
== speculative_steal_index
) {
4323 speculative_steal_index
= speculative_age_index
+ 1;
4325 if (speculative_steal_index
> VM_PAGE_MAX_SPECULATIVE_AGE_Q
)
4326 speculative_steal_index
= VM_PAGE_MIN_SPECULATIVE_AGE_Q
;
4328 aq
= &vm_page_queue_speculative
[speculative_age_index
];
4330 if (!vm_page_queue_empty(&aq
->age_q
))
4331 vm_page_speculate_ageit(aq
);
4333 aq
->age_ts
.tv_sec
= vm_page_speculative_q_age_ms
/ 1000;
4334 aq
->age_ts
.tv_nsec
= (vm_page_speculative_q_age_ms
% 1000) * 1000 * NSEC_PER_USEC
;
4336 ADD_MACH_TIMESPEC(&aq
->age_ts
, &ts
);
4339 vm_page_enqueue_tail(&aq
->age_q
, &m
->pageq
);
4340 m
->vm_page_q_state
= VM_PAGE_ON_SPECULATIVE_Q
;
4341 vm_page_speculative_count
++;
4342 vm_page_pageable_external_count
++;
4345 vm_object_lock_assert_exclusive(m_object
);
4347 m_object
->pages_created
++;
4348 #if DEVELOPMENT || DEBUG
4349 vm_page_speculative_created
++;
4358 * move pages from the specified aging bin to
4359 * the speculative bin that pageout_scan claims from
4361 * The page queues must be locked.
4364 vm_page_speculate_ageit(struct vm_speculative_age_q
*aq
)
4366 struct vm_speculative_age_q
*sq
;
4369 sq
= &vm_page_queue_speculative
[VM_PAGE_SPECULATIVE_AGED_Q
];
4371 if (vm_page_queue_empty(&sq
->age_q
)) {
4372 sq
->age_q
.next
= aq
->age_q
.next
;
4373 sq
->age_q
.prev
= aq
->age_q
.prev
;
4375 t
= (vm_page_t
)VM_PAGE_UNPACK_PTR(sq
->age_q
.next
);
4376 t
->pageq
.prev
= VM_PAGE_PACK_PTR(&sq
->age_q
);
4378 t
= (vm_page_t
)VM_PAGE_UNPACK_PTR(sq
->age_q
.prev
);
4379 t
->pageq
.next
= VM_PAGE_PACK_PTR(&sq
->age_q
);
4381 t
= (vm_page_t
)VM_PAGE_UNPACK_PTR(sq
->age_q
.prev
);
4382 t
->pageq
.next
= aq
->age_q
.next
;
4384 t
= (vm_page_t
)VM_PAGE_UNPACK_PTR(aq
->age_q
.next
);
4385 t
->pageq
.prev
= sq
->age_q
.prev
;
4387 t
= (vm_page_t
)VM_PAGE_UNPACK_PTR(aq
->age_q
.prev
);
4388 t
->pageq
.next
= VM_PAGE_PACK_PTR(&sq
->age_q
);
4390 sq
->age_q
.prev
= aq
->age_q
.prev
;
4392 vm_page_queue_init(&aq
->age_q
);
4401 assert(VM_PAGE_OBJECT(m
) != kernel_object
);
4402 assert(VM_PAGE_GET_PHYS_PAGE(m
) != vm_page_guard_addr
);
4404 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
4406 * if this page is currently on the pageout queue, we can't do the
4407 * vm_page_queues_remove (which doesn't handle the pageout queue case)
4408 * and we can't remove it manually since we would need the object lock
4409 * (which is not required here) to decrement the activity_in_progress
4410 * reference which is held on the object while the page is in the pageout queue...
4411 * just let the normal laundry processing proceed
4413 if (m
->laundry
|| m
->private ||
4414 (m
->vm_page_q_state
== VM_PAGE_USED_BY_COMPRESSOR
) ||
4415 (m
->vm_page_q_state
== VM_PAGE_ON_PAGEOUT_Q
) ||
4419 m
->no_cache
= FALSE
;
4421 vm_page_queues_remove(m
, FALSE
);
4423 vm_page_enqueue_inactive(m
, FALSE
);
4428 vm_page_reactivate_all_throttled(void)
4430 vm_page_t first_throttled
, last_throttled
;
4431 vm_page_t first_active
;
4433 int extra_active_count
;
4434 int extra_internal_count
, extra_external_count
;
4435 vm_object_t m_object
;
4437 if (!VM_DYNAMIC_PAGING_ENABLED())
4440 extra_active_count
= 0;
4441 extra_internal_count
= 0;
4442 extra_external_count
= 0;
4443 vm_page_lock_queues();
4444 if (! vm_page_queue_empty(&vm_page_queue_throttled
)) {
4446 * Switch "throttled" pages to "active".
4448 vm_page_queue_iterate(&vm_page_queue_throttled
, m
, vm_page_t
, pageq
) {
4450 assert(m
->vm_page_q_state
== VM_PAGE_ON_THROTTLED_Q
);
4452 m_object
= VM_PAGE_OBJECT(m
);
4454 extra_active_count
++;
4455 if (m_object
->internal
) {
4456 extra_internal_count
++;
4458 extra_external_count
++;
4461 m
->vm_page_q_state
= VM_PAGE_ON_ACTIVE_Q
;
4463 #if CONFIG_BACKGROUND_QUEUE
4464 if (m
->vm_page_in_background
)
4465 vm_page_add_to_backgroundq(m
, FALSE
);
4470 * Transfer the entire throttled queue to a regular LRU page queues.
4471 * We insert it at the head of the active queue, so that these pages
4472 * get re-evaluated by the LRU algorithm first, since they've been
4473 * completely out of it until now.
4475 first_throttled
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_throttled
);
4476 last_throttled
= (vm_page_t
) vm_page_queue_last(&vm_page_queue_throttled
);
4477 first_active
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_active
);
4478 if (vm_page_queue_empty(&vm_page_queue_active
)) {
4479 vm_page_queue_active
.prev
= VM_PAGE_CONVERT_TO_QUEUE_ENTRY(last_throttled
);
4481 first_active
->pageq
.prev
= VM_PAGE_CONVERT_TO_QUEUE_ENTRY(last_throttled
);
4483 vm_page_queue_active
.next
= VM_PAGE_CONVERT_TO_QUEUE_ENTRY(first_throttled
);
4484 first_throttled
->pageq
.prev
= VM_PAGE_CONVERT_TO_QUEUE_ENTRY(&vm_page_queue_active
);
4485 last_throttled
->pageq
.next
= VM_PAGE_CONVERT_TO_QUEUE_ENTRY(first_active
);
4488 printf("reactivated %d throttled pages\n", vm_page_throttled_count
);
4490 vm_page_queue_init(&vm_page_queue_throttled
);
4492 * Adjust the global page counts.
4494 vm_page_active_count
+= extra_active_count
;
4495 vm_page_pageable_internal_count
+= extra_internal_count
;
4496 vm_page_pageable_external_count
+= extra_external_count
;
4497 vm_page_throttled_count
= 0;
4499 assert(vm_page_throttled_count
== 0);
4500 assert(vm_page_queue_empty(&vm_page_queue_throttled
));
4501 vm_page_unlock_queues();
4506 * move pages from the indicated local queue to the global active queue
4507 * its ok to fail if we're below the hard limit and force == FALSE
4508 * the nolocks == TRUE case is to allow this function to be run on
4509 * the hibernate path
4513 vm_page_reactivate_local(uint32_t lid
, boolean_t force
, boolean_t nolocks
)
4516 vm_page_t first_local
, last_local
;
4517 vm_page_t first_active
;
4521 if (vm_page_local_q
== NULL
)
4524 lq
= &vm_page_local_q
[lid
].vpl_un
.vpl
;
4526 if (nolocks
== FALSE
) {
4527 if (lq
->vpl_count
< vm_page_local_q_hard_limit
&& force
== FALSE
) {
4528 if ( !vm_page_trylockspin_queues())
4531 vm_page_lockspin_queues();
4533 VPL_LOCK(&lq
->vpl_lock
);
4535 if (lq
->vpl_count
) {
4537 * Switch "local" pages to "active".
4539 assert(!vm_page_queue_empty(&lq
->vpl_queue
));
4541 vm_page_queue_iterate(&lq
->vpl_queue
, m
, vm_page_t
, pageq
) {
4543 vm_page_check_pageable_safe(m
);
4544 assert(m
->vm_page_q_state
== VM_PAGE_ON_ACTIVE_LOCAL_Q
);
4545 assert(!m
->fictitious
);
4547 if (m
->local_id
!= lid
)
4548 panic("vm_page_reactivate_local: found vm_page_t(%p) with wrong cpuid", m
);
4551 m
->vm_page_q_state
= VM_PAGE_ON_ACTIVE_Q
;
4553 #if CONFIG_BACKGROUND_QUEUE
4554 if (m
->vm_page_in_background
)
4555 vm_page_add_to_backgroundq(m
, FALSE
);
4559 if (count
!= lq
->vpl_count
)
4560 panic("vm_page_reactivate_local: count = %d, vm_page_local_count = %d\n", count
, lq
->vpl_count
);
4563 * Transfer the entire local queue to a regular LRU page queues.
4565 first_local
= (vm_page_t
) vm_page_queue_first(&lq
->vpl_queue
);
4566 last_local
= (vm_page_t
) vm_page_queue_last(&lq
->vpl_queue
);
4567 first_active
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_active
);
4569 if (vm_page_queue_empty(&vm_page_queue_active
)) {
4570 vm_page_queue_active
.prev
= VM_PAGE_CONVERT_TO_QUEUE_ENTRY(last_local
);
4572 first_active
->pageq
.prev
= VM_PAGE_CONVERT_TO_QUEUE_ENTRY(last_local
);
4574 vm_page_queue_active
.next
= VM_PAGE_CONVERT_TO_QUEUE_ENTRY(first_local
);
4575 first_local
->pageq
.prev
= VM_PAGE_CONVERT_TO_QUEUE_ENTRY(&vm_page_queue_active
);
4576 last_local
->pageq
.next
= VM_PAGE_CONVERT_TO_QUEUE_ENTRY(first_active
);
4578 vm_page_queue_init(&lq
->vpl_queue
);
4580 * Adjust the global page counts.
4582 vm_page_active_count
+= lq
->vpl_count
;
4583 vm_page_pageable_internal_count
+= lq
->vpl_internal_count
;
4584 vm_page_pageable_external_count
+= lq
->vpl_external_count
;
4586 lq
->vpl_internal_count
= 0;
4587 lq
->vpl_external_count
= 0;
4589 assert(vm_page_queue_empty(&lq
->vpl_queue
));
4591 if (nolocks
== FALSE
) {
4592 VPL_UNLOCK(&lq
->vpl_lock
);
4593 vm_page_unlock_queues();
4598 * vm_page_part_zero_fill:
4600 * Zero-fill a part of the page.
4602 #define PMAP_ZERO_PART_PAGE_IMPLEMENTED
4604 vm_page_part_zero_fill(
4612 * we don't hold the page queue lock
4613 * so this check isn't safe to make
4618 #ifdef PMAP_ZERO_PART_PAGE_IMPLEMENTED
4619 pmap_zero_part_page(VM_PAGE_GET_PHYS_PAGE(m
), m_pa
, len
);
4623 tmp
= vm_page_grab();
4624 if (tmp
== VM_PAGE_NULL
) {
4625 vm_page_wait(THREAD_UNINT
);
4630 vm_page_zero_fill(tmp
);
4632 vm_page_part_copy(m
, 0, tmp
, 0, m_pa
);
4634 if((m_pa
+ len
) < PAGE_SIZE
) {
4635 vm_page_part_copy(m
, m_pa
+ len
, tmp
,
4636 m_pa
+ len
, PAGE_SIZE
- (m_pa
+ len
));
4638 vm_page_copy(tmp
,m
);
4645 * vm_page_zero_fill:
4647 * Zero-fill the specified page.
4654 "vm_page_zero_fill, object 0x%X offset 0x%X page 0x%X\n",
4655 VM_PAGE_OBJECT(m
), m
->offset
, m
, 0,0);
4658 * we don't hold the page queue lock
4659 * so this check isn't safe to make
4664 // dbgTrace(0xAEAEAEAE, VM_PAGE_GET_PHYS_PAGE(m), 0); /* (BRINGUP) */
4665 pmap_zero_page(VM_PAGE_GET_PHYS_PAGE(m
));
4669 * vm_page_part_copy:
4671 * copy part of one page to another
4684 * we don't hold the page queue lock
4685 * so this check isn't safe to make
4687 VM_PAGE_CHECK(src_m
);
4688 VM_PAGE_CHECK(dst_m
);
4690 pmap_copy_part_page(VM_PAGE_GET_PHYS_PAGE(src_m
), src_pa
,
4691 VM_PAGE_GET_PHYS_PAGE(dst_m
), dst_pa
, len
);
4697 * Copy one page to another
4700 int vm_page_copy_cs_validations
= 0;
4701 int vm_page_copy_cs_tainted
= 0;
4708 vm_object_t src_m_object
;
4710 src_m_object
= VM_PAGE_OBJECT(src_m
);
4713 "vm_page_copy, object 0x%X offset 0x%X to object 0x%X offset 0x%X\n",
4714 src_m_object
, src_m
->offset
,
4715 VM_PAGE_OBJECT(dest_m
), dest_m
->offset
,
4719 * we don't hold the page queue lock
4720 * so this check isn't safe to make
4722 VM_PAGE_CHECK(src_m
);
4723 VM_PAGE_CHECK(dest_m
);
4725 vm_object_lock_assert_held(src_m_object
);
4727 if (src_m_object
!= VM_OBJECT_NULL
&&
4728 src_m_object
->code_signed
) {
4730 * We're copying a page from a code-signed object.
4731 * Whoever ends up mapping the copy page might care about
4732 * the original page's integrity, so let's validate the
4735 vm_page_copy_cs_validations
++;
4736 vm_page_validate_cs(src_m
);
4737 #if DEVELOPMENT || DEBUG
4738 DTRACE_VM4(codesigned_copy
,
4739 vm_object_t
, src_m_object
,
4740 vm_object_offset_t
, src_m
->offset
,
4741 int, src_m
->cs_validated
,
4742 int, src_m
->cs_tainted
);
4743 #endif /* DEVELOPMENT || DEBUG */
4747 if (vm_page_is_slideable(src_m
)) {
4748 boolean_t was_busy
= src_m
->busy
;
4750 (void) vm_page_slide(src_m
, 0);
4751 assert(src_m
->busy
);
4753 PAGE_WAKEUP_DONE(src_m
);
4758 * Propagate the cs_tainted bit to the copy page. Do not propagate
4759 * the cs_validated bit.
4761 dest_m
->cs_tainted
= src_m
->cs_tainted
;
4762 if (dest_m
->cs_tainted
) {
4763 vm_page_copy_cs_tainted
++;
4765 dest_m
->slid
= src_m
->slid
;
4766 dest_m
->error
= src_m
->error
; /* sliding src_m might have failed... */
4767 pmap_copy_page(VM_PAGE_GET_PHYS_PAGE(src_m
), VM_PAGE_GET_PHYS_PAGE(dest_m
));
4775 printf("vm_page %p: \n", p
);
4776 printf(" pageq: next=%p prev=%p\n",
4777 (vm_page_t
)VM_PAGE_UNPACK_PTR(p
->pageq
.next
),
4778 (vm_page_t
)VM_PAGE_UNPACK_PTR(p
->pageq
.prev
));
4779 printf(" listq: next=%p prev=%p\n",
4780 (vm_page_t
)(VM_PAGE_UNPACK_PTR(p
->listq
.next
)),
4781 (vm_page_t
)(VM_PAGE_UNPACK_PTR(p
->listq
.prev
)));
4782 printf(" next=%p\n", (vm_page_t
)(VM_PAGE_UNPACK_PTR(p
->next_m
)));
4783 printf(" object=%p offset=0x%llx\n",VM_PAGE_OBJECT(p
), p
->offset
);
4784 printf(" wire_count=%u\n", p
->wire_count
);
4785 printf(" q_state=%u\n", p
->vm_page_q_state
);
4787 printf(" %slaundry, %sref, %sgobbled, %sprivate\n",
4788 (p
->laundry
? "" : "!"),
4789 (p
->reference
? "" : "!"),
4790 (p
->gobbled
? "" : "!"),
4791 (p
->private ? "" : "!"));
4792 printf(" %sbusy, %swanted, %stabled, %sfictitious, %spmapped, %swpmapped\n",
4793 (p
->busy
? "" : "!"),
4794 (p
->wanted
? "" : "!"),
4795 (p
->tabled
? "" : "!"),
4796 (p
->fictitious
? "" : "!"),
4797 (p
->pmapped
? "" : "!"),
4798 (p
->wpmapped
? "" : "!"));
4799 printf(" %sfree_when_done, %sabsent, %serror, %sdirty, %scleaning, %sprecious, %sclustered\n",
4800 (p
->free_when_done
? "" : "!"),
4801 (p
->absent
? "" : "!"),
4802 (p
->error
? "" : "!"),
4803 (p
->dirty
? "" : "!"),
4804 (p
->cleaning
? "" : "!"),
4805 (p
->precious
? "" : "!"),
4806 (p
->clustered
? "" : "!"));
4807 printf(" %soverwriting, %srestart, %sunusual\n",
4808 (p
->overwriting
? "" : "!"),
4809 (p
->restart
? "" : "!"),
4810 (p
->unusual
? "" : "!"));
4811 printf(" %scs_validated, %scs_tainted, %scs_nx, %sno_cache\n",
4812 (p
->cs_validated
? "" : "!"),
4813 (p
->cs_tainted
? "" : "!"),
4814 (p
->cs_nx
? "" : "!"),
4815 (p
->no_cache
? "" : "!"));
4817 printf("phys_page=0x%x\n", VM_PAGE_GET_PHYS_PAGE(p
));
4821 * Check that the list of pages is ordered by
4822 * ascending physical address and has no holes.
4825 vm_page_verify_contiguous(
4827 unsigned int npages
)
4830 unsigned int page_count
;
4831 vm_offset_t prev_addr
;
4833 prev_addr
= VM_PAGE_GET_PHYS_PAGE(pages
);
4835 for (m
= NEXT_PAGE(pages
); m
!= VM_PAGE_NULL
; m
= NEXT_PAGE(m
)) {
4836 if (VM_PAGE_GET_PHYS_PAGE(m
) != prev_addr
+ 1) {
4837 printf("m %p prev_addr 0x%lx, current addr 0x%x\n",
4838 m
, (long)prev_addr
, VM_PAGE_GET_PHYS_PAGE(m
));
4839 printf("pages %p page_count %d npages %d\n", pages
, page_count
, npages
);
4840 panic("vm_page_verify_contiguous: not contiguous!");
4842 prev_addr
= VM_PAGE_GET_PHYS_PAGE(m
);
4845 if (page_count
!= npages
) {
4846 printf("pages %p actual count 0x%x but requested 0x%x\n",
4847 pages
, page_count
, npages
);
4848 panic("vm_page_verify_contiguous: count error");
4855 * Check the free lists for proper length etc.
4857 static boolean_t vm_page_verify_this_free_list_enabled
= FALSE
;
4859 vm_page_verify_free_list(
4860 vm_page_queue_head_t
*vm_page_queue
,
4862 vm_page_t look_for_page
,
4863 boolean_t expect_page
)
4865 unsigned int npages
;
4868 boolean_t found_page
;
4870 if (! vm_page_verify_this_free_list_enabled
)
4875 prev_m
= (vm_page_t
)((uintptr_t)vm_page_queue
);
4877 vm_page_queue_iterate(vm_page_queue
,
4882 if (m
== look_for_page
) {
4885 if ((vm_page_t
)VM_PAGE_UNPACK_PTR(m
->pageq
.prev
) != prev_m
)
4886 panic("vm_page_verify_free_list(color=%u, npages=%u): page %p corrupted prev ptr %p instead of %p\n",
4887 color
, npages
, m
, (vm_page_t
)VM_PAGE_UNPACK_PTR(m
->pageq
.prev
), prev_m
);
4889 panic("vm_page_verify_free_list(color=%u, npages=%u): page %p not busy\n",
4891 if (color
!= (unsigned int) -1) {
4892 if (VM_PAGE_GET_COLOR(m
) != color
)
4893 panic("vm_page_verify_free_list(color=%u, npages=%u): page %p wrong color %u instead of %u\n",
4894 color
, npages
, m
, VM_PAGE_GET_COLOR(m
), color
);
4895 if (m
->vm_page_q_state
!= VM_PAGE_ON_FREE_Q
)
4896 panic("vm_page_verify_free_list(color=%u, npages=%u): page %p - expecting q_state == VM_PAGE_ON_FREE_Q, found %d\n",
4897 color
, npages
, m
, m
->vm_page_q_state
);
4899 if (m
->vm_page_q_state
!= VM_PAGE_ON_FREE_LOCAL_Q
)
4900 panic("vm_page_verify_free_list(npages=%u): local page %p - expecting q_state == VM_PAGE_ON_FREE_LOCAL_Q, found %d\n",
4901 npages
, m
, m
->vm_page_q_state
);
4906 if (look_for_page
!= VM_PAGE_NULL
) {
4907 unsigned int other_color
;
4909 if (expect_page
&& !found_page
) {
4910 printf("vm_page_verify_free_list(color=%u, npages=%u): page %p not found phys=%u\n",
4911 color
, npages
, look_for_page
, VM_PAGE_GET_PHYS_PAGE(look_for_page
));
4912 _vm_page_print(look_for_page
);
4913 for (other_color
= 0;
4914 other_color
< vm_colors
;
4916 if (other_color
== color
)
4918 vm_page_verify_free_list(&vm_page_queue_free
[other_color
].qhead
,
4919 other_color
, look_for_page
, FALSE
);
4921 if (color
== (unsigned int) -1) {
4922 vm_page_verify_free_list(&vm_lopage_queue_free
,
4923 (unsigned int) -1, look_for_page
, FALSE
);
4925 panic("vm_page_verify_free_list(color=%u)\n", color
);
4927 if (!expect_page
&& found_page
) {
4928 printf("vm_page_verify_free_list(color=%u, npages=%u): page %p found phys=%u\n",
4929 color
, npages
, look_for_page
, VM_PAGE_GET_PHYS_PAGE(look_for_page
));
4935 static boolean_t vm_page_verify_all_free_lists_enabled
= FALSE
;
4937 vm_page_verify_free_lists( void )
4939 unsigned int color
, npages
, nlopages
;
4940 boolean_t toggle
= TRUE
;
4942 if (! vm_page_verify_all_free_lists_enabled
)
4947 lck_mtx_lock(&vm_page_queue_free_lock
);
4949 if (vm_page_verify_this_free_list_enabled
== TRUE
) {
4951 * This variable has been set globally for extra checking of
4952 * each free list Q. Since we didn't set it, we don't own it
4953 * and we shouldn't toggle it.
4958 if (toggle
== TRUE
) {
4959 vm_page_verify_this_free_list_enabled
= TRUE
;
4962 for( color
= 0; color
< vm_colors
; color
++ ) {
4963 npages
+= vm_page_verify_free_list(&vm_page_queue_free
[color
].qhead
,
4964 color
, VM_PAGE_NULL
, FALSE
);
4966 nlopages
= vm_page_verify_free_list(&vm_lopage_queue_free
,
4968 VM_PAGE_NULL
, FALSE
);
4969 if (npages
!= vm_page_free_count
|| nlopages
!= vm_lopage_free_count
)
4970 panic("vm_page_verify_free_lists: "
4971 "npages %u free_count %d nlopages %u lo_free_count %u",
4972 npages
, vm_page_free_count
, nlopages
, vm_lopage_free_count
);
4974 if (toggle
== TRUE
) {
4975 vm_page_verify_this_free_list_enabled
= FALSE
;
4978 lck_mtx_unlock(&vm_page_queue_free_lock
);
4981 #endif /* MACH_ASSERT */
4987 * 1 or more clients (currently only SEP) ask for a large contiguous chunk of memory
4988 * after the system has 'aged'. To ensure that other allocation requests don't mess
4989 * with the chances of that request being satisfied, we pre-allocate a single contiguous
4990 * 10MB buffer and hand it out to the first request of >= 4MB.
4993 kern_return_t
cpm_preallocate_early(void);
4995 vm_page_t cpm_preallocated_pages_list
= NULL
;
4996 boolean_t preallocated_buffer_available
= FALSE
;
4998 #define PREALLOCATED_CONTIG_BUFFER_PAGES_COUNT ((10 * 1024 * 1024) / PAGE_SIZE_64) /* 10 MB */
4999 #define MIN_CONTIG_PAGES_REQUEST_FOR_PREALLOCATED_BUFFER ((4 * 1024 *1024) / PAGE_SIZE_64) /* 4 MB */
5002 cpm_preallocate_early(void)
5005 kern_return_t kr
= KERN_SUCCESS
;
5006 vm_map_size_t prealloc_size
= (PREALLOCATED_CONTIG_BUFFER_PAGES_COUNT
* PAGE_SIZE_64
);
5008 printf("cpm_preallocate_early called to preallocate contiguous buffer of %llu pages\n", PREALLOCATED_CONTIG_BUFFER_PAGES_COUNT
);
5010 kr
= cpm_allocate(CAST_DOWN(vm_size_t
, prealloc_size
), &cpm_preallocated_pages_list
, 0, 0, TRUE
, 0);
5012 if (kr
!= KERN_SUCCESS
) {
5013 printf("cpm_allocate for preallocated contig buffer failed with %d.\n", kr
);
5015 preallocated_buffer_available
= TRUE
;
5020 #endif /* __arm64__ */
5023 extern boolean_t (* volatile consider_buffer_cache_collect
)(int);
5026 * CONTIGUOUS PAGE ALLOCATION
5028 * Find a region large enough to contain at least n pages
5029 * of contiguous physical memory.
5031 * This is done by traversing the vm_page_t array in a linear fashion
5032 * we assume that the vm_page_t array has the avaiable physical pages in an
5033 * ordered, ascending list... this is currently true of all our implementations
5034 * and must remain so... there can be 'holes' in the array... we also can
5035 * no longer tolerate the vm_page_t's in the list being 'freed' and reclaimed
5036 * which use to happen via 'vm_page_convert'... that function was no longer
5037 * being called and was removed...
5039 * The basic flow consists of stabilizing some of the interesting state of
5040 * a vm_page_t behind the vm_page_queue and vm_page_free locks... we start our
5041 * sweep at the beginning of the array looking for pages that meet our criterea
5042 * for a 'stealable' page... currently we are pretty conservative... if the page
5043 * meets this criterea and is physically contiguous to the previous page in the 'run'
5044 * we keep developing it. If we hit a page that doesn't fit, we reset our state
5045 * and start to develop a new run... if at this point we've already considered
5046 * at least MAX_CONSIDERED_BEFORE_YIELD pages, we'll drop the 2 locks we hold,
5047 * and mutex_pause (which will yield the processor), to keep the latency low w/r
5048 * to other threads trying to acquire free pages (or move pages from q to q),
5049 * and then continue from the spot we left off... we only make 1 pass through the
5050 * array. Once we have a 'run' that is long enough, we'll go into the loop which
5051 * which steals the pages from the queues they're currently on... pages on the free
5052 * queue can be stolen directly... pages that are on any of the other queues
5053 * must be removed from the object they are tabled on... this requires taking the
5054 * object lock... we do this as a 'try' to prevent deadlocks... if the 'try' fails
5055 * or if the state of the page behind the vm_object lock is no longer viable, we'll
5056 * dump the pages we've currently stolen back to the free list, and pick up our
5057 * scan from the point where we aborted the 'current' run.
5061 * - neither vm_page_queue nor vm_free_list lock can be held on entry
5063 * Returns a pointer to a list of gobbled/wired pages or VM_PAGE_NULL.
5068 #define MAX_CONSIDERED_BEFORE_YIELD 1000
5071 #define RESET_STATE_OF_RUN() \
5073 prevcontaddr = -2; \
5075 free_considered = 0; \
5076 substitute_needed = 0; \
5081 * Can we steal in-use (i.e. not free) pages when searching for
5082 * physically-contiguous pages ?
5084 #define VM_PAGE_FIND_CONTIGUOUS_CAN_STEAL 1
5086 static unsigned int vm_page_find_contiguous_last_idx
= 0, vm_page_lomem_find_contiguous_last_idx
= 0;
5088 int vm_page_find_contig_debug
= 0;
5092 vm_page_find_contiguous(
5093 unsigned int contig_pages
,
5100 ppnum_t prevcontaddr
= 0;
5101 ppnum_t start_pnum
= 0;
5102 unsigned int npages
= 0, considered
= 0, scanned
= 0;
5103 unsigned int page_idx
= 0, start_idx
= 0, last_idx
= 0, orig_last_idx
= 0;
5104 unsigned int idx_last_contig_page_found
= 0;
5105 int free_considered
= 0, free_available
= 0;
5106 int substitute_needed
= 0;
5107 boolean_t wrapped
, zone_gc_called
= FALSE
;
5110 clock_sec_t tv_start_sec
= 0, tv_end_sec
= 0;
5111 clock_usec_t tv_start_usec
= 0, tv_end_usec
= 0;
5116 int stolen_pages
= 0;
5117 int compressed_pages
= 0;
5120 if (contig_pages
== 0)
5121 return VM_PAGE_NULL
;
5126 vm_page_verify_free_lists();
5129 clock_get_system_microtime(&tv_start_sec
, &tv_start_usec
);
5131 PAGE_REPLACEMENT_ALLOWED(TRUE
);
5133 vm_page_lock_queues();
5136 if (preallocated_buffer_available
) {
5138 if ((contig_pages
>= MIN_CONTIG_PAGES_REQUEST_FOR_PREALLOCATED_BUFFER
) && (contig_pages
<= PREALLOCATED_CONTIG_BUFFER_PAGES_COUNT
)) {
5140 m
= cpm_preallocated_pages_list
;
5142 start_idx
= (unsigned int) (m
- &vm_pages
[0]);
5144 if (wire
== FALSE
) {
5146 last_idx
= start_idx
;
5148 for(npages
= 0; npages
< contig_pages
; npages
++, last_idx
++) {
5150 assert(vm_pages
[last_idx
].gobbled
== FALSE
);
5152 vm_pages
[last_idx
].gobbled
= TRUE
;
5153 vm_page_gobble_count
++;
5155 assert(1 == vm_pages
[last_idx
].wire_count
);
5157 * Gobbled pages are counted as wired pages. So no need to drop
5158 * the global wired page count. Just the page's wire count is fine.
5160 vm_pages
[last_idx
].wire_count
--;
5161 vm_pages
[last_idx
].vm_page_q_state
= VM_PAGE_NOT_ON_Q
;
5166 last_idx
= start_idx
+ contig_pages
- 1;
5168 vm_pages
[last_idx
].snext
= NULL
;
5170 printf("Using preallocated buffer: Requested size (pages):%d... index range: %d-%d...freeing %llu pages\n", contig_pages
, start_idx
, last_idx
, PREALLOCATED_CONTIG_BUFFER_PAGES_COUNT
- contig_pages
);
5173 for(npages
= contig_pages
; npages
< PREALLOCATED_CONTIG_BUFFER_PAGES_COUNT
; npages
++, last_idx
++) {
5175 VM_PAGE_ZERO_PAGEQ_ENTRY(&vm_pages
[last_idx
]);
5176 vm_page_free(&vm_pages
[last_idx
]);
5179 cpm_preallocated_pages_list
= NULL
;
5180 preallocated_buffer_available
= FALSE
;
5185 #endif /* __arm64__ */
5187 lck_mtx_lock(&vm_page_queue_free_lock
);
5189 RESET_STATE_OF_RUN();
5193 free_available
= vm_page_free_count
- vm_page_free_reserved
;
5197 if(flags
& KMA_LOMEM
)
5198 idx_last_contig_page_found
= vm_page_lomem_find_contiguous_last_idx
;
5200 idx_last_contig_page_found
= vm_page_find_contiguous_last_idx
;
5202 orig_last_idx
= idx_last_contig_page_found
;
5203 last_idx
= orig_last_idx
;
5205 for (page_idx
= last_idx
, start_idx
= last_idx
;
5206 npages
< contig_pages
&& page_idx
< vm_pages_count
;
5211 page_idx
>= orig_last_idx
) {
5213 * We're back where we started and we haven't
5214 * found any suitable contiguous range. Let's
5220 m
= &vm_pages
[page_idx
];
5222 assert(!m
->fictitious
);
5223 assert(!m
->private);
5225 if (max_pnum
&& VM_PAGE_GET_PHYS_PAGE(m
) > max_pnum
) {
5226 /* no more low pages... */
5229 if (!npages
& ((VM_PAGE_GET_PHYS_PAGE(m
) & pnum_mask
) != 0)) {
5233 RESET_STATE_OF_RUN();
5235 } else if (VM_PAGE_WIRED(m
) || m
->gobbled
||
5236 m
->laundry
|| m
->wanted
||
5237 m
->cleaning
|| m
->overwriting
|| m
->free_when_done
) {
5239 * page is in a transient state
5240 * or a state we don't want to deal
5241 * with, so don't consider it which
5242 * means starting a new run
5244 RESET_STATE_OF_RUN();
5246 } else if ((m
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
) ||
5247 (m
->vm_page_q_state
== VM_PAGE_ON_FREE_LOCAL_Q
) ||
5248 (m
->vm_page_q_state
== VM_PAGE_ON_FREE_LOPAGE_Q
) ||
5249 (m
->vm_page_q_state
== VM_PAGE_ON_PAGEOUT_Q
)) {
5251 * page needs to be on one of our queues (other then the pageout or special free queues)
5252 * or it needs to belong to the compressor pool (which is now indicated
5253 * by vm_page_q_state == VM_PAGE_USED_BY_COMPRESSOR and falls out
5254 * from the check for VM_PAGE_NOT_ON_Q)
5255 * in order for it to be stable behind the
5256 * locks we hold at this point...
5257 * if not, don't consider it which
5258 * means starting a new run
5260 RESET_STATE_OF_RUN();
5262 } else if ((m
->vm_page_q_state
!= VM_PAGE_ON_FREE_Q
) && (!m
->tabled
|| m
->busy
)) {
5264 * pages on the free list are always 'busy'
5265 * so we couldn't test for 'busy' in the check
5266 * for the transient states... pages that are
5267 * 'free' are never 'tabled', so we also couldn't
5268 * test for 'tabled'. So we check here to make
5269 * sure that a non-free page is not busy and is
5270 * tabled on an object...
5271 * if not, don't consider it which
5272 * means starting a new run
5274 RESET_STATE_OF_RUN();
5277 if (VM_PAGE_GET_PHYS_PAGE(m
) != prevcontaddr
+ 1) {
5278 if ((VM_PAGE_GET_PHYS_PAGE(m
) & pnum_mask
) != 0) {
5279 RESET_STATE_OF_RUN();
5283 start_idx
= page_idx
;
5284 start_pnum
= VM_PAGE_GET_PHYS_PAGE(m
);
5289 prevcontaddr
= VM_PAGE_GET_PHYS_PAGE(m
);
5292 if (m
->vm_page_q_state
== VM_PAGE_ON_FREE_Q
) {
5296 * This page is not free.
5297 * If we can't steal used pages,
5298 * we have to give up this run
5300 * Otherwise, we might need to
5301 * move the contents of this page
5302 * into a substitute page.
5304 #if VM_PAGE_FIND_CONTIGUOUS_CAN_STEAL
5305 if (m
->pmapped
|| m
->dirty
|| m
->precious
) {
5306 substitute_needed
++;
5309 RESET_STATE_OF_RUN();
5313 if ((free_considered
+ substitute_needed
) > free_available
) {
5315 * if we let this run continue
5316 * we will end up dropping the vm_page_free_count
5317 * below the reserve limit... we need to abort
5318 * this run, but we can at least re-consider this
5319 * page... thus the jump back to 'retry'
5321 RESET_STATE_OF_RUN();
5323 if (free_available
&& considered
<= MAX_CONSIDERED_BEFORE_YIELD
) {
5328 * free_available == 0
5329 * so can't consider any free pages... if
5330 * we went to retry in this case, we'd
5331 * get stuck looking at the same page
5332 * w/o making any forward progress
5333 * we also want to take this path if we've already
5334 * reached our limit that controls the lock latency
5339 if (considered
> MAX_CONSIDERED_BEFORE_YIELD
&& npages
<= 1) {
5341 PAGE_REPLACEMENT_ALLOWED(FALSE
);
5343 lck_mtx_unlock(&vm_page_queue_free_lock
);
5344 vm_page_unlock_queues();
5348 PAGE_REPLACEMENT_ALLOWED(TRUE
);
5350 vm_page_lock_queues();
5351 lck_mtx_lock(&vm_page_queue_free_lock
);
5353 RESET_STATE_OF_RUN();
5355 * reset our free page limit since we
5356 * dropped the lock protecting the vm_page_free_queue
5358 free_available
= vm_page_free_count
- vm_page_free_reserved
;
5369 if (npages
!= contig_pages
) {
5372 * We didn't find a contiguous range but we didn't
5373 * start from the very first page.
5374 * Start again from the very first page.
5376 RESET_STATE_OF_RUN();
5377 if( flags
& KMA_LOMEM
)
5378 idx_last_contig_page_found
= vm_page_lomem_find_contiguous_last_idx
= 0;
5380 idx_last_contig_page_found
= vm_page_find_contiguous_last_idx
= 0;
5382 page_idx
= last_idx
;
5386 lck_mtx_unlock(&vm_page_queue_free_lock
);
5390 unsigned int cur_idx
;
5391 unsigned int tmp_start_idx
;
5392 vm_object_t locked_object
= VM_OBJECT_NULL
;
5393 boolean_t abort_run
= FALSE
;
5395 assert(page_idx
- start_idx
== contig_pages
);
5397 tmp_start_idx
= start_idx
;
5400 * first pass through to pull the free pages
5401 * off of the free queue so that in case we
5402 * need substitute pages, we won't grab any
5403 * of the free pages in the run... we'll clear
5404 * the 'free' bit in the 2nd pass, and even in
5405 * an abort_run case, we'll collect all of the
5406 * free pages in this run and return them to the free list
5408 while (start_idx
< page_idx
) {
5410 m1
= &vm_pages
[start_idx
++];
5412 #if !VM_PAGE_FIND_CONTIGUOUS_CAN_STEAL
5413 assert(m1
->vm_page_q_state
== VM_PAGE_ON_FREE_Q
);
5416 if (m1
->vm_page_q_state
== VM_PAGE_ON_FREE_Q
) {
5419 color
= VM_PAGE_GET_COLOR(m1
);
5421 vm_page_verify_free_list(&vm_page_queue_free
[color
].qhead
, color
, m1
, TRUE
);
5423 vm_page_queue_remove(&vm_page_queue_free
[color
].qhead
,
5428 VM_PAGE_ZERO_PAGEQ_ENTRY(m1
);
5430 vm_page_verify_free_list(&vm_page_queue_free
[color
].qhead
, color
, VM_PAGE_NULL
, FALSE
);
5433 * Clear the "free" bit so that this page
5434 * does not get considered for another
5435 * concurrent physically-contiguous allocation.
5437 m1
->vm_page_q_state
= VM_PAGE_NOT_ON_Q
;
5440 vm_page_free_count
--;
5443 if( flags
& KMA_LOMEM
)
5444 vm_page_lomem_find_contiguous_last_idx
= page_idx
;
5446 vm_page_find_contiguous_last_idx
= page_idx
;
5449 * we can drop the free queue lock at this point since
5450 * we've pulled any 'free' candidates off of the list
5451 * we need it dropped so that we can do a vm_page_grab
5452 * when substituing for pmapped/dirty pages
5454 lck_mtx_unlock(&vm_page_queue_free_lock
);
5456 start_idx
= tmp_start_idx
;
5457 cur_idx
= page_idx
- 1;
5459 while (start_idx
++ < page_idx
) {
5461 * must go through the list from back to front
5462 * so that the page list is created in the
5463 * correct order - low -> high phys addresses
5465 m1
= &vm_pages
[cur_idx
--];
5467 if (m1
->vm_page_object
== 0) {
5469 * page has already been removed from
5470 * the free list in the 1st pass
5472 assert(m1
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
);
5473 assert(m1
->offset
== (vm_object_offset_t
) -1);
5475 assert(!m1
->wanted
);
5476 assert(!m1
->laundry
);
5480 boolean_t disconnected
, reusable
;
5482 if (abort_run
== TRUE
)
5485 assert(m1
->vm_page_q_state
!= VM_PAGE_NOT_ON_Q
);
5487 object
= VM_PAGE_OBJECT(m1
);
5489 if (object
!= locked_object
) {
5490 if (locked_object
) {
5491 vm_object_unlock(locked_object
);
5492 locked_object
= VM_OBJECT_NULL
;
5494 if (vm_object_lock_try(object
))
5495 locked_object
= object
;
5497 if (locked_object
== VM_OBJECT_NULL
||
5498 (VM_PAGE_WIRED(m1
) || m1
->gobbled
||
5499 m1
->laundry
|| m1
->wanted
||
5500 m1
->cleaning
|| m1
->overwriting
|| m1
->free_when_done
|| m1
->busy
) ||
5501 (m1
->vm_page_q_state
== VM_PAGE_ON_PAGEOUT_Q
)) {
5503 if (locked_object
) {
5504 vm_object_unlock(locked_object
);
5505 locked_object
= VM_OBJECT_NULL
;
5507 tmp_start_idx
= cur_idx
;
5512 disconnected
= FALSE
;
5515 if ((m1
->reusable
||
5516 object
->all_reusable
) &&
5517 (m1
->vm_page_q_state
== VM_PAGE_ON_INACTIVE_INTERNAL_Q
) &&
5520 /* reusable page... */
5521 refmod
= pmap_disconnect(VM_PAGE_GET_PHYS_PAGE(m1
));
5522 disconnected
= TRUE
;
5525 * ... not reused: can steal
5526 * without relocating contents.
5536 vm_object_offset_t offset
;
5538 m2
= vm_page_grab();
5540 if (m2
== VM_PAGE_NULL
) {
5541 if (locked_object
) {
5542 vm_object_unlock(locked_object
);
5543 locked_object
= VM_OBJECT_NULL
;
5545 tmp_start_idx
= cur_idx
;
5549 if (! disconnected
) {
5551 refmod
= pmap_disconnect(VM_PAGE_GET_PHYS_PAGE(m1
));
5556 /* copy the page's contents */
5557 pmap_copy_page(VM_PAGE_GET_PHYS_PAGE(m1
), VM_PAGE_GET_PHYS_PAGE(m2
));
5558 /* copy the page's state */
5559 assert(!VM_PAGE_WIRED(m1
));
5560 assert(m1
->vm_page_q_state
!= VM_PAGE_ON_FREE_Q
);
5561 assert(m1
->vm_page_q_state
!= VM_PAGE_ON_PAGEOUT_Q
);
5562 assert(!m1
->laundry
);
5563 m2
->reference
= m1
->reference
;
5564 assert(!m1
->gobbled
);
5565 assert(!m1
->private);
5566 m2
->no_cache
= m1
->no_cache
;
5569 assert(!m1
->wanted
);
5570 assert(!m1
->fictitious
);
5571 m2
->pmapped
= m1
->pmapped
; /* should flush cache ? */
5572 m2
->wpmapped
= m1
->wpmapped
;
5573 assert(!m1
->free_when_done
);
5574 m2
->absent
= m1
->absent
;
5575 m2
->error
= m1
->error
;
5576 m2
->dirty
= m1
->dirty
;
5577 assert(!m1
->cleaning
);
5578 m2
->precious
= m1
->precious
;
5579 m2
->clustered
= m1
->clustered
;
5580 assert(!m1
->overwriting
);
5581 m2
->restart
= m1
->restart
;
5582 m2
->unusual
= m1
->unusual
;
5583 m2
->cs_validated
= m1
->cs_validated
;
5584 m2
->cs_tainted
= m1
->cs_tainted
;
5585 m2
->cs_nx
= m1
->cs_nx
;
5588 * If m1 had really been reusable,
5589 * we would have just stolen it, so
5590 * let's not propagate it's "reusable"
5591 * bit and assert that m2 is not
5592 * marked as "reusable".
5594 // m2->reusable = m1->reusable;
5595 assert(!m2
->reusable
);
5597 // assert(!m1->lopage);
5598 m2
->slid
= m1
->slid
;
5600 if (m1
->vm_page_q_state
== VM_PAGE_USED_BY_COMPRESSOR
)
5601 m2
->vm_page_q_state
= VM_PAGE_USED_BY_COMPRESSOR
;
5604 * page may need to be flushed if
5605 * it is marshalled into a UPL
5606 * that is going to be used by a device
5607 * that doesn't support coherency
5609 m2
->written_by_kernel
= TRUE
;
5612 * make sure we clear the ref/mod state
5613 * from the pmap layer... else we risk
5614 * inheriting state from the last time
5615 * this page was used...
5617 pmap_clear_refmod(VM_PAGE_GET_PHYS_PAGE(m2
), VM_MEM_MODIFIED
| VM_MEM_REFERENCED
);
5619 if (refmod
& VM_MEM_REFERENCED
)
5620 m2
->reference
= TRUE
;
5621 if (refmod
& VM_MEM_MODIFIED
) {
5622 SET_PAGE_DIRTY(m2
, TRUE
);
5624 offset
= m1
->offset
;
5627 * completely cleans up the state
5628 * of the page so that it is ready
5629 * to be put onto the free list, or
5630 * for this purpose it looks like it
5631 * just came off of the free list
5633 vm_page_free_prepare(m1
);
5636 * now put the substitute page
5639 vm_page_insert_internal(m2
, locked_object
, offset
, VM_KERN_MEMORY_NONE
, TRUE
, TRUE
, FALSE
, FALSE
, NULL
);
5641 if (m2
->vm_page_q_state
== VM_PAGE_USED_BY_COMPRESSOR
) {
5643 m2
->wpmapped
= TRUE
;
5645 PMAP_ENTER(kernel_pmap
, m2
->offset
, m2
,
5646 VM_PROT_READ
| VM_PROT_WRITE
, VM_PROT_NONE
, 0, TRUE
, kr
);
5648 assert(kr
== KERN_SUCCESS
);
5654 vm_page_activate(m2
);
5656 vm_page_deactivate(m2
);
5658 PAGE_WAKEUP_DONE(m2
);
5661 assert(m1
->vm_page_q_state
!= VM_PAGE_USED_BY_COMPRESSOR
);
5664 * completely cleans up the state
5665 * of the page so that it is ready
5666 * to be put onto the free list, or
5667 * for this purpose it looks like it
5668 * just came off of the free list
5670 vm_page_free_prepare(m1
);
5676 #if CONFIG_BACKGROUND_QUEUE
5677 vm_page_assign_background_state(m1
);
5679 VM_PAGE_ZERO_PAGEQ_ENTRY(m1
);
5683 if (locked_object
) {
5684 vm_object_unlock(locked_object
);
5685 locked_object
= VM_OBJECT_NULL
;
5688 if (abort_run
== TRUE
) {
5690 * want the index of the last
5691 * page in this run that was
5692 * successfully 'stolen', so back
5693 * it up 1 for the auto-decrement on use
5694 * and 1 more to bump back over this page
5696 page_idx
= tmp_start_idx
+ 2;
5697 if (page_idx
>= vm_pages_count
) {
5699 if (m
!= VM_PAGE_NULL
) {
5700 vm_page_unlock_queues();
5701 vm_page_free_list(m
, FALSE
);
5702 vm_page_lock_queues();
5708 page_idx
= last_idx
= 0;
5714 * We didn't find a contiguous range but we didn't
5715 * start from the very first page.
5716 * Start again from the very first page.
5718 RESET_STATE_OF_RUN();
5720 if( flags
& KMA_LOMEM
)
5721 idx_last_contig_page_found
= vm_page_lomem_find_contiguous_last_idx
= page_idx
;
5723 idx_last_contig_page_found
= vm_page_find_contiguous_last_idx
= page_idx
;
5725 last_idx
= page_idx
;
5727 if (m
!= VM_PAGE_NULL
) {
5728 vm_page_unlock_queues();
5729 vm_page_free_list(m
, FALSE
);
5730 vm_page_lock_queues();
5735 lck_mtx_lock(&vm_page_queue_free_lock
);
5737 * reset our free page limit since we
5738 * dropped the lock protecting the vm_page_free_queue
5740 free_available
= vm_page_free_count
- vm_page_free_reserved
;
5744 for (m1
= m
; m1
!= VM_PAGE_NULL
; m1
= NEXT_PAGE(m1
)) {
5746 assert(m1
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
);
5747 assert(m1
->wire_count
== 0);
5751 m1
->vm_page_q_state
= VM_PAGE_IS_WIRED
;
5756 vm_page_gobble_count
+= npages
;
5759 * gobbled pages are also counted as wired pages
5761 vm_page_wire_count
+= npages
;
5763 assert(vm_page_verify_contiguous(m
, npages
));
5766 PAGE_REPLACEMENT_ALLOWED(FALSE
);
5768 vm_page_unlock_queues();
5771 clock_get_system_microtime(&tv_end_sec
, &tv_end_usec
);
5773 tv_end_sec
-= tv_start_sec
;
5774 if (tv_end_usec
< tv_start_usec
) {
5776 tv_end_usec
+= 1000000;
5778 tv_end_usec
-= tv_start_usec
;
5779 if (tv_end_usec
>= 1000000) {
5781 tv_end_sec
-= 1000000;
5783 if (vm_page_find_contig_debug
) {
5784 printf("%s(num=%d,low=%d): found %d pages at 0x%llx in %ld.%06ds... started at %d... scanned %d pages... yielded %d times... dumped run %d times... stole %d pages... stole %d compressed pages\n",
5785 __func__
, contig_pages
, max_pnum
, npages
, (vm_object_offset_t
)start_pnum
<< PAGE_SHIFT
,
5786 (long)tv_end_sec
, tv_end_usec
, orig_last_idx
,
5787 scanned
, yielded
, dumped_run
, stolen_pages
, compressed_pages
);
5792 vm_page_verify_free_lists();
5794 if (m
== NULL
&& zone_gc_called
== FALSE
) {
5795 printf("%s(num=%d,low=%d): found %d pages at 0x%llx...scanned %d pages... yielded %d times... dumped run %d times... stole %d pages... stole %d compressed pages... wired count is %d\n",
5796 __func__
, contig_pages
, max_pnum
, npages
, (vm_object_offset_t
)start_pnum
<< PAGE_SHIFT
,
5797 scanned
, yielded
, dumped_run
, stolen_pages
, compressed_pages
, vm_page_wire_count
);
5799 if (consider_buffer_cache_collect
!= NULL
) {
5800 (void)(*consider_buffer_cache_collect
)(1);
5803 consider_zone_gc(FALSE
);
5805 zone_gc_called
= TRUE
;
5807 printf("vm_page_find_contiguous: zone_gc called... wired count is %d\n", vm_page_wire_count
);
5808 goto full_scan_again
;
5815 * Allocate a list of contiguous, wired pages.
5827 unsigned int npages
;
5829 if (size
% PAGE_SIZE
!= 0)
5830 return KERN_INVALID_ARGUMENT
;
5832 npages
= (unsigned int) (size
/ PAGE_SIZE
);
5833 if (npages
!= size
/ PAGE_SIZE
) {
5834 /* 32-bit overflow */
5835 return KERN_INVALID_ARGUMENT
;
5839 * Obtain a pointer to a subset of the free
5840 * list large enough to satisfy the request;
5841 * the region will be physically contiguous.
5843 pages
= vm_page_find_contiguous(npages
, max_pnum
, pnum_mask
, wire
, flags
);
5845 if (pages
== VM_PAGE_NULL
)
5846 return KERN_NO_SPACE
;
5848 * determine need for wakeups
5850 if ((vm_page_free_count
< vm_page_free_min
) ||
5851 ((vm_page_free_count
< vm_page_free_target
) &&
5852 ((vm_page_inactive_count
+ vm_page_speculative_count
) < vm_page_inactive_min
)))
5853 thread_wakeup((event_t
) &vm_page_free_wanted
);
5855 VM_CHECK_MEMORYSTATUS
;
5858 * The CPM pages should now be available and
5859 * ordered by ascending physical address.
5861 assert(vm_page_verify_contiguous(pages
, npages
));
5864 return KERN_SUCCESS
;
5868 unsigned int vm_max_delayed_work_limit
= DEFAULT_DELAYED_WORK_LIMIT
;
5871 * when working on a 'run' of pages, it is necessary to hold
5872 * the vm_page_queue_lock (a hot global lock) for certain operations
5873 * on the page... however, the majority of the work can be done
5874 * while merely holding the object lock... in fact there are certain
5875 * collections of pages that don't require any work brokered by the
5876 * vm_page_queue_lock... to mitigate the time spent behind the global
5877 * lock, go to a 2 pass algorithm... collect pages up to DELAYED_WORK_LIMIT
5878 * while doing all of the work that doesn't require the vm_page_queue_lock...
5879 * then call vm_page_do_delayed_work to acquire the vm_page_queue_lock and do the
5880 * necessary work for each page... we will grab the busy bit on the page
5881 * if it's not already held so that vm_page_do_delayed_work can drop the object lock
5882 * if it can't immediately take the vm_page_queue_lock in order to compete
5883 * for the locks in the same order that vm_pageout_scan takes them.
5884 * the operation names are modeled after the names of the routines that
5885 * need to be called in order to make the changes very obvious in the
5890 vm_page_do_delayed_work(
5893 struct vm_page_delayed_work
*dwp
,
5898 vm_page_t local_free_q
= VM_PAGE_NULL
;
5901 * pageout_scan takes the vm_page_lock_queues first
5902 * then tries for the object lock... to avoid what
5903 * is effectively a lock inversion, we'll go to the
5904 * trouble of taking them in that same order... otherwise
5905 * if this object contains the majority of the pages resident
5906 * in the UBC (or a small set of large objects actively being
5907 * worked on contain the majority of the pages), we could
5908 * cause the pageout_scan thread to 'starve' in its attempt
5909 * to find pages to move to the free queue, since it has to
5910 * successfully acquire the object lock of any candidate page
5911 * before it can steal/clean it.
5913 if (!vm_page_trylockspin_queues()) {
5914 vm_object_unlock(object
);
5916 vm_page_lockspin_queues();
5918 for (j
= 0; ; j
++) {
5919 if (!vm_object_lock_avoid(object
) &&
5920 _vm_object_lock_try(object
))
5922 vm_page_unlock_queues();
5924 vm_page_lockspin_queues();
5927 for (j
= 0; j
< dw_count
; j
++, dwp
++) {
5931 if (dwp
->dw_mask
& DW_vm_pageout_throttle_up
)
5932 vm_pageout_throttle_up(m
);
5933 #if CONFIG_PHANTOM_CACHE
5934 if (dwp
->dw_mask
& DW_vm_phantom_cache_update
)
5935 vm_phantom_cache_update(m
);
5937 if (dwp
->dw_mask
& DW_vm_page_wire
)
5938 vm_page_wire(m
, tag
, FALSE
);
5939 else if (dwp
->dw_mask
& DW_vm_page_unwire
) {
5942 queueit
= (dwp
->dw_mask
& (DW_vm_page_free
| DW_vm_page_deactivate_internal
)) ? FALSE
: TRUE
;
5944 vm_page_unwire(m
, queueit
);
5946 if (dwp
->dw_mask
& DW_vm_page_free
) {
5947 vm_page_free_prepare_queues(m
);
5949 assert(m
->pageq
.next
== 0 && m
->pageq
.prev
== 0);
5951 * Add this page to our list of reclaimed pages,
5952 * to be freed later.
5954 m
->snext
= local_free_q
;
5957 if (dwp
->dw_mask
& DW_vm_page_deactivate_internal
)
5958 vm_page_deactivate_internal(m
, FALSE
);
5959 else if (dwp
->dw_mask
& DW_vm_page_activate
) {
5960 if (m
->vm_page_q_state
!= VM_PAGE_ON_ACTIVE_Q
) {
5961 vm_page_activate(m
);
5964 else if (dwp
->dw_mask
& DW_vm_page_speculate
)
5965 vm_page_speculate(m
, TRUE
);
5966 else if (dwp
->dw_mask
& DW_enqueue_cleaned
) {
5968 * if we didn't hold the object lock and did this,
5969 * we might disconnect the page, then someone might
5970 * soft fault it back in, then we would put it on the
5971 * cleaned queue, and so we would have a referenced (maybe even dirty)
5972 * page on that queue, which we don't want
5974 int refmod_state
= pmap_disconnect(VM_PAGE_GET_PHYS_PAGE(m
));
5976 if ((refmod_state
& VM_MEM_REFERENCED
)) {
5978 * this page has been touched since it got cleaned; let's activate it
5979 * if it hasn't already been
5981 vm_pageout_enqueued_cleaned
++;
5982 vm_pageout_cleaned_reactivated
++;
5983 vm_pageout_cleaned_commit_reactivated
++;
5985 if (m
->vm_page_q_state
!= VM_PAGE_ON_ACTIVE_Q
)
5986 vm_page_activate(m
);
5988 m
->reference
= FALSE
;
5989 vm_page_enqueue_cleaned(m
);
5992 else if (dwp
->dw_mask
& DW_vm_page_lru
)
5994 else if (dwp
->dw_mask
& DW_VM_PAGE_QUEUES_REMOVE
) {
5995 if (m
->vm_page_q_state
!= VM_PAGE_ON_PAGEOUT_Q
)
5996 vm_page_queues_remove(m
, TRUE
);
5998 if (dwp
->dw_mask
& DW_set_reference
)
5999 m
->reference
= TRUE
;
6000 else if (dwp
->dw_mask
& DW_clear_reference
)
6001 m
->reference
= FALSE
;
6003 if (dwp
->dw_mask
& DW_move_page
) {
6004 if (m
->vm_page_q_state
!= VM_PAGE_ON_PAGEOUT_Q
) {
6005 vm_page_queues_remove(m
, FALSE
);
6007 assert(VM_PAGE_OBJECT(m
) != kernel_object
);
6009 vm_page_enqueue_inactive(m
, FALSE
);
6012 if (dwp
->dw_mask
& DW_clear_busy
)
6015 if (dwp
->dw_mask
& DW_PAGE_WAKEUP
)
6019 vm_page_unlock_queues();
6022 vm_page_free_list(local_free_q
, TRUE
);
6024 VM_CHECK_MEMORYSTATUS
;
6034 vm_page_t lo_page_list
= VM_PAGE_NULL
;
6038 if ( !(flags
& KMA_LOMEM
))
6039 panic("vm_page_alloc_list: called w/o KMA_LOMEM");
6041 for (i
= 0; i
< page_count
; i
++) {
6043 mem
= vm_page_grablo();
6045 if (mem
== VM_PAGE_NULL
) {
6047 vm_page_free_list(lo_page_list
, FALSE
);
6049 *list
= VM_PAGE_NULL
;
6051 return (KERN_RESOURCE_SHORTAGE
);
6053 mem
->snext
= lo_page_list
;
6056 *list
= lo_page_list
;
6058 return (KERN_SUCCESS
);
6062 vm_page_set_offset(vm_page_t page
, vm_object_offset_t offset
)
6064 page
->offset
= offset
;
6068 vm_page_get_next(vm_page_t page
)
6070 return (page
->snext
);
6074 vm_page_get_offset(vm_page_t page
)
6076 return (page
->offset
);
6080 vm_page_get_phys_page(vm_page_t page
)
6082 return (VM_PAGE_GET_PHYS_PAGE(page
));
6086 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6090 static vm_page_t hibernate_gobble_queue
;
6092 static int hibernate_drain_pageout_queue(struct vm_pageout_queue
*);
6093 static int hibernate_flush_dirty_pages(int);
6094 static int hibernate_flush_queue(vm_page_queue_head_t
*, int);
6096 void hibernate_flush_wait(void);
6097 void hibernate_mark_in_progress(void);
6098 void hibernate_clear_in_progress(void);
6100 void hibernate_free_range(int, int);
6101 void hibernate_hash_insert_page(vm_page_t
);
6102 uint32_t hibernate_mark_as_unneeded(addr64_t
, addr64_t
, hibernate_page_list_t
*, hibernate_page_list_t
*);
6103 void hibernate_rebuild_vm_structs(void);
6104 uint32_t hibernate_teardown_vm_structs(hibernate_page_list_t
*, hibernate_page_list_t
*);
6105 ppnum_t
hibernate_lookup_paddr(unsigned int);
6107 struct hibernate_statistics
{
6108 int hibernate_considered
;
6109 int hibernate_reentered_on_q
;
6110 int hibernate_found_dirty
;
6111 int hibernate_skipped_cleaning
;
6112 int hibernate_skipped_transient
;
6113 int hibernate_skipped_precious
;
6114 int hibernate_skipped_external
;
6115 int hibernate_queue_nolock
;
6116 int hibernate_queue_paused
;
6117 int hibernate_throttled
;
6118 int hibernate_throttle_timeout
;
6119 int hibernate_drained
;
6120 int hibernate_drain_timeout
;
6122 int cd_found_precious
;
6125 int cd_found_unusual
;
6126 int cd_found_cleaning
;
6127 int cd_found_laundry
;
6129 int cd_found_xpmapped
;
6130 int cd_skipped_xpmapped
;
6133 int cd_vm_page_wire_count
;
6134 int cd_vm_struct_pages_unneeded
;
6142 * clamp the number of 'xpmapped' pages we'll sweep into the hibernation image
6143 * so that we don't overrun the estimated image size, which would
6144 * result in a hibernation failure.
6146 #define HIBERNATE_XPMAPPED_LIMIT 40000
6150 hibernate_drain_pageout_queue(struct vm_pageout_queue
*q
)
6152 wait_result_t wait_result
;
6154 vm_page_lock_queues();
6156 while ( !vm_page_queue_empty(&q
->pgo_pending
) ) {
6158 q
->pgo_draining
= TRUE
;
6160 assert_wait_timeout((event_t
) (&q
->pgo_laundry
+1), THREAD_INTERRUPTIBLE
, 5000, 1000*NSEC_PER_USEC
);
6162 vm_page_unlock_queues();
6164 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
6166 if (wait_result
== THREAD_TIMED_OUT
&& !vm_page_queue_empty(&q
->pgo_pending
)) {
6167 hibernate_stats
.hibernate_drain_timeout
++;
6169 if (q
== &vm_pageout_queue_external
)
6174 vm_page_lock_queues();
6176 hibernate_stats
.hibernate_drained
++;
6178 vm_page_unlock_queues();
6184 boolean_t hibernate_skip_external
= FALSE
;
6187 hibernate_flush_queue(vm_page_queue_head_t
*q
, int qcount
)
6190 vm_object_t l_object
= NULL
;
6191 vm_object_t m_object
= NULL
;
6192 int refmod_state
= 0;
6193 int try_failed_count
= 0;
6195 int current_run
= 0;
6196 struct vm_pageout_queue
*iq
;
6197 struct vm_pageout_queue
*eq
;
6198 struct vm_pageout_queue
*tq
;
6200 KDBG(IOKDBG_CODE(DBG_HIBERNATE
, 4) | DBG_FUNC_START
,
6201 VM_KERNEL_UNSLIDE_OR_PERM(q
), qcount
);
6203 iq
= &vm_pageout_queue_internal
;
6204 eq
= &vm_pageout_queue_external
;
6206 vm_page_lock_queues();
6208 while (qcount
&& !vm_page_queue_empty(q
)) {
6210 if (current_run
++ == 1000) {
6211 if (hibernate_should_abort()) {
6218 m
= (vm_page_t
) vm_page_queue_first(q
);
6219 m_object
= VM_PAGE_OBJECT(m
);
6222 * check to see if we currently are working
6223 * with the same object... if so, we've
6224 * already got the lock
6226 if (m_object
!= l_object
) {
6228 * the object associated with candidate page is
6229 * different from the one we were just working
6230 * with... dump the lock if we still own it
6232 if (l_object
!= NULL
) {
6233 vm_object_unlock(l_object
);
6237 * Try to lock object; since we've alread got the
6238 * page queues lock, we can only 'try' for this one.
6239 * if the 'try' fails, we need to do a mutex_pause
6240 * to allow the owner of the object lock a chance to
6243 if ( !vm_object_lock_try_scan(m_object
)) {
6245 if (try_failed_count
> 20) {
6246 hibernate_stats
.hibernate_queue_nolock
++;
6248 goto reenter_pg_on_q
;
6251 vm_page_unlock_queues();
6252 mutex_pause(try_failed_count
++);
6253 vm_page_lock_queues();
6255 hibernate_stats
.hibernate_queue_paused
++;
6258 l_object
= m_object
;
6261 if ( !m_object
->alive
|| m
->cleaning
|| m
->laundry
|| m
->busy
|| m
->absent
|| m
->error
) {
6263 * page is not to be cleaned
6264 * put it back on the head of its queue
6267 hibernate_stats
.hibernate_skipped_cleaning
++;
6269 hibernate_stats
.hibernate_skipped_transient
++;
6271 goto reenter_pg_on_q
;
6273 if (m_object
->copy
== VM_OBJECT_NULL
) {
6274 if (m_object
->purgable
== VM_PURGABLE_VOLATILE
|| m_object
->purgable
== VM_PURGABLE_EMPTY
) {
6276 * let the normal hibernate image path
6279 goto reenter_pg_on_q
;
6282 if ( !m
->dirty
&& m
->pmapped
) {
6283 refmod_state
= pmap_get_refmod(VM_PAGE_GET_PHYS_PAGE(m
));
6285 if ((refmod_state
& VM_MEM_MODIFIED
)) {
6286 SET_PAGE_DIRTY(m
, FALSE
);
6293 * page is not to be cleaned
6294 * put it back on the head of its queue
6297 hibernate_stats
.hibernate_skipped_precious
++;
6299 goto reenter_pg_on_q
;
6302 if (hibernate_skip_external
== TRUE
&& !m_object
->internal
) {
6304 hibernate_stats
.hibernate_skipped_external
++;
6306 goto reenter_pg_on_q
;
6310 if (m_object
->internal
) {
6311 if (VM_PAGE_Q_THROTTLED(iq
))
6313 } else if (VM_PAGE_Q_THROTTLED(eq
))
6317 wait_result_t wait_result
;
6320 if (l_object
!= NULL
) {
6321 vm_object_unlock(l_object
);
6325 while (retval
== 0) {
6327 tq
->pgo_throttled
= TRUE
;
6329 assert_wait_timeout((event_t
) &tq
->pgo_laundry
, THREAD_INTERRUPTIBLE
, 1000, 1000*NSEC_PER_USEC
);
6331 vm_page_unlock_queues();
6333 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
6335 vm_page_lock_queues();
6337 if (wait_result
!= THREAD_TIMED_OUT
)
6339 if (!VM_PAGE_Q_THROTTLED(tq
))
6342 if (hibernate_should_abort())
6345 if (--wait_count
== 0) {
6347 hibernate_stats
.hibernate_throttle_timeout
++;
6350 hibernate_skip_external
= TRUE
;
6359 hibernate_stats
.hibernate_throttled
++;
6364 * we've already factored out pages in the laundry which
6365 * means this page can't be on the pageout queue so it's
6366 * safe to do the vm_page_queues_remove
6368 vm_page_queues_remove(m
, TRUE
);
6370 if (m_object
->internal
== TRUE
)
6371 pmap_disconnect_options(VM_PAGE_GET_PHYS_PAGE(m
), PMAP_OPTIONS_COMPRESSOR
, NULL
);
6373 vm_pageout_cluster(m
);
6375 hibernate_stats
.hibernate_found_dirty
++;
6380 vm_page_queue_remove(q
, m
, vm_page_t
, pageq
);
6381 vm_page_queue_enter(q
, m
, vm_page_t
, pageq
);
6383 hibernate_stats
.hibernate_reentered_on_q
++;
6385 hibernate_stats
.hibernate_considered
++;
6388 try_failed_count
= 0;
6390 if (l_object
!= NULL
) {
6391 vm_object_unlock(l_object
);
6395 vm_page_unlock_queues();
6397 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 4) | DBG_FUNC_END
, hibernate_stats
.hibernate_found_dirty
, retval
, 0, 0, 0);
6404 hibernate_flush_dirty_pages(int pass
)
6406 struct vm_speculative_age_q
*aq
;
6409 if (vm_page_local_q
) {
6410 for (i
= 0; i
< vm_page_local_q_count
; i
++)
6411 vm_page_reactivate_local(i
, TRUE
, FALSE
);
6414 for (i
= 0; i
<= VM_PAGE_MAX_SPECULATIVE_AGE_Q
; i
++) {
6418 aq
= &vm_page_queue_speculative
[i
];
6420 if (vm_page_queue_empty(&aq
->age_q
))
6424 vm_page_lockspin_queues();
6426 vm_page_queue_iterate(&aq
->age_q
,
6433 vm_page_unlock_queues();
6436 if (hibernate_flush_queue(&aq
->age_q
, qcount
))
6440 if (hibernate_flush_queue(&vm_page_queue_inactive
, vm_page_inactive_count
- vm_page_anonymous_count
- vm_page_cleaned_count
))
6442 /* XXX FBDP TODO: flush secluded queue */
6443 if (hibernate_flush_queue(&vm_page_queue_anonymous
, vm_page_anonymous_count
))
6445 if (hibernate_flush_queue(&vm_page_queue_cleaned
, vm_page_cleaned_count
))
6447 if (hibernate_drain_pageout_queue(&vm_pageout_queue_internal
))
6451 vm_compressor_record_warmup_start();
6453 if (hibernate_flush_queue(&vm_page_queue_active
, vm_page_active_count
)) {
6455 vm_compressor_record_warmup_end();
6458 if (hibernate_drain_pageout_queue(&vm_pageout_queue_internal
)) {
6460 vm_compressor_record_warmup_end();
6464 vm_compressor_record_warmup_end();
6466 if (hibernate_skip_external
== FALSE
&& hibernate_drain_pageout_queue(&vm_pageout_queue_external
))
6474 hibernate_reset_stats()
6476 bzero(&hibernate_stats
, sizeof(struct hibernate_statistics
));
6481 hibernate_flush_memory()
6485 assert(VM_CONFIG_COMPRESSOR_IS_PRESENT
);
6487 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 3) | DBG_FUNC_START
, vm_page_free_count
, 0, 0, 0, 0);
6489 hibernate_cleaning_in_progress
= TRUE
;
6490 hibernate_skip_external
= FALSE
;
6492 if ((retval
= hibernate_flush_dirty_pages(1)) == 0) {
6494 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 10) | DBG_FUNC_START
, VM_PAGE_COMPRESSOR_COUNT
, 0, 0, 0, 0);
6496 vm_compressor_flush();
6498 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 10) | DBG_FUNC_END
, VM_PAGE_COMPRESSOR_COUNT
, 0, 0, 0, 0);
6500 if (consider_buffer_cache_collect
!= NULL
) {
6501 unsigned int orig_wire_count
;
6503 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 7) | DBG_FUNC_START
, 0, 0, 0, 0, 0);
6504 orig_wire_count
= vm_page_wire_count
;
6506 (void)(*consider_buffer_cache_collect
)(1);
6507 consider_zone_gc(FALSE
);
6509 HIBLOG("hibernate_flush_memory: buffer_cache_gc freed up %d wired pages\n", orig_wire_count
- vm_page_wire_count
);
6511 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 7) | DBG_FUNC_END
, orig_wire_count
- vm_page_wire_count
, 0, 0, 0, 0);
6514 hibernate_cleaning_in_progress
= FALSE
;
6516 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 3) | DBG_FUNC_END
, vm_page_free_count
, hibernate_stats
.hibernate_found_dirty
, retval
, 0, 0);
6519 HIBLOG("hibernate_flush_memory() failed to finish - vm_page_compressor_count(%d)\n", VM_PAGE_COMPRESSOR_COUNT
);
6522 HIBPRINT("hibernate_flush_memory() considered(%d) reentered_on_q(%d) found_dirty(%d)\n",
6523 hibernate_stats
.hibernate_considered
,
6524 hibernate_stats
.hibernate_reentered_on_q
,
6525 hibernate_stats
.hibernate_found_dirty
);
6526 HIBPRINT(" skipped_cleaning(%d) skipped_transient(%d) skipped_precious(%d) skipped_external(%d) queue_nolock(%d)\n",
6527 hibernate_stats
.hibernate_skipped_cleaning
,
6528 hibernate_stats
.hibernate_skipped_transient
,
6529 hibernate_stats
.hibernate_skipped_precious
,
6530 hibernate_stats
.hibernate_skipped_external
,
6531 hibernate_stats
.hibernate_queue_nolock
);
6532 HIBPRINT(" queue_paused(%d) throttled(%d) throttle_timeout(%d) drained(%d) drain_timeout(%d)\n",
6533 hibernate_stats
.hibernate_queue_paused
,
6534 hibernate_stats
.hibernate_throttled
,
6535 hibernate_stats
.hibernate_throttle_timeout
,
6536 hibernate_stats
.hibernate_drained
,
6537 hibernate_stats
.hibernate_drain_timeout
);
6544 hibernate_page_list_zero(hibernate_page_list_t
*list
)
6547 hibernate_bitmap_t
* bitmap
;
6549 bitmap
= &list
->bank_bitmap
[0];
6550 for (bank
= 0; bank
< list
->bank_count
; bank
++)
6554 bzero((void *) &bitmap
->bitmap
[0], bitmap
->bitmapwords
<< 2);
6555 // set out-of-bound bits at end of bitmap.
6556 last_bit
= ((bitmap
->last_page
- bitmap
->first_page
+ 1) & 31);
6558 bitmap
->bitmap
[bitmap
->bitmapwords
- 1] = (0xFFFFFFFF >> last_bit
);
6560 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
6565 hibernate_free_gobble_pages(void)
6570 m
= (vm_page_t
) hibernate_gobble_queue
;
6578 hibernate_gobble_queue
= VM_PAGE_NULL
;
6581 HIBLOG("Freed %d pages\n", count
);
6585 hibernate_consider_discard(vm_page_t m
, boolean_t preflight
)
6587 vm_object_t object
= NULL
;
6589 boolean_t discard
= FALSE
;
6594 panic("hibernate_consider_discard: private");
6596 object
= VM_PAGE_OBJECT(m
);
6598 if (!vm_object_lock_try(object
)) {
6600 if (!preflight
) hibernate_stats
.cd_lock_failed
++;
6603 if (VM_PAGE_WIRED(m
)) {
6604 if (!preflight
) hibernate_stats
.cd_found_wired
++;
6608 if (!preflight
) hibernate_stats
.cd_found_precious
++;
6611 if (m
->busy
|| !object
->alive
) {
6613 * Somebody is playing with this page.
6615 if (!preflight
) hibernate_stats
.cd_found_busy
++;
6618 if (m
->absent
|| m
->unusual
|| m
->error
) {
6620 * If it's unusual in anyway, ignore it
6622 if (!preflight
) hibernate_stats
.cd_found_unusual
++;
6626 if (!preflight
) hibernate_stats
.cd_found_cleaning
++;
6630 if (!preflight
) hibernate_stats
.cd_found_laundry
++;
6635 refmod_state
= pmap_get_refmod(VM_PAGE_GET_PHYS_PAGE(m
));
6637 if (refmod_state
& VM_MEM_REFERENCED
)
6638 m
->reference
= TRUE
;
6639 if (refmod_state
& VM_MEM_MODIFIED
) {
6640 SET_PAGE_DIRTY(m
, FALSE
);
6645 * If it's clean or purgeable we can discard the page on wakeup.
6647 discard
= (!m
->dirty
)
6648 || (VM_PURGABLE_VOLATILE
== object
->purgable
)
6649 || (VM_PURGABLE_EMPTY
== object
->purgable
);
6652 if (discard
== FALSE
) {
6654 hibernate_stats
.cd_found_dirty
++;
6655 } else if (m
->xpmapped
&& m
->reference
&& !object
->internal
) {
6656 if (hibernate_stats
.cd_found_xpmapped
< HIBERNATE_XPMAPPED_LIMIT
) {
6658 hibernate_stats
.cd_found_xpmapped
++;
6662 hibernate_stats
.cd_skipped_xpmapped
++;
6669 vm_object_unlock(object
);
6676 hibernate_discard_page(vm_page_t m
)
6678 vm_object_t m_object
;
6680 if (m
->absent
|| m
->unusual
|| m
->error
)
6682 * If it's unusual in anyway, ignore
6686 m_object
= VM_PAGE_OBJECT(m
);
6688 #if MACH_ASSERT || DEBUG
6689 if (!vm_object_lock_try(m_object
))
6690 panic("hibernate_discard_page(%p) !vm_object_lock_try", m
);
6692 /* No need to lock page queue for token delete, hibernate_vm_unlock()
6693 makes sure these locks are uncontended before sleep */
6694 #endif /* MACH_ASSERT || DEBUG */
6696 if (m
->pmapped
== TRUE
)
6698 __unused
int refmod_state
= pmap_disconnect(VM_PAGE_GET_PHYS_PAGE(m
));
6702 panic("hibernate_discard_page(%p) laundry", m
);
6704 panic("hibernate_discard_page(%p) private", m
);
6706 panic("hibernate_discard_page(%p) fictitious", m
);
6708 if (VM_PURGABLE_VOLATILE
== m_object
->purgable
)
6710 /* object should be on a queue */
6711 assert((m_object
->objq
.next
!= NULL
) && (m_object
->objq
.prev
!= NULL
));
6712 purgeable_q_t old_queue
= vm_purgeable_object_remove(m_object
);
6714 if (m_object
->purgeable_when_ripe
) {
6715 vm_purgeable_token_delete_first(old_queue
);
6717 vm_object_lock_assert_exclusive(m_object
);
6718 m_object
->purgable
= VM_PURGABLE_EMPTY
;
6721 * Purgeable ledgers: pages of VOLATILE and EMPTY objects are
6722 * accounted in the "volatile" ledger, so no change here.
6723 * We have to update vm_page_purgeable_count, though, since we're
6724 * effectively purging this object.
6727 assert(m_object
->resident_page_count
>= m_object
->wired_page_count
);
6728 delta
= (m_object
->resident_page_count
- m_object
->wired_page_count
);
6729 assert(vm_page_purgeable_count
>= delta
);
6731 OSAddAtomic(-delta
, (SInt32
*)&vm_page_purgeable_count
);
6736 #if MACH_ASSERT || DEBUG
6737 vm_object_unlock(m_object
);
6738 #endif /* MACH_ASSERT || DEBUG */
6742 Grab locks for hibernate_page_list_setall()
6745 hibernate_vm_lock_queues(void)
6747 vm_object_lock(compressor_object
);
6748 vm_page_lock_queues();
6749 lck_mtx_lock(&vm_page_queue_free_lock
);
6750 lck_mtx_lock(&vm_purgeable_queue_lock
);
6752 if (vm_page_local_q
) {
6754 for (i
= 0; i
< vm_page_local_q_count
; i
++) {
6756 lq
= &vm_page_local_q
[i
].vpl_un
.vpl
;
6757 VPL_LOCK(&lq
->vpl_lock
);
6763 hibernate_vm_unlock_queues(void)
6765 if (vm_page_local_q
) {
6767 for (i
= 0; i
< vm_page_local_q_count
; i
++) {
6769 lq
= &vm_page_local_q
[i
].vpl_un
.vpl
;
6770 VPL_UNLOCK(&lq
->vpl_lock
);
6773 lck_mtx_unlock(&vm_purgeable_queue_lock
);
6774 lck_mtx_unlock(&vm_page_queue_free_lock
);
6775 vm_page_unlock_queues();
6776 vm_object_unlock(compressor_object
);
6780 Bits zero in the bitmaps => page needs to be saved. All pages default to be saved,
6781 pages known to VM to not need saving are subtracted.
6782 Wired pages to be saved are present in page_list_wired, pageable in page_list.
6786 hibernate_page_list_setall(hibernate_page_list_t
* page_list
,
6787 hibernate_page_list_t
* page_list_wired
,
6788 hibernate_page_list_t
* page_list_pal
,
6789 boolean_t preflight
,
6790 boolean_t will_discard
,
6791 uint32_t * pagesOut
)
6793 uint64_t start
, end
, nsec
;
6796 uint32_t pages
= page_list
->page_count
;
6797 uint32_t count_anonymous
= 0, count_throttled
= 0, count_compressor
= 0;
6798 uint32_t count_inactive
= 0, count_active
= 0, count_speculative
= 0, count_cleaned
= 0;
6799 uint32_t count_wire
= pages
;
6800 uint32_t count_discard_active
= 0;
6801 uint32_t count_discard_inactive
= 0;
6802 uint32_t count_discard_cleaned
= 0;
6803 uint32_t count_discard_purgeable
= 0;
6804 uint32_t count_discard_speculative
= 0;
6805 uint32_t count_discard_vm_struct_pages
= 0;
6808 hibernate_bitmap_t
* bitmap
;
6809 hibernate_bitmap_t
* bitmap_wired
;
6810 boolean_t discard_all
;
6813 HIBLOG("hibernate_page_list_setall(preflight %d) start\n", preflight
);
6817 page_list_wired
= NULL
;
6818 page_list_pal
= NULL
;
6819 discard_all
= FALSE
;
6821 discard_all
= will_discard
;
6824 #if MACH_ASSERT || DEBUG
6827 assert(hibernate_vm_locks_are_safe());
6828 vm_page_lock_queues();
6829 if (vm_page_local_q
) {
6830 for (i
= 0; i
< vm_page_local_q_count
; i
++) {
6832 lq
= &vm_page_local_q
[i
].vpl_un
.vpl
;
6833 VPL_LOCK(&lq
->vpl_lock
);
6837 #endif /* MACH_ASSERT || DEBUG */
6840 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 8) | DBG_FUNC_START
, count_wire
, 0, 0, 0, 0);
6842 clock_get_uptime(&start
);
6845 hibernate_page_list_zero(page_list
);
6846 hibernate_page_list_zero(page_list_wired
);
6847 hibernate_page_list_zero(page_list_pal
);
6849 hibernate_stats
.cd_vm_page_wire_count
= vm_page_wire_count
;
6850 hibernate_stats
.cd_pages
= pages
;
6853 if (vm_page_local_q
) {
6854 for (i
= 0; i
< vm_page_local_q_count
; i
++)
6855 vm_page_reactivate_local(i
, TRUE
, !preflight
);
6859 vm_object_lock(compressor_object
);
6860 vm_page_lock_queues();
6861 lck_mtx_lock(&vm_page_queue_free_lock
);
6864 m
= (vm_page_t
) hibernate_gobble_queue
;
6870 hibernate_page_bitset(page_list
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6871 hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6876 if (!preflight
) for( i
= 0; i
< real_ncpus
; i
++ )
6878 if (cpu_data_ptr
[i
] && cpu_data_ptr
[i
]->cpu_processor
)
6880 for (m
= PROCESSOR_DATA(cpu_data_ptr
[i
]->cpu_processor
, free_pages
); m
; m
= m
->snext
)
6882 assert(m
->vm_page_q_state
== VM_PAGE_ON_FREE_LOCAL_Q
);
6886 hibernate_page_bitset(page_list
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6887 hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6889 hibernate_stats
.cd_local_free
++;
6890 hibernate_stats
.cd_total_free
++;
6895 for( i
= 0; i
< vm_colors
; i
++ )
6897 vm_page_queue_iterate(&vm_page_queue_free
[i
].qhead
,
6902 assert(m
->vm_page_q_state
== VM_PAGE_ON_FREE_Q
);
6907 hibernate_page_bitset(page_list
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6908 hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6910 hibernate_stats
.cd_total_free
++;
6915 vm_page_queue_iterate(&vm_lopage_queue_free
,
6920 assert(m
->vm_page_q_state
== VM_PAGE_ON_FREE_LOPAGE_Q
);
6925 hibernate_page_bitset(page_list
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6926 hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6928 hibernate_stats
.cd_total_free
++;
6932 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_throttled
);
6933 while (m
&& !vm_page_queue_end(&vm_page_queue_throttled
, (vm_page_queue_entry_t
)m
))
6935 assert(m
->vm_page_q_state
== VM_PAGE_ON_THROTTLED_Q
);
6937 next
= (vm_page_t
)VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
6939 if ((kIOHibernateModeDiscardCleanInactive
& gIOHibernateMode
)
6940 && hibernate_consider_discard(m
, preflight
))
6942 if (!preflight
) hibernate_page_bitset(page_list
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6943 count_discard_inactive
++;
6944 discard
= discard_all
;
6949 if (!preflight
) hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6951 if (discard
) hibernate_discard_page(m
);
6955 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_anonymous
);
6956 while (m
&& !vm_page_queue_end(&vm_page_queue_anonymous
, (vm_page_queue_entry_t
)m
))
6958 assert(m
->vm_page_q_state
== VM_PAGE_ON_INACTIVE_INTERNAL_Q
);
6960 next
= (vm_page_t
)VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
6962 if ((kIOHibernateModeDiscardCleanInactive
& gIOHibernateMode
)
6963 && hibernate_consider_discard(m
, preflight
))
6965 if (!preflight
) hibernate_page_bitset(page_list
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6967 count_discard_purgeable
++;
6969 count_discard_inactive
++;
6970 discard
= discard_all
;
6975 if (!preflight
) hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6976 if (discard
) hibernate_discard_page(m
);
6980 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_cleaned
);
6981 while (m
&& !vm_page_queue_end(&vm_page_queue_cleaned
, (vm_page_queue_entry_t
)m
))
6983 assert(m
->vm_page_q_state
== VM_PAGE_ON_INACTIVE_CLEANED_Q
);
6985 next
= (vm_page_t
)VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
6987 if ((kIOHibernateModeDiscardCleanInactive
& gIOHibernateMode
)
6988 && hibernate_consider_discard(m
, preflight
))
6990 if (!preflight
) hibernate_page_bitset(page_list
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
6992 count_discard_purgeable
++;
6994 count_discard_cleaned
++;
6995 discard
= discard_all
;
7000 if (!preflight
) hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
7001 if (discard
) hibernate_discard_page(m
);
7005 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_active
);
7006 while (m
&& !vm_page_queue_end(&vm_page_queue_active
, (vm_page_queue_entry_t
)m
))
7008 assert(m
->vm_page_q_state
== VM_PAGE_ON_ACTIVE_Q
);
7010 next
= (vm_page_t
)VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
7012 if ((kIOHibernateModeDiscardCleanActive
& gIOHibernateMode
)
7013 && hibernate_consider_discard(m
, preflight
))
7015 if (!preflight
) hibernate_page_bitset(page_list
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
7017 count_discard_purgeable
++;
7019 count_discard_active
++;
7020 discard
= discard_all
;
7025 if (!preflight
) hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
7026 if (discard
) hibernate_discard_page(m
);
7030 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_inactive
);
7031 while (m
&& !vm_page_queue_end(&vm_page_queue_inactive
, (vm_page_queue_entry_t
)m
))
7033 assert(m
->vm_page_q_state
== VM_PAGE_ON_INACTIVE_EXTERNAL_Q
);
7035 next
= (vm_page_t
)VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
7037 if ((kIOHibernateModeDiscardCleanInactive
& gIOHibernateMode
)
7038 && hibernate_consider_discard(m
, preflight
))
7040 if (!preflight
) hibernate_page_bitset(page_list
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
7042 count_discard_purgeable
++;
7044 count_discard_inactive
++;
7045 discard
= discard_all
;
7050 if (!preflight
) hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
7051 if (discard
) hibernate_discard_page(m
);
7054 /* XXX FBDP TODO: secluded queue */
7056 for( i
= 0; i
<= VM_PAGE_MAX_SPECULATIVE_AGE_Q
; i
++ )
7058 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_speculative
[i
].age_q
);
7059 while (m
&& !vm_page_queue_end(&vm_page_queue_speculative
[i
].age_q
, (vm_page_queue_entry_t
)m
))
7061 assert(m
->vm_page_q_state
== VM_PAGE_ON_SPECULATIVE_Q
);
7063 next
= (vm_page_t
)VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
7065 if ((kIOHibernateModeDiscardCleanInactive
& gIOHibernateMode
)
7066 && hibernate_consider_discard(m
, preflight
))
7068 if (!preflight
) hibernate_page_bitset(page_list
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
7069 count_discard_speculative
++;
7070 discard
= discard_all
;
7073 count_speculative
++;
7075 if (!preflight
) hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
7076 if (discard
) hibernate_discard_page(m
);
7081 vm_page_queue_iterate(&compressor_object
->memq
, m
, vm_page_t
, listq
)
7083 assert(m
->vm_page_q_state
== VM_PAGE_USED_BY_COMPRESSOR
);
7087 if (!preflight
) hibernate_page_bitset(page_list_wired
, TRUE
, VM_PAGE_GET_PHYS_PAGE(m
));
7090 if (preflight
== FALSE
&& discard_all
== TRUE
) {
7091 KDBG(IOKDBG_CODE(DBG_HIBERNATE
, 12) | DBG_FUNC_START
);
7093 HIBLOG("hibernate_teardown started\n");
7094 count_discard_vm_struct_pages
= hibernate_teardown_vm_structs(page_list
, page_list_wired
);
7095 HIBLOG("hibernate_teardown completed - discarded %d\n", count_discard_vm_struct_pages
);
7097 pages
-= count_discard_vm_struct_pages
;
7098 count_wire
-= count_discard_vm_struct_pages
;
7100 hibernate_stats
.cd_vm_struct_pages_unneeded
= count_discard_vm_struct_pages
;
7102 KDBG(IOKDBG_CODE(DBG_HIBERNATE
, 12) | DBG_FUNC_END
);
7106 // pull wired from hibernate_bitmap
7107 bitmap
= &page_list
->bank_bitmap
[0];
7108 bitmap_wired
= &page_list_wired
->bank_bitmap
[0];
7109 for (bank
= 0; bank
< page_list
->bank_count
; bank
++)
7111 for (i
= 0; i
< bitmap
->bitmapwords
; i
++)
7112 bitmap
->bitmap
[i
] = bitmap
->bitmap
[i
] | ~bitmap_wired
->bitmap
[i
];
7113 bitmap
= (hibernate_bitmap_t
*) &bitmap
->bitmap
[bitmap
->bitmapwords
];
7114 bitmap_wired
= (hibernate_bitmap_t
*) &bitmap_wired
->bitmap
[bitmap_wired
->bitmapwords
];
7118 // machine dependent adjustments
7119 hibernate_page_list_setall_machine(page_list
, page_list_wired
, preflight
, &pages
);
7122 hibernate_stats
.cd_count_wire
= count_wire
;
7123 hibernate_stats
.cd_discarded
= count_discard_active
+ count_discard_inactive
+ count_discard_purgeable
+
7124 count_discard_speculative
+ count_discard_cleaned
+ count_discard_vm_struct_pages
;
7127 clock_get_uptime(&end
);
7128 absolutetime_to_nanoseconds(end
- start
, &nsec
);
7129 HIBLOG("hibernate_page_list_setall time: %qd ms\n", nsec
/ 1000000ULL);
7131 HIBLOG("pages %d, wire %d, act %d, inact %d, cleaned %d spec %d, zf %d, throt %d, compr %d, xpmapped %d\n %s discard act %d inact %d purgeable %d spec %d cleaned %d\n",
7132 pages
, count_wire
, count_active
, count_inactive
, count_cleaned
, count_speculative
, count_anonymous
, count_throttled
, count_compressor
, hibernate_stats
.cd_found_xpmapped
,
7133 discard_all
? "did" : "could",
7134 count_discard_active
, count_discard_inactive
, count_discard_purgeable
, count_discard_speculative
, count_discard_cleaned
);
7136 if (hibernate_stats
.cd_skipped_xpmapped
)
7137 HIBLOG("WARNING: hibernate_page_list_setall skipped %d xpmapped pages\n", hibernate_stats
.cd_skipped_xpmapped
);
7139 *pagesOut
= pages
- count_discard_active
- count_discard_inactive
- count_discard_purgeable
- count_discard_speculative
- count_discard_cleaned
;
7141 if (preflight
&& will_discard
) *pagesOut
-= count_compressor
+ count_throttled
+ count_anonymous
+ count_inactive
+ count_cleaned
+ count_speculative
+ count_active
;
7143 #if MACH_ASSERT || DEBUG
7146 if (vm_page_local_q
) {
7147 for (i
= 0; i
< vm_page_local_q_count
; i
++) {
7149 lq
= &vm_page_local_q
[i
].vpl_un
.vpl
;
7150 VPL_UNLOCK(&lq
->vpl_lock
);
7153 vm_page_unlock_queues();
7155 #endif /* MACH_ASSERT || DEBUG */
7158 lck_mtx_unlock(&vm_page_queue_free_lock
);
7159 vm_page_unlock_queues();
7160 vm_object_unlock(compressor_object
);
7163 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE
, 8) | DBG_FUNC_END
, count_wire
, *pagesOut
, 0, 0, 0);
7167 hibernate_page_list_discard(hibernate_page_list_t
* page_list
)
7169 uint64_t start
, end
, nsec
;
7173 uint32_t count_discard_active
= 0;
7174 uint32_t count_discard_inactive
= 0;
7175 uint32_t count_discard_purgeable
= 0;
7176 uint32_t count_discard_cleaned
= 0;
7177 uint32_t count_discard_speculative
= 0;
7180 #if MACH_ASSERT || DEBUG
7181 vm_page_lock_queues();
7182 if (vm_page_local_q
) {
7183 for (i
= 0; i
< vm_page_local_q_count
; i
++) {
7185 lq
= &vm_page_local_q
[i
].vpl_un
.vpl
;
7186 VPL_LOCK(&lq
->vpl_lock
);
7189 #endif /* MACH_ASSERT || DEBUG */
7191 clock_get_uptime(&start
);
7193 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_anonymous
);
7194 while (m
&& !vm_page_queue_end(&vm_page_queue_anonymous
, (vm_page_queue_entry_t
)m
))
7196 assert(m
->vm_page_q_state
== VM_PAGE_ON_INACTIVE_INTERNAL_Q
);
7198 next
= (vm_page_t
) VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
7199 if (hibernate_page_bittst(page_list
, VM_PAGE_GET_PHYS_PAGE(m
)))
7202 count_discard_purgeable
++;
7204 count_discard_inactive
++;
7205 hibernate_discard_page(m
);
7210 for( i
= 0; i
<= VM_PAGE_MAX_SPECULATIVE_AGE_Q
; i
++ )
7212 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_speculative
[i
].age_q
);
7213 while (m
&& !vm_page_queue_end(&vm_page_queue_speculative
[i
].age_q
, (vm_page_queue_entry_t
)m
))
7215 assert(m
->vm_page_q_state
== VM_PAGE_ON_SPECULATIVE_Q
);
7217 next
= (vm_page_t
) VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
7218 if (hibernate_page_bittst(page_list
, VM_PAGE_GET_PHYS_PAGE(m
)))
7220 count_discard_speculative
++;
7221 hibernate_discard_page(m
);
7227 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_inactive
);
7228 while (m
&& !vm_page_queue_end(&vm_page_queue_inactive
, (vm_page_queue_entry_t
)m
))
7230 assert(m
->vm_page_q_state
== VM_PAGE_ON_INACTIVE_EXTERNAL_Q
);
7232 next
= (vm_page_t
) VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
7233 if (hibernate_page_bittst(page_list
, VM_PAGE_GET_PHYS_PAGE(m
)))
7236 count_discard_purgeable
++;
7238 count_discard_inactive
++;
7239 hibernate_discard_page(m
);
7243 /* XXX FBDP TODO: secluded queue */
7245 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_active
);
7246 while (m
&& !vm_page_queue_end(&vm_page_queue_active
, (vm_page_queue_entry_t
)m
))
7248 assert(m
->vm_page_q_state
== VM_PAGE_ON_ACTIVE_Q
);
7250 next
= (vm_page_t
) VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
7251 if (hibernate_page_bittst(page_list
, VM_PAGE_GET_PHYS_PAGE(m
)))
7254 count_discard_purgeable
++;
7256 count_discard_active
++;
7257 hibernate_discard_page(m
);
7262 m
= (vm_page_t
) vm_page_queue_first(&vm_page_queue_cleaned
);
7263 while (m
&& !vm_page_queue_end(&vm_page_queue_cleaned
, (vm_page_queue_entry_t
)m
))
7265 assert(m
->vm_page_q_state
== VM_PAGE_ON_INACTIVE_CLEANED_Q
);
7267 next
= (vm_page_t
) VM_PAGE_UNPACK_PTR(m
->pageq
.next
);
7268 if (hibernate_page_bittst(page_list
, VM_PAGE_GET_PHYS_PAGE(m
)))
7271 count_discard_purgeable
++;
7273 count_discard_cleaned
++;
7274 hibernate_discard_page(m
);
7279 #if MACH_ASSERT || DEBUG
7280 if (vm_page_local_q
) {
7281 for (i
= 0; i
< vm_page_local_q_count
; i
++) {
7283 lq
= &vm_page_local_q
[i
].vpl_un
.vpl
;
7284 VPL_UNLOCK(&lq
->vpl_lock
);
7287 vm_page_unlock_queues();
7288 #endif /* MACH_ASSERT || DEBUG */
7290 clock_get_uptime(&end
);
7291 absolutetime_to_nanoseconds(end
- start
, &nsec
);
7292 HIBLOG("hibernate_page_list_discard time: %qd ms, discarded act %d inact %d purgeable %d spec %d cleaned %d\n",
7294 count_discard_active
, count_discard_inactive
, count_discard_purgeable
, count_discard_speculative
, count_discard_cleaned
);
7297 boolean_t hibernate_paddr_map_inited
= FALSE
;
7298 unsigned int hibernate_teardown_last_valid_compact_indx
= -1;
7299 vm_page_t hibernate_rebuild_hash_list
= NULL
;
7301 unsigned int hibernate_teardown_found_tabled_pages
= 0;
7302 unsigned int hibernate_teardown_found_created_pages
= 0;
7303 unsigned int hibernate_teardown_found_free_pages
= 0;
7304 unsigned int hibernate_teardown_vm_page_free_count
;
7307 struct ppnum_mapping
{
7308 struct ppnum_mapping
*ppnm_next
;
7309 ppnum_t ppnm_base_paddr
;
7310 unsigned int ppnm_sindx
;
7311 unsigned int ppnm_eindx
;
7314 struct ppnum_mapping
*ppnm_head
;
7315 struct ppnum_mapping
*ppnm_last_found
= NULL
;
7319 hibernate_create_paddr_map()
7322 ppnum_t next_ppnum_in_run
= 0;
7323 struct ppnum_mapping
*ppnm
= NULL
;
7325 if (hibernate_paddr_map_inited
== FALSE
) {
7327 for (i
= 0; i
< vm_pages_count
; i
++) {
7330 ppnm
->ppnm_eindx
= i
;
7332 if (ppnm
== NULL
|| VM_PAGE_GET_PHYS_PAGE(&vm_pages
[i
]) != next_ppnum_in_run
) {
7334 ppnm
= kalloc(sizeof(struct ppnum_mapping
));
7336 ppnm
->ppnm_next
= ppnm_head
;
7339 ppnm
->ppnm_sindx
= i
;
7340 ppnm
->ppnm_base_paddr
= VM_PAGE_GET_PHYS_PAGE(&vm_pages
[i
]);
7342 next_ppnum_in_run
= VM_PAGE_GET_PHYS_PAGE(&vm_pages
[i
]) + 1;
7346 hibernate_paddr_map_inited
= TRUE
;
7351 hibernate_lookup_paddr(unsigned int indx
)
7353 struct ppnum_mapping
*ppnm
= NULL
;
7355 ppnm
= ppnm_last_found
;
7358 if (indx
>= ppnm
->ppnm_sindx
&& indx
< ppnm
->ppnm_eindx
)
7361 for (ppnm
= ppnm_head
; ppnm
; ppnm
= ppnm
->ppnm_next
) {
7363 if (indx
>= ppnm
->ppnm_sindx
&& indx
< ppnm
->ppnm_eindx
) {
7364 ppnm_last_found
= ppnm
;
7369 panic("hibernate_lookup_paddr of %d failed\n", indx
);
7371 return (ppnm
->ppnm_base_paddr
+ (indx
- ppnm
->ppnm_sindx
));
7376 hibernate_mark_as_unneeded(addr64_t saddr
, addr64_t eaddr
, hibernate_page_list_t
*page_list
, hibernate_page_list_t
*page_list_wired
)
7378 addr64_t saddr_aligned
;
7379 addr64_t eaddr_aligned
;
7382 unsigned int mark_as_unneeded_pages
= 0;
7384 saddr_aligned
= (saddr
+ PAGE_MASK_64
) & ~PAGE_MASK_64
;
7385 eaddr_aligned
= eaddr
& ~PAGE_MASK_64
;
7387 for (addr
= saddr_aligned
; addr
< eaddr_aligned
; addr
+= PAGE_SIZE_64
) {
7389 paddr
= pmap_find_phys(kernel_pmap
, addr
);
7393 hibernate_page_bitset(page_list
, TRUE
, paddr
);
7394 hibernate_page_bitset(page_list_wired
, TRUE
, paddr
);
7396 mark_as_unneeded_pages
++;
7398 return (mark_as_unneeded_pages
);
7403 hibernate_hash_insert_page(vm_page_t mem
)
7405 vm_page_bucket_t
*bucket
;
7407 vm_object_t m_object
;
7409 m_object
= VM_PAGE_OBJECT(mem
);
7411 assert(mem
->hashed
);
7413 assert(mem
->offset
!= (vm_object_offset_t
) -1);
7416 * Insert it into the object_object/offset hash table
7418 hash_id
= vm_page_hash(m_object
, mem
->offset
);
7419 bucket
= &vm_page_buckets
[hash_id
];
7421 mem
->next_m
= bucket
->page_list
;
7422 bucket
->page_list
= VM_PAGE_PACK_PTR(mem
);
7427 hibernate_free_range(int sindx
, int eindx
)
7432 while (sindx
< eindx
) {
7433 mem
= &vm_pages
[sindx
];
7435 vm_page_init(mem
, hibernate_lookup_paddr(sindx
), FALSE
);
7437 mem
->lopage
= FALSE
;
7438 mem
->vm_page_q_state
= VM_PAGE_ON_FREE_Q
;
7440 color
= VM_PAGE_GET_COLOR(mem
);
7441 #if defined(__x86_64__)
7442 vm_page_queue_enter_clump(&vm_page_queue_free
[color
].qhead
,
7447 vm_page_queue_enter(&vm_page_queue_free
[color
].qhead
,
7452 vm_page_free_count
++;
7459 extern void hibernate_rebuild_pmap_structs(void);
7462 hibernate_rebuild_vm_structs(void)
7464 int i
, cindx
, sindx
, eindx
;
7465 vm_page_t mem
, tmem
, mem_next
;
7466 AbsoluteTime startTime
, endTime
;
7469 if (hibernate_rebuild_needed
== FALSE
)
7472 KDBG(IOKDBG_CODE(DBG_HIBERNATE
, 13) | DBG_FUNC_START
);
7473 HIBLOG("hibernate_rebuild started\n");
7475 clock_get_uptime(&startTime
);
7477 hibernate_rebuild_pmap_structs();
7479 bzero(&vm_page_buckets
[0], vm_page_bucket_count
* sizeof(vm_page_bucket_t
));
7480 eindx
= vm_pages_count
;
7483 * Mark all the vm_pages[] that have not been initialized yet as being
7484 * transient. This is needed to ensure that buddy page search is corrrect.
7485 * Without this random data in these vm_pages[] can trip the buddy search
7487 for (i
= hibernate_teardown_last_valid_compact_indx
+1; i
< eindx
; ++i
)
7488 vm_pages
[i
].vm_page_q_state
= VM_PAGE_NOT_ON_Q
;
7490 for (cindx
= hibernate_teardown_last_valid_compact_indx
; cindx
>= 0; cindx
--) {
7492 mem
= &vm_pages
[cindx
];
7493 assert(mem
->vm_page_q_state
!= VM_PAGE_ON_FREE_Q
);
7495 * hibernate_teardown_vm_structs leaves the location where
7496 * this vm_page_t must be located in "next".
7498 tmem
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(mem
->next_m
));
7499 mem
->next_m
= VM_PAGE_PACK_PTR(NULL
);
7501 sindx
= (int)(tmem
- &vm_pages
[0]);
7505 * this vm_page_t was moved by hibernate_teardown_vm_structs,
7506 * so move it back to its real location
7512 hibernate_hash_insert_page(mem
);
7514 * the 'hole' between this vm_page_t and the previous
7515 * vm_page_t we moved needs to be initialized as
7516 * a range of free vm_page_t's
7518 hibernate_free_range(sindx
+ 1, eindx
);
7523 hibernate_free_range(0, sindx
);
7525 assert(vm_page_free_count
== hibernate_teardown_vm_page_free_count
);
7528 * process the list of vm_page_t's that were entered in the hash,
7529 * but were not located in the vm_pages arrary... these are
7530 * vm_page_t's that were created on the fly (i.e. fictitious)
7532 for (mem
= hibernate_rebuild_hash_list
; mem
; mem
= mem_next
) {
7533 mem_next
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(mem
->next_m
));
7536 hibernate_hash_insert_page(mem
);
7538 hibernate_rebuild_hash_list
= NULL
;
7540 clock_get_uptime(&endTime
);
7541 SUB_ABSOLUTETIME(&endTime
, &startTime
);
7542 absolutetime_to_nanoseconds(endTime
, &nsec
);
7544 HIBLOG("hibernate_rebuild completed - took %qd msecs\n", nsec
/ 1000000ULL);
7546 hibernate_rebuild_needed
= FALSE
;
7548 KDBG(IOKDBG_CODE(DBG_HIBERNATE
, 13) | DBG_FUNC_END
);
7552 extern void hibernate_teardown_pmap_structs(addr64_t
*, addr64_t
*);
7555 hibernate_teardown_vm_structs(hibernate_page_list_t
*page_list
, hibernate_page_list_t
*page_list_wired
)
7558 unsigned int compact_target_indx
;
7559 vm_page_t mem
, mem_next
;
7560 vm_page_bucket_t
*bucket
;
7561 unsigned int mark_as_unneeded_pages
= 0;
7562 unsigned int unneeded_vm_page_bucket_pages
= 0;
7563 unsigned int unneeded_vm_pages_pages
= 0;
7564 unsigned int unneeded_pmap_pages
= 0;
7565 addr64_t start_of_unneeded
= 0;
7566 addr64_t end_of_unneeded
= 0;
7569 if (hibernate_should_abort())
7572 hibernate_rebuild_needed
= TRUE
;
7574 HIBLOG("hibernate_teardown: wired_pages %d, free_pages %d, active_pages %d, inactive_pages %d, speculative_pages %d, cleaned_pages %d, compressor_pages %d\n",
7575 vm_page_wire_count
, vm_page_free_count
, vm_page_active_count
, vm_page_inactive_count
, vm_page_speculative_count
,
7576 vm_page_cleaned_count
, compressor_object
->resident_page_count
);
7578 for (i
= 0; i
< vm_page_bucket_count
; i
++) {
7580 bucket
= &vm_page_buckets
[i
];
7582 for (mem
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(bucket
->page_list
)); mem
!= VM_PAGE_NULL
; mem
= mem_next
) {
7583 assert(mem
->hashed
);
7585 mem_next
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(mem
->next_m
));
7587 if (mem
< &vm_pages
[0] || mem
>= &vm_pages
[vm_pages_count
]) {
7588 mem
->next_m
= VM_PAGE_PACK_PTR(hibernate_rebuild_hash_list
);
7589 hibernate_rebuild_hash_list
= mem
;
7593 unneeded_vm_page_bucket_pages
= hibernate_mark_as_unneeded((addr64_t
)&vm_page_buckets
[0], (addr64_t
)&vm_page_buckets
[vm_page_bucket_count
], page_list
, page_list_wired
);
7594 mark_as_unneeded_pages
+= unneeded_vm_page_bucket_pages
;
7596 hibernate_teardown_vm_page_free_count
= vm_page_free_count
;
7598 compact_target_indx
= 0;
7600 for (i
= 0; i
< vm_pages_count
; i
++) {
7604 if (mem
->vm_page_q_state
== VM_PAGE_ON_FREE_Q
) {
7608 assert(!mem
->lopage
);
7610 color
= VM_PAGE_GET_COLOR(mem
);
7612 vm_page_queue_remove(&vm_page_queue_free
[color
].qhead
,
7617 VM_PAGE_ZERO_PAGEQ_ENTRY(mem
);
7619 vm_page_free_count
--;
7621 hibernate_teardown_found_free_pages
++;
7623 if (vm_pages
[compact_target_indx
].vm_page_q_state
!= VM_PAGE_ON_FREE_Q
)
7624 compact_target_indx
= i
;
7627 * record this vm_page_t's original location
7628 * we need this even if it doesn't get moved
7629 * as an indicator to the rebuild function that
7630 * we don't have to move it
7632 mem
->next_m
= VM_PAGE_PACK_PTR(mem
);
7634 if (vm_pages
[compact_target_indx
].vm_page_q_state
== VM_PAGE_ON_FREE_Q
) {
7636 * we've got a hole to fill, so
7637 * move this vm_page_t to it's new home
7639 vm_pages
[compact_target_indx
] = *mem
;
7640 mem
->vm_page_q_state
= VM_PAGE_ON_FREE_Q
;
7642 hibernate_teardown_last_valid_compact_indx
= compact_target_indx
;
7643 compact_target_indx
++;
7645 hibernate_teardown_last_valid_compact_indx
= i
;
7648 unneeded_vm_pages_pages
= hibernate_mark_as_unneeded((addr64_t
)&vm_pages
[hibernate_teardown_last_valid_compact_indx
+1],
7649 (addr64_t
)&vm_pages
[vm_pages_count
-1], page_list
, page_list_wired
);
7650 mark_as_unneeded_pages
+= unneeded_vm_pages_pages
;
7652 hibernate_teardown_pmap_structs(&start_of_unneeded
, &end_of_unneeded
);
7654 if (start_of_unneeded
) {
7655 unneeded_pmap_pages
= hibernate_mark_as_unneeded(start_of_unneeded
, end_of_unneeded
, page_list
, page_list_wired
);
7656 mark_as_unneeded_pages
+= unneeded_pmap_pages
;
7658 HIBLOG("hibernate_teardown: mark_as_unneeded_pages %d, %d, %d\n", unneeded_vm_page_bucket_pages
, unneeded_vm_pages_pages
, unneeded_pmap_pages
);
7660 return (mark_as_unneeded_pages
);
7664 #endif /* HIBERNATION */
7666 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7668 #include <mach_vm_debug.h>
7671 #include <mach_debug/hash_info.h>
7672 #include <vm/vm_debug.h>
7675 * Routine: vm_page_info
7677 * Return information about the global VP table.
7678 * Fills the buffer with as much information as possible
7679 * and returns the desired size of the buffer.
7681 * Nothing locked. The caller should provide
7682 * possibly-pageable memory.
7687 hash_info_bucket_t
*info
,
7691 lck_spin_t
*bucket_lock
;
7693 if (vm_page_bucket_count
< count
)
7694 count
= vm_page_bucket_count
;
7696 for (i
= 0; i
< count
; i
++) {
7697 vm_page_bucket_t
*bucket
= &vm_page_buckets
[i
];
7698 unsigned int bucket_count
= 0;
7701 bucket_lock
= &vm_page_bucket_locks
[i
/ BUCKETS_PER_LOCK
];
7702 lck_spin_lock(bucket_lock
);
7704 for (m
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(bucket
->page_list
));
7706 m
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(m
->next_m
)))
7709 lck_spin_unlock(bucket_lock
);
7711 /* don't touch pageable memory while holding locks */
7712 info
[i
].hib_count
= bucket_count
;
7715 return vm_page_bucket_count
;
7717 #endif /* MACH_VM_DEBUG */
7719 #if VM_PAGE_BUCKETS_CHECK
7721 vm_page_buckets_check(void)
7725 unsigned int p_hash
;
7726 vm_page_bucket_t
*bucket
;
7727 lck_spin_t
*bucket_lock
;
7729 if (!vm_page_buckets_check_ready
) {
7734 if (hibernate_rebuild_needed
||
7735 hibernate_rebuild_hash_list
) {
7736 panic("BUCKET_CHECK: hibernation in progress: "
7737 "rebuild_needed=%d rebuild_hash_list=%p\n",
7738 hibernate_rebuild_needed
,
7739 hibernate_rebuild_hash_list
);
7741 #endif /* HIBERNATION */
7743 #if VM_PAGE_FAKE_BUCKETS
7745 for (cp
= (char *) vm_page_fake_buckets_start
;
7746 cp
< (char *) vm_page_fake_buckets_end
;
7749 panic("BUCKET_CHECK: corruption at %p in fake buckets "
7750 "[0x%llx:0x%llx]\n",
7752 (uint64_t) vm_page_fake_buckets_start
,
7753 (uint64_t) vm_page_fake_buckets_end
);
7756 #endif /* VM_PAGE_FAKE_BUCKETS */
7758 for (i
= 0; i
< vm_page_bucket_count
; i
++) {
7759 vm_object_t p_object
;
7761 bucket
= &vm_page_buckets
[i
];
7762 if (!bucket
->page_list
) {
7766 bucket_lock
= &vm_page_bucket_locks
[i
/ BUCKETS_PER_LOCK
];
7767 lck_spin_lock(bucket_lock
);
7768 p
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(bucket
->page_list
));
7770 while (p
!= VM_PAGE_NULL
) {
7771 p_object
= VM_PAGE_OBJECT(p
);
7774 panic("BUCKET_CHECK: page %p (%p,0x%llx) "
7775 "hash %d in bucket %d at %p "
7777 p
, p_object
, p
->offset
,
7780 p_hash
= vm_page_hash(p_object
, p
->offset
);
7782 panic("BUCKET_CHECK: corruption in bucket %d "
7783 "at %p: page %p object %p offset 0x%llx "
7785 i
, bucket
, p
, p_object
, p
->offset
,
7788 p
= (vm_page_t
)(VM_PAGE_UNPACK_PTR(p
->next_m
));
7790 lck_spin_unlock(bucket_lock
);
7793 // printf("BUCKET_CHECK: checked buckets\n");
7795 #endif /* VM_PAGE_BUCKETS_CHECK */
7798 * 'vm_fault_enter' will place newly created pages (zero-fill and COW) onto the
7799 * local queues if they exist... its the only spot in the system where we add pages
7800 * to those queues... once on those queues, those pages can only move to one of the
7801 * global page queues or the free queues... they NEVER move from local q to local q.
7802 * the 'local' state is stable when vm_page_queues_remove is called since we're behind
7803 * the global vm_page_queue_lock at this point... we still need to take the local lock
7804 * in case this operation is being run on a different CPU then the local queue's identity,
7805 * but we don't have to worry about the page moving to a global queue or becoming wired
7806 * while we're grabbing the local lock since those operations would require the global
7807 * vm_page_queue_lock to be held, and we already own it.
7809 * this is why its safe to utilze the wire_count field in the vm_page_t as the local_id...
7810 * 'wired' and local are ALWAYS mutually exclusive conditions.
7813 #if CONFIG_BACKGROUND_QUEUE
7815 vm_page_queues_remove(vm_page_t mem
, boolean_t remove_from_backgroundq
)
7818 vm_page_queues_remove(vm_page_t mem
, boolean_t __unused remove_from_backgroundq
)
7821 boolean_t was_pageable
= TRUE
;
7822 vm_object_t m_object
;
7824 m_object
= VM_PAGE_OBJECT(mem
);
7826 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
7828 if (mem
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
)
7830 assert(mem
->pageq
.next
== 0 && mem
->pageq
.prev
== 0);
7831 #if CONFIG_BACKGROUND_QUEUE
7832 if (remove_from_backgroundq
== TRUE
) {
7833 vm_page_remove_from_backgroundq(mem
);
7835 if (mem
->vm_page_on_backgroundq
) {
7836 assert(mem
->vm_page_backgroundq
.next
!= 0);
7837 assert(mem
->vm_page_backgroundq
.prev
!= 0);
7839 assert(mem
->vm_page_backgroundq
.next
== 0);
7840 assert(mem
->vm_page_backgroundq
.prev
== 0);
7842 #endif /* CONFIG_BACKGROUND_QUEUE */
7846 if (mem
->vm_page_q_state
== VM_PAGE_USED_BY_COMPRESSOR
)
7848 assert(mem
->pageq
.next
== 0 && mem
->pageq
.prev
== 0);
7849 #if CONFIG_BACKGROUND_QUEUE
7850 assert(mem
->vm_page_backgroundq
.next
== 0 &&
7851 mem
->vm_page_backgroundq
.prev
== 0 &&
7852 mem
->vm_page_on_backgroundq
== FALSE
);
7856 if (mem
->vm_page_q_state
== VM_PAGE_IS_WIRED
) {
7858 * might put these guys on a list for debugging purposes
7859 * if we do, we'll need to remove this assert
7861 assert(mem
->pageq
.next
== 0 && mem
->pageq
.prev
== 0);
7862 #if CONFIG_BACKGROUND_QUEUE
7863 assert(mem
->vm_page_backgroundq
.next
== 0 &&
7864 mem
->vm_page_backgroundq
.prev
== 0 &&
7865 mem
->vm_page_on_backgroundq
== FALSE
);
7870 assert(m_object
!= compressor_object
);
7871 assert(m_object
!= kernel_object
);
7872 assert(m_object
!= vm_submap_object
);
7873 assert(!mem
->fictitious
);
7875 switch(mem
->vm_page_q_state
) {
7877 case VM_PAGE_ON_ACTIVE_LOCAL_Q
:
7881 lq
= &vm_page_local_q
[mem
->local_id
].vpl_un
.vpl
;
7882 VPL_LOCK(&lq
->vpl_lock
);
7883 vm_page_queue_remove(&lq
->vpl_queue
,
7884 mem
, vm_page_t
, pageq
);
7887 if (m_object
->internal
) {
7888 lq
->vpl_internal_count
--;
7890 lq
->vpl_external_count
--;
7892 VPL_UNLOCK(&lq
->vpl_lock
);
7893 was_pageable
= FALSE
;
7896 case VM_PAGE_ON_ACTIVE_Q
:
7898 vm_page_queue_remove(&vm_page_queue_active
,
7899 mem
, vm_page_t
, pageq
);
7900 vm_page_active_count
--;
7904 case VM_PAGE_ON_INACTIVE_INTERNAL_Q
:
7906 assert(m_object
->internal
== TRUE
);
7908 vm_page_inactive_count
--;
7909 vm_page_queue_remove(&vm_page_queue_anonymous
,
7910 mem
, vm_page_t
, pageq
);
7911 vm_page_anonymous_count
--;
7912 vm_purgeable_q_advance_all();
7916 case VM_PAGE_ON_INACTIVE_EXTERNAL_Q
:
7918 assert(m_object
->internal
== FALSE
);
7920 vm_page_inactive_count
--;
7921 vm_page_queue_remove(&vm_page_queue_inactive
,
7922 mem
, vm_page_t
, pageq
);
7923 vm_purgeable_q_advance_all();
7927 case VM_PAGE_ON_INACTIVE_CLEANED_Q
:
7929 assert(m_object
->internal
== FALSE
);
7931 vm_page_inactive_count
--;
7932 vm_page_queue_remove(&vm_page_queue_cleaned
,
7933 mem
, vm_page_t
, pageq
);
7934 vm_page_cleaned_count
--;
7938 case VM_PAGE_ON_THROTTLED_Q
:
7940 assert(m_object
->internal
== TRUE
);
7942 vm_page_queue_remove(&vm_page_queue_throttled
,
7943 mem
, vm_page_t
, pageq
);
7944 vm_page_throttled_count
--;
7945 was_pageable
= FALSE
;
7949 case VM_PAGE_ON_SPECULATIVE_Q
:
7951 assert(m_object
->internal
== FALSE
);
7953 vm_page_remque(&mem
->pageq
);
7954 vm_page_speculative_count
--;
7958 #if CONFIG_SECLUDED_MEMORY
7959 case VM_PAGE_ON_SECLUDED_Q
:
7961 vm_page_queue_remove(&vm_page_queue_secluded
,
7962 mem
, vm_page_t
, pageq
);
7963 vm_page_secluded_count
--;
7964 if (m_object
== VM_OBJECT_NULL
) {
7965 vm_page_secluded_count_free
--;
7966 was_pageable
= FALSE
;
7968 assert(!m_object
->internal
);
7969 vm_page_secluded_count_inuse
--;
7970 was_pageable
= FALSE
;
7971 // was_pageable = TRUE;
7975 #endif /* CONFIG_SECLUDED_MEMORY */
7980 * if (mem->vm_page_q_state == VM_PAGE_ON_PAGEOUT_Q)
7981 * NOTE: vm_page_queues_remove does not deal with removing pages from the pageout queue...
7982 * the caller is responsible for determing if the page is on that queue, and if so, must
7983 * either first remove it (it needs both the page queues lock and the object lock to do
7984 * this via vm_pageout_steal_laundry), or avoid the call to vm_page_queues_remove
7986 * we also don't expect to encounter VM_PAGE_ON_FREE_Q, VM_PAGE_ON_FREE_LOCAL_Q, VM_PAGE_ON_FREE_LOPAGE_Q
7987 * or any of the undefined states
7989 panic("vm_page_queues_remove - bad page q_state (%p, %d)\n", mem
, mem
->vm_page_q_state
);
7994 VM_PAGE_ZERO_PAGEQ_ENTRY(mem
);
7995 mem
->vm_page_q_state
= VM_PAGE_NOT_ON_Q
;
7997 #if CONFIG_BACKGROUND_QUEUE
7998 if (remove_from_backgroundq
== TRUE
)
7999 vm_page_remove_from_backgroundq(mem
);
8002 if (m_object
->internal
) {
8003 vm_page_pageable_internal_count
--;
8005 vm_page_pageable_external_count
--;
8011 vm_page_remove_internal(vm_page_t page
)
8013 vm_object_t __object
= VM_PAGE_OBJECT(page
);
8014 if (page
== __object
->memq_hint
) {
8015 vm_page_t __new_hint
;
8016 vm_page_queue_entry_t __qe
;
8017 __qe
= (vm_page_queue_entry_t
)vm_page_queue_next(&page
->listq
);
8018 if (vm_page_queue_end(&__object
->memq
, __qe
)) {
8019 __qe
= (vm_page_queue_entry_t
)vm_page_queue_prev(&page
->listq
);
8020 if (vm_page_queue_end(&__object
->memq
, __qe
)) {
8024 __new_hint
= (vm_page_t
)((uintptr_t) __qe
);
8025 __object
->memq_hint
= __new_hint
;
8027 vm_page_queue_remove(&__object
->memq
, page
, vm_page_t
, listq
);
8028 #if CONFIG_SECLUDED_MEMORY
8029 if (__object
->eligible_for_secluded
) {
8030 vm_page_secluded
.eligible_for_secluded
--;
8032 #endif /* CONFIG_SECLUDED_MEMORY */
8036 vm_page_enqueue_inactive(vm_page_t mem
, boolean_t first
)
8038 vm_object_t m_object
;
8040 m_object
= VM_PAGE_OBJECT(mem
);
8042 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
8043 assert(!mem
->fictitious
);
8044 assert(!mem
->laundry
);
8045 assert(mem
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
);
8046 vm_page_check_pageable_safe(mem
);
8048 if (m_object
->internal
) {
8049 mem
->vm_page_q_state
= VM_PAGE_ON_INACTIVE_INTERNAL_Q
;
8052 vm_page_queue_enter_first(&vm_page_queue_anonymous
, mem
, vm_page_t
, pageq
);
8054 vm_page_queue_enter(&vm_page_queue_anonymous
, mem
, vm_page_t
, pageq
);
8056 vm_page_anonymous_count
++;
8057 vm_page_pageable_internal_count
++;
8059 mem
->vm_page_q_state
= VM_PAGE_ON_INACTIVE_EXTERNAL_Q
;
8062 vm_page_queue_enter_first(&vm_page_queue_inactive
, mem
, vm_page_t
, pageq
);
8064 vm_page_queue_enter(&vm_page_queue_inactive
, mem
, vm_page_t
, pageq
);
8066 vm_page_pageable_external_count
++;
8068 vm_page_inactive_count
++;
8069 token_new_pagecount
++;
8071 #if CONFIG_BACKGROUND_QUEUE
8072 if (mem
->vm_page_in_background
)
8073 vm_page_add_to_backgroundq(mem
, FALSE
);
8078 vm_page_enqueue_active(vm_page_t mem
, boolean_t first
)
8080 vm_object_t m_object
;
8082 m_object
= VM_PAGE_OBJECT(mem
);
8084 LCK_MTX_ASSERT(&vm_page_queue_lock
, LCK_MTX_ASSERT_OWNED
);
8085 assert(!mem
->fictitious
);
8086 assert(!mem
->laundry
);
8087 assert(mem
->vm_page_q_state
== VM_PAGE_NOT_ON_Q
);
8088 vm_page_check_pageable_safe(mem
);
8090 mem
->vm_page_q_state
= VM_PAGE_ON_ACTIVE_Q
;
8092 vm_page_queue_enter_first(&vm_page_queue_active
, mem
, vm_page_t
, pageq
);
8094 vm_page_queue_enter(&vm_page_queue_active
, mem
, vm_page_t
, pageq
);
8095 vm_page_active_count
++;
8097 if (m_object
->internal
) {
8098 vm_page_pageable_internal_count
++;
8100 vm_page_pageable_external_count
++;
8103 #if CONFIG_BACKGROUND_QUEUE
8104 if (mem
->vm_page_in_background
)
8105 vm_page_add_to_backgroundq(mem
, FALSE
);
8110 * Pages from special kernel objects shouldn't
8111 * be placed on pageable queues.
8114 vm_page_check_pageable_safe(vm_page_t page
)
8116 vm_object_t page_object
;
8118 page_object
= VM_PAGE_OBJECT(page
);
8120 if (page_object
== kernel_object
) {
8121 panic("vm_page_check_pageable_safe: trying to add page" \
8122 "from kernel object (%p) to pageable queue", kernel_object
);
8125 if (page_object
== compressor_object
) {
8126 panic("vm_page_check_pageable_safe: trying to add page" \
8127 "from compressor object (%p) to pageable queue", compressor_object
);
8130 if (page_object
== vm_submap_object
) {
8131 panic("vm_page_check_pageable_safe: trying to add page" \
8132 "from submap object (%p) to pageable queue", vm_submap_object
);
8136 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8137 * wired page diagnose
8138 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
8140 #include <libkern/OSKextLibPrivate.h>
8142 #define KA_SIZE(namelen, subtotalscount) \
8143 (sizeof(struct vm_allocation_site) + (namelen) + 1 + ((subtotalscount) * sizeof(struct vm_allocation_total)))
8145 #define KA_NAME(alloc) \
8146 ((char *)(&(alloc)->subtotals[(alloc->subtotalscount)]))
8148 #define KA_NAME_LEN(alloc) \
8149 (VM_TAG_NAME_LEN_MAX & (alloc->flags >> VM_TAG_NAME_LEN_SHIFT))
8154 uintptr_t* frameptr
;
8155 uintptr_t* frameptr_next
;
8157 uintptr_t kstackb
, kstackt
;
8158 const vm_allocation_site_t
* site
;
8160 kern_allocation_name_t name
;
8162 cthread
= current_thread();
8163 if (__improbable(cthread
== NULL
)) return VM_KERN_MEMORY_OSFMK
;
8165 if ((name
= thread_get_kernel_state(cthread
)->allocation_name
))
8167 if (!name
->tag
) vm_tag_alloc(name
);
8171 kstackb
= cthread
->kernel_stack
;
8172 kstackt
= kstackb
+ kernel_stack_size
;
8174 /* Load stack frame pointer (EBP on x86) into frameptr */
8175 frameptr
= __builtin_frame_address(0);
8177 while (frameptr
!= NULL
)
8179 /* Verify thread stack bounds */
8180 if (((uintptr_t)(frameptr
+ 2) > kstackt
) || ((uintptr_t)frameptr
< kstackb
)) break;
8182 /* Next frame pointer is pointed to by the previous one */
8183 frameptr_next
= (uintptr_t*) *frameptr
;
8185 /* Pull return address from one spot above the frame pointer */
8186 retaddr
= *(frameptr
+ 1);
8189 if ((retaddr
< vm_kernel_stext
) || (retaddr
> vm_kernel_top
))
8191 site
= OSKextGetAllocationSiteForCaller(retaddr
);
8194 frameptr
= frameptr_next
;
8197 return (site
? site
->tag
: VM_KERN_MEMORY_NONE
);
8200 static uint64_t free_tag_bits
[VM_MAX_TAG_VALUE
/64];
8203 vm_tag_alloc_locked(vm_allocation_site_t
* site
, vm_allocation_site_t
** releasesiteP
)
8208 vm_allocation_site_t
* prev
;
8210 if (site
->tag
) return;
8215 avail
= free_tag_bits
[idx
];
8218 tag
= __builtin_clzll(avail
);
8219 avail
&= ~(1ULL << (63 - tag
));
8220 free_tag_bits
[idx
] = avail
;
8225 if (idx
>= ARRAY_COUNT(free_tag_bits
))
8227 for (idx
= 0; idx
< ARRAY_COUNT(vm_allocation_sites
); idx
++)
8229 prev
= vm_allocation_sites
[idx
];
8230 if (!prev
) continue;
8231 if (!KA_NAME_LEN(prev
)) continue;
8232 if (!prev
->tag
) continue;
8233 if (prev
->total
) continue;
8234 if (1 != prev
->refcount
) continue;
8236 assert(idx
== prev
->tag
);
8238 prev
->tag
= VM_KERN_MEMORY_NONE
;
8239 *releasesiteP
= prev
;
8242 if (idx
>= ARRAY_COUNT(vm_allocation_sites
))
8244 tag
= VM_KERN_MEMORY_ANY
;
8251 OSAddAtomic16(1, &site
->refcount
);
8253 if (VM_KERN_MEMORY_ANY
!= tag
) vm_allocation_sites
[tag
] = site
;
8255 if (tag
> vm_allocation_tag_highest
) vm_allocation_tag_highest
= tag
;
8259 vm_tag_free_locked(vm_tag_t tag
)
8265 if (VM_KERN_MEMORY_ANY
== tag
) return;
8268 avail
= free_tag_bits
[idx
];
8270 bit
= (1ULL << (63 - tag
));
8271 assert(!(avail
& bit
));
8272 free_tag_bits
[idx
] = (avail
| bit
);
8279 for (tag
= VM_KERN_MEMORY_FIRST_DYNAMIC
; tag
< VM_KERN_MEMORY_ANY
; tag
++)
8281 vm_tag_free_locked(tag
);
8284 for (tag
= VM_KERN_MEMORY_ANY
+ 1; tag
< VM_MAX_TAG_VALUE
; tag
++)
8286 vm_tag_free_locked(tag
);
8291 vm_tag_alloc(vm_allocation_site_t
* site
)
8294 vm_allocation_site_t
* releasesite
;
8296 if (VM_TAG_BT
& site
->flags
)
8299 if (VM_KERN_MEMORY_NONE
!= tag
) return (tag
);
8305 lck_spin_lock(&vm_allocation_sites_lock
);
8306 vm_tag_alloc_locked(site
, &releasesite
);
8307 lck_spin_unlock(&vm_allocation_sites_lock
);
8308 if (releasesite
) kern_allocation_name_release(releasesite
);
8315 vm_tag_update_size(vm_tag_t tag
, int64_t delta
)
8317 vm_allocation_site_t
* allocation
;
8320 assert(VM_KERN_MEMORY_NONE
!= tag
);
8321 assert(tag
< VM_MAX_TAG_VALUE
);
8323 allocation
= vm_allocation_sites
[tag
];
8327 assertf(allocation
->total
>= ((uint64_t)-delta
), "tag %d, site %p", tag
, allocation
);
8329 prior
= OSAddAtomic64(delta
, &allocation
->total
);
8331 #if DEBUG || DEVELOPMENT
8334 new = prior
+ delta
;
8337 peak
= allocation
->peak
;
8338 if (new <= peak
) break;
8340 while (!OSCompareAndSwap64(peak
, new, &allocation
->peak
));
8342 #endif /* DEBUG || DEVELOPMENT */
8344 if (tag
< VM_KERN_MEMORY_FIRST_DYNAMIC
) return;
8346 if (!prior
&& !allocation
->tag
) vm_tag_alloc(allocation
);
8350 kern_allocation_update_size(kern_allocation_name_t allocation
, int64_t delta
)
8355 assertf(allocation
->total
>= ((uint64_t)-delta
), "name %p", allocation
);
8357 prior
= OSAddAtomic64(delta
, &allocation
->total
);
8359 #if DEBUG || DEVELOPMENT
8362 new = prior
+ delta
;
8365 peak
= allocation
->peak
;
8366 if (new <= peak
) break;
8368 while (!OSCompareAndSwap64(peak
, new, &allocation
->peak
));
8370 #endif /* DEBUG || DEVELOPMENT */
8372 if (!prior
&& !allocation
->tag
) vm_tag_alloc(allocation
);
8375 #if VM_MAX_TAG_ZONES
8378 vm_allocation_zones_init(void)
8384 size
= VM_MAX_TAG_VALUE
* sizeof(vm_allocation_zone_total_t
**)
8385 + 2 * VM_MAX_TAG_ZONES
* sizeof(vm_allocation_zone_total_t
);
8387 ret
= kernel_memory_allocate(kernel_map
,
8388 &addr
, round_page(size
), 0,
8389 KMA_ZERO
, VM_KERN_MEMORY_DIAG
);
8390 assert(KERN_SUCCESS
== ret
);
8392 vm_allocation_zone_totals
= (vm_allocation_zone_total_t
**) addr
;
8393 addr
+= VM_MAX_TAG_VALUE
* sizeof(vm_allocation_zone_total_t
**);
8395 // prepopulate VM_KERN_MEMORY_DIAG & VM_KERN_MEMORY_KALLOC so allocations
8396 // in vm_tag_update_zone_size() won't recurse
8397 vm_allocation_zone_totals
[VM_KERN_MEMORY_DIAG
] = (vm_allocation_zone_total_t
*) addr
;
8398 addr
+= VM_MAX_TAG_ZONES
* sizeof(vm_allocation_zone_total_t
);
8399 vm_allocation_zone_totals
[VM_KERN_MEMORY_KALLOC
] = (vm_allocation_zone_total_t
*) addr
;
8403 vm_tag_will_update_zone(vm_tag_t tag
, uint32_t zidx
)
8405 vm_allocation_zone_total_t
* zone
;
8407 assert(VM_KERN_MEMORY_NONE
!= tag
);
8408 assert(tag
< VM_MAX_TAG_VALUE
);
8410 if (zidx
>= VM_MAX_TAG_ZONES
) return;
8412 zone
= vm_allocation_zone_totals
[tag
];
8415 zone
= kalloc_tag(VM_MAX_TAG_ZONES
* sizeof(*zone
), VM_KERN_MEMORY_DIAG
);
8417 bzero(zone
, VM_MAX_TAG_ZONES
* sizeof(*zone
));
8418 if (!OSCompareAndSwapPtr(NULL
, zone
, &vm_allocation_zone_totals
[tag
]))
8420 kfree(zone
, VM_MAX_TAG_ZONES
* sizeof(*zone
));
8426 vm_tag_update_zone_size(vm_tag_t tag
, uint32_t zidx
, int64_t delta
, int64_t dwaste
)
8428 vm_allocation_zone_total_t
* zone
;
8431 assert(VM_KERN_MEMORY_NONE
!= tag
);
8432 assert(tag
< VM_MAX_TAG_VALUE
);
8434 if (zidx
>= VM_MAX_TAG_ZONES
) return;
8436 zone
= vm_allocation_zone_totals
[tag
];
8440 /* the zone is locked */
8443 assertf(zone
->total
>= ((uint64_t)-delta
), "zidx %d, tag %d, %p", zidx
, tag
, zone
);
8444 zone
->total
+= delta
;
8448 zone
->total
+= delta
;
8449 if (zone
->total
> zone
->peak
) zone
->peak
= zone
->total
;
8453 if (zone
->wastediv
< 65536) zone
->wastediv
++;
8454 else new -= (new >> 16);
8455 __assert_only
bool ov
= os_add_overflow(new, dwaste
, &new);
8462 #endif /* VM_MAX_TAG_ZONES */
8465 kern_allocation_update_subtotal(kern_allocation_name_t allocation
, uint32_t subtag
, int64_t delta
)
8467 kern_allocation_name_t other
;
8468 struct vm_allocation_total
* total
;
8472 assert(VM_KERN_MEMORY_NONE
!= subtag
);
8473 for (; subidx
< allocation
->subtotalscount
; subidx
++)
8475 if (VM_KERN_MEMORY_NONE
== allocation
->subtotals
[subidx
].tag
)
8477 allocation
->subtotals
[subidx
].tag
= subtag
;
8480 if (subtag
== allocation
->subtotals
[subidx
].tag
) break;
8482 assert(subidx
< allocation
->subtotalscount
);
8483 if (subidx
>= allocation
->subtotalscount
) return;
8485 total
= &allocation
->subtotals
[subidx
];
8486 other
= vm_allocation_sites
[subtag
];
8491 assertf(total
->total
>= ((uint64_t)-delta
), "name %p", allocation
);
8492 OSAddAtomic64(delta
, &total
->total
);
8493 assertf(other
->mapped
>= ((uint64_t)-delta
), "other %p", other
);
8494 OSAddAtomic64(delta
, &other
->mapped
);
8498 OSAddAtomic64(delta
, &other
->mapped
);
8499 OSAddAtomic64(delta
, &total
->total
);
8504 kern_allocation_get_name(kern_allocation_name_t allocation
)
8506 return (KA_NAME(allocation
));
8509 kern_allocation_name_t
8510 kern_allocation_name_allocate(const char * name
, uint32_t subtotalscount
)
8514 namelen
= (uint32_t) strnlen(name
, MACH_MEMORY_INFO_NAME_MAX_LEN
- 1);
8516 kern_allocation_name_t allocation
;
8517 allocation
= kalloc(KA_SIZE(namelen
, subtotalscount
));
8518 bzero(allocation
, KA_SIZE(namelen
, subtotalscount
));
8520 allocation
->refcount
= 1;
8521 allocation
->subtotalscount
= subtotalscount
;
8522 allocation
->flags
= (namelen
<< VM_TAG_NAME_LEN_SHIFT
);
8523 strlcpy(KA_NAME(allocation
), name
, namelen
+ 1);
8525 return (allocation
);
8529 kern_allocation_name_release(kern_allocation_name_t allocation
)
8531 assert(allocation
->refcount
> 0);
8532 if (1 == OSAddAtomic16(-1, &allocation
->refcount
))
8534 kfree(allocation
, KA_SIZE(KA_NAME_LEN(allocation
), allocation
->subtotalscount
));
8539 kern_allocation_name_get_vm_tag(kern_allocation_name_t allocation
)
8541 return (vm_tag_alloc(allocation
));
8545 vm_page_count_object(mach_memory_info_t
* info
, unsigned int __unused num_info
, vm_object_t object
)
8547 if (!object
->wired_page_count
) return;
8548 if (object
!= kernel_object
)
8550 assert(object
->wire_tag
< num_info
);
8551 info
[object
->wire_tag
].size
+= ptoa_64(object
->wired_page_count
);
8555 typedef void (*vm_page_iterate_proc
)(mach_memory_info_t
* info
,
8556 unsigned int num_info
, vm_object_t object
);
8559 vm_page_iterate_purgeable_objects(mach_memory_info_t
* info
, unsigned int num_info
,
8560 vm_page_iterate_proc proc
, purgeable_q_t queue
,
8565 for (object
= (vm_object_t
) queue_first(&queue
->objq
[group
]);
8566 !queue_end(&queue
->objq
[group
], (queue_entry_t
) object
);
8567 object
= (vm_object_t
) queue_next(&object
->objq
))
8569 proc(info
, num_info
, object
);
8574 vm_page_iterate_objects(mach_memory_info_t
* info
, unsigned int num_info
,
8575 vm_page_iterate_proc proc
)
8577 purgeable_q_t volatile_q
;
8578 queue_head_t
* nonvolatile_q
;
8582 lck_spin_lock(&vm_objects_wired_lock
);
8583 queue_iterate(&vm_objects_wired
,
8588 proc(info
, num_info
, object
);
8590 lck_spin_unlock(&vm_objects_wired_lock
);
8592 lck_mtx_lock(&vm_purgeable_queue_lock
);
8593 nonvolatile_q
= &purgeable_nonvolatile_queue
;
8594 for (object
= (vm_object_t
) queue_first(nonvolatile_q
);
8595 !queue_end(nonvolatile_q
, (queue_entry_t
) object
);
8596 object
= (vm_object_t
) queue_next(&object
->objq
))
8598 proc(info
, num_info
, object
);
8601 volatile_q
= &purgeable_queues
[PURGEABLE_Q_TYPE_OBSOLETE
];
8602 vm_page_iterate_purgeable_objects(info
, num_info
, proc
, volatile_q
, 0);
8604 volatile_q
= &purgeable_queues
[PURGEABLE_Q_TYPE_FIFO
];
8605 for (group
= 0; group
< NUM_VOLATILE_GROUPS
; group
++)
8607 vm_page_iterate_purgeable_objects(info
, num_info
, proc
, volatile_q
, group
);
8610 volatile_q
= &purgeable_queues
[PURGEABLE_Q_TYPE_LIFO
];
8611 for (group
= 0; group
< NUM_VOLATILE_GROUPS
; group
++)
8613 vm_page_iterate_purgeable_objects(info
, num_info
, proc
, volatile_q
, group
);
8615 lck_mtx_unlock(&vm_purgeable_queue_lock
);
8619 process_account(mach_memory_info_t
* info
, unsigned int num_info
, uint64_t zones_collectable_bytes
, boolean_t iterated
)
8622 unsigned int idx
, count
, nextinfo
;
8623 vm_allocation_site_t
* site
;
8624 lck_spin_lock(&vm_allocation_sites_lock
);
8626 for (idx
= 0; idx
<= vm_allocation_tag_highest
; idx
++)
8628 site
= vm_allocation_sites
[idx
];
8629 if (!site
) continue;
8630 info
[idx
].mapped
= site
->mapped
;
8631 info
[idx
].tag
= site
->tag
;
8634 info
[idx
].size
= site
->total
;
8635 #if DEBUG || DEVELOPMENT
8636 info
[idx
].peak
= site
->peak
;
8637 #endif /* DEBUG || DEVELOPMENT */
8641 if (!site
->subtotalscount
&& (site
->total
!= info
[idx
].size
))
8643 printf("tag mismatch[%d] 0x%qx, iter 0x%qx\n", idx
, site
->total
, info
[idx
].size
);
8644 info
[idx
].size
= site
->total
;
8649 nextinfo
= (vm_allocation_tag_highest
+ 1);
8651 if (count
>= num_info
) count
= num_info
;
8653 for (idx
= 0; idx
< count
; idx
++)
8655 site
= vm_allocation_sites
[idx
];
8656 if (!site
) continue;
8657 info
[idx
].flags
|= VM_KERN_SITE_WIRED
;
8658 if (idx
< VM_KERN_MEMORY_FIRST_DYNAMIC
)
8660 info
[idx
].site
= idx
;
8661 info
[idx
].flags
|= VM_KERN_SITE_TAG
;
8662 if (VM_KERN_MEMORY_ZONE
== idx
)
8664 info
[idx
].flags
|= VM_KERN_SITE_HIDE
;
8665 info
[idx
].flags
&= ~VM_KERN_SITE_WIRED
;
8666 info
[idx
].collectable_bytes
= zones_collectable_bytes
;
8669 else if ((namelen
= (VM_TAG_NAME_LEN_MAX
& (site
->flags
>> VM_TAG_NAME_LEN_SHIFT
))))
8672 info
[idx
].flags
|= VM_KERN_SITE_NAMED
;
8673 if (namelen
> sizeof(info
[idx
].name
)) namelen
= sizeof(info
[idx
].name
);
8674 strncpy(&info
[idx
].name
[0], KA_NAME(site
), namelen
);
8676 else if (VM_TAG_KMOD
& site
->flags
)
8678 info
[idx
].site
= OSKextGetKmodIDForSite(site
, NULL
, 0);
8679 info
[idx
].flags
|= VM_KERN_SITE_KMOD
;
8683 info
[idx
].site
= VM_KERNEL_UNSLIDE(site
);
8684 info
[idx
].flags
|= VM_KERN_SITE_KERNEL
;
8686 #if VM_MAX_TAG_ZONES
8687 vm_allocation_zone_total_t
* zone
;
8689 vm_size_t elem_size
;
8691 if (vm_allocation_zone_totals
8692 && (zone
= vm_allocation_zone_totals
[idx
])
8693 && (nextinfo
< num_info
))
8695 for (zidx
= 0; zidx
< VM_MAX_TAG_ZONES
; zidx
++)
8697 if (!zone
[zidx
].peak
) continue;
8698 info
[nextinfo
] = info
[idx
];
8699 info
[nextinfo
].zone
= zone_index_from_tag_index(zidx
, &elem_size
);
8700 info
[nextinfo
].flags
&= ~VM_KERN_SITE_WIRED
;
8701 info
[nextinfo
].flags
|= VM_KERN_SITE_ZONE
;
8702 info
[nextinfo
].size
= zone
[zidx
].total
;
8703 info
[nextinfo
].peak
= zone
[zidx
].peak
;
8704 info
[nextinfo
].mapped
= 0;
8705 if (zone
[zidx
].wastediv
)
8707 info
[nextinfo
].collectable_bytes
= ((zone
[zidx
].waste
* zone
[zidx
].total
/ elem_size
) / zone
[zidx
].wastediv
);
8712 #endif /* VM_MAX_TAG_ZONES */
8713 if (site
->subtotalscount
)
8715 uint64_t mapped
, mapcost
, take
;
8719 info
[idx
].size
= site
->total
;
8720 mapped
= info
[idx
].size
;
8721 info
[idx
].mapped
= mapped
;
8723 for (sub
= 0; sub
< site
->subtotalscount
; sub
++)
8725 alloctag
= site
->subtotals
[sub
].tag
;
8726 assert(alloctag
< num_info
);
8727 if (info
[alloctag
].name
[0]) continue;
8728 take
= info
[alloctag
].mapped
;
8729 if (take
> info
[alloctag
].size
) take
= info
[alloctag
].size
;
8730 if (take
> mapped
) take
= mapped
;
8731 info
[alloctag
].mapped
-= take
;
8732 info
[alloctag
].size
-= take
;
8736 info
[idx
].size
= mapcost
;
8739 lck_spin_unlock(&vm_allocation_sites_lock
);
8745 vm_page_diagnose_estimate(void)
8747 vm_allocation_site_t
* site
;
8751 lck_spin_lock(&vm_allocation_sites_lock
);
8752 for (count
= idx
= 0; idx
< VM_MAX_TAG_VALUE
; idx
++)
8754 site
= vm_allocation_sites
[idx
];
8755 if (!site
) continue;
8757 #if VM_MAX_TAG_ZONES
8758 if (vm_allocation_zone_totals
)
8760 vm_allocation_zone_total_t
* zone
;
8761 zone
= vm_allocation_zone_totals
[idx
];
8762 if (!zone
) continue;
8763 for (uint32_t zidx
= 0; zidx
< VM_MAX_TAG_ZONES
; zidx
++) if (zone
[zidx
].peak
) count
++;
8767 lck_spin_unlock(&vm_allocation_sites_lock
);
8769 /* some slop for new tags created */
8771 count
+= VM_KERN_COUNTER_COUNT
;
8778 vm_page_diagnose(mach_memory_info_t
* info
, unsigned int num_info
, uint64_t zones_collectable_bytes
)
8780 uint64_t wired_size
;
8781 uint64_t wired_managed_size
;
8782 uint64_t wired_reserved_size
;
8783 uint64_t booter_size
;
8785 mach_memory_info_t
* counts
;
8787 bzero(info
, num_info
* sizeof(mach_memory_info_t
));
8789 if (!vm_page_wire_count_initial
) return (KERN_ABORTED
);
8792 wired_size
= ptoa_64(vm_page_wire_count
);
8793 wired_reserved_size
= ptoa_64(vm_page_wire_count_initial
- vm_page_stolen_count
);
8795 wired_size
= ptoa_64(vm_page_wire_count
+ vm_lopage_free_count
+ vm_page_throttled_count
);
8796 wired_reserved_size
= ptoa_64(vm_page_wire_count_initial
- vm_page_stolen_count
+ vm_page_throttled_count
);
8798 wired_managed_size
= ptoa_64(vm_page_wire_count
- vm_page_wire_count_initial
);
8800 booter_size
= ml_get_booter_memory_size();
8801 wired_size
+= booter_size
;
8803 assert(num_info
>= VM_KERN_COUNTER_COUNT
);
8804 num_info
-= VM_KERN_COUNTER_COUNT
;
8805 counts
= &info
[num_info
];
8807 #define SET_COUNT(xcount, xsize, xflags) \
8808 counts[xcount].tag = VM_MAX_TAG_VALUE + xcount; \
8809 counts[xcount].site = (xcount); \
8810 counts[xcount].size = (xsize); \
8811 counts[xcount].mapped = (xsize); \
8812 counts[xcount].flags = VM_KERN_SITE_COUNTER | xflags;
8814 SET_COUNT(VM_KERN_COUNT_MANAGED
, ptoa_64(vm_page_pages
), 0);
8815 SET_COUNT(VM_KERN_COUNT_WIRED
, wired_size
, 0);
8816 SET_COUNT(VM_KERN_COUNT_WIRED_MANAGED
, wired_managed_size
, 0);
8817 SET_COUNT(VM_KERN_COUNT_RESERVED
, wired_reserved_size
, VM_KERN_SITE_WIRED
);
8818 SET_COUNT(VM_KERN_COUNT_STOLEN
, ptoa_64(vm_page_stolen_count
), VM_KERN_SITE_WIRED
);
8819 SET_COUNT(VM_KERN_COUNT_LOPAGE
, ptoa_64(vm_lopage_free_count
), VM_KERN_SITE_WIRED
);
8820 SET_COUNT(VM_KERN_COUNT_WIRED_BOOT
, ptoa_64(vm_page_wire_count_on_boot
), 0);
8821 SET_COUNT(VM_KERN_COUNT_BOOT_STOLEN
, booter_size
, VM_KERN_SITE_WIRED
);
8823 #define SET_MAP(xcount, xsize, xfree, xlargest) \
8824 counts[xcount].site = (xcount); \
8825 counts[xcount].size = (xsize); \
8826 counts[xcount].mapped = (xsize); \
8827 counts[xcount].free = (xfree); \
8828 counts[xcount].largest = (xlargest); \
8829 counts[xcount].flags = VM_KERN_SITE_COUNTER;
8831 vm_map_size_t map_size
, map_free
, map_largest
;
8833 vm_map_sizes(kernel_map
, &map_size
, &map_free
, &map_largest
);
8834 SET_MAP(VM_KERN_COUNT_MAP_KERNEL
, map_size
, map_free
, map_largest
);
8836 vm_map_sizes(zone_map
, &map_size
, &map_free
, &map_largest
);
8837 SET_MAP(VM_KERN_COUNT_MAP_ZONE
, map_size
, map_free
, map_largest
);
8839 vm_map_sizes(kalloc_map
, &map_size
, &map_free
, &map_largest
);
8840 SET_MAP(VM_KERN_COUNT_MAP_KALLOC
, map_size
, map_free
, map_largest
);
8842 iterate
= !VM_TAG_ACTIVE_UPDATE
;
8845 enum { kMaxKernelDepth
= 1 };
8846 vm_map_t maps
[kMaxKernelDepth
];
8847 vm_map_entry_t entries
[kMaxKernelDepth
];
8849 vm_map_entry_t entry
;
8850 vm_object_offset_t offset
;
8852 int stackIdx
, count
;
8854 vm_page_iterate_objects(info
, num_info
, &vm_page_count_object
);
8861 for (entry
= map
->hdr
.links
.next
; map
; entry
= entry
->links
.next
)
8863 if (entry
->is_sub_map
)
8865 assert(stackIdx
< kMaxKernelDepth
);
8866 maps
[stackIdx
] = map
;
8867 entries
[stackIdx
] = entry
;
8869 map
= VME_SUBMAP(entry
);
8873 if (VME_OBJECT(entry
) == kernel_object
)
8876 vm_object_lock(VME_OBJECT(entry
));
8877 for (offset
= entry
->links
.start
; offset
< entry
->links
.end
; offset
+= page_size
)
8879 page
= vm_page_lookup(VME_OBJECT(entry
), offset
);
8880 if (page
&& VM_PAGE_WIRED(page
)) count
++;
8882 vm_object_unlock(VME_OBJECT(entry
));
8886 assert(VME_ALIAS(entry
) != VM_KERN_MEMORY_NONE
);
8887 assert(VME_ALIAS(entry
) < num_info
);
8888 info
[VME_ALIAS(entry
)].size
+= ptoa_64(count
);
8891 while (map
&& (entry
== vm_map_last_entry(map
)))
8894 if (!stackIdx
) map
= NULL
;
8898 map
= maps
[stackIdx
];
8899 entry
= entries
[stackIdx
];
8906 process_account(info
, num_info
, zones_collectable_bytes
, iterate
);
8908 return (KERN_SUCCESS
);
8911 #if DEBUG || DEVELOPMENT
8914 vm_kern_allocation_info(uintptr_t addr
, vm_size_t
* size
, vm_tag_t
* tag
, vm_size_t
* zone_size
)
8919 vm_map_entry_t entry
;
8921 zsize
= zone_element_info((void *) addr
, tag
);
8924 *zone_size
= *size
= zsize
;
8925 return (KERN_SUCCESS
);
8929 ret
= KERN_INVALID_ADDRESS
;
8930 for (map
= kernel_map
; map
; )
8933 if (!vm_map_lookup_entry(map
, addr
, &entry
)) break;
8934 if (entry
->is_sub_map
)
8936 if (map
!= kernel_map
) break;
8937 map
= VME_SUBMAP(entry
);
8940 if (entry
->vme_start
!= addr
) break;
8941 *tag
= VME_ALIAS(entry
);
8942 *size
= (entry
->vme_end
- addr
);
8946 if (map
!= kernel_map
) vm_map_unlock(map
);
8947 vm_map_unlock(kernel_map
);
8952 #endif /* DEBUG || DEVELOPMENT */
8955 vm_tag_get_kext(vm_tag_t tag
, char * name
, vm_size_t namelen
)
8957 vm_allocation_site_t
* site
;
8961 lck_spin_lock(&vm_allocation_sites_lock
);
8962 if ((site
= vm_allocation_sites
[tag
]))
8964 if (VM_TAG_KMOD
& site
->flags
)
8966 kmodId
= OSKextGetKmodIDForSite(site
, name
, namelen
);
8969 lck_spin_unlock(&vm_allocation_sites_lock
);