xref: /xnu-11417.140.69/osfmk/vm/pmap.h (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4) !
1 /*
2  * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * @OSF_COPYRIGHT@
30  */
31 /*
32  * Mach Operating System
33  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34  * All Rights Reserved.
35  *
36  * Permission to use, copy, modify and distribute this software and its
37  * documentation is hereby granted, provided that both the copyright
38  * notice and this permission notice appear in all copies of the
39  * software, derivative works or modified versions, and any portions
40  * thereof, and that both notices appear in supporting documentation.
41  *
42  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45  *
46  * Carnegie Mellon requests users of this software to return to
47  *
48  *  Software Distribution Coordinator  or  [email protected]
49  *  School of Computer Science
50  *  Carnegie Mellon University
51  *  Pittsburgh PA 15213-3890
52  *
53  * any improvements or extensions that they make and grant Carnegie Mellon
54  * the rights to redistribute these changes.
55  */
56 /*
57  */
58 /*
59  *	File:	vm/pmap.h
60  *	Author:	Avadis Tevanian, Jr.
61  *	Date:	1985
62  *
63  *	Machine address mapping definitions -- machine-independent
64  *	section.  [For machine-dependent section, see "machine/pmap.h".]
65  */
66 
67 #ifndef _VM_PMAP_H_
68 #define _VM_PMAP_H_
69 
70 #include <mach/kern_return.h>
71 #include <mach/vm_param.h>
72 #include <mach/vm_types.h>
73 #include <mach/vm_attributes.h>
74 #include <mach/boolean.h>
75 #include <mach/vm_prot.h>
76 #include <kern/trustcache.h>
77 
78 #if __has_include(<CoreEntitlements/CoreEntitlements.h>)
79 #include <CoreEntitlements/CoreEntitlements.h>
80 #endif
81 
82 #ifdef  KERNEL_PRIVATE
83 
84 /*
85  *	The following is a description of the interface to the
86  *	machine-dependent "physical map" data structure.  The module
87  *	must provide a "pmap_t" data type that represents the
88  *	set of valid virtual-to-physical addresses for one user
89  *	address space.  [The kernel address space is represented
90  *	by a distinguished "pmap_t".]  The routines described manage
91  *	this type, install and update virtual-to-physical mappings,
92  *	and perform operations on physical addresses common to
93  *	many address spaces.
94  */
95 
96 /* Copy between a physical page and a virtual address */
97 /* LP64todo - switch to vm_map_offset_t when it grows */
98 extern kern_return_t    copypv(
99 	addr64_t source,
100 	addr64_t sink,
101 	unsigned int size,
102 	int which);
103 
104 /* bcopy_phys and bzero_phys flags. */
105 #define cppvPsnk                0x000000001     /* Destination is a physical address */
106 #define cppvPsnkb               31
107 #define cppvPsrc                0x000000002     /* Source is a physical address */
108 #define cppvPsrcb               30
109 #define cppvFsnk                0x000000004     /* Destination requires flushing (only on non-coherent I/O) */
110 #define cppvFsnkb               29
111 #define cppvFsrc                0x000000008     /* Source requires flushing (only on non-coherent I/O) */
112 #define cppvFsrcb               28
113 #define cppvNoModSnk            0x000000010     /* Ignored in bcopy_phys() */
114 #define cppvNoModSnkb           27
115 #define cppvNoRefSrc            0x000000020     /* Ignored in bcopy_phys() */
116 #define cppvNoRefSrcb           26
117 #define cppvKmap                0x000000040     /* Use the kernel's vm_map */
118 #define cppvKmapb               25
119 
120 extern boolean_t pmap_has_managed_page(ppnum_t first, ppnum_t last);
121 
122 
123 #if MACH_KERNEL_PRIVATE || BSD_KERNEL_PRIVATE
124 #include <mach/mach_types.h>
125 #include <vm/memory_types.h>
126 
127 /*
128  * Routines used during BSD process creation.
129  */
130 
131 extern pmap_t           pmap_create_options(    /* Create a pmap_t. */
132 	ledger_t        ledger,
133 	vm_map_size_t   size,
134 	unsigned int    flags);
135 
136 #if __has_feature(ptrauth_calls) && (defined(XNU_TARGET_OS_OSX) || (DEVELOPMENT || DEBUG))
137 /**
138  * Informs the pmap layer that a process will be running with user JOP disabled,
139  * as if PMAP_CREATE_DISABLE_JOP had been passed during pmap creation.
140  *
141  * @note This function cannot be used once the target process has started
142  * executing code.  It is intended for cases where user JOP is disabled based on
143  * the code signature (e.g., special "keys-off" entitlements), which is too late
144  * to change the flags passed to pmap_create_options.
145  *
146  * @param pmap	The pmap belonging to the target process
147  */
148 extern void             pmap_disable_user_jop(
149 	pmap_t          pmap);
150 #endif /* __has_feature(ptrauth_calls) && (defined(XNU_TARGET_OS_OSX) || (DEVELOPMENT || DEBUG)) */
151 #endif /* MACH_KERNEL_PRIVATE || BSD_KERNEL_PRIVATE */
152 
153 #ifdef  MACH_KERNEL_PRIVATE
154 
155 #include <mach_assert.h>
156 
157 #include <machine/pmap.h>
158 /*
159  *	Routines used for initialization.
160  *	There is traditionally also a pmap_bootstrap,
161  *	used very early by machine-dependent code,
162  *	but it is not part of the interface.
163  *
164  *	LP64todo -
165  *	These interfaces are tied to the size of the
166  *	kernel pmap - and therefore use the "local"
167  *	vm_offset_t, etc... types.
168  */
169 
170 extern void *pmap_steal_memory(vm_size_t size, vm_size_t alignment); /* Early memory allocation */
171 extern void *pmap_steal_freeable_memory(vm_size_t size); /* Early memory allocation */
172 
173 extern uint_t pmap_free_pages(void); /* report remaining unused physical pages */
174 #if defined(__arm__) || defined(__arm64__)
175 extern ppnum_t pmap_first_pnum;           /* the first valid physical page on the system == atop(gDramBase) */
176 extern uint_t pmap_free_pages_span(void); /* report phys address range of unused physical pages */
177 #endif /* defined(__arm__) || defined(__arm64__) */
178 
179 extern void pmap_startup(vm_offset_t *startp, vm_offset_t *endp); /* allocate vm_page structs */
180 
181 extern void pmap_init(void); /* Initialization, once we have kernel virtual memory.  */
182 
183 extern void mapping_adjust(void); /* Adjust free mapping count */
184 
185 extern void mapping_free_prime(void); /* Primes the mapping block release list */
186 
187 #ifndef MACHINE_PAGES
188 /*
189  *	If machine/pmap.h defines MACHINE_PAGES, it must implement
190  *	the above functions.  The pmap module has complete control.
191  *	Otherwise, it must implement the following functions:
192  *		pmap_free_pages
193  *		pmap_virtual_space
194  *		pmap_next_page
195  *		pmap_init
196  *	and vm/vm_resident.c implements pmap_steal_memory and pmap_startup
197  *	using pmap_free_pages, pmap_next_page, pmap_virtual_space,
198  *	and pmap_enter.  pmap_free_pages may over-estimate the number
199  *	of unused physical pages, and pmap_next_page may return FALSE
200  *	to indicate that there are no more unused pages to return.
201  *	However, for best performance pmap_free_pages should be accurate.
202  */
203 
204 /*
205  * Routines to return the next unused physical page.
206  */
207 extern boolean_t pmap_next_page(ppnum_t *pnum);
208 extern boolean_t pmap_next_page_hi(ppnum_t *pnum, boolean_t might_free);
209 #ifdef __x86_64__
210 extern kern_return_t pmap_next_page_large(ppnum_t *pnum);
211 extern void pmap_hi_pages_done(void);
212 #endif
213 
214 #if CONFIG_SPTM
215 __enum_decl(pmap_mapping_type_t, uint8_t, {
216 	PMAP_MAPPING_TYPE_INFER = SPTM_UNTYPED,
217 	PMAP_MAPPING_TYPE_DEFAULT = XNU_DEFAULT,
218 	PMAP_MAPPING_TYPE_ROZONE = XNU_ROZONE,
219 	PMAP_MAPPING_TYPE_RESTRICTED = XNU_KERNEL_RESTRICTED
220 });
221 #else
222 __enum_decl(pmap_mapping_type_t, uint8_t, {
223 	PMAP_MAPPING_TYPE_INFER = 0,
224 	PMAP_MAPPING_TYPE_DEFAULT,
225 	PMAP_MAPPING_TYPE_ROZONE,
226 	PMAP_MAPPING_TYPE_RESTRICTED
227 });
228 #endif
229 
230 /*
231  * Report virtual space available for the kernel.
232  */
233 extern void pmap_virtual_space(
234 	vm_offset_t     *virtual_start,
235 	vm_offset_t     *virtual_end);
236 #endif  /* MACHINE_PAGES */
237 
238 /*
239  * Routines to manage the physical map data structure.
240  */
241 extern pmap_t(pmap_kernel)(void);               /* Return the kernel's pmap */
242 extern void             pmap_reference(pmap_t pmap);    /* Gain a reference. */
243 extern void             pmap_destroy(pmap_t pmap); /* Release a reference. */
244 extern void             pmap_switch(pmap_t pmap, thread_t thread);
245 extern void             pmap_require(pmap_t pmap);
246 
247 #if MACH_ASSERT
248 extern void pmap_set_process(pmap_t pmap,
249     int pid,
250     char *procname);
251 #endif /* MACH_ASSERT */
252 
253 extern kern_return_t    pmap_enter(     /* Enter a mapping */
254 	pmap_t          pmap,
255 	vm_map_offset_t v,
256 	ppnum_t         pn,
257 	vm_prot_t       prot,
258 	vm_prot_t       fault_type,
259 	unsigned int    flags,
260 	boolean_t       wired,
261 	pmap_mapping_type_t mapping_type);
262 
263 extern kern_return_t    pmap_enter_options(
264 	pmap_t pmap,
265 	vm_map_offset_t v,
266 	ppnum_t pn,
267 	vm_prot_t prot,
268 	vm_prot_t fault_type,
269 	unsigned int flags,
270 	boolean_t wired,
271 	unsigned int options,
272 	void *arg,
273 	pmap_mapping_type_t mapping_type);
274 extern kern_return_t    pmap_enter_options_addr(
275 	pmap_t pmap,
276 	vm_map_offset_t v,
277 	pmap_paddr_t pa,
278 	vm_prot_t prot,
279 	vm_prot_t fault_type,
280 	unsigned int flags,
281 	boolean_t wired,
282 	unsigned int options,
283 	void *arg,
284 	pmap_mapping_type_t mapping_type);
285 
286 extern void             pmap_remove_some_phys(
287 	pmap_t          pmap,
288 	ppnum_t         pn);
289 
290 extern void             pmap_lock_phys_page(
291 	ppnum_t         pn);
292 
293 extern void             pmap_unlock_phys_page(
294 	ppnum_t         pn);
295 
296 
297 /*
298  *	Routines that operate on physical addresses.
299  */
300 
301 extern void             pmap_page_protect(      /* Restrict access to page. */
302 	ppnum_t phys,
303 	vm_prot_t       prot);
304 
305 extern void             pmap_page_protect_options(      /* Restrict access to page. */
306 	ppnum_t phys,
307 	vm_prot_t       prot,
308 	unsigned int    options,
309 	void            *arg);
310 
311 extern void(pmap_zero_page)(
312 	ppnum_t         pn);
313 
314 extern void(pmap_zero_page_with_options)(
315 	ppnum_t         pn,
316 	int             options);
317 
318 extern void(pmap_zero_part_page)(
319 	ppnum_t         pn,
320 	vm_offset_t     offset,
321 	vm_size_t       len);
322 
323 extern void(pmap_copy_page)(
324 	ppnum_t         src,
325 	ppnum_t         dest,
326 	int             options);
327 
328 extern void(pmap_copy_part_page)(
329 	ppnum_t         src,
330 	vm_offset_t     src_offset,
331 	ppnum_t         dst,
332 	vm_offset_t     dst_offset,
333 	vm_size_t       len);
334 
335 extern void(pmap_copy_part_lpage)(
336 	vm_offset_t     src,
337 	ppnum_t         dst,
338 	vm_offset_t     dst_offset,
339 	vm_size_t       len);
340 
341 extern void(pmap_copy_part_rpage)(
342 	ppnum_t         src,
343 	vm_offset_t     src_offset,
344 	vm_offset_t     dst,
345 	vm_size_t       len);
346 
347 extern unsigned int(pmap_disconnect)(   /* disconnect mappings and return reference and change */
348 	ppnum_t         phys);
349 
350 extern unsigned int(pmap_disconnect_options)(   /* disconnect mappings and return reference and change */
351 	ppnum_t         phys,
352 	unsigned int    options,
353 	void            *arg);
354 
355 extern kern_return_t(pmap_attribute_cache_sync)(      /* Flush appropriate
356                                                        * cache based on
357                                                        * page number sent */
358 	ppnum_t         pn,
359 	vm_size_t       size,
360 	vm_machine_attribute_t attribute,
361 	vm_machine_attribute_val_t* value);
362 
363 extern unsigned int(pmap_cache_attributes)(
364 	ppnum_t         pn);
365 
366 /*
367  * Set (override) cache attributes for the specified physical page
368  */
369 extern  void            pmap_set_cache_attributes(
370 	ppnum_t,
371 	unsigned int);
372 
373 extern void            *pmap_map_compressor_page(
374 	ppnum_t);
375 
376 extern void             pmap_unmap_compressor_page(
377 	ppnum_t,
378 	void*);
379 
380 /**
381  * The following declarations are meant to provide a uniform interface by which the VM layer can
382  * pass batches of pages to the pmap layer directly, in the various page list formats natively
383  * used by the VM.  If a new type of list is to be added, the various structures and iterator
384  * functions below should be updated to understand it, and then it should "just work" with the
385  * pmap layer.
386  */
387 
388 /* The various supported page list types. */
389 __enum_decl(unified_page_list_type_t, uint8_t, {
390 	/* Universal page list array, essentially an array of ppnum_t. */
391 	UNIFIED_PAGE_LIST_TYPE_UPL_ARRAY,
392 	/**
393 	 * Singly-linked list of vm_page_t, using vmp_snext field.
394 	 * This is typically used to construct local lists of pages to be freed.
395 	 */
396 	UNIFIED_PAGE_LIST_TYPE_VM_PAGE_LIST,
397 	/* Doubly-linked queue of vm_page_t's associated with a VM object, using vmp_listq field. */
398 	UNIFIED_PAGE_LIST_TYPE_VM_PAGE_OBJ_Q,
399 	/* Doubly-linked queue of vm_page_t's in a FIFO queue or global free list, using vmp_pageq field. */
400 	UNIFIED_PAGE_LIST_TYPE_VM_PAGE_FIFO_Q,
401 });
402 
403 /* Uniform data structure encompassing the various page list types handled by the VM layer. */
404 typedef struct {
405 	union {
406 		/* Base address and size (in pages) of UPL array for type UNIFIED_PAGE_LIST_TYPE_UPL_ARRAY */
407 		struct {
408 			upl_page_info_array_t upl_info;
409 			unsigned int upl_size;
410 		} upl;
411 		/* Head of singly-linked vm_page_t list for UNIFIED_PAGE_LIST_TYPE_VM_PAGE_LIST */
412 		vm_page_t page_slist;
413 		/* Head of queue for UNIFIED_PAGE_LIST_TYPE_VM_PAGE_OBJ_Q and UNIFIED_PAGE_LIST_TYPE_VM_PAGE_FIFO_Q */
414 		void *pageq; /* vm_page_queue_head_t* */
415 	};
416 	unified_page_list_type_t type;
417 } unified_page_list_t;
418 
419 /* Uniform data structure representing an iterator position within a unified_page_list_t object. */
420 typedef struct {
421 	/* Pointer to list structure from which this iterator was created. */
422 	const unified_page_list_t *list;
423 	union {
424 		/* Position within UPL array, for UNIFIED_PAGE_LIST_TYPE_UPL_ARRAY */
425 		unsigned int upl_index;
426 		/* Position within page list or page queue, for all other types */
427 		vm_page_t pageq_pos;
428 	};
429 } unified_page_list_iterator_t;
430 
431 extern void unified_page_list_iterator_init(
432 	const unified_page_list_t *page_list,
433 	unified_page_list_iterator_t *iter);
434 
435 extern void unified_page_list_iterator_next(unified_page_list_iterator_t *iter);
436 
437 extern bool unified_page_list_iterator_end(const unified_page_list_iterator_t *iter);
438 
439 extern ppnum_t unified_page_list_iterator_page(
440 	const unified_page_list_iterator_t *iter,
441 	bool *is_fictitious);
442 
443 extern vm_page_t unified_page_list_iterator_vm_page(
444 	const unified_page_list_iterator_t *iter);
445 
446 extern void pmap_batch_set_cache_attributes(
447 	const unified_page_list_t *,
448 	unsigned int);
449 extern void pmap_sync_page_data_phys(ppnum_t pa);
450 extern void pmap_sync_page_attributes_phys(ppnum_t pa);
451 
452 
453 /*
454  * debug/assertions. pmap_verify_free returns true iff
455  * the given physical page is mapped into no pmap.
456  * pmap_assert_free() will panic() if pn is not free.
457  */
458 extern bool pmap_verify_free(ppnum_t pn);
459 #if MACH_ASSERT
460 extern void pmap_assert_free(ppnum_t pn);
461 #endif
462 
463 
464 /*
465  *	Sundry required (internal) routines
466  */
467 #ifdef CURRENTLY_UNUSED_AND_UNTESTED
468 extern void             pmap_collect(pmap_t pmap);/* Perform garbage
469                                                    * collection, if any */
470 #endif
471 /*
472  *	Optional routines
473  */
474 extern void(pmap_copy)(                         /* Copy range of mappings,
475                                                  * if desired. */
476 	pmap_t          dest,
477 	pmap_t          source,
478 	vm_map_offset_t dest_va,
479 	vm_map_size_t   size,
480 	vm_map_offset_t source_va);
481 
482 extern kern_return_t(pmap_attribute)(           /* Get/Set special memory
483                                                  * attributes */
484 	pmap_t          pmap,
485 	vm_map_offset_t va,
486 	vm_map_size_t   size,
487 	vm_machine_attribute_t  attribute,
488 	vm_machine_attribute_val_t* value);
489 
490 /*
491  * Routines defined as macros.
492  */
493 #ifndef PMAP_ACTIVATE_USER
494 #ifndef PMAP_ACTIVATE
495 #define PMAP_ACTIVATE_USER(thr, cpu)
496 #else   /* PMAP_ACTIVATE */
497 #define PMAP_ACTIVATE_USER(thr, cpu) {                  \
498 	pmap_t  pmap;                                           \
499                                                                 \
500 	pmap = (thr)->map->pmap;                                \
501 	if (pmap != pmap_kernel())                              \
502 	        PMAP_ACTIVATE(pmap, (thr), (cpu));              \
503 }
504 #endif  /* PMAP_ACTIVATE */
505 #endif  /* PMAP_ACTIVATE_USER */
506 
507 #ifndef PMAP_DEACTIVATE_USER
508 #ifndef PMAP_DEACTIVATE
509 #define PMAP_DEACTIVATE_USER(thr, cpu)
510 #else   /* PMAP_DEACTIVATE */
511 #define PMAP_DEACTIVATE_USER(thr, cpu) {                        \
512 	pmap_t  pmap;                                           \
513                                                                 \
514 	pmap = (thr)->map->pmap;                                \
515 	if ((pmap) != pmap_kernel())                    \
516 	        PMAP_DEACTIVATE(pmap, (thr), (cpu));    \
517 }
518 #endif  /* PMAP_DEACTIVATE */
519 #endif  /* PMAP_DEACTIVATE_USER */
520 
521 #ifndef PMAP_ACTIVATE_KERNEL
522 #ifndef PMAP_ACTIVATE
523 #define PMAP_ACTIVATE_KERNEL(cpu)
524 #else   /* PMAP_ACTIVATE */
525 #define PMAP_ACTIVATE_KERNEL(cpu)                       \
526 	        PMAP_ACTIVATE(pmap_kernel(), THREAD_NULL, cpu)
527 #endif  /* PMAP_ACTIVATE */
528 #endif  /* PMAP_ACTIVATE_KERNEL */
529 
530 #ifndef PMAP_DEACTIVATE_KERNEL
531 #ifndef PMAP_DEACTIVATE
532 #define PMAP_DEACTIVATE_KERNEL(cpu)
533 #else   /* PMAP_DEACTIVATE */
534 #define PMAP_DEACTIVATE_KERNEL(cpu)                     \
535 	        PMAP_DEACTIVATE(pmap_kernel(), THREAD_NULL, cpu)
536 #endif  /* PMAP_DEACTIVATE */
537 #endif  /* PMAP_DEACTIVATE_KERNEL */
538 
539 #ifndef PMAP_SET_CACHE_ATTR
540 #define PMAP_SET_CACHE_ATTR(mem, object, cache_attr, batch_pmap_op)             \
541 	MACRO_BEGIN                                                             \
542 	        if (!batch_pmap_op) {                                           \
543 	                pmap_set_cache_attributes(VM_PAGE_GET_PHYS_PAGE(mem), cache_attr); \
544 	                (object)->set_cache_attr = TRUE;                        \
545 	        }                                                               \
546 	MACRO_END
547 #endif  /* PMAP_SET_CACHE_ATTR */
548 
549 #ifndef PMAP_BATCH_SET_CACHE_ATTR
550 #define PMAP_BATCH_SET_CACHE_ATTR(object, user_page_list,                   \
551 	    cache_attr, num_pages, batch_pmap_op)                               \
552 	MACRO_BEGIN                                                             \
553 	        if ((batch_pmap_op)) {                                          \
554 	                const unified_page_list_t __pmap_batch_list = {         \
555 	                        .upl = {.upl_info = (user_page_list),           \
556 	                                .upl_size = (num_pages),},              \
557 	                        .type = UNIFIED_PAGE_LIST_TYPE_UPL_ARRAY,       \
558 	                };                                                      \
559 	                pmap_batch_set_cache_attributes(                        \
560 	                                &__pmap_batch_list,                     \
561 	                                (cache_attr));                          \
562 	                (object)->set_cache_attr = TRUE;                        \
563 	        }                                                               \
564 	MACRO_END
565 #endif  /* PMAP_BATCH_SET_CACHE_ATTR */
566 
567 /*
568  *	Routines to manage reference/modify bits based on
569  *	physical addresses, simulating them if not provided
570  *	by the hardware.
571  */
572 struct pfc {
573 	long    pfc_cpus;
574 	long    pfc_invalid_global;
575 };
576 
577 typedef struct pfc      pmap_flush_context;
578 
579 /* Clear reference bit */
580 extern void             pmap_clear_reference(ppnum_t     pn);
581 /* Return reference bit */
582 extern boolean_t(pmap_is_referenced)(ppnum_t     pn);
583 /* Set modify bit */
584 extern void             pmap_set_modify(ppnum_t  pn);
585 /* Clear modify bit */
586 extern void             pmap_clear_modify(ppnum_t pn);
587 /* Return modify bit */
588 extern boolean_t        pmap_is_modified(ppnum_t pn);
589 /* Return modified and referenced bits */
590 extern unsigned int pmap_get_refmod(ppnum_t pn);
591 /* Clear modified and referenced bits */
592 extern void                     pmap_clear_refmod(ppnum_t pn, unsigned int mask);
593 #define VM_MEM_MODIFIED         0x01    /* Modified bit */
594 #define VM_MEM_REFERENCED       0x02    /* Referenced bit */
595 extern void                     pmap_clear_refmod_options(ppnum_t pn, unsigned int mask, unsigned int options, void *);
596 
597 /*
598  * Clears the reference and/or modified bits on a range of virtually
599  * contiguous pages.
600  * It returns true if the operation succeeded. If it returns false,
601  * nothing has been modified.
602  * This operation is only supported on some platforms, so callers MUST
603  * handle the case where it returns false.
604  */
605 extern bool
606 pmap_clear_refmod_range_options(
607 	pmap_t pmap,
608 	vm_map_address_t start,
609 	vm_map_address_t end,
610 	unsigned int mask,
611 	unsigned int options);
612 
613 
614 extern void pmap_flush_context_init(pmap_flush_context *);
615 extern void pmap_flush(pmap_flush_context *);
616 
617 /*
618  *	Routines that operate on ranges of virtual addresses.
619  */
620 extern void             pmap_protect(   /* Change protections. */
621 	pmap_t          map,
622 	vm_map_offset_t s,
623 	vm_map_offset_t e,
624 	vm_prot_t       prot);
625 
626 extern void             pmap_protect_options(   /* Change protections. */
627 	pmap_t          map,
628 	vm_map_offset_t s,
629 	vm_map_offset_t e,
630 	vm_prot_t       prot,
631 	unsigned int    options,
632 	void            *arg);
633 
634 extern void(pmap_pageable)(
635 	pmap_t          pmap,
636 	vm_map_offset_t start,
637 	vm_map_offset_t end,
638 	boolean_t       pageable);
639 
640 extern uint64_t pmap_shared_region_size_min(pmap_t map);
641 
642 extern kern_return_t pmap_nest(pmap_t,
643     pmap_t,
644     addr64_t,
645     uint64_t);
646 extern kern_return_t pmap_unnest(pmap_t,
647     addr64_t,
648     uint64_t);
649 
650 #define PMAP_UNNEST_CLEAN       1
651 
652 #if __arm64__
653 #if CONFIG_SPTM
654 #define PMAP_FORK_NEST 1
655 #endif /* CONFIG_SPTM */
656 
657 #if PMAP_FORK_NEST
658 extern kern_return_t pmap_fork_nest(
659 	pmap_t old_pmap,
660 	pmap_t new_pmap,
661 	vm_map_offset_t *nesting_start,
662 	vm_map_offset_t *nesting_end);
663 #endif /* PMAP_FORK_NEST */
664 #endif /* __arm64__ */
665 
666 extern kern_return_t pmap_unnest_options(pmap_t,
667     addr64_t,
668     uint64_t,
669     unsigned int);
670 extern boolean_t pmap_adjust_unnest_parameters(pmap_t, vm_map_offset_t *, vm_map_offset_t *);
671 extern void             pmap_advise_pagezero_range(pmap_t, uint64_t);
672 #endif  /* MACH_KERNEL_PRIVATE */
673 
674 extern boolean_t        pmap_is_noencrypt(ppnum_t);
675 extern void             pmap_set_noencrypt(ppnum_t pn);
676 extern void             pmap_clear_noencrypt(ppnum_t pn);
677 
678 /*
679  * JMM - This portion is exported to other kernel components right now,
680  * but will be pulled back in the future when the needed functionality
681  * is provided in a cleaner manner.
682  */
683 
684 extern const pmap_t     kernel_pmap;            /* The kernel's map */
685 #define pmap_kernel()   (kernel_pmap)
686 
687 #define VM_MEM_SUPERPAGE        0x100           /* map a superpage instead of a base page */
688 #define VM_MEM_STACK            0x200
689 
690 /* N.B. These use the same numerical space as the PMAP_EXPAND_OPTIONS
691  * definitions in i386/pmap_internal.h
692  */
693 #define PMAP_CREATE_64BIT          0x1
694 
695 #if __x86_64__
696 
697 #define PMAP_CREATE_EPT            0x2
698 #define PMAP_CREATE_TEST           0x4 /* pmap will be used for testing purposes only */
699 #define PMAP_CREATE_KNOWN_FLAGS (PMAP_CREATE_64BIT | PMAP_CREATE_EPT | PMAP_CREATE_TEST)
700 
701 #else
702 
703 #define PMAP_CREATE_STAGE2         0
704 #if __arm64e__
705 #define PMAP_CREATE_DISABLE_JOP    0x4
706 #else
707 #define PMAP_CREATE_DISABLE_JOP    0
708 #endif
709 #if __ARM_MIXED_PAGE_SIZE__
710 #define PMAP_CREATE_FORCE_4K_PAGES 0x8
711 #else
712 #define PMAP_CREATE_FORCE_4K_PAGES 0
713 #endif /* __ARM_MIXED_PAGE_SIZE__ */
714 #define PMAP_CREATE_X86_64         0
715 #if CONFIG_ROSETTA
716 #define PMAP_CREATE_ROSETTA        0x20
717 #else
718 #define PMAP_CREATE_ROSETTA        0
719 #endif /* CONFIG_ROSETTA */
720 
721 #define PMAP_CREATE_TEST           0x40 /* pmap will be used for testing purposes only */
722 
723 /* Define PMAP_CREATE_KNOWN_FLAGS in terms of optional flags */
724 #define PMAP_CREATE_KNOWN_FLAGS (PMAP_CREATE_64BIT | PMAP_CREATE_STAGE2 | PMAP_CREATE_DISABLE_JOP | \
725     PMAP_CREATE_FORCE_4K_PAGES | PMAP_CREATE_X86_64 | PMAP_CREATE_ROSETTA | PMAP_CREATE_TEST)
726 
727 #endif /* __x86_64__ */
728 
729 #define PMAP_OPTIONS_NOWAIT     0x1             /* don't block, return
730 	                                         * KERN_RESOURCE_SHORTAGE
731 	                                         * instead */
732 #define PMAP_OPTIONS_NOENTER    0x2             /* expand pmap if needed
733 	                                         * but don't enter mapping
734 	                                         */
735 #define PMAP_OPTIONS_COMPRESSOR 0x4             /* credit the compressor for
736 	                                         * this operation */
737 #define PMAP_OPTIONS_INTERNAL   0x8             /* page from internal object */
738 #define PMAP_OPTIONS_REUSABLE   0x10            /* page is "reusable" */
739 #define PMAP_OPTIONS_NOFLUSH    0x20            /* delay flushing of pmap */
740 #define PMAP_OPTIONS_NOREFMOD   0x40            /* don't need ref/mod on disconnect */
741 #define PMAP_OPTIONS_ALT_ACCT   0x80            /* use alternate accounting scheme for page */
742 #define PMAP_OPTIONS_REMOVE     0x100           /* removing a mapping */
743 #define PMAP_OPTIONS_SET_REUSABLE   0x200       /* page is now "reusable" */
744 #define PMAP_OPTIONS_CLEAR_REUSABLE 0x400       /* page no longer "reusable" */
745 #define PMAP_OPTIONS_COMPRESSOR_IFF_MODIFIED 0x800 /* credit the compressor
746 	                                            * iff page was modified */
747 #define PMAP_OPTIONS_PROTECT_IMMEDIATE 0x1000   /* allow protections to be
748 	                                         * be upgraded */
749 #define PMAP_OPTIONS_CLEAR_WRITE 0x2000
750 #define PMAP_OPTIONS_TRANSLATED_ALLOW_EXECUTE 0x4000 /* Honor execute for translated processes */
751 #if defined(__arm__) || defined(__arm64__)
752 #define PMAP_OPTIONS_FF_LOCKED  0x8000
753 #define PMAP_OPTIONS_FF_WIRED   0x10000
754 #endif
755 #define PMAP_OPTIONS_XNU_USER_DEBUG 0x20000
756 
757 /* Indicates that pmap_enter() or pmap_remove() is being called with preemption already disabled. */
758 #define PMAP_OPTIONS_NOPREEMPT  0x80000
759 
760 #define PMAP_OPTIONS_MAP_TPRO 0x40000
761 
762 #define PMAP_OPTIONS_RESERVED_MASK 0xFF000000   /* encoding space reserved for internal pmap use */
763 
764 #if     !defined(__LP64__)
765 extern vm_offset_t      pmap_extract(pmap_t pmap,
766     vm_map_offset_t va);
767 #endif
768 extern void             pmap_change_wiring(     /* Specify pageability */
769 	pmap_t          pmap,
770 	vm_map_offset_t va,
771 	boolean_t       wired);
772 
773 /* LP64todo - switch to vm_map_offset_t when it grows */
774 extern void             pmap_remove(    /* Remove mappings. */
775 	pmap_t          map,
776 	vm_map_offset_t s,
777 	vm_map_offset_t e);
778 
779 extern void             pmap_remove_options(    /* Remove mappings. */
780 	pmap_t          map,
781 	vm_map_offset_t s,
782 	vm_map_offset_t e,
783 	int             options);
784 
785 extern void             fillPage(ppnum_t pa, unsigned int fill);
786 
787 #if defined(__LP64__)
788 extern void pmap_pre_expand(pmap_t pmap, vm_map_offset_t vaddr);
789 extern kern_return_t pmap_pre_expand_large(pmap_t pmap, vm_map_offset_t vaddr);
790 extern vm_size_t pmap_query_pagesize(pmap_t map, vm_map_offset_t vaddr);
791 #endif
792 
793 mach_vm_size_t pmap_query_resident(pmap_t pmap,
794     vm_map_offset_t s,
795     vm_map_offset_t e,
796     mach_vm_size_t *compressed_bytes_p);
797 
798 extern void pmap_set_vm_map_cs_enforced(pmap_t pmap, bool new_value);
799 extern bool pmap_get_vm_map_cs_enforced(pmap_t pmap);
800 
801 /* Inform the pmap layer that there is a JIT entry in this map. */
802 extern void pmap_set_jit_entitled(pmap_t pmap);
803 
804 /* Ask the pmap layer if there is a JIT entry in this map. */
805 extern bool pmap_get_jit_entitled(pmap_t pmap);
806 
807 /* Inform the pmap layer that the XO register is repurposed for this map */
808 extern void pmap_set_tpro(pmap_t pmap);
809 
810 /* Ask the pmap layer if there is a TPRO entry in this map. */
811 extern bool pmap_get_tpro(pmap_t pmap);
812 
813 /*
814  * Tell the pmap layer what range within the nested region the VM intends to
815  * use.
816  */
817 extern void pmap_trim(pmap_t grand, pmap_t subord, addr64_t vstart, uint64_t size);
818 
819 extern bool pmap_is_nested(pmap_t pmap);
820 
821 /*
822  * Dump page table contents into the specified buffer.  Returns KERN_INSUFFICIENT_BUFFER_SIZE
823  * if insufficient space, KERN_NOT_SUPPORTED if unsupported in the current configuration.
824  * This is expected to only be called from kernel debugger context,
825  * so synchronization is not required.
826  */
827 
828 extern kern_return_t pmap_dump_page_tables(pmap_t pmap, void *bufp, void *buf_end, unsigned int level_mask, size_t *bytes_copied);
829 
830 /* Asks the pmap layer for number of bits used for VA address. */
831 extern uint32_t pmap_user_va_bits(pmap_t pmap);
832 extern uint32_t pmap_kernel_va_bits(void);
833 
834 /*
835  * Indicates if any special policy is applied to this protection by the pmap
836  * layer.
837  */
838 bool pmap_has_prot_policy(pmap_t pmap, bool translated_allow_execute, vm_prot_t prot);
839 
840 /*
841  * Causes the pmap to return any available pages that it can return cheaply to
842  * the VM.
843  */
844 uint64_t pmap_release_pages_fast(void);
845 
846 #define PMAP_QUERY_PAGE_PRESENT                 0x01
847 #define PMAP_QUERY_PAGE_REUSABLE                0x02
848 #define PMAP_QUERY_PAGE_INTERNAL                0x04
849 #define PMAP_QUERY_PAGE_ALTACCT                 0x08
850 #define PMAP_QUERY_PAGE_COMPRESSED              0x10
851 #define PMAP_QUERY_PAGE_COMPRESSED_ALTACCT      0x20
852 extern kern_return_t pmap_query_page_info(
853 	pmap_t          pmap,
854 	vm_map_offset_t va,
855 	int             *disp);
856 
857 extern bool pmap_in_ppl(void);
858 
859 extern uint32_t pmap_lookup_in_static_trust_cache(const uint8_t cdhash[CS_CDHASH_LEN]);
860 extern bool pmap_lookup_in_loaded_trust_caches(const uint8_t cdhash[CS_CDHASH_LEN]);
861 
862 /**
863  * Indicates whether the device supports register-level MMIO access control.
864  *
865  * @note Unlike the pmap-io-ranges mechanism, which enforces PPL-only register
866  *       writability at page granularity, this mechanism allows specific registers
867  *       on a read-mostly page to be written using a dedicated guarded mode trap
868  *       without requiring a full PPL driver extension.
869  *
870  * @return True if the device supports register-level MMIO access control.
871  */
872 extern bool pmap_has_iofilter_protected_write(void);
873 
874 /**
875  * Performs a write to the I/O register specified by addr on supported devices.
876  *
877  * @note On supported devices (determined by pmap_has_iofilter_protected_write()), this
878  *       function goes over the sorted I/O filter entry table. If there is a hit, the
879  *       write is performed from Guarded Mode. Otherwise, the write is performed from
880  *       Normal Mode (kernel mode). Note that you can still hit an exception if the
881  *       register is owned by PPL but not allowed by an io-filter-entry in the device tree.
882  *
883  * @note On unsupported devices, this function will panic.
884  *
885  * @param addr The address of the register.
886  * @param value The value to be written.
887  * @param width The width of the I/O register, supported values are 1, 2, 4 and 8.
888  */
889 extern void pmap_iofilter_protected_write(vm_address_t addr, uint64_t value, uint64_t width);
890 
891 extern void *pmap_claim_reserved_ppl_page(void);
892 extern void pmap_free_reserved_ppl_page(void *kva);
893 
894 extern void pmap_ledger_verify_size(size_t);
895 extern ledger_t pmap_ledger_alloc(void);
896 extern void pmap_ledger_free(ledger_t);
897 
898 extern bool pmap_is_bad_ram(ppnum_t ppn);
899 
900 extern bool pmap_is_page_restricted(ppnum_t pn);
901 
902 #if __arm64__
903 extern bool pmap_is_exotic(pmap_t pmap);
904 #else /* __arm64__ */
905 #define pmap_is_exotic(pmap) false
906 #endif /* __arm64__ */
907 
908 
909 /*
910  * Returns a subset of pmap_cs non-default configuration,
911  * e.g. loosening up of some restrictions through pmap_cs or amfi
912  * boot-args. The return value is a bit field with possible bits
913  * described below. If default, the function will return 0. Note that
914  * this does not work the other way: 0 does not imply that pmap_cs
915  * runs in default configuration, and only a small configuration
916  * subset is returned by this function.
917  *
918  * Never assume the system is "secure" if this returns 0.
919  */
920 extern int pmap_cs_configuration(void);
921 
922 #if XNU_KERNEL_PRIVATE
923 
924 typedef enum {
925 	PMAP_FEAT_UEXEC = 1
926 } pmap_feature_flags_t;
927 
928 #if defined(__x86_64__)
929 
930 extern bool             pmap_supported_feature(pmap_t pmap, pmap_feature_flags_t feat);
931 
932 #endif
933 #if defined(__arm64__)
934 
935 /**
936  * Check if a particular pmap is used for stage2 translations or not.
937  */
938 extern bool
939 pmap_performs_stage2_translations(const pmap_t pmap);
940 
941 #endif /* defined(__arm64__) */
942 
943 extern ppnum_t          kernel_pmap_present_mapping(uint64_t vaddr, uint64_t * pvincr, uintptr_t * pvphysaddr);
944 
945 #endif /* XNU_KERNEL_PRIVATE */
946 
947 #if CONFIG_SPTM
948 /*
949  * The TrustedExecutionMonitor address space data structure is kept within the
950  * pmap structure in order to provide a coherent API to the rest of the kernel
951  * for working with code signing monitors.
952  *
953  * However, a lot of parts of the kernel don't have visibility into the pmap
954  * data structure as they are opaque unless you're in the Mach portion of the
955  * kernel. To allievate this, we provide pmap APIs to the rest of the kernel.
956  */
957 #include <TrustedExecutionMonitor/API.h>
958 
959 /*
960  * All pages allocated by TXM are also kept within the TXM VM object, which allows
961  * tracking it for accounting and debugging purposes.
962  */
963 extern vm_object_t txm_vm_object;
964 
965 /**
966  * Acquire the pointer of the kernel pmap being used for the system.
967  */
968 extern pmap_t
969 pmap_txm_kernel_pmap(void);
970 
971 /**
972  * Acquire the TXM address space object stored within the pmap.
973  */
974 extern TXMAddressSpace_t*
975 pmap_txm_addr_space(const pmap_t pmap);
976 
977 /**
978  * Set the TXM address space object within the pmap.
979  */
980 extern void
981 pmap_txm_set_addr_space(
982 	pmap_t pmap,
983 	TXMAddressSpace_t *txm_addr_space);
984 
985 /**
986  * Set the trust level of the TXM address space object within the pmap.
987  */
988 extern void
989 pmap_txm_set_trust_level(
990 	pmap_t pmap,
991 	CSTrust_t trust_level);
992 
993 /**
994  * Get the trust level of the TXM address space object within the pmap.
995  */
996 extern kern_return_t
997 pmap_txm_get_trust_level_kdp(
998 	pmap_t pmap,
999 	CSTrust_t *trust_level);
1000 
1001 /**
1002  * Get the address range of the JIT region within the pmap, if any.
1003  */
1004 kern_return_t
1005 pmap_txm_get_jit_address_range_kdp(
1006 	pmap_t pmap,
1007 	uintptr_t *jit_region_start,
1008 	uintptr_t *jit_region_end);
1009 
1010 /**
1011  * Take a shared lock on the pmap in order to enforce safe concurrency for
1012  * an operation on the TXM address space object. Passing in NULL takes the lock
1013  * on the current pmap.
1014  */
1015 extern void
1016 pmap_txm_acquire_shared_lock(pmap_t pmap);
1017 
1018 /**
1019  * Release the shared lock which was previously acquired for operations on
1020  * the TXM address space object. Passing in NULL releases the lock for the
1021  * current pmap.
1022  */
1023 extern void
1024 pmap_txm_release_shared_lock(pmap_t pmap);
1025 
1026 /**
1027  * Take an exclusive lock on the pmap in order to enforce safe concurrency for
1028  * an operation on the TXM address space object. Passing in NULL takes the lock
1029  * on the current pmap.
1030  */
1031 extern void
1032 pmap_txm_acquire_exclusive_lock(pmap_t pmap);
1033 
1034 /**
1035  * Release the exclusive lock which was previously acquired for operations on
1036  * the TXM address space object. Passing in NULL releases the lock for the
1037  * current pmap.
1038  */
1039 extern void
1040 pmap_txm_release_exclusive_lock(pmap_t pmap);
1041 
1042 /**
1043  * Transfer a page to the TXM_DEFAULT type after resolving its mapping from its
1044  * virtual to physical address.
1045  */
1046 extern void
1047 pmap_txm_transfer_page(const vm_address_t addr);
1048 
1049 /**
1050  * Grab an available page from the VM free list, add it to the TXM VM object and
1051  * then transfer it to be owned by TXM.
1052  *
1053  * Returns the physical address of the page allocated.
1054  */
1055 extern vm_map_address_t
1056 pmap_txm_allocate_page(void);
1057 
1058 #endif /* CONFIG_SPTM */
1059 
1060 
1061 #endif  /* KERNEL_PRIVATE */
1062 
1063 #endif  /* _VM_PMAP_H_ */
1064