2 * Copyright (c) 2000-2020 Apple Computer, 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 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
63 * Resident memory system definitions.
66 #ifndef _VM_VM_PAGE_H_
67 #define _VM_VM_PAGE_H_
70 #include <vm/vm_options.h>
71 #include <vm/vm_protos.h>
72 #include <mach/boolean.h>
73 #include <mach/vm_prot.h>
74 #include <mach/vm_param.h>
75 #include <mach/memory_object_types.h> /* for VMP_CS_BITS... */
81 * in order to make the size of a vm_page_t 64 bytes (cache line size for both arm64 and x86_64)
82 * we'll keep the next_m pointer packed... as long as the kernel virtual space where we allocate
83 * vm_page_t's from doesn't span more then 256 Gbytes, we're safe. There are live tests in the
84 * vm_page_t array allocation and the zone init code to determine if we can safely pack and unpack
85 * pointers from the 2 ends of these spaces
87 typedef uint32_t vm_page_packed_t
;
89 struct vm_page_packed_queue_entry
{
90 vm_page_packed_t next
; /* next element */
91 vm_page_packed_t prev
; /* previous element */
94 typedef struct vm_page_packed_queue_entry
*vm_page_queue_t
;
95 typedef struct vm_page_packed_queue_entry vm_page_queue_head_t
;
96 typedef struct vm_page_packed_queue_entry vm_page_queue_chain_t
;
97 typedef struct vm_page_packed_queue_entry
*vm_page_queue_entry_t
;
99 typedef vm_page_packed_t vm_page_object_t
;
104 * we can't do the packing trick on 32 bit architectures
105 * so just turn the macros into noops.
107 typedef struct vm_page
*vm_page_packed_t
;
109 #define vm_page_queue_t queue_t
110 #define vm_page_queue_head_t queue_head_t
111 #define vm_page_queue_chain_t queue_chain_t
112 #define vm_page_queue_entry_t queue_entry_t
114 #define vm_page_object_t vm_object_t
118 #include <vm/vm_object.h>
119 #include <kern/queue.h>
120 #include <kern/locks.h>
122 #include <kern/macro_help.h>
123 #include <libkern/OSAtomic.h>
127 #define VM_PAGE_COMPRESSOR_COUNT (compressor_object->resident_page_count)
130 * Management of resident (logical) pages.
132 * A small structure is kept for each resident
133 * page, indexed by page number. Each structure
134 * is an element of several lists:
136 * A hash table bucket used to quickly
137 * perform object/offset lookups
139 * A list of all pages for a given object,
140 * so they can be quickly deactivated at
141 * time of deallocation.
143 * An ordered list of pages due for pageout.
145 * In addition, the structure contains the object
146 * and offset to which this page belongs (for pageout),
147 * and sundry status bits.
149 * Fields in this structure are locked either by the lock on the
150 * object that the page belongs to (O) or by the lock on the page
151 * queues (P). [Some fields require that both locks be held to
152 * change that field; holding either lock is sufficient to read.]
155 #define VM_PAGE_NULL ((vm_page_t) 0)
157 extern char vm_page_inactive_states
[];
158 extern char vm_page_pageable_states
[];
159 extern char vm_page_non_speculative_pageable_states
[];
160 extern char vm_page_active_or_inactive_states
[];
163 #define VM_PAGE_INACTIVE(m) (vm_page_inactive_states[m->vmp_q_state])
164 #define VM_PAGE_PAGEABLE(m) (vm_page_pageable_states[m->vmp_q_state])
165 #define VM_PAGE_NON_SPECULATIVE_PAGEABLE(m) (vm_page_non_speculative_pageable_states[m->vmp_q_state])
166 #define VM_PAGE_ACTIVE_OR_INACTIVE(m) (vm_page_active_or_inactive_states[m->vmp_q_state])
169 #define VM_PAGE_NOT_ON_Q 0 /* page is not present on any queue, nor is it wired... mainly a transient state */
170 #define VM_PAGE_IS_WIRED 1 /* page is currently wired */
171 #define VM_PAGE_USED_BY_COMPRESSOR 2 /* page is in use by the compressor to hold compressed data */
172 #define VM_PAGE_ON_FREE_Q 3 /* page is on the main free queue */
173 #define VM_PAGE_ON_FREE_LOCAL_Q 4 /* page is on one of the per-CPU free queues */
174 #define VM_PAGE_ON_FREE_LOPAGE_Q 5 /* page is on the lopage pool free list */
175 #define VM_PAGE_ON_THROTTLED_Q 6 /* page is on the throttled queue... we stash anonymous pages here when not paging */
176 #define VM_PAGE_ON_PAGEOUT_Q 7 /* page is on one of the pageout queues (internal/external) awaiting processing */
177 #define VM_PAGE_ON_SPECULATIVE_Q 8 /* page is on one of the speculative queues */
178 #define VM_PAGE_ON_ACTIVE_LOCAL_Q 9 /* page has recently been created and is being held in one of the per-CPU local queues */
179 #define VM_PAGE_ON_ACTIVE_Q 10 /* page is in global active queue */
180 #define VM_PAGE_ON_INACTIVE_INTERNAL_Q 11 /* page is on the inactive internal queue a.k.a. anonymous queue */
181 #define VM_PAGE_ON_INACTIVE_EXTERNAL_Q 12 /* page in on the inactive external queue a.k.a. file backed queue */
182 #define VM_PAGE_ON_INACTIVE_CLEANED_Q 13 /* page has been cleaned to a backing file and is ready to be stolen */
183 #define VM_PAGE_ON_SECLUDED_Q 14 /* page is on secluded queue */
184 #define VM_PAGE_Q_STATE_LAST_VALID_VALUE 14 /* we currently use 4 bits for the state... don't let this go beyond 15 */
186 #define VM_PAGE_Q_STATE_ARRAY_SIZE (VM_PAGE_Q_STATE_LAST_VALID_VALUE+1)
190 * The structure itself. See the block comment above for what (O) and (P) mean.
192 #define vmp_pageq vmp_q_un.vmp_q_pageq
193 #define vmp_snext vmp_q_un.vmp_q_snext
197 vm_page_queue_chain_t vmp_q_pageq
; /* queue info for FIFO queue or free list (P) */
198 struct vm_page
*vmp_q_snext
;
201 vm_page_queue_chain_t vmp_listq
; /* all pages in same object (O) */
203 #if CONFIG_BACKGROUND_QUEUE
204 vm_page_queue_chain_t vmp_backgroundq
; /* anonymous pages in the background pool (P) */
207 vm_object_offset_t vmp_offset
; /* offset into that object (O,P) */
208 vm_page_object_t vmp_object
; /* which object am I in (O&P) */
211 * The following word of flags is always protected by the "page queues" lock.
213 * We use 'vmp_wire_count' to store the local queue id if local queues are enabled.
214 * See the comments at 'vm_page_queues_remove' as to why this is safe to do.
216 #define vmp_local_id vmp_wire_count
217 unsigned int vmp_wire_count
:16, /* how many wired down maps use me? (O&P) */
218 vmp_q_state
:4, /* which q is the page on (P) */
220 vmp_on_backgroundq
:1,
221 vmp_gobbled
:1, /* page used internally (P) */
222 vmp_laundry
:1, /* page is being cleaned now (P)*/
223 vmp_no_cache
:1, /* page is not to be cached and should */
224 /* be reused ahead of other pages (P) */
225 vmp_private
:1, /* Page should not be returned to the free list (P) */
226 vmp_reference
:1, /* page has been used (P) */
228 vmp_unused_page_bits
:4;
231 * MUST keep the 2 32 bit words used as bit fields
232 * separated since the compiler has a nasty habit
233 * of using 64 bit loads and stores on them as
234 * if they were a single 64 bit field... since
235 * they are protected by 2 different locks, this
238 vm_page_packed_t vmp_next_m
; /* VP bucket link (O) */
241 * The following word of flags is protected by the "VM object" lock.
243 * IMPORTANT: the "vmp_pmapped", "vmp_xpmapped" and "vmp_clustered" bits can be modified while holding the
244 * VM object "shared" lock + the page lock provided through the pmap_lock_phys_page function.
245 * This is done in vm_fault_enter() and the CONSUME_CLUSTERED macro.
246 * It's also ok to modify them behind just the VM object "exclusive" lock.
248 unsigned int vmp_busy
:1, /* page is in transit (O) */
249 vmp_wanted
:1, /* someone is waiting for page (O) */
250 vmp_tabled
:1, /* page is in VP table (O) */
251 vmp_hashed
:1, /* page is in vm_page_buckets[] (O) + the bucket lock */
252 vmp_fictitious
:1, /* Physical page doesn't exist (O) */
253 vmp_clustered
:1, /* page is not the faulted page (O) or (O-shared AND pmap_page) */
254 vmp_pmapped
:1, /* page has at some time been entered into a pmap (O) or */
255 /* (O-shared AND pmap_page) */
256 vmp_xpmapped
:1, /* page has been entered with execute permission (O) or */
257 /* (O-shared AND pmap_page) */
258 vmp_wpmapped
:1, /* page has been entered at some point into a pmap for write (O) */
259 vmp_free_when_done
:1, /* page is to be freed once cleaning is completed (O) */
260 vmp_absent
:1, /* Data has been requested, but is not yet available (O) */
261 vmp_error
:1, /* Data manager was unable to provide data due to error (O) */
262 vmp_dirty
:1, /* Page must be cleaned (O) */
263 vmp_cleaning
:1, /* Page clean has begun (O) */
264 vmp_precious
:1, /* Page is precious; data must be returned even if clean (O) */
265 vmp_overwriting
:1, /* Request to unlock has been made without having data. (O) */
266 /* [See vm_fault_page_overwrite] */
267 vmp_restart
:1, /* Page was pushed higher in shadow chain by copy_call-related pagers */
268 /* start again at top of chain */
269 vmp_unusual
:1, /* Page is absent, error, restart or page locked */
270 vmp_cs_validated
:VMP_CS_BITS
, /* code-signing: page was checked */
271 vmp_cs_tainted
:VMP_CS_BITS
, /* code-signing: page is tainted */
272 vmp_cs_nx
:VMP_CS_BITS
, /* code-signing: page is nx */
274 vmp_written_by_kernel
:1; /* page was written by kernel (i.e. decompressed) */
276 #if !defined(__arm__) && !defined(__arm64__)
277 ppnum_t vmp_phys_page
; /* Physical page number of the page */
281 typedef struct vm_page
*vm_page_t
;
282 extern vm_page_t vm_pages
;
283 extern vm_page_t vm_page_array_beginning_addr
;
284 extern vm_page_t vm_page_array_ending_addr
;
288 vm_map_offset_t fault_phys_offset
)
290 assertf(fault_phys_offset
< PAGE_SIZE
&&
291 !(fault_phys_offset
& FOURK_PAGE_MASK
),
292 "offset 0x%llx\n", (uint64_t)fault_phys_offset
);
293 return 1 << (fault_phys_offset
>> FOURK_PAGE_SHIFT
);
298 vm_map_size_t fault_page_size
,
299 vm_map_offset_t fault_phys_offset
)
301 assertf(fault_page_size
<= PAGE_SIZE
,
302 "fault_page_size 0x%llx fault_phys_offset 0x%llx\n",
303 (uint64_t)fault_page_size
, (uint64_t)fault_phys_offset
);
304 if (fault_page_size
== PAGE_SIZE
) {
305 return p
->vmp_cs_validated
== VMP_CS_ALL_TRUE
;
307 return p
->vmp_cs_validated
& VMP_CS_FOR_OFFSET(fault_phys_offset
);
312 vm_map_size_t fault_page_size
,
313 vm_map_offset_t fault_phys_offset
)
315 assertf(fault_page_size
<= PAGE_SIZE
,
316 "fault_page_size 0x%llx fault_phys_offset 0x%llx\n",
317 (uint64_t)fault_page_size
, (uint64_t)fault_phys_offset
);
318 if (fault_page_size
== PAGE_SIZE
) {
319 return p
->vmp_cs_tainted
!= VMP_CS_ALL_FALSE
;
321 return p
->vmp_cs_tainted
& VMP_CS_FOR_OFFSET(fault_phys_offset
);
326 vm_map_size_t fault_page_size
,
327 vm_map_offset_t fault_phys_offset
)
329 assertf(fault_page_size
<= PAGE_SIZE
,
330 "fault_page_size 0x%llx fault_phys_offset 0x%llx\n",
331 (uint64_t)fault_page_size
, (uint64_t)fault_phys_offset
);
332 if (fault_page_size
== PAGE_SIZE
) {
333 return p
->vmp_cs_nx
!= VMP_CS_ALL_FALSE
;
335 return p
->vmp_cs_nx
& VMP_CS_FOR_OFFSET(fault_phys_offset
);
338 VMP_CS_SET_VALIDATED(
340 vm_map_size_t fault_page_size
,
341 vm_map_offset_t fault_phys_offset
,
344 assertf(fault_page_size
<= PAGE_SIZE
,
345 "fault_page_size 0x%llx fault_phys_offset 0x%llx\n",
346 (uint64_t)fault_page_size
, (uint64_t)fault_phys_offset
);
348 if (fault_page_size
== PAGE_SIZE
) {
349 p
->vmp_cs_validated
= VMP_CS_ALL_TRUE
;
351 p
->vmp_cs_validated
|= VMP_CS_FOR_OFFSET(fault_phys_offset
);
353 if (fault_page_size
== PAGE_SIZE
) {
354 p
->vmp_cs_validated
= VMP_CS_ALL_FALSE
;
356 p
->vmp_cs_validated
&= ~VMP_CS_FOR_OFFSET(fault_phys_offset
);
362 vm_map_size_t fault_page_size
,
363 vm_map_offset_t fault_phys_offset
,
366 assertf(fault_page_size
<= PAGE_SIZE
,
367 "fault_page_size 0x%llx fault_phys_offset 0x%llx\n",
368 (uint64_t)fault_page_size
, (uint64_t)fault_phys_offset
);
370 if (fault_page_size
== PAGE_SIZE
) {
371 p
->vmp_cs_tainted
= VMP_CS_ALL_TRUE
;
373 p
->vmp_cs_tainted
|= VMP_CS_FOR_OFFSET(fault_phys_offset
);
375 if (fault_page_size
== PAGE_SIZE
) {
376 p
->vmp_cs_tainted
= VMP_CS_ALL_FALSE
;
378 p
->vmp_cs_tainted
&= ~VMP_CS_FOR_OFFSET(fault_phys_offset
);
384 vm_map_size_t fault_page_size
,
385 vm_map_offset_t fault_phys_offset
,
388 assertf(fault_page_size
<= PAGE_SIZE
,
389 "fault_page_size 0x%llx fault_phys_offset 0x%llx\n",
390 (uint64_t)fault_page_size
, (uint64_t)fault_phys_offset
);
392 if (fault_page_size
== PAGE_SIZE
) {
393 p
->vmp_cs_nx
= VMP_CS_ALL_TRUE
;
395 p
->vmp_cs_nx
|= VMP_CS_FOR_OFFSET(fault_phys_offset
);
397 if (fault_page_size
== PAGE_SIZE
) {
398 p
->vmp_cs_nx
= VMP_CS_ALL_FALSE
;
400 p
->vmp_cs_nx
&= ~VMP_CS_FOR_OFFSET(fault_phys_offset
);
405 #if defined(__arm__) || defined(__arm64__)
407 extern unsigned int vm_first_phys_ppnum
;
409 struct vm_page_with_ppnum
{
410 struct vm_page vm_page_wo_ppnum
;
412 ppnum_t vmp_phys_page
;
414 typedef struct vm_page_with_ppnum
*vm_page_with_ppnum_t
;
417 static inline ppnum_t
418 VM_PAGE_GET_PHYS_PAGE(vm_page_t m
)
420 if (m
>= vm_page_array_beginning_addr
&& m
< vm_page_array_ending_addr
) {
421 return (ppnum_t
)((uintptr_t)(m
- vm_page_array_beginning_addr
) + vm_first_phys_ppnum
);
423 return ((vm_page_with_ppnum_t
)m
)->vmp_phys_page
;
427 #define VM_PAGE_SET_PHYS_PAGE(m, ppnum) \
429 if ((m) < vm_page_array_beginning_addr || (m) >= vm_page_array_ending_addr) \
430 ((vm_page_with_ppnum_t)(m))->vmp_phys_page = ppnum; \
431 assert(ppnum == VM_PAGE_GET_PHYS_PAGE(m)); \
434 #define VM_PAGE_GET_COLOR(m) (VM_PAGE_GET_PHYS_PAGE(m) & vm_color_mask)
436 #else /* defined(__arm__) || defined(__arm64__) */
439 struct vm_page_with_ppnum
{
440 struct vm_page vm_page_with_ppnum
;
442 typedef struct vm_page_with_ppnum
*vm_page_with_ppnum_t
;
445 #define VM_PAGE_GET_PHYS_PAGE(page) (page)->vmp_phys_page
446 #define VM_PAGE_SET_PHYS_PAGE(page, ppnum) \
448 (page)->vmp_phys_page = ppnum; \
451 #define VM_PAGE_GET_CLUMP(m) ((VM_PAGE_GET_PHYS_PAGE(m)) >> vm_clump_shift)
452 #define VM_PAGE_GET_COLOR(m) ((VM_PAGE_GET_CLUMP(m)) & vm_color_mask)
454 #endif /* defined(__arm__) || defined(__arm64__) */
458 #if defined(__LP64__)
460 * Parameters for pointer packing
463 * VM Pages pointers might point to:
465 * 1. VM_PAGE_PACKED_ALIGNED aligned kernel globals,
467 * 2. VM_PAGE_PACKED_ALIGNED aligned heap allocated vm pages
469 * 3. entries in the vm_pages array (whose entries aren't VM_PAGE_PACKED_ALIGNED
473 * The current scheme uses 31 bits of storage and 6 bits of shift using the
474 * VM_PACK_POINTER() scheme for (1-2), and packs (3) as an index within the
475 * vm_pages array, setting the top bit (VM_PAGE_PACKED_FROM_ARRAY).
477 * This scheme gives us a reach of 128G from VM_MIN_KERNEL_AND_KEXT_ADDRESS.
479 #define VM_VPLQ_ALIGNMENT 128
480 #define VM_PAGE_PACKED_PTR_ALIGNMENT 64 /* must be a power of 2 */
481 #define VM_PAGE_PACKED_ALIGNED __attribute__((aligned(VM_PAGE_PACKED_PTR_ALIGNMENT)))
482 #define VM_PAGE_PACKED_PTR_BITS 31
483 #define VM_PAGE_PACKED_PTR_SHIFT 6
484 #define VM_PAGE_PACKED_PTR_BASE ((uintptr_t)VM_MIN_KERNEL_AND_KEXT_ADDRESS)
486 #define VM_PAGE_PACKED_FROM_ARRAY 0x80000000
488 static inline vm_page_packed_t
489 vm_page_pack_ptr(uintptr_t p
)
491 if (p
>= (uintptr_t)vm_page_array_beginning_addr
&&
492 p
< (uintptr_t)vm_page_array_ending_addr
) {
493 ptrdiff_t diff
= (vm_page_t
)p
- vm_page_array_beginning_addr
;
494 assert((vm_page_t
)p
== &vm_pages
[diff
]);
495 return (vm_page_packed_t
)(diff
| VM_PAGE_PACKED_FROM_ARRAY
);
498 VM_ASSERT_POINTER_PACKABLE(p
, VM_PAGE_PACKED_PTR
);
499 vm_offset_t packed
= VM_PACK_POINTER(p
, VM_PAGE_PACKED_PTR
);
500 return CAST_DOWN_EXPLICIT(vm_page_packed_t
, packed
);
504 static inline uintptr_t
505 vm_page_unpack_ptr(uintptr_t p
)
507 extern unsigned int vm_pages_count
;
509 if (p
>= VM_PAGE_PACKED_FROM_ARRAY
) {
510 p
&= ~VM_PAGE_PACKED_FROM_ARRAY
;
511 assert(p
< (uintptr_t)vm_pages_count
);
512 return (uintptr_t)&vm_pages
[p
];
515 return VM_UNPACK_POINTER(p
, VM_PAGE_PACKED_PTR
);
519 #define VM_PAGE_PACK_PTR(p) vm_page_pack_ptr((uintptr_t)(p))
520 #define VM_PAGE_UNPACK_PTR(p) vm_page_unpack_ptr((uintptr_t)(p))
522 #define VM_PAGE_OBJECT(p) ((vm_object_t)(VM_PAGE_UNPACK_PTR(p->vmp_object)))
523 #define VM_PAGE_PACK_OBJECT(o) ((vm_page_object_t)(VM_PAGE_PACK_PTR(o)))
526 #define VM_PAGE_ZERO_PAGEQ_ENTRY(p) \
528 (p)->vmp_snext = 0; \
532 #define VM_PAGE_CONVERT_TO_QUEUE_ENTRY(p) VM_PAGE_PACK_PTR(p)
535 static __inline__
void
536 vm_page_enqueue_tail(
538 vm_page_queue_entry_t elt
)
540 vm_page_queue_entry_t old_tail
;
542 old_tail
= (vm_page_queue_entry_t
)VM_PAGE_UNPACK_PTR(que
->prev
);
543 elt
->next
= VM_PAGE_PACK_PTR(que
);
544 elt
->prev
= que
->prev
;
545 que
->prev
= old_tail
->next
= VM_PAGE_PACK_PTR(elt
);
549 static __inline__
void
551 vm_page_queue_entry_t elt
)
553 vm_page_queue_entry_t next
;
554 vm_page_queue_entry_t prev
;
555 vm_page_packed_t next_pck
= elt
->next
;
556 vm_page_packed_t prev_pck
= elt
->prev
;
558 next
= (vm_page_queue_entry_t
)VM_PAGE_UNPACK_PTR(next_pck
);
560 /* next may equal prev (and the queue head) if elt was the only element */
561 prev
= (vm_page_queue_entry_t
)VM_PAGE_UNPACK_PTR(prev_pck
);
563 next
->prev
= prev_pck
;
564 prev
->next
= next_pck
;
572 * Macro: vm_page_queue_init
574 * Initialize the given queue.
576 * void vm_page_queue_init(q)
577 * vm_page_queue_t q; \* MODIFIED *\
579 #define vm_page_queue_init(q) \
581 VM_ASSERT_POINTER_PACKABLE((vm_offset_t)(q), VM_PAGE_PACKED_PTR); \
582 (q)->next = VM_PAGE_PACK_PTR(q); \
583 (q)->prev = VM_PAGE_PACK_PTR(q); \
588 * Macro: vm_page_queue_enter
590 * Insert a new element at the tail of the vm_page queue.
592 * void vm_page_queue_enter(q, elt, field)
595 * <field> is the list field in vm_page_t
597 * This macro's arguments have to match the generic "queue_enter()" macro which is
598 * what is used for this on 32 bit kernels.
600 #define vm_page_queue_enter(head, elt, field) \
602 vm_page_packed_t __pck_elt = VM_PAGE_PACK_PTR(elt); \
603 vm_page_packed_t __pck_head = VM_PAGE_PACK_PTR(head); \
604 vm_page_packed_t __pck_prev = (head)->prev; \
606 if (__pck_head == __pck_prev) { \
607 (head)->next = __pck_elt; \
610 __prev = (vm_page_t)VM_PAGE_UNPACK_PTR(__pck_prev); \
611 __prev->field.next = __pck_elt; \
613 (elt)->field.prev = __pck_prev; \
614 (elt)->field.next = __pck_head; \
615 (head)->prev = __pck_elt; \
619 #if defined(__x86_64__)
621 * These are helper macros for vm_page_queue_enter_clump to assist
622 * with conditional compilation (release / debug / development)
624 #if DEVELOPMENT || DEBUG
626 #define __DEBUG_CHECK_BUDDIES(__prev, __p, field) \
628 if (__prev != NULL) { \
629 assert(__p == (vm_page_t)VM_PAGE_UNPACK_PTR(__prev->next)); \
630 assert(__prev == (vm_page_queue_entry_t)VM_PAGE_UNPACK_PTR(__p->field.prev)); \
634 #define __DEBUG_VERIFY_LINKS(__first, __n_free, __last_next) \
637 vm_page_queue_entry_t __tmp; \
638 for (__i = 0, __tmp = __first; __i < __n_free; __i++) { \
639 __tmp = (vm_page_queue_entry_t)VM_PAGE_UNPACK_PTR(__tmp->next); \
641 assert(__tmp == __last_next); \
644 #define __DEBUG_STAT_INCREMENT_INRANGE vm_clump_inrange++
645 #define __DEBUG_STAT_INCREMENT_INSERTS vm_clump_inserts++
646 #define __DEBUG_STAT_INCREMENT_PROMOTES(__n_free) vm_clump_promotes+=__n_free
650 #define __DEBUG_CHECK_BUDDIES(__prev, __p, field)
651 #define __DEBUG_VERIFY_LINKS(__first, __n_free, __last_next)
652 #define __DEBUG_STAT_INCREMENT_INRANGE
653 #define __DEBUG_STAT_INCREMENT_INSERTS
654 #define __DEBUG_STAT_INCREMENT_PROMOTES(__n_free)
656 #endif /* if DEVELOPMENT || DEBUG */
659 * Insert a new page into a free queue and clump pages within the same 16K boundary together
662 vm_page_queue_enter_clump(
663 vm_page_queue_t head
,
666 vm_page_queue_entry_t first
= NULL
; /* first page in the clump */
667 vm_page_queue_entry_t last
= NULL
; /* last page in the clump */
668 vm_page_queue_entry_t prev
= NULL
;
669 vm_page_queue_entry_t next
;
671 extern unsigned int vm_pages_count
;
672 extern unsigned int vm_clump_size
, vm_clump_mask
, vm_clump_shift
, vm_clump_promote_threshold
;
673 extern unsigned long vm_clump_allocs
, vm_clump_inserts
, vm_clump_inrange
, vm_clump_promotes
;
676 * If elt is part of the vm_pages[] array, find its neighboring buddies in the array.
678 if (vm_page_array_beginning_addr
<= elt
&& elt
< &vm_pages
[vm_pages_count
]) {
684 first
= last
= (vm_page_queue_entry_t
)elt
;
685 clump_num
= VM_PAGE_GET_CLUMP(elt
);
686 n
= VM_PAGE_GET_PHYS_PAGE(elt
) & vm_clump_mask
;
689 * Check for preceeding vm_pages[] entries in the same chunk
691 for (i
= 0, p
= elt
- 1; i
< n
&& vm_page_array_beginning_addr
<= p
; i
++, p
--) {
692 if (p
->vmp_q_state
== VM_PAGE_ON_FREE_Q
&& clump_num
== VM_PAGE_GET_CLUMP(p
)) {
694 prev
= (vm_page_queue_entry_t
)p
;
696 first
= (vm_page_queue_entry_t
)p
;
702 * Check the following vm_pages[] entries in the same chunk
704 for (i
= n
+ 1, p
= elt
+ 1; i
< vm_clump_size
&& p
< &vm_pages
[vm_pages_count
]; i
++, p
++) {
705 if (p
->vmp_q_state
== VM_PAGE_ON_FREE_Q
&& clump_num
== VM_PAGE_GET_CLUMP(p
)) {
706 if (last
== (vm_page_queue_entry_t
)elt
) { /* first one only */
707 __DEBUG_CHECK_BUDDIES(prev
, p
, vmp_pageq
);
711 prev
= (vm_page_queue_entry_t
)VM_PAGE_UNPACK_PTR(p
->vmp_pageq
.prev
);
713 last
= (vm_page_queue_entry_t
)p
;
717 __DEBUG_STAT_INCREMENT_INRANGE
;
720 /* if elt is not part of vm_pages or if 1st page in clump, insert at tail */
722 prev
= (vm_page_queue_entry_t
)VM_PAGE_UNPACK_PTR(head
->prev
);
725 /* insert the element */
726 next
= (vm_page_queue_entry_t
)VM_PAGE_UNPACK_PTR(prev
->next
);
727 elt
->vmp_pageq
.next
= prev
->next
;
728 elt
->vmp_pageq
.prev
= next
->prev
;
729 prev
->next
= next
->prev
= VM_PAGE_PACK_PTR(elt
);
730 __DEBUG_STAT_INCREMENT_INSERTS
;
733 * Check if clump needs to be promoted to head.
735 if (n_free
>= vm_clump_promote_threshold
&& n_free
> 1) {
736 vm_page_queue_entry_t first_prev
;
738 first_prev
= (vm_page_queue_entry_t
)VM_PAGE_UNPACK_PTR(first
->prev
);
740 /* If not at head already */
741 if (first_prev
!= head
) {
742 vm_page_queue_entry_t last_next
;
743 vm_page_queue_entry_t head_next
;
745 last_next
= (vm_page_queue_entry_t
)VM_PAGE_UNPACK_PTR(last
->next
);
747 /* verify that the links within the clump are consistent */
748 __DEBUG_VERIFY_LINKS(first
, n_free
, last_next
);
750 /* promote clump to head */
751 first_prev
->next
= last
->next
;
752 last_next
->prev
= first
->prev
;
753 first
->prev
= VM_PAGE_PACK_PTR(head
);
754 last
->next
= head
->next
;
756 head_next
= (vm_page_queue_entry_t
)VM_PAGE_UNPACK_PTR(head
->next
);
757 head_next
->prev
= VM_PAGE_PACK_PTR(last
);
758 head
->next
= VM_PAGE_PACK_PTR(first
);
759 __DEBUG_STAT_INCREMENT_PROMOTES(n_free
);
766 * Macro: vm_page_queue_enter_first
768 * Insert a new element at the head of the vm_page queue.
770 * void queue_enter_first(q, elt, , field)
773 * <field> is the linkage field in vm_page
775 * This macro's arguments have to match the generic "queue_enter_first()" macro which is
776 * what is used for this on 32 bit kernels.
778 #define vm_page_queue_enter_first(head, elt, field) \
780 vm_page_packed_t __pck_next = (head)->next; \
781 vm_page_packed_t __pck_head = VM_PAGE_PACK_PTR(head); \
782 vm_page_packed_t __pck_elt = VM_PAGE_PACK_PTR(elt); \
784 if (__pck_head == __pck_next) { \
785 (head)->prev = __pck_elt; \
788 __next = (vm_page_t)VM_PAGE_UNPACK_PTR(__pck_next); \
789 __next->field.prev = __pck_elt; \
792 (elt)->field.next = __pck_next; \
793 (elt)->field.prev = __pck_head; \
794 (head)->next = __pck_elt; \
799 * Macro: vm_page_queue_remove
801 * Remove an arbitrary page from a vm_page queue.
803 * void vm_page_queue_remove(q, qe, field)
804 * arguments as in vm_page_queue_enter
806 * This macro's arguments have to match the generic "queue_enter()" macro which is
807 * what is used for this on 32 bit kernels.
809 #define vm_page_queue_remove(head, elt, field) \
811 vm_page_packed_t __pck_next = (elt)->field.next; \
812 vm_page_packed_t __pck_prev = (elt)->field.prev; \
813 vm_page_t __next = (vm_page_t)VM_PAGE_UNPACK_PTR(__pck_next); \
814 vm_page_t __prev = (vm_page_t)VM_PAGE_UNPACK_PTR(__pck_prev); \
816 if ((void *)(head) == (void *)__next) { \
817 (head)->prev = __pck_prev; \
819 __next->field.prev = __pck_prev; \
822 if ((void *)(head) == (void *)__prev) { \
823 (head)->next = __pck_next; \
825 __prev->field.next = __pck_next; \
828 (elt)->field.next = 0; \
829 (elt)->field.prev = 0; \
834 * Macro: vm_page_queue_remove_first
837 * Remove and return the entry at the head of a vm_page queue.
840 * vm_page_queue_remove_first(head, entry, field)
841 * N.B. entry is returned by reference
843 * This macro's arguments have to match the generic "queue_remove_first()" macro which is
844 * what is used for this on 32 bit kernels.
846 #define vm_page_queue_remove_first(head, entry, field) \
848 vm_page_packed_t __pck_head = VM_PAGE_PACK_PTR(head); \
849 vm_page_packed_t __pck_next; \
852 (entry) = (vm_page_t)VM_PAGE_UNPACK_PTR((head)->next); \
853 __pck_next = (entry)->field.next; \
854 __next = (vm_page_t)VM_PAGE_UNPACK_PTR(__pck_next); \
856 if (__pck_head == __pck_next) { \
857 (head)->prev = __pck_head; \
859 __next->field.prev = __pck_head; \
862 (head)->next = __pck_next; \
863 (entry)->field.next = 0; \
864 (entry)->field.prev = 0; \
868 #if defined(__x86_64__)
870 * Macro: vm_page_queue_remove_first_with_clump
872 * Remove and return the entry at the head of the free queue
873 * end is set to 1 to indicate that we just returned the last page in a clump
876 * vm_page_queue_remove_first_with_clump(head, entry, end)
877 * entry is returned by reference
878 * end is returned by reference
880 #define vm_page_queue_remove_first_with_clump(head, entry, end) \
882 vm_page_packed_t __pck_head = VM_PAGE_PACK_PTR(head); \
883 vm_page_packed_t __pck_next; \
886 (entry) = (vm_page_t)VM_PAGE_UNPACK_PTR((head)->next); \
887 __pck_next = (entry)->vmp_pageq.next; \
888 __next = (vm_page_t)VM_PAGE_UNPACK_PTR(__pck_next); \
891 if (__pck_head == __pck_next) { \
892 (head)->prev = __pck_head; \
895 __next->vmp_pageq.prev = __pck_head; \
896 if (VM_PAGE_GET_CLUMP(entry) != VM_PAGE_GET_CLUMP(__next)) { \
901 (head)->next = __pck_next; \
902 (entry)->vmp_pageq.next = 0; \
903 (entry)->vmp_pageq.prev = 0; \
908 * Macro: vm_page_queue_end
910 * Tests whether a new entry is really the end of
913 * boolean_t vm_page_queue_end(q, qe)
915 * vm_page_queue_entry_t qe;
917 #define vm_page_queue_end(q, qe) ((q) == (qe))
921 * Macro: vm_page_queue_empty
923 * Tests whether a queue is empty.
925 * boolean_t vm_page_queue_empty(q)
928 #define vm_page_queue_empty(q) vm_page_queue_end((q), ((vm_page_queue_entry_t)vm_page_queue_first(q)))
933 * Macro: vm_page_queue_first
935 * Returns the first entry in the queue,
937 * uintpr_t vm_page_queue_first(q)
938 * vm_page_queue_t q; \* IN *\
940 #define vm_page_queue_first(q) (VM_PAGE_UNPACK_PTR((q)->next))
945 * Macro: vm_page_queue_last
947 * Returns the last entry in the queue.
949 * vm_page_queue_entry_t queue_last(q)
950 * queue_t q; \* IN *\
952 #define vm_page_queue_last(q) (VM_PAGE_UNPACK_PTR((q)->prev))
957 * Macro: vm_page_queue_next
959 * Returns the entry after an item in the queue.
961 * uintpr_t vm_page_queue_next(qc)
962 * vm_page_queue_t qc;
964 #define vm_page_queue_next(qc) (VM_PAGE_UNPACK_PTR((qc)->next))
969 * Macro: vm_page_queue_prev
971 * Returns the entry before an item in the queue.
973 * uinptr_t vm_page_queue_prev(qc)
974 * vm_page_queue_t qc;
976 #define vm_page_queue_prev(qc) (VM_PAGE_UNPACK_PTR((qc)->prev))
981 * Macro: vm_page_queue_iterate
983 * iterate over each item in a vm_page queue.
984 * Generates a 'for' loop, setting elt to
985 * each item in turn (by reference).
987 * vm_page_queue_iterate(q, elt, field)
990 * <field> is the chain field in vm_page_t
992 #define vm_page_queue_iterate(head, elt, field) \
993 for ((elt) = (vm_page_t)vm_page_queue_first(head); \
994 !vm_page_queue_end((head), (vm_page_queue_entry_t)(elt)); \
995 (elt) = (vm_page_t)vm_page_queue_next(&(elt)->field)) \
999 #define VM_VPLQ_ALIGNMENT 128
1000 #define VM_PAGE_PACKED_PTR_ALIGNMENT sizeof(vm_offset_t)
1001 #define VM_PAGE_PACKED_ALIGNED
1002 #define VM_PAGE_PACKED_PTR_BITS 32
1003 #define VM_PAGE_PACKED_PTR_SHIFT 0
1004 #define VM_PAGE_PACKED_PTR_BASE 0
1006 #define VM_PAGE_PACKED_FROM_ARRAY 0
1008 #define VM_PAGE_PACK_PTR(p) (p)
1009 #define VM_PAGE_UNPACK_PTR(p) ((uintptr_t)(p))
1011 #define VM_PAGE_OBJECT(p) ((vm_object_t)((p)->vmp_object))
1012 #define VM_PAGE_PACK_OBJECT(o) ((vm_page_object_t)(VM_PAGE_PACK_PTR(o)))
1015 #define VM_PAGE_ZERO_PAGEQ_ENTRY(p) \
1017 (p)->vmp_pageq.next = 0; \
1018 (p)->vmp_pageq.prev = 0; \
1021 #define VM_PAGE_CONVERT_TO_QUEUE_ENTRY(p) ((queue_entry_t)(p))
1023 #define vm_page_remque remque
1024 #define vm_page_enqueue_tail enqueue_tail
1025 #define vm_page_queue_init queue_init
1026 #define vm_page_queue_enter(h, e, f) queue_enter(h, e, vm_page_t, f)
1027 #define vm_page_queue_enter_first(h, e, f) queue_enter_first(h, e, vm_page_t, f)
1028 #define vm_page_queue_remove(h, e, f) queue_remove(h, e, vm_page_t, f)
1029 #define vm_page_queue_remove_first(h, e, f) queue_remove_first(h, e, vm_page_t, f)
1030 #define vm_page_queue_end queue_end
1031 #define vm_page_queue_empty queue_empty
1032 #define vm_page_queue_first queue_first
1033 #define vm_page_queue_last queue_last
1034 #define vm_page_queue_next queue_next
1035 #define vm_page_queue_prev queue_prev
1036 #define vm_page_queue_iterate(h, e, f) queue_iterate(h, e, vm_page_t, f)
1043 * VM_PAGE_MIN_SPECULATIVE_AGE_Q through VM_PAGE_MAX_SPECULATIVE_AGE_Q
1044 * represents a set of aging bins that are 'protected'...
1046 * VM_PAGE_SPECULATIVE_AGED_Q is a list of the speculative pages that have
1047 * not yet been 'claimed' but have been aged out of the protective bins
1048 * this occurs in vm_page_speculate when it advances to the next bin
1049 * and discovers that it is still occupied... at that point, all of the
1050 * pages in that bin are moved to the VM_PAGE_SPECULATIVE_AGED_Q. the pages
1051 * in that bin are all guaranteed to have reached at least the maximum age
1052 * we allow for a protected page... they can be older if there is no
1053 * memory pressure to pull them from the bin, or there are no new speculative pages
1054 * being generated to push them out.
1055 * this list is the one that vm_pageout_scan will prefer when looking
1056 * for pages to move to the underweight free list
1058 * VM_PAGE_MAX_SPECULATIVE_AGE_Q * VM_PAGE_SPECULATIVE_Q_AGE_MS
1059 * defines the amount of time a speculative page is normally
1060 * allowed to live in the 'protected' state (i.e. not available
1061 * to be stolen if vm_pageout_scan is running and looking for
1062 * pages)... however, if the total number of speculative pages
1063 * in the protected state exceeds our limit (defined in vm_pageout.c)
1064 * and there are none available in VM_PAGE_SPECULATIVE_AGED_Q, then
1065 * vm_pageout_scan is allowed to steal pages from the protected
1066 * bucket even if they are underage.
1068 * vm_pageout_scan is also allowed to pull pages from a protected
1069 * bin if the bin has reached the "age of consent" we've set
1071 #define VM_PAGE_MAX_SPECULATIVE_AGE_Q 10
1072 #define VM_PAGE_MIN_SPECULATIVE_AGE_Q 1
1073 #define VM_PAGE_SPECULATIVE_AGED_Q 0
1075 #define VM_PAGE_SPECULATIVE_Q_AGE_MS 500
1077 struct vm_speculative_age_q
{
1079 * memory queue for speculative pages via clustered pageins
1081 vm_page_queue_head_t age_q
;
1082 mach_timespec_t age_ts
;
1083 } VM_PAGE_PACKED_ALIGNED
;
1088 struct vm_speculative_age_q vm_page_queue_speculative
[];
1090 extern int speculative_steal_index
;
1091 extern int speculative_age_index
;
1092 extern unsigned int vm_page_speculative_q_age_ms
;
1095 typedef struct vm_locks_array
{
1096 char pad
__attribute__ ((aligned(64)));
1097 lck_mtx_t vm_page_queue_lock2
__attribute__ ((aligned(64)));
1098 lck_mtx_t vm_page_queue_free_lock2
__attribute__ ((aligned(64)));
1099 char pad2
__attribute__ ((aligned(64)));
1103 #if CONFIG_BACKGROUND_QUEUE
1104 extern void vm_page_assign_background_state(vm_page_t mem
);
1105 extern void vm_page_update_background_state(vm_page_t mem
);
1106 extern void vm_page_add_to_backgroundq(vm_page_t mem
, boolean_t first
);
1107 extern void vm_page_remove_from_backgroundq(vm_page_t mem
);
1110 #define VM_PAGE_WIRED(m) ((m)->vmp_q_state == VM_PAGE_IS_WIRED)
1111 #define NEXT_PAGE(m) ((m)->vmp_snext)
1112 #define NEXT_PAGE_PTR(m) (&(m)->vmp_snext)
1115 * XXX The unusual bit should not be necessary. Most of the bit
1116 * XXX fields above really want to be masks.
1120 * For debugging, this macro can be defined to perform
1121 * some useful check on a page structure.
1122 * INTENTIONALLY left as a no-op so that the
1123 * current call-sites can be left intact for future uses.
1126 #define VM_PAGE_CHECK(mem) \
1132 * The free page list is actually n lists, one per color,
1133 * where the number of colors is a function of the machine's
1134 * cache geometry set at system initialization. To disable
1135 * coloring, set vm_colors to 1 and vm_color_mask to 0.
1136 * The boot-arg "colors" may be used to override vm_colors.
1137 * Note that there is little harm in having more colors than needed.
1140 #define MAX_COLORS 128
1141 #define DEFAULT_COLORS 32
1144 unsigned int vm_colors
; /* must be in range 1..MAX_COLORS */
1146 unsigned int vm_color_mask
; /* must be (vm_colors-1) */
1148 unsigned int vm_cache_geometry_colors
; /* optimal #colors based on cache geometry */
1151 * Wired memory is a very limited resource and we can't let users exhaust it
1152 * and deadlock the entire system. We enforce the following limits:
1154 * vm_per_task_user_wire_limit
1155 * how much memory can be user-wired in one user task
1157 * vm_global_user_wire_limit (default: same as vm_per_task_user_wire_limit)
1158 * how much memory can be user-wired in all user tasks
1160 * These values are set to defaults based on the number of pages managed
1161 * by the VM system. They can be overriden via sysctls.
1162 * See kmem_set_user_wire_limits for details on the default values.
1164 * Regardless of the amount of memory in the system, we never reserve
1165 * more than VM_NOT_USER_WIREABLE_MAX bytes as unlockable.
1167 #if defined(__LP64__)
1168 #define VM_NOT_USER_WIREABLE_MAX (32ULL*1024*1024*1024) /* 32GB */
1170 #define VM_NOT_USER_WIREABLE_MAX (1UL*1024*1024*1024) /* 1GB */
1171 #endif /* __LP64__ */
1173 vm_map_size_t vm_per_task_user_wire_limit
;
1175 vm_map_size_t vm_global_user_wire_limit
;
1177 uint64_t vm_add_wire_count_over_global_limit
;
1179 uint64_t vm_add_wire_count_over_user_limit
;
1182 * Each pageable resident page falls into one of three lists:
1185 * Available for allocation now. The free list is
1186 * actually an array of lists, one per color.
1188 * Not referenced in any map, but still has an
1189 * object/offset-page mapping, and may be dirty.
1190 * This is the list of pages that should be
1191 * paged out next. There are actually two
1192 * inactive lists, one for pages brought in from
1193 * disk or other backing store, and another
1194 * for "zero-filled" pages. See vm_pageout_scan()
1195 * for the distinction and usage.
1197 * A list of pages which have been placed in
1198 * at least one physical map. This list is
1199 * ordered, in LRU-like fashion.
1203 #define VPL_LOCK_SPIN 1
1206 vm_page_queue_head_t vpl_queue
;
1207 unsigned int vpl_count
;
1208 unsigned int vpl_internal_count
;
1209 unsigned int vpl_external_count
;
1210 #ifdef VPL_LOCK_SPIN
1211 lck_spin_t vpl_lock
;
1214 lck_mtx_ext_t vpl_lock_ext
;
1219 struct vpl
* /* __zpercpu */ vm_page_local_q
;
1221 unsigned int vm_page_local_q_soft_limit
;
1223 unsigned int vm_page_local_q_hard_limit
;
1225 vm_locks_array_t vm_page_locks
;
1228 vm_page_queue_head_t vm_lopage_queue_free
; /* low memory free queue */
1230 vm_page_queue_head_t vm_page_queue_active
; /* active memory queue */
1232 vm_page_queue_head_t vm_page_queue_inactive
; /* inactive memory queue for normal pages */
1233 #if CONFIG_SECLUDED_MEMORY
1235 vm_page_queue_head_t vm_page_queue_secluded
; /* reclaimable pages secluded for Camera */
1236 #endif /* CONFIG_SECLUDED_MEMORY */
1238 vm_page_queue_head_t vm_page_queue_cleaned
; /* clean-queue inactive memory */
1240 vm_page_queue_head_t vm_page_queue_anonymous
; /* inactive memory queue for anonymous pages */
1242 vm_page_queue_head_t vm_page_queue_throttled
; /* memory queue for throttled pageout pages */
1245 queue_head_t vm_objects_wired
;
1247 lck_spin_t vm_objects_wired_lock
;
1249 #if CONFIG_BACKGROUND_QUEUE
1251 #define VM_PAGE_BACKGROUND_TARGET_MAX 50000
1253 #define VM_PAGE_BG_DISABLED 0
1254 #define VM_PAGE_BG_LEVEL_1 1
1257 vm_page_queue_head_t vm_page_queue_background
;
1259 uint64_t vm_page_background_promoted_count
;
1261 uint32_t vm_page_background_count
;
1263 uint32_t vm_page_background_target
;
1265 uint32_t vm_page_background_internal_count
;
1267 uint32_t vm_page_background_external_count
;
1269 uint32_t vm_page_background_mode
;
1271 uint32_t vm_page_background_exclude_external
;
1276 vm_offset_t first_phys_addr
; /* physical address for first_page */
1278 vm_offset_t last_phys_addr
; /* physical address for last_page */
1281 unsigned int vm_page_free_count
; /* How many pages are free? (sum of all colors) */
1283 unsigned int vm_page_active_count
; /* How many pages are active? */
1285 unsigned int vm_page_inactive_count
; /* How many pages are inactive? */
1287 unsigned int vm_page_kernelcache_count
; /* How many pages are used for the kernelcache? */
1288 #if CONFIG_SECLUDED_MEMORY
1290 unsigned int vm_page_secluded_count
; /* How many pages are secluded? */
1292 unsigned int vm_page_secluded_count_free
; /* how many of them are free? */
1294 unsigned int vm_page_secluded_count_inuse
; /* how many of them are in use? */
1296 * We keep filling the secluded pool with new eligible pages and
1297 * we can overshoot our target by a lot.
1298 * When there's memory pressure, vm_pageout_scan() will re-balance the queues,
1299 * pushing the extra secluded pages to the active or free queue.
1300 * Since these "over target" secluded pages are actually "available", jetsam
1301 * should consider them as such, so make them visible to jetsam via the
1302 * "vm_page_secluded_count_over_target" counter and update it whenever we
1303 * update vm_page_secluded_count or vm_page_secluded_target.
1306 unsigned int vm_page_secluded_count_over_target
;
1307 #define VM_PAGE_SECLUDED_COUNT_OVER_TARGET_UPDATE() \
1309 if (vm_page_secluded_count > vm_page_secluded_target) { \
1310 vm_page_secluded_count_over_target = \
1311 (vm_page_secluded_count - vm_page_secluded_target); \
1313 vm_page_secluded_count_over_target = 0; \
1316 #define VM_PAGE_SECLUDED_COUNT_OVER_TARGET() vm_page_secluded_count_over_target
1317 #else /* CONFIG_SECLUDED_MEMORY */
1318 #define VM_PAGE_SECLUDED_COUNT_OVER_TARGET_UPDATE() \
1321 #define VM_PAGE_SECLUDED_COUNT_OVER_TARGET() 0
1322 #endif /* CONFIG_SECLUDED_MEMORY */
1324 unsigned int vm_page_cleaned_count
; /* How many pages are in the clean queue? */
1326 unsigned int vm_page_throttled_count
;/* How many inactives are throttled */
1328 unsigned int vm_page_speculative_count
; /* How many speculative pages are unclaimed? */
1329 extern unsigned int vm_page_pageable_internal_count
;
1330 extern unsigned int vm_page_pageable_external_count
;
1332 unsigned int vm_page_xpmapped_external_count
; /* How many pages are mapped executable? */
1334 unsigned int vm_page_external_count
; /* How many pages are file-backed? */
1336 unsigned int vm_page_internal_count
; /* How many pages are anonymous? */
1338 unsigned int vm_page_wire_count
; /* How many pages are wired? */
1340 unsigned int vm_page_wire_count_initial
; /* How many pages wired at startup */
1342 unsigned int vm_page_wire_count_on_boot
; /* even earlier than _initial */
1344 unsigned int vm_page_free_target
; /* How many do we want free? */
1346 unsigned int vm_page_free_min
; /* When to wakeup pageout */
1348 unsigned int vm_page_throttle_limit
; /* When to throttle new page creation */
1350 unsigned int vm_page_inactive_target
;/* How many do we want inactive? */
1351 #if CONFIG_SECLUDED_MEMORY
1353 unsigned int vm_page_secluded_target
;/* How many do we want secluded? */
1354 #endif /* CONFIG_SECLUDED_MEMORY */
1356 unsigned int vm_page_anonymous_min
; /* When it's ok to pre-clean */
1358 unsigned int vm_page_free_reserved
; /* How many pages reserved to do pageout */
1360 unsigned int vm_page_gobble_count
;
1362 unsigned int vm_page_stolen_count
; /* Count of stolen pages not acccounted in zones */
1364 unsigned int vm_page_kern_lpage_count
; /* Count of large pages used in early boot */
1367 #if DEVELOPMENT || DEBUG
1369 unsigned int vm_page_speculative_used
;
1373 unsigned int vm_page_purgeable_count
;/* How many pages are purgeable now ? */
1375 unsigned int vm_page_purgeable_wired_count
;/* How many purgeable pages are wired now ? */
1377 uint64_t vm_page_purged_count
; /* How many pages got purged so far ? */
1379 extern unsigned int vm_page_free_wanted
;
1380 /* how many threads are waiting for memory */
1382 extern unsigned int vm_page_free_wanted_privileged
;
1383 /* how many VM privileged threads are waiting for memory */
1384 #if CONFIG_SECLUDED_MEMORY
1385 extern unsigned int vm_page_free_wanted_secluded
;
1386 /* how many threads are waiting for secluded memory */
1387 #endif /* CONFIG_SECLUDED_MEMORY */
1389 extern const ppnum_t vm_page_fictitious_addr
;
1390 /* (fake) phys_addr of fictitious pages */
1392 extern const ppnum_t vm_page_guard_addr
;
1393 /* (fake) phys_addr of guard pages */
1396 extern boolean_t vm_page_deactivate_hint
;
1398 extern int vm_compressor_mode
;
1401 * Defaults to true, so highest memory is used first.
1403 extern boolean_t vm_himemory_mode
;
1405 extern boolean_t vm_lopage_needed
;
1406 extern uint32_t vm_lopage_free_count
;
1407 extern uint32_t vm_lopage_free_limit
;
1408 extern uint32_t vm_lopage_lowater
;
1409 extern boolean_t vm_lopage_refill
;
1410 extern uint64_t max_valid_dma_address
;
1411 extern ppnum_t max_valid_low_ppnum
;
1414 * Prototypes for functions exported by this module.
1416 extern void vm_page_bootstrap(
1417 vm_offset_t
*startp
,
1420 extern void vm_page_init_local_q(unsigned int num_cpus
);
1422 extern void vm_page_create(
1426 extern void vm_page_create_retired(
1429 extern vm_page_t
kdp_vm_page_lookup(
1431 vm_object_offset_t offset
);
1433 extern vm_page_t
vm_page_lookup(
1435 vm_object_offset_t offset
);
1437 extern vm_page_t
vm_page_grab_fictitious(boolean_t canwait
);
1439 extern vm_page_t
vm_page_grab_guard(boolean_t canwait
);
1441 extern void vm_page_release_fictitious(
1444 extern void vm_free_delayed_pages(void);
1446 extern bool vm_pool_low(void);
1448 extern vm_page_t
vm_page_grab(void);
1449 extern vm_page_t
vm_page_grab_options(int flags
);
1451 #define VM_PAGE_GRAB_OPTIONS_NONE 0x00000000
1452 #if CONFIG_SECLUDED_MEMORY
1453 #define VM_PAGE_GRAB_SECLUDED 0x00000001
1454 #endif /* CONFIG_SECLUDED_MEMORY */
1455 #define VM_PAGE_GRAB_Q_LOCK_HELD 0x00000002
1457 extern vm_page_t
vm_page_grablo(void);
1459 extern void vm_page_release(
1461 boolean_t page_queues_locked
);
1463 extern boolean_t
vm_page_wait(
1464 int interruptible
);
1466 extern vm_page_t
vm_page_alloc(
1468 vm_object_offset_t offset
);
1470 extern void vm_page_init(
1475 extern void vm_page_free(
1478 extern void vm_page_free_unlocked(
1480 boolean_t remove_from_hash
);
1482 extern void vm_page_balance_inactive(
1485 extern void vm_page_activate(
1488 extern void vm_page_deactivate(
1491 extern void vm_page_deactivate_internal(
1493 boolean_t clear_hw_reference
);
1495 extern void vm_page_enqueue_cleaned(vm_page_t page
);
1497 extern void vm_page_lru(
1500 extern void vm_page_speculate(
1504 extern void vm_page_speculate_ageit(
1505 struct vm_speculative_age_q
*aq
);
1507 extern void vm_page_reactivate_all_throttled(void);
1509 extern void vm_page_reactivate_local(uint32_t lid
, boolean_t force
, boolean_t nolocks
);
1511 extern void vm_page_rename(
1513 vm_object_t new_object
,
1514 vm_object_offset_t new_offset
);
1516 extern void vm_page_insert(
1519 vm_object_offset_t offset
);
1521 extern void vm_page_insert_wired(
1524 vm_object_offset_t offset
,
1527 extern void vm_page_insert_internal(
1530 vm_object_offset_t offset
,
1532 boolean_t queues_lock_held
,
1533 boolean_t insert_in_hash
,
1534 boolean_t batch_pmap_op
,
1535 boolean_t delayed_accounting
,
1536 uint64_t *delayed_ledger_update
);
1538 extern void vm_page_replace(
1541 vm_object_offset_t offset
);
1543 extern void vm_page_remove(
1545 boolean_t remove_from_hash
);
1547 extern void vm_page_zero_fill(
1550 extern void vm_page_part_zero_fill(
1555 extern void vm_page_copy(
1557 vm_page_t dest_page
);
1559 extern void vm_page_part_copy(
1566 extern void vm_page_wire(
1569 boolean_t check_memorystatus
);
1571 extern void vm_page_unwire(
1575 extern void vm_set_page_size(void);
1577 extern void vm_page_gobble(
1580 extern void vm_page_validate_cs(
1582 vm_map_size_t fault_page_size
,
1583 vm_map_offset_t fault_phys_offset
);
1584 extern void vm_page_validate_cs_mapped(
1586 vm_map_size_t fault_page_size
,
1587 vm_map_offset_t fault_phys_offset
,
1589 extern void vm_page_validate_cs_mapped_slow(
1592 extern void vm_page_validate_cs_mapped_chunk(
1595 vm_offset_t chunk_offset
,
1596 vm_size_t chunk_size
,
1597 boolean_t
*validated
,
1600 extern void vm_page_free_prepare_queues(
1603 extern void vm_page_free_prepare_object(
1605 boolean_t remove_from_hash
);
1608 extern wait_result_t
vm_page_sleep(
1614 extern void vm_pressure_response(void);
1617 extern void memorystatus_pages_update(unsigned int pages_avail
);
1619 #define VM_CHECK_MEMORYSTATUS do { \
1620 memorystatus_pages_update( \
1621 vm_page_pageable_external_count + \
1622 vm_page_free_count + \
1623 VM_PAGE_SECLUDED_COUNT_OVER_TARGET() + \
1624 (VM_DYNAMIC_PAGING_ENABLED() ? 0 : vm_page_purgeable_count) \
1628 #else /* CONFIG_JETSAM */
1630 #if !XNU_TARGET_OS_OSX
1632 #define VM_CHECK_MEMORYSTATUS do {} while(0)
1634 #else /* !XNU_TARGET_OS_OSX */
1636 #define VM_CHECK_MEMORYSTATUS vm_pressure_response()
1638 #endif /* !XNU_TARGET_OS_OSX */
1640 #endif /* CONFIG_JETSAM */
1643 * Functions implemented as macros. m->vmp_wanted and m->vmp_busy are
1644 * protected by the object lock.
1647 #if !XNU_TARGET_OS_OSX
1648 #define SET_PAGE_DIRTY(m, set_pmap_modified) \
1650 vm_page_t __page__ = (m); \
1651 if (__page__->vmp_pmapped == TRUE && \
1652 __page__->vmp_wpmapped == TRUE && \
1653 __page__->vmp_dirty == FALSE && \
1654 (set_pmap_modified)) { \
1655 pmap_set_modify(VM_PAGE_GET_PHYS_PAGE(__page__)); \
1657 __page__->vmp_dirty = TRUE; \
1659 #else /* !XNU_TARGET_OS_OSX */
1660 #define SET_PAGE_DIRTY(m, set_pmap_modified) \
1662 vm_page_t __page__ = (m); \
1663 __page__->vmp_dirty = TRUE; \
1665 #endif /* !XNU_TARGET_OS_OSX */
1667 #define PAGE_ASSERT_WAIT(m, interruptible) \
1668 (((m)->vmp_wanted = TRUE), \
1669 assert_wait((event_t) (m), (interruptible)))
1672 #define PAGE_SLEEP(o, m, interruptible) \
1673 vm_page_sleep(o, m, interruptible)
1675 #define PAGE_SLEEP(o, m, interruptible) \
1676 (((m)->vmp_wanted = TRUE), \
1677 thread_sleep_vm_object((o), (m), (interruptible)))
1680 #define PAGE_WAKEUP_DONE(m) \
1682 (m)->vmp_busy = FALSE; \
1683 if ((m)->vmp_wanted) { \
1684 (m)->vmp_wanted = FALSE; \
1685 thread_wakeup((event_t) (m)); \
1689 #define PAGE_WAKEUP(m) \
1691 if ((m)->vmp_wanted) { \
1692 (m)->vmp_wanted = FALSE; \
1693 thread_wakeup((event_t) (m)); \
1697 #define VM_PAGE_FREE(p) \
1699 vm_page_free_unlocked(p, TRUE); \
1702 #define VM_PAGE_WAIT() ((void)vm_page_wait(THREAD_UNINT))
1704 #define vm_page_queue_lock (vm_page_locks.vm_page_queue_lock2)
1705 #define vm_page_queue_free_lock (vm_page_locks.vm_page_queue_free_lock2)
1707 #define vm_page_lock_queues() lck_mtx_lock(&vm_page_queue_lock)
1708 #define vm_page_trylock_queues() lck_mtx_try_lock(&vm_page_queue_lock)
1709 #define vm_page_unlock_queues() lck_mtx_unlock(&vm_page_queue_lock)
1711 #define vm_page_lockspin_queues() lck_mtx_lock_spin(&vm_page_queue_lock)
1712 #define vm_page_trylockspin_queues() lck_mtx_try_lock_spin(&vm_page_queue_lock)
1713 #define vm_page_lockconvert_queues() lck_mtx_convert_spin(&vm_page_queue_lock)
1715 #ifdef VPL_LOCK_SPIN
1716 extern lck_grp_t vm_page_lck_grp_local
;
1718 #define VPL_LOCK_INIT(vlq, vpl_grp, vpl_attr) lck_spin_init(&vlq->vpl_lock, vpl_grp, vpl_attr)
1719 #define VPL_LOCK(vpl) lck_spin_lock_grp(vpl, &vm_page_lck_grp_local)
1720 #define VPL_UNLOCK(vpl) lck_spin_unlock(vpl)
1722 #define VPL_LOCK_INIT(vlq, vpl_grp, vpl_attr) lck_mtx_init_ext(&vlq->vpl_lock, &vlq->vpl_lock_ext, vpl_grp, vpl_attr)
1723 #define VPL_LOCK(vpl) lck_mtx_lock_spin(vpl)
1724 #define VPL_UNLOCK(vpl) lck_mtx_unlock(vpl)
1728 #if DEVELOPMENT || DEBUG
1729 #define VM_PAGE_SPECULATIVE_USED_ADD() \
1731 OSAddAtomic(1, &vm_page_speculative_used); \
1734 #define VM_PAGE_SPECULATIVE_USED_ADD()
1738 #define VM_PAGE_CONSUME_CLUSTERED(mem) \
1740 ppnum_t __phys_page; \
1741 __phys_page = VM_PAGE_GET_PHYS_PAGE(mem); \
1742 pmap_lock_phys_page(__phys_page); \
1743 if (mem->vmp_clustered) { \
1745 o = VM_PAGE_OBJECT(mem); \
1748 mem->vmp_clustered = FALSE; \
1749 VM_PAGE_SPECULATIVE_USED_ADD(); \
1751 pmap_unlock_phys_page(__phys_page); \
1755 #define VM_PAGE_COUNT_AS_PAGEIN(mem) \
1759 o = VM_PAGE_OBJECT(mem); \
1760 DTRACE_VM2(pgin, int, 1, (uint64_t *), NULL); \
1761 current_task()->pageins++; \
1762 if (o->internal) { \
1763 DTRACE_VM2(anonpgin, int, 1, (uint64_t *), NULL); \
1765 DTRACE_VM2(fspgin, int, 1, (uint64_t *), NULL); \
1770 /* adjust for stolen pages accounted elsewhere */
1771 #define VM_PAGE_MOVE_STOLEN(page_count) \
1773 vm_page_stolen_count -= (page_count); \
1774 vm_page_wire_count_initial -= (page_count); \
1777 #define DW_vm_page_unwire 0x01
1778 #define DW_vm_page_wire 0x02
1779 #define DW_vm_page_free 0x04
1780 #define DW_vm_page_activate 0x08
1781 #define DW_vm_page_deactivate_internal 0x10
1782 #define DW_vm_page_speculate 0x20
1783 #define DW_vm_page_lru 0x40
1784 #define DW_vm_pageout_throttle_up 0x80
1785 #define DW_PAGE_WAKEUP 0x100
1786 #define DW_clear_busy 0x200
1787 #define DW_clear_reference 0x400
1788 #define DW_set_reference 0x800
1789 #define DW_move_page 0x1000
1790 #define DW_VM_PAGE_QUEUES_REMOVE 0x2000
1791 #define DW_enqueue_cleaned 0x4000
1792 #define DW_vm_phantom_cache_update 0x8000
1794 struct vm_page_delayed_work
{
1799 #define DEFAULT_DELAYED_WORK_LIMIT 32
1801 struct vm_page_delayed_work_ctx
{
1802 struct vm_page_delayed_work dwp
[DEFAULT_DELAYED_WORK_LIMIT
];
1803 thread_t delayed_owner
;
1806 void vm_page_do_delayed_work(vm_object_t object
, vm_tag_t tag
, struct vm_page_delayed_work
*dwp
, int dw_count
);
1808 extern unsigned int vm_max_delayed_work_limit
;
1810 extern void vm_page_delayed_work_init_ctx(void);
1812 #define DELAYED_WORK_LIMIT(max) ((vm_max_delayed_work_limit >= max ? max : vm_max_delayed_work_limit))
1815 * vm_page_do_delayed_work may need to drop the object lock...
1816 * if it does, we need the pages it's looking at to
1817 * be held stable via the busy bit, so if busy isn't already
1818 * set, we need to set it and ask vm_page_do_delayed_work
1819 * to clear it and wakeup anyone that might have blocked on
1820 * it once we're done processing the page.
1823 #define VM_PAGE_ADD_DELAYED_WORK(dwp, mem, dw_cnt) \
1825 if (mem->vmp_busy == FALSE) { \
1826 mem->vmp_busy = TRUE; \
1827 if ( !(dwp->dw_mask & DW_vm_page_free)) \
1828 dwp->dw_mask |= (DW_clear_busy | DW_PAGE_WAKEUP); \
1835 extern vm_page_t
vm_object_page_grab(vm_object_t
);
1837 #if VM_PAGE_BUCKETS_CHECK
1838 extern void vm_page_buckets_check(void);
1839 #endif /* VM_PAGE_BUCKETS_CHECK */
1841 extern void vm_page_queues_remove(vm_page_t mem
, boolean_t remove_from_backgroundq
);
1842 extern void vm_page_remove_internal(vm_page_t page
);
1843 extern void vm_page_enqueue_inactive(vm_page_t mem
, boolean_t first
);
1844 extern void vm_page_enqueue_active(vm_page_t mem
, boolean_t first
);
1845 extern void vm_page_check_pageable_safe(vm_page_t page
);
1847 #if CONFIG_SECLUDED_MEMORY
1848 extern uint64_t secluded_shutoff_trigger
;
1849 extern uint64_t secluded_shutoff_headroom
;
1850 extern void start_secluded_suppression(task_t
);
1851 extern void stop_secluded_suppression(task_t
);
1852 #endif /* CONFIG_SECLUDED_MEMORY */
1854 extern void vm_retire_boot_pages(void);
1855 extern uint32_t vm_retired_pages_count(void);
1857 #endif /* _VM_VM_PAGE_H_ */