1 /*
2 * Copyright (c) 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 * This header file is used to store the types, prototypes, and inline functions
30 * that define some of the most important data structures used in the pmap. This
31 * header is only meant for sharing types within the pmap; if a type is meant to
32 * be used by the rest of the kernel, then put it into osfmk/arm/pmap.h.
33 */
34 #ifndef _ARM_PMAP_PMAP_DATA_H_
35 #define _ARM_PMAP_PMAP_DATA_H_
36
37 #include <stdint.h>
38
39 #include <kern/ledger.h>
40 #include <mach/vm_types.h>
41 #include <mach_assert.h>
42 #include <vm/vm_page.h>
43
44 #include <arm/cpu_data.h>
45 #include <arm/machine_routines.h>
46 #include <arm/proc_reg.h>
47 #if defined(__arm64__)
48 #include <arm64/proc_reg.h>
49 #endif /* defined(__arm64__) */
50
51 /* Temporary include before moving all ledger functions into pmap_data.c */
52 #include <os/refcnt.h>
53
54 /**
55 * These headers are safe to be included in this file since they shouldn't rely
56 * on any of the internal pmap header files (so no circular dependencies).
57 */
58 #include <arm/pmap.h>
59 #include <arm/pmap/pmap_pt_geometry.h>
60
61 /**
62 * These values represent the first and last kernel-managed physical addresses.
63 * We keep track of extra metadata on kernel-managed pages compared to other
64 * pages (usually iBoot carved out memory or I/O).
65 */
66 extern pmap_paddr_t vm_first_phys, vm_last_phys;
67
68 /**
69 * Return whether the given address represents a kernel-managed physical page.
70 *
71 * Whether a page is considered "kernel-managed" is determined by the BootArgs
72 * passed by the bootloader. Typically memory carved out by the bootloader as
73 * well as I/O memory should return false.
74 *
75 * @param pa The physical address to check.
76 */
77 static inline bool
pa_valid(pmap_paddr_t pa)78 pa_valid(pmap_paddr_t pa)
79 {
80 return (pa >= vm_first_phys) && (pa < vm_last_phys);
81 }
82
83 /**
84 * The pmap has a variety of data structures (pv_head_table/pp_attr_table) that
85 * contain an entry for every kernel-managed page in the system. These systems
86 * are indexed with physical address indices ("pai") generated by this function.
87 *
88 * The logic is simple since there should be one entry in each of these data
89 * structures for each kernel-managed physical page in the system. These data
90 * structures are allocated on boot based on the amount of memory available.
91 *
92 * @note PAIs are defined using the VM page size, which might not be identical
93 * to the underlying hardware page size for an arbitrary address space.
94 * This means that the data structures relying on PAIs will contain one
95 * entry for each VM page, not hardware page.
96 *
97 * @note This function is only valid for physical addresses that are
98 * kernel-managed.
99 */
100 static inline unsigned int
pa_index(pmap_paddr_t pa)101 pa_index(pmap_paddr_t pa)
102 {
103 return (unsigned int)atop(pa - vm_first_phys);
104 }
105
106 /* See the definition of pv_head_table for more information. */
107 extern pv_entry_t **pv_head_table;
108
109 /* Represents a NULL entry in the pv_head_table. */
110 #define PV_ENTRY_NULL ((pv_entry_t *) 0)
111
112 /**
113 * Given a physical address index, return the corresponding pv_head_table entry.
114 *
115 * @note Despite returning a pointer to a pv_entry_t pointer, the entry might
116 * actually be a different type of pointer (pt_entry_t or pt_desc_t)
117 * depending on the type for this entry. Determine the type using
118 * pvh_test_type().
119 *
120 * @param pai The index returned by pa_index() for the page whose pv_head_table
121 * entry should be retrieved.
122 */
123 static inline pv_entry_t **
pai_to_pvh(unsigned int pai)124 pai_to_pvh(unsigned int pai)
125 {
126 return &pv_head_table[pai];
127 }
128
129 /**
130 * Each pv_head_table entry can be one of four different types:
131 *
132 * - PVH_TYPE_NULL: No mappings to the physical page exist outside of the
133 * physical aperture. Physical aperture mappings are not
134 * tracked in the pv_head_table.
135 *
136 * - PVH_TYPE_PVEP: There are multiple mappings to the physical page.
137 * These entries are linked lists of pv_entry_t objects (which
138 * each contain a pointer to the associated PTE and a pointer
139 * to the next entry in the list).
140 *
141 * - PVH_TYPE_PTEP: There is a single mapping to the physical page. Once more
142 * mappings are created, this entry will get upgraded to an
143 * entry of type PVH_TYPE_PVEP. These entries are pointers
144 * directly to the page table entry that contain the mapping
145 * (pt_entry_t*).
146 *
147 * - PVH_TYPE_PTDP: The physical page is being used as a page table. These
148 * entries are pointers to page table descriptor structures
149 * (pt_desc_t) which contain metadata related to each page
150 * table.
151 *
152 * The type is stored in the bottom two bits of each pv_head_table entry. That
153 * type needs to be checked before dereferencing the pointer to determine which
154 * pointer type to dereference as.
155 */
156 #define PVH_TYPE_NULL 0x0UL
157 #define PVH_TYPE_PVEP 0x1UL
158 #define PVH_TYPE_PTEP 0x2UL
159 #define PVH_TYPE_PTDP 0x3UL
160
161 #define PVH_TYPE_MASK (0x3UL)
162
163 #if defined(__arm64__)
164
165 /**
166 * PV_HEAD_TABLE Flags.
167 *
168 * All flags listed below are stored in the pv_head_table entry/pointer
169 * (per-physical-page) unless otherwise noted.
170 *
171 * Please update the pv_walk LLDB macro if these flags are changed or added to.
172 */
173
174 /**
175 * This flag is set for every mapping created by an IOMMU.
176 *
177 * Stored in each PTE pointer (for PVH_TYPE_PVEP lists), or in the pv_head_table
178 * entry/pointer for single-PTE entries (PVH_TYPE_PTEP).
179 */
180 #define PVH_FLAG_IOMMU 0x4UL
181
182 /**
183 * This flag is only valid when PVH_FLAG_IOMMU is set. For an IOMMU mapping, if
184 * this bit is set, then the PTE pointer points directly into the IOMMU page
185 * table for this mapping. If this bit is cleared, then the "PTE pointer" is
186 * actually a pointer to the IOMMU descriptor object that owns this mapping.
187 *
188 * There are cases where it's not easy to tie an IOMMU mapping directly to a
189 * specific page table, so this allows us to at least get a pointer to which
190 * IOMMU created this mapping which is useful for debugging purposes.
191 *
192 * Stored in each PTE pointer (for PVH_TYPE_PVEP lists), or in the pv_head_table
193 * entry/pointer for single-PTE entries (PVH_TYPE_PTEP).
194 */
195 #define PVH_FLAG_IOMMU_TABLE (1ULL << 63)
196
197 /**
198 * This flag is set when the first CPU (non-IOMMU) mapping is created. This is
199 * important to keep track of because various accounting statistics are based on
200 * the options specified for the first CPU mapping. This flag, and thus the
201 * accounting statistics, will persist as long as there *any* mappings of the
202 * page (including IOMMU mappings). This works because the accounting for a page
203 * should not need to change until the page is recycled by the VM layer, and we
204 * double-check that there are no mappings (CPU or IOMMU) when a page is
205 * recycled (see: pmap_verify_free()).
206 */
207 #define PVH_FLAG_CPU (1ULL << 62)
208
209 /* This bit is used as a lock when modifying a pv_head_table entry. */
210 #define PVH_LOCK_BIT 61
211 #define PVH_FLAG_LOCK (1ULL << PVH_LOCK_BIT)
212
213 /**
214 * This flag is set when there are any executable mappings to this physical
215 * page. This is used to prevent any writable mappings from being created at
216 * the same time an executable mapping exists.
217 */
218 #define PVH_FLAG_EXEC (1ULL << 60)
219
220 /**
221 * Marking a pv_head_table entry with this flag denotes that this page is a
222 * kernelcache text or data page that shouldn't have dynamically-created
223 * mappings. See PVH_FLAG_LOCKDOWN_MASK for more details.
224 */
225 #define PVH_FLAG_LOCKDOWN_KC (1ULL << 59)
226
227 /**
228 * This flag is used to mark that a page has been hashed into the hibernation
229 * image.
230 *
231 * The hibernation driver will use this to ensure that all PPL-owned memory is
232 * correctly included into the hibernation image (a missing PPL page could be
233 * a security concern when coming out of hibernation).
234 */
235 #define PVH_FLAG_HASHED (1ULL << 58)
236
237 /**
238 * Marking a pv_head_table entry with this flag denotes that this page is a
239 * code signature page that shouldn't have dynamically-created mappings.
240 * See PVH_FLAG_LOCKDOWN_MASK for more details.
241 */
242 #define PVH_FLAG_LOCKDOWN_CS (1ULL << 57)
243
244 /**
245 * Marking a pv_head_table entry with this flag denotes that this page is a
246 * read-only allocator page that shouldn't have dynamically-created mappings.
247 * See PVH_FLAG_LOCKDOWN_MASK for more details.
248 */
249 #define PVH_FLAG_LOCKDOWN_RO (1ULL << 56)
250
251 /**
252 * Marking a pv_head_table entry with any bit in this mask denotes that this page
253 * has been locked down by the PPL. Locked down pages can't have new mappings
254 * created or existing mappings removed, and all existing mappings will have been
255 * converted to read-only. This essentially makes the page immutable.
256 */
257 #define PVH_FLAG_LOCKDOWN_MASK (PVH_FLAG_LOCKDOWN_KC | PVH_FLAG_LOCKDOWN_CS | PVH_FLAG_LOCKDOWN_RO)
258
259 /**
260 * These bits need to be set to safely dereference a pv_head_table
261 * entry/pointer.
262 *
263 * Any change to this #define should also update the copy located in the pmap.py
264 * LLDB macros file.
265 */
266 #define PVH_HIGH_FLAGS (PVH_FLAG_CPU | PVH_FLAG_LOCK | PVH_FLAG_EXEC | PVH_FLAG_LOCKDOWN_MASK | PVH_FLAG_HASHED)
267
268 #else /* defined(__arm64__) */
269
270 /* See the equivalent arm64 pv_head_table flags above for descriptions of these flags. */
271 #define PVH_LOCK_BIT 31
272 #define PVH_FLAG_LOCK (1UL << PVH_LOCK_BIT)
273 #define PVH_HIGH_FLAGS PVH_FLAG_LOCK
274
275 #endif /* defined(__arm64__) */
276
277 /* Mask used to clear out the TYPE bits from a pv_head_table entry/pointer. */
278 #define PVH_LIST_MASK (~PVH_TYPE_MASK)
279
280 /* Which 32-bit word in each pv_head_table entry/pointer contains the LOCK bit. */
281 #if defined(__arm64__)
282 #define PVH_LOCK_WORD 1 /* Assumes little-endian */
283 #else /* defined(__arm64__) */
284 #define PVH_LOCK_WORD 0
285 #endif /* defined(__arm64__) */
286
287 /**
288 * Assert that a pv_head_table entry is locked. Will panic if the lock isn't
289 * acquired.
290 *
291 * @param index The physical address index to check.
292 */
293 static inline void
pvh_assert_locked(__assert_only unsigned int index)294 pvh_assert_locked(__assert_only unsigned int index)
295 {
296 assert((vm_offset_t)(pv_head_table[index]) & PVH_FLAG_LOCK);
297 }
298
299
300 /**
301 * Lock a pv_head_table entry.
302 *
303 * @param index The physical address index of the pv_head_table entry to lock.
304 */
305 static inline void
pvh_lock(unsigned int index)306 pvh_lock(unsigned int index)
307 {
308 pmap_lock_bit((uint32_t*)(&pv_head_table[index]) + PVH_LOCK_WORD,
309 PVH_LOCK_BIT - (PVH_LOCK_WORD * 32));
310 }
311
312 /**
313 * Unlock a pv_head_table entry.
314 *
315 * @param index The physical address index of the pv_head_table entry to unlock.
316 */
317 static inline void
pvh_unlock(unsigned int index)318 pvh_unlock(unsigned int index)
319 {
320 pvh_assert_locked(index);
321
322 pmap_unlock_bit((uint32_t*)(&pv_head_table[index]) + PVH_LOCK_WORD,
323 PVH_LOCK_BIT - (PVH_LOCK_WORD * 32));
324 }
325
326 /**
327 * Check that a pv_head_table entry/pointer is a specific type.
328 *
329 * @param pvh The pv_head_table entry/pointer to check.
330 * @param type The type to check for.
331 *
332 * @return True if the pv_head_table entry is of the passed in type, false
333 * otherwise.
334 */
335 static inline bool
pvh_test_type(pv_entry_t ** pvh,vm_offset_t type)336 pvh_test_type(pv_entry_t **pvh, vm_offset_t type)
337 {
338 return ((*(vm_offset_t *)pvh) & PVH_TYPE_MASK) == type;
339 }
340
341 /**
342 * Convert a pv_head_table entry/pointer into a page table entry pointer. This
343 * should only be done if the type of this entry is PVH_TYPE_PTEP.
344 *
345 * @param pvh The pv_head_table entry/pointer to convert into a pt_entry_t*.
346 *
347 * @return Return back a safe to derefence pointer to the single mapping of this
348 * physical page by masking off the TYPE bits and adding any missing
349 * flags to the upper portion of the pointer.
350 */
351 static inline pt_entry_t*
pvh_ptep(pv_entry_t ** pvh)352 pvh_ptep(pv_entry_t **pvh)
353 {
354 return (pt_entry_t *)(((*(vm_offset_t *)pvh) & PVH_LIST_MASK) | PVH_HIGH_FLAGS);
355 }
356
357 /**
358 * Convert a pv_head_table entry/pointer into a PVE list pointer. This
359 * should only be done if the type of this entry is PVH_TYPE_PVEP.
360 *
361 * @param pvh The pv_head_table entry/pointer to convert into a safe to
362 * dereference pv_entry_t*.
363 *
364 * @return Return back a safe to derefence pointer to the first mapping of this
365 * physical page by masking off the TYPE bits and adding any missing
366 * flags to the upper portion of the pointer.
367 */
368 static inline pv_entry_t*
pvh_pve_list(pv_entry_t ** pvh)369 pvh_pve_list(pv_entry_t **pvh)
370 {
371 return (pv_entry_t *)(((*(vm_offset_t *)pvh) & PVH_LIST_MASK) | PVH_HIGH_FLAGS);
372 }
373
374 /**
375 * Return the flags associated with a pv_head_table entry/pointer.
376 *
377 * @param pvh The pv_head_table entry whose flags to get.
378 */
379 static inline vm_offset_t
pvh_get_flags(pv_entry_t ** pvh)380 pvh_get_flags(pv_entry_t **pvh)
381 {
382 return (*(vm_offset_t *)pvh) & PVH_HIGH_FLAGS;
383 }
384
385 /**
386 * Atomically set the flags associated with a pv_head_table entry/pointer.
387 *
388 * @param pvh The pv_head_table entry whose flags are getting set.
389 */
390 static inline void
pvh_set_flags(pv_entry_t ** pvh,vm_offset_t flags)391 pvh_set_flags(pv_entry_t **pvh, vm_offset_t flags)
392 {
393 os_atomic_store((vm_offset_t *)pvh, ((*(vm_offset_t *)pvh) & ~PVH_HIGH_FLAGS) | flags, relaxed);
394 }
395
396 /**
397 * Update a pv_head_table entry/pointer to be a different type and/or point to
398 * a different object.
399 *
400 * @note The pv_head_table entry MUST already be locked.
401 *
402 * @note This function will clobber any existing flags stored in the PVH pointer
403 * (except PVH_FLAG_LOCK). It's up to the caller to preserve flags if that
404 * functionality is needed (either by ensuring `pvep` contains those
405 * flags, or by manually setting the flags after this call).
406 *
407 * @param pvh The pv_head_table entry/pointer to update.
408 * @param pvep The new entry to use. This could be either a pt_entry_t*,
409 * pv_entry_t*, or pt_desc_t* depending on the type.
410 * @param type The type of the new entry.
411 */
412 static inline void
pvh_update_head(pv_entry_t ** pvh,void * pvep,unsigned int type)413 pvh_update_head(pv_entry_t **pvh, void *pvep, unsigned int type)
414 {
415 assert((*(vm_offset_t *)pvh) & PVH_FLAG_LOCK);
416 os_atomic_store((vm_offset_t *)pvh, (vm_offset_t)pvep | type | PVH_FLAG_LOCK, relaxed);
417 }
418
419 /**
420 * Update a pv_head_table entry/pointer to be a different type and/or point to
421 * a different object.
422 *
423 * @note The pv_head_table entry CAN'T already be locked.
424 *
425 * @note This function will clobber any existing flags stored in the PVH
426 * pointer. It's up to the caller to preserve flags if that functionality
427 * is needed (either by ensuring `pvep` contains those flags, or by
428 * manually setting the flags after this call).
429 *
430 * @param pvh The pv_head_table entry/pointer to update.
431 * @param pvep The new entry to use. This could be either a pt_entry_t*,
432 * pv_entry_t*, or pt_desc_t* depending on the type.
433 * @param type The type of the new entry.
434 */
435 static inline void
pvh_update_head_unlocked(pv_entry_t ** pvh,void * pvep,unsigned int type)436 pvh_update_head_unlocked(pv_entry_t **pvh, void *pvep, unsigned int type)
437 {
438 assert(!((*(vm_offset_t *)pvh) & PVH_FLAG_LOCK));
439 *(vm_offset_t *)pvh = ((vm_offset_t)pvep | type) & ~PVH_FLAG_LOCK;
440 }
441
442 /**
443 * Given a page table entry pointer retrieved from the pv_head_table (from an
444 * entry of type PVH_TYPE_PTEP or PVH_TYPE_PVEP), return back whether the PTE is
445 * an IOMMU mapping.
446 *
447 * @note The way this function determines whether the passed in pointer is
448 * pointing to an IOMMU PTE, is by checking for a special flag stored in
449 * the lower bits of the pointer. This flag is only set on pointers stored
450 * in the pv_head_table, and as such, this function will only work on
451 * pointers retrieved from the pv_head_table. If a pointer to a PTE was
452 * directly retrieved from an IOMMU's page tables, this function would
453 * always return false despite actually being an IOMMU PTE.
454 *
455 * @param ptep A PTE pointer obtained from the pv_head_table to check.
456 *
457 * @return True if the entry is an IOMMU mapping, false otherwise.
458 */
459 static inline bool
pvh_ptep_is_iommu(const pt_entry_t * ptep)460 pvh_ptep_is_iommu(const pt_entry_t *ptep)
461 {
462 #ifdef PVH_FLAG_IOMMU
463 return (vm_offset_t)ptep & PVH_FLAG_IOMMU;
464 #else /* PVH_FLAG_IOMMU */
465 #pragma unused(ptep)
466 return false;
467 #endif /* PVH_FLAG_IOMMU */
468 }
469
470 /**
471 * Sometimes the PTE pointers retrieved from the pv_head_table (from an entry of
472 * type PVH_TYPE_PTEP or PVH_TYPE_PVEP) contain flags themselves. This function
473 * strips out those flags and returns back a dereferencable pointer.
474 *
475 * @param ptep The PTE pointer to strip out the unwanted flags.
476 *
477 * @return A valid dereferencable pointer to the page table entry.
478 */
479 static inline const pt_entry_t*
pvh_strip_ptep(const pt_entry_t * ptep)480 pvh_strip_ptep(const pt_entry_t *ptep)
481 {
482 #ifdef PVH_FLAG_IOMMU
483 const vm_offset_t pte_va = (vm_offset_t)ptep;
484 return (const pt_entry_t*)((pte_va & ~PVH_FLAG_IOMMU) | PVH_FLAG_IOMMU_TABLE);
485 #else /* PVH_FLAG_IOMMU */
486 return ptep;
487 #endif /* PVH_FLAG_IOMMU */
488 }
489
490 /**
491 * PVH_TYPE_PVEP Helper Functions.
492 *
493 * The following are methods used to manipulate PVE lists. This is the type of
494 * pv_head_table entry used when there are multiple mappings to a single
495 * physical page.
496 */
497
498 /**
499 * Whether a physical page is using "alternate accounting" (ALTACCT) for its
500 * ledger statistics is something that needs to be tracked on a per-mapping
501 * basis, not on a per-physical-page basis. Because of that, it's tracked
502 * differently depending on whether there's a single mapping to a page
503 * (PVH_TYPE_PTEP) or multiple (PVH_TYPE_PVEP). For single mappings, the bit is
504 * tracked in the pp_attr_table. But when there are multiple mappings, the least
505 * significant bit of the corresponding "pve_pte" pointer in each pv_entry object
506 * is used as a marker for pages using alternate accounting.
507 *
508 * @note See the definition for PP_ATTR_ALTACCT for a more detailed description
509 * of what "alternate accounting" actually means in respect to the
510 * footprint ledger.
511 */
512 #define PVE_PTEP_ALTACCT ((uintptr_t) 0x1)
513 #define PVE_PTEP_INTERNAL ((uintptr_t) 0x2)
514 #define PVE_PTEP_FLAGS (PVE_PTEP_ALTACCT | PVE_PTEP_INTERNAL)
515
516 /**
517 * Set the ALTACCT bit for a specific PTE pointer.
518 *
519 * @param pvep A pointer to the current pv_entry mapping in the linked list of
520 * mappings.
521 * @param idx Index of the chosen PTE pointer inside the PVE.
522 */
523 static inline void
pve_set_altacct(pv_entry_t * pvep,unsigned idx)524 pve_set_altacct(pv_entry_t *pvep, unsigned idx)
525 {
526 assert(idx < PTE_PER_PVE);
527 pvep->pve_ptep[idx] = (pt_entry_t *)((uintptr_t)pvep->pve_ptep[idx] | PVE_PTEP_ALTACCT);
528 }
529
530 /**
531 * Set the INTERNAL bit for a specific PTE pointer.
532 *
533 * @param pvep A pointer to the current pv_entry mapping in the linked list of
534 * mappings.
535 * @param idx Index of the chosen PTE pointer inside the PVE.
536 */
537 static inline void
pve_set_internal(pv_entry_t * pvep,unsigned idx)538 pve_set_internal(pv_entry_t *pvep, unsigned idx)
539 {
540 assert(idx < PTE_PER_PVE);
541 pvep->pve_ptep[idx] = (pt_entry_t *)((uintptr_t)pvep->pve_ptep[idx] | PVE_PTEP_INTERNAL);
542 }
543
544 /**
545 * Clear the ALTACCT bit for a specific PTE pointer.
546 *
547 * @param pvep A pointer to the current pv_entry mapping in the linked list of
548 * mappings.
549 * @param idx Index of the chosen PTE pointer inside the PVE.
550 */
551 static inline void
pve_clr_altacct(pv_entry_t * pvep,unsigned idx)552 pve_clr_altacct(pv_entry_t *pvep, unsigned idx)
553 {
554 assert(idx < PTE_PER_PVE);
555 pvep->pve_ptep[idx] = (pt_entry_t *)((uintptr_t)pvep->pve_ptep[idx] & ~PVE_PTEP_ALTACCT);
556 }
557
558 /**
559 * Clear the INTERNAL bit for a specific PTE pointer.
560 *
561 * @param pvep A pointer to the current pv_entry mapping in the linked list of
562 * mappings.
563 * @param idx Index of the chosen PTE pointer inside the PVE.
564 */
565 static inline void
pve_clr_internal(pv_entry_t * pvep,unsigned idx)566 pve_clr_internal(pv_entry_t *pvep, unsigned idx)
567 {
568 assert(idx < PTE_PER_PVE);
569 pvep->pve_ptep[idx] = (pt_entry_t *)((uintptr_t)pvep->pve_ptep[idx] & ~PVE_PTEP_INTERNAL);
570 }
571
572 /**
573 * Return the ALTACCT bit for a specific PTE pointer.
574 *
575 * @param pvep A pointer to the current pv_entry mapping in the linked list of
576 * mappings.
577 * @param idx Index of the chosen PTE pointer inside the PVE.
578 */
579 static inline bool
pve_get_altacct(pv_entry_t * pvep,unsigned idx)580 pve_get_altacct(pv_entry_t *pvep, unsigned idx)
581 {
582 assert(idx < PTE_PER_PVE);
583 return (uintptr_t)pvep->pve_ptep[idx] & PVE_PTEP_ALTACCT;
584 }
585
586 /**
587 * Return the INTERNAL bit for a specific PTE pointer.
588 *
589 * @param pvep A pointer to the current pv_entry mapping in the linked list of
590 * mappings.
591 * @param idx Index of the chosen PTE pointer inside the PVE.
592 */
593 static inline bool
pve_get_internal(pv_entry_t * pvep,unsigned idx)594 pve_get_internal(pv_entry_t *pvep, unsigned idx)
595 {
596 assert(idx < PTE_PER_PVE);
597 return (uintptr_t)pvep->pve_ptep[idx] & PVE_PTEP_INTERNAL;
598 }
599
600 /**
601 * Return the next mapping (pv_entry) in a linked list of mappings. This applies
602 * to pv_head_table entries of type PVH_TYPE_PVEP.
603 *
604 * @param pvep A pointer to the current pv_entry mapping in the linked list of
605 * mappings.
606 *
607 * @return The next virtual mapping for a physical page, or PV_ENTRY_NULL if the
608 * end of the list has been reached.
609 */
610 static inline pv_entry_t *
pve_next(pv_entry_t * pvep)611 pve_next(pv_entry_t *pvep)
612 {
613 return pvep->pve_next;
614 }
615
616 /**
617 * Return a pointer to the pve_next field in a pv_entry. This value is used
618 * when adding and removing entries to a PVE list.
619 *
620 * @param pvep The pv_entry whose pve_next field is being accessed.
621 *
622 * @return Pointer to the pve_next field.
623 */
624 static inline pv_entry_t **
pve_next_ptr(pv_entry_t * pvep)625 pve_next_ptr(pv_entry_t *pvep)
626 {
627 return &pvep->pve_next;
628 }
629
630 /**
631 * Return a pointer to the page table entry for this mapping.
632 *
633 * @param pvep The pv_entry whose pve_ptep field is to be returned.
634 * @param idx Index of the chosen PTE pointer inside the PVE.
635 *
636 * @return Pointer to the page table entry.
637 */
638 static inline pt_entry_t *
pve_get_ptep(pv_entry_t * pvep,unsigned idx)639 pve_get_ptep(pv_entry_t *pvep, unsigned idx)
640 {
641 assert(idx < PTE_PER_PVE);
642 return (pt_entry_t *)((uintptr_t)pvep->pve_ptep[idx] & ~PVE_PTEP_FLAGS);
643 }
644
645 /**
646 * Update the page table entry for a specific physical to virtual mapping.
647 *
648 * @param pvep The pv_entry to update.
649 * @param idx Index of the chosen PTE pointer inside the PVE.
650 * @param ptep_new The new page table entry.
651 */
652 static inline void
pve_set_ptep(pv_entry_t * pvep,unsigned idx,pt_entry_t * ptep_new)653 pve_set_ptep(pv_entry_t *pvep, unsigned idx, pt_entry_t *ptep_new)
654 {
655 assert(idx < PTE_PER_PVE);
656 pvep->pve_ptep[idx] = ptep_new;
657 }
658
659 /**
660 * Initialize all fields in a PVE to NULL.
661 *
662 * @param pvep The pv_entry to initialize.
663 */
664 static inline void
pve_init(pv_entry_t * pvep)665 pve_init(pv_entry_t *pvep)
666 {
667 pvep->pve_next = PV_ENTRY_NULL;
668 for (int i = 0; i < PTE_PER_PVE; i++) {
669 pvep->pve_ptep[i] = PT_ENTRY_NULL;
670 }
671 }
672
673 /**
674 * Find PTE pointer in PVE and return its index.
675 *
676 * @param pvep The PVE to search.
677 * @param ptep PTE to search for.
678 *
679 * @return Index of the found entry, or -1 if no entry exists.
680 */
681 static inline int
pve_find_ptep_index(pv_entry_t * pvep,pt_entry_t * ptep)682 pve_find_ptep_index(pv_entry_t *pvep, pt_entry_t *ptep)
683 {
684 for (int i = 0; i < PTE_PER_PVE; i++) {
685 if (pve_get_ptep(pvep, i) == ptep) {
686 return i;
687 }
688 }
689
690 return -1;
691 }
692
693 /**
694 * Checks if no PTEs are currently associated with this PVE.
695 *
696 * @param pvep The PVE to search.
697 *
698 * @return True if no PTEs are currently associated with this PVE, or false.
699 */
700 static inline bool
pve_is_empty(pv_entry_t * pvep)701 pve_is_empty(pv_entry_t *pvep)
702 {
703 for (int i = 0; i < PTE_PER_PVE; i++) {
704 if (pve_get_ptep(pvep, i) != PT_ENTRY_NULL) {
705 return false;
706 }
707 }
708
709 return true;
710 }
711
712 /**
713 * Prepend a new pv_entry node to a PVE list.
714 *
715 * @note This function will clobber any existing flags stored in the PVH
716 * pointer. It's up to the caller to preserve flags if that functionality
717 * is needed (either by ensuring `pvep` contains those flags, or by
718 * manually setting the flags after this call).
719 *
720 * @param pvh The linked list of mappings to update.
721 * @param pvep The new mapping to add to the linked list.
722 */
723 static inline void
pve_add(pv_entry_t ** pvh,pv_entry_t * pvep)724 pve_add(pv_entry_t **pvh, pv_entry_t *pvep)
725 {
726 assert(pvh_test_type(pvh, PVH_TYPE_PVEP));
727
728 pvep->pve_next = pvh_pve_list(pvh);
729 pvh_update_head(pvh, pvep, PVH_TYPE_PVEP);
730 }
731
732 /**
733 * Remove an entry from a PVE list of mappings.
734 *
735 * @note This function will clobber any existing flags stored in the PVH
736 * pointer. It's up to the caller to preserve flags if that functionality
737 * is needed (either by ensuring `pvep` contains those flags, or by
738 * manually setting the flags after this call).
739 *
740 * @param pvh The pv_head_table entry of the PVE list to remove a mapping from.
741 * This is the first entry in the list of pv_entry_t mappings.
742 * @param pvepp A pointer to the pv_entry_t* that's being removed. If this entry
743 * is the first in the linked list of mappings, then this should be
744 * identical to the pv_head_table entry. If the mapping isn't the
745 * first, then this is a pointer to the pve_next field in the
746 * previous mapping.
747 * @param pvep The entry that should be removed. Should be identical to a
748 * dereference of the pvepp parameter (unless it's the pv_head_table
749 * entry).
750 */
751 static inline void
pve_remove(pv_entry_t ** pvh,pv_entry_t ** pvepp,pv_entry_t * pvep)752 pve_remove(pv_entry_t **pvh, pv_entry_t **pvepp, pv_entry_t *pvep)
753 {
754 assert(pvh_test_type(pvh, PVH_TYPE_PVEP));
755
756 if (pvepp == pvh) {
757 if (pve_next(pvep) == PV_ENTRY_NULL) {
758 /* The last mapping to this page is being removed. */
759 pvh_update_head(pvh, PV_ENTRY_NULL, PVH_TYPE_NULL);
760 } else {
761 /**
762 * There are still mappings left, make the next one the new head of
763 * the list. This effectively removes the first entry from the list.
764 */
765 pvh_update_head(pvh, pve_next(pvep), PVH_TYPE_PVEP);
766 }
767 } else {
768 /**
769 * Move the previous entry's next field to the entry after the one being
770 * removed. This will clobber the ALTACCT bit.
771 */
772 *pvepp = pve_next(pvep);
773 }
774 }
775
776 /**
777 * PVH_TYPE_PTDP Types and Helper Functions.
778 *
779 * The following are types and methods used to manipulate page table descriptor
780 * (PTD) objects. This is the type of pv_head_table entry used when a page is
781 * being used as a page table.
782 */
783
784 /**
785 * When the pmap layer allocates memory, it always does so in chunks of the VM
786 * page size (which are represented by the PAGE_SIZE/PAGE_SHIFT macros). The VM
787 * page size might not match up with the hardware page size for a given address
788 * space (this is especially true on systems that support more than one page
789 * size).
790 *
791 * The pv_head_table is allocated to have one entry per VM page, not hardware
792 * page (which can change depending on the address space). Because of that, a
793 * single VM-page-sized region (single pv_head_table entry) can potentially hold
794 * up to four page tables. Only one page table descriptor (PTD) is allocated per
795 * pv_head_table entry (per VM page), so on some systems, one PTD might have to
796 * keep track of up to four different page tables.
797 */
798 #if (__ARM_VMSA__ == 7)
799
800 #define PT_INDEX_MAX 1
801
802 #else /* (__ARM_VMSA__ == 7) */
803
804 #if __ARM_MIXED_PAGE_SIZE__
805 #define PT_INDEX_MAX (ARM_PGBYTES / 4096)
806 #elif (ARM_PGSHIFT == 14)
807 #define PT_INDEX_MAX 1
808 #elif (ARM_PGSHIFT == 12)
809 #define PT_INDEX_MAX 4
810 #else
811 #error Unsupported ARM_PGSHIFT
812 #endif /* __ARM_MIXED_PAGE_SIZE__ || ARM_PGSHIFT == 14 || ARM_PGSHIFT == 12 */
813
814 #endif /* (__ARM_VMSA__ == 7) */
815
816 /**
817 * Page table descriptor (PTD) info structure.
818 *
819 * Contains information about a page table. These pieces of data are separate
820 * from the PTD itself because in address spaces where the VM page size doesn't
821 * match the underlying hardware page size, one PTD could represent multiple
822 * page tables (and so will need multiple PTD info structures).
823 *
824 * These fields are also in their own struct so that they can be allocated
825 * separately from the associated pt_desc_t object. This allows us to allocate
826 * the counts in this structure in a way that ensures they don't fall within the
827 * same cache line as the main pt_desc_t object. This is important because the
828 * fields in this structure are atomically updated which could cause false
829 * sharing cache performance issues with the "va" field in pt_desc_t if all of
830 * the fields were within the same structure.
831 */
832 typedef struct {
833 /**
834 * Pre-defined sentinel values for ptd_info_t.refcnt. If these refcnt values
835 * change, make sure to update the showpte LLDB macro to reflect the
836 * changes.
837 */
838 #define PT_DESC_REFCOUNT 0x4000U
839 #define PT_DESC_IOMMU_GRANTED_REFCOUNT 0x8000U
840 #define PT_DESC_IOMMU_ACCEPTED_REFCOUNT 0x8001U
841
842 /*
843 * For non-leaf pagetables, should always be PT_DESC_REFCOUNT.
844 * For leaf pagetables, should reflect the number of non-empty PTEs.
845 * For IOMMU pages, should always be either PT_DESC_IOMMU_GRANTED_REFCOUNT
846 * or PT_DESC_IOMMU_ACCEPTED_REFCOUNT.
847 */
848 unsigned short refcnt;
849
850 /*
851 * For non-leaf pagetables, should be 0.
852 * For leaf pagetables, should reflect the number of wired entries.
853 * For IOMMU pages, may optionally reflect a driver-defined refcount (IOMMU
854 * operations are implicitly wired).
855 */
856 unsigned short wiredcnt;
857 } ptd_info_t;
858
859 /**
860 * Page Table Descriptor (PTD).
861 *
862 * Provides a per-table data structure and a way of keeping track of all page
863 * tables in the system.
864 *
865 * This structure is also used as a convenient way of keeping track of IOMMU
866 * pages (which may or may not be used as page tables). In that case the "iommu"
867 * field will point to the owner of the page, ptd_info[0].refcnt will be
868 * PT_DESC_IOMMU_GRANTED_REFCOUNT or PT_DESC_IOMMU_ACCEPTED_REFCOUNT, and
869 * ptd_info[0].wiredcnt can be used as an arbitrary refcnt controlled by the
870 * IOMMU driver.
871 */
872 typedef struct pt_desc {
873 /**
874 * This queue chain provides a mechanism for keeping a list of pages
875 * being used as page tables. This is used to potentially reclaim userspace
876 * page tables as a fast way of "allocating" a page.
877 *
878 * Refer to osfmk/kern/queue.h for more information about queue chains.
879 */
880 queue_chain_t pt_page;
881
882 /* Each page table is either owned by a pmap or a specific IOMMU. */
883 union {
884 struct pmap *pmap;
885 };
886
887 /**
888 * The following fields contain per-page-table properties, and as such,
889 * might have multiple elements each. This is due to a single PTD
890 * potentially representing multiple page tables (in address spaces where
891 * the VM page size differs from the hardware page size). Use the
892 * ptd_get_index() function to get the correct index for a specific page
893 * table.
894 */
895
896 /**
897 * The first address of the virtual address space this page table is
898 * translating for, or a value set by an IOMMU driver if this PTD is being
899 * used to track an IOMMU page.
900 */
901 vm_offset_t va[PT_INDEX_MAX];
902
903 /**
904 * ptd_info_t's are allocated separately so as to reduce false sharing
905 * with the va field. This is desirable because ptd_info_t's are updated
906 * atomically from all CPUs.
907 */
908 ptd_info_t *ptd_info;
909 } pt_desc_t;
910
911 /**
912 * Convert a pv_head_table entry/pointer into a page table descriptor pointer.
913 * This should only be done if the type of this entry is PVH_TYPE_PTDP.
914 *
915 * @param pvh The pv_head_table entry/pointer to convert into a safe to
916 * dereference pt_desc_t*.
917 *
918 * @return Return back a safe to derefence pointer to the page table descriptor
919 * for this physical page by masking off the TYPE bits and adding any
920 * missing flags to the upper portion of the pointer.
921 */
922 static inline pt_desc_t*
pvh_ptd(pv_entry_t ** pvh)923 pvh_ptd(pv_entry_t **pvh)
924 {
925 return (pt_desc_t *)(((*(vm_offset_t *)pvh) & PVH_LIST_MASK) | PVH_HIGH_FLAGS);
926 }
927
928 /**
929 * Given an arbitrary page table entry, return back the page table descriptor
930 * (PTD) object for the page table that contains that entry.
931 *
932 * @param ptep Pointer to a PTE whose page table descriptor object to return.
933 *
934 * @return The PTD object for the passed in page table.
935 */
936 static inline pt_desc_t *
ptep_get_ptd(const pt_entry_t * ptep)937 ptep_get_ptd(const pt_entry_t *ptep)
938 {
939 assert(ptep != NULL);
940
941 const vm_offset_t pt_base_va = (vm_offset_t)ptep;
942 pv_entry_t **pvh = pai_to_pvh(pa_index(ml_static_vtop(pt_base_va)));
943
944 if (__improbable(!pvh_test_type(pvh, PVH_TYPE_PTDP))) {
945 panic("%s: invalid PV head 0x%llx for PTE 0x%p", __func__, (uint64_t)(*pvh), ptep);
946 }
947
948 return pvh_ptd(pvh);
949 }
950
951 /**
952 * Given an arbitrary page table entry, return back the pmap that owns that
953 * page table.
954 *
955 * @note This won't work correctly for page tables owned by IOMMUs, because
956 * those table aren't owned by any specific pmap.
957 *
958 * @param ptep Pointer to a page table entry whose owner we're trying to return.
959 *
960 * @return The pmap that owns the given page table entry.
961 */
962 static inline struct pmap *
ptep_get_pmap(const pt_entry_t * ptep)963 ptep_get_pmap(const pt_entry_t *ptep)
964 {
965 return ptep_get_ptd(ptep)->pmap;
966 }
967
968
969 /**
970 * Given an arbitrary translation table entry, get the page table descriptor
971 * (PTD) object for the page table pointed to by the TTE.
972 *
973 * @param tte The translation table entry to parse. For instance, if this is an
974 * L2 TTE, then the PTD for the L3 table this entry points to will be
975 * returned.
976 *
977 * @return The page table descriptor (PTD) for the page table pointed to by this
978 * TTE.
979 */
980 static inline pt_desc_t *
tte_get_ptd(const tt_entry_t tte)981 tte_get_ptd(const tt_entry_t tte)
982 {
983 const vm_offset_t pt_base_va = (vm_offset_t)(tte & ~PAGE_MASK);
984 pv_entry_t **pvh = pai_to_pvh(pa_index(pt_base_va));
985
986 if (__improbable(!pvh_test_type(pvh, PVH_TYPE_PTDP))) {
987 panic("%s: invalid PV head 0x%llx for TTE 0x%llx", __func__, (uint64_t)(*pvh), (uint64_t)tte);
988 }
989
990 return pvh_ptd(pvh);
991 }
992
993 /**
994 * In address spaces where the VM page size doesn't match the underlying
995 * hardware page size, one PTD could represent multiple page tables. This
996 * function returns the correct index value depending on which page table is
997 * being accessed. That index value can then be used to access the
998 * per-page-table properties stored within a PTD.
999 *
1000 * @note See the description above the PT_INDEX_MAX definition for a more
1001 * detailed explanation of why multiple page tables can be represented
1002 * by a single PTD object in the pv_head_table.
1003 *
1004 * @param ptd The page table descriptor that's being accessed.
1005 * @param ttep Pointer to the translation table entry that's being accessed.
1006 *
1007 * @return The correct index value for a specific, hardware-sized page
1008 * table.
1009 */
1010 static inline unsigned
ptd_get_index(__unused const pt_desc_t * ptd,__unused const tt_entry_t * ttep)1011 ptd_get_index(__unused const pt_desc_t *ptd, __unused const tt_entry_t *ttep)
1012 {
1013 #if PT_INDEX_MAX == 1
1014 return 0;
1015 #else
1016 assert(ptd != NULL);
1017
1018 const uint64_t pmap_page_shift = pt_attr_leaf_shift(pmap_get_pt_attr(ptd->pmap));
1019 const vm_offset_t ttep_page = (vm_offset_t)ttep >> pmap_page_shift;
1020
1021 /**
1022 * Use the difference between the VM page shift and the hardware page shift
1023 * to get the index of the correct page table. In practice, this equates to
1024 * masking out the bottom two bits of the L3 table index in address spaces
1025 * where the VM page size is greater than the hardware page size. In address
1026 * spaces where they're identical, the index will always be zero.
1027 */
1028 const unsigned int ttep_index = ttep_page & ((1U << (PAGE_SHIFT - pmap_page_shift)) - 1);
1029 assert(ttep_index < PT_INDEX_MAX);
1030
1031 return ttep_index;
1032 #endif
1033 }
1034
1035 /**
1036 * In address spaces where the VM page size doesn't match the underlying
1037 * hardware page size, one PTD could represent multiple page tables. This
1038 * function returns the correct ptd_info_t structure depending on which page
1039 * table is being accessed.
1040 *
1041 * @note See the description above the PT_INDEX_MAX definition for a more
1042 * detailed explanation of why multiple page tables can be represented
1043 * by a single PTD object in the pv_head_table.
1044 *
1045 * @param ptd The page table descriptor that's being accessed.
1046 * @param ttep Pointer to the translation table entry that's being accessed.
1047 *
1048 * @return The correct ptd_info_t structure for a specific, hardware-sized page
1049 * table.
1050 */
1051 static inline ptd_info_t *
ptd_get_info(pt_desc_t * ptd,const tt_entry_t * ttep)1052 ptd_get_info(pt_desc_t *ptd, const tt_entry_t *ttep)
1053 {
1054 assert((ptd != NULL) && (ptd->ptd_info[0].refcnt < PT_DESC_IOMMU_GRANTED_REFCOUNT));
1055
1056 return &ptd->ptd_info[ptd_get_index(ptd, ttep)];
1057 }
1058
1059 /**
1060 * Given a pointer to a page table entry, return back the ptd_info structure
1061 * for the page table that contains that entry.
1062 *
1063 * @param ptep Pointer to a PTE whose ptd_info object to return.
1064 *
1065 * @return The ptd_info object for the page table that contains the passed in
1066 * page table entry.
1067 */
1068 static inline ptd_info_t *
ptep_get_info(const pt_entry_t * ptep)1069 ptep_get_info(const pt_entry_t *ptep)
1070 {
1071 return ptd_get_info(ptep_get_ptd(ptep), ptep);
1072 }
1073
1074 /**
1075 * Return the virtual address mapped by the passed in leaf page table entry,
1076 * using an already-retrieved pagetable descriptor.
1077 *
1078 * @param ptdp pointer to the descriptor for the pagetable containing ptep
1079 * @param ptep Pointer to a PTE to parse
1080 */
1081 static inline vm_map_address_t
ptd_get_va(const pt_desc_t * ptdp,const pt_entry_t * ptep)1082 ptd_get_va(const pt_desc_t *ptdp, const pt_entry_t *ptep)
1083 {
1084 const pt_attr_t * const pt_attr = pmap_get_pt_attr(ptdp->pmap);
1085
1086 vm_map_address_t va = ptdp->va[ptd_get_index(ptdp, ptep)];
1087 vm_offset_t ptep_index = ((vm_offset_t)ptep & pt_attr_leaf_offmask(pt_attr)) / sizeof(*ptep);
1088
1089 va += (ptep_index << pt_attr_leaf_shift(pt_attr));
1090
1091 return va;
1092 }
1093
1094 /**
1095 * Return the virtual address that is being mapped by the passed in leaf page
1096 * table entry.
1097 *
1098 * @param ptep Pointer to a PTE to parse.
1099 */
1100 static inline vm_map_address_t
ptep_get_va(const pt_entry_t * ptep)1101 ptep_get_va(const pt_entry_t *ptep)
1102 {
1103 return ptd_get_va(ptep_get_ptd(ptep), ptep);
1104 }
1105
1106 /**
1107 * Physical Page Attribute Table (pp_attr_table) defines and helper functions.
1108 */
1109
1110 /* How many bits to use for flags on a per-VM-page basis. */
1111 typedef uint16_t pp_attr_t;
1112
1113 /* See the definition of pp_attr_table for more information. */
1114 extern volatile pp_attr_t* pp_attr_table;
1115
1116 /**
1117 * Flags stored in the pp_attr_table on a per-physical-page basis.
1118 *
1119 * Please update the pv_walk LLDB macro if these flags are changed or added to.
1120 */
1121
1122 /**
1123 * The bottom 6-bits are used to store the default WIMG (cacheability and memory
1124 * type) setting for this physical page. This can be changed by calling
1125 * pmap_set_cache_attributes().
1126 *
1127 * If a default WIMG setting isn't set for a page, then the default is Normal,
1128 * Cached memory (VM_WIMG_DEFAULT).
1129 */
1130 #define PP_ATTR_WIMG_MASK 0x003F
1131 #define PP_ATTR_WIMG(x) ((x) & PP_ATTR_WIMG_MASK)
1132
1133 /**
1134 * The reference and modify bits keep track of whether a page has been accessed
1135 * or modified since the last time the bits were cleared. These bits are used to
1136 * enforce policy decisions in the VM layer.
1137 */
1138 #define PP_ATTR_REFERENCED 0x0040
1139 #define PP_ATTR_MODIFIED 0x0080
1140
1141 /**
1142 * This physical page is being used as anonymous memory that's internally
1143 * managed by the VM and is not connected to an external pager. This flag is
1144 * only set/cleared on the first CPU mapping of a page (see PVH_FLAG_CPU). Any
1145 * subsequent mappings won't set/clear this flag until all mappings are removed
1146 * and a new CPU mapping is added.
1147 */
1148 #define PP_ATTR_INTERNAL 0x0100
1149
1150 /**
1151 * This flag is used to keep track of pages that are still resident but are not
1152 * considered dirty and can be reclaimed under memory pressure. These pages do
1153 * not count as a part of the memory footprint, so the footprint ledger does not
1154 * need to be updated for these pages. This is hinted to the VM by the
1155 * `madvise(MADV_FREE_REUSABLE)` system call.
1156 */
1157 #define PP_ATTR_REUSABLE 0x0200
1158
1159 /**
1160 * This flag denotes that a page is utilizing "alternate accounting". This means
1161 * that the pmap doesn't need to keep track of these pages with regards to the
1162 * footprint ledger because the VM is already accounting for them in a different
1163 * way. These include IOKit mappings (VM adds their entire virtual size to the
1164 * footprint), and purgeable pages (VM counts them only when non-volatile and
1165 * only for one "owner"), among others.
1166 *
1167 * Note that alternate accounting status is tracked on a per-mapping basis (not
1168 * per-page). Because of that the ALTACCT flag in the pp_attr_table is only used
1169 * when there's a single mapping to a page. When there are multiple mappings,
1170 * the status of this flag is tracked in the pv_head_table (see PVE_PTEP_ALTACCT
1171 * above).
1172 */
1173 #define PP_ATTR_ALTACCT 0x0400
1174
1175 /**
1176 * This bit was originally used on x86 to keep track of what pages to not
1177 * encrypt during the hibernation process as a performance optimization when
1178 * encryption was done in software. This doesn't apply to the ARM
1179 * hibernation process because all pages are automatically encrypted using
1180 * hardware acceleration. Despite that, the pmap still keeps track of this flag
1181 * as a debugging aid on internal builds.
1182 *
1183 * TODO: This bit can probably be reclaimed:
1184 * rdar://70740650 (PMAP Cleanup: Potentially reclaim the PP_ATTR_NOENCRYPT bit on ARM)
1185 */
1186 #define PP_ATTR_NOENCRYPT 0x0800
1187
1188 /**
1189 * These bits denote that a physical page is expecting the next access or
1190 * modification to set the PP_ATTR_REFERENCED and PP_ATTR_MODIFIED flags
1191 * respectively.
1192 */
1193 #define PP_ATTR_REFFAULT 0x1000
1194 #define PP_ATTR_MODFAULT 0x2000
1195
1196 #if XNU_MONITOR
1197 /**
1198 * Denotes that a page is owned by the PPL. This is modified/checked with the
1199 * PVH lock held, to avoid ownership related races. This does not need to be a
1200 * PP_ATTR bit (as we have the lock), but for now this is a convenient place to
1201 * put the bit.
1202 */
1203 #define PP_ATTR_MONITOR 0x4000
1204
1205 /**
1206 * Denotes that a page *cannot* be owned by the PPL. This is required in order
1207 * to temporarily 'pin' kernel pages that are used to store PPL output
1208 * parameters. Otherwise a malicious or buggy caller could pass PPL-owned memory
1209 * for these parameters and in so doing stage a write gadget against the PPL.
1210 */
1211 #define PP_ATTR_NO_MONITOR 0x8000
1212
1213 /**
1214 * All of the bits owned by the PPL; kernel requests to set or clear these bits
1215 * are illegal.
1216 */
1217 #define PP_ATTR_PPL_OWNED_BITS (PP_ATTR_MONITOR | PP_ATTR_NO_MONITOR)
1218 #endif /* XNU_MONITOR */
1219
1220 /**
1221 * Atomically set some flags in a pp_attr_table entry.
1222 *
1223 * @param pai The physical address index for the entry to update.
1224 * @param bits The flags to set in the entry.
1225 */
1226 static inline void
ppattr_set_bits(unsigned int pai,pp_attr_t bits)1227 ppattr_set_bits(unsigned int pai, pp_attr_t bits)
1228 {
1229 volatile pp_attr_t *ppattr = &pp_attr_table[pai];
1230 os_atomic_or(ppattr, bits, acq_rel);
1231 }
1232
1233 /**
1234 * Atomically clear some flags in a pp_attr_table entry.
1235 *
1236 * @param pai The physical address index for the entry to update.
1237 * @param bits The flags to clear in the entry.
1238 */
1239 static inline void
ppattr_clear_bits(unsigned int pai,pp_attr_t bits)1240 ppattr_clear_bits(unsigned int pai, pp_attr_t bits)
1241 {
1242 volatile pp_attr_t *ppattr = &pp_attr_table[pai];
1243 os_atomic_andnot(ppattr, bits, acq_rel);
1244 }
1245
1246 /**
1247 * Return true if the pp_attr_table entry contains the passed in bits.
1248 *
1249 * @param pai The physical address index for the entry to test.
1250 * @param bits The flags to check for.
1251 */
1252 static inline bool
ppattr_test_bits(unsigned int pai,pp_attr_t bits)1253 ppattr_test_bits(unsigned int pai, pp_attr_t bits)
1254 {
1255 const volatile pp_attr_t *ppattr = &pp_attr_table[pai];
1256 return (*ppattr & bits) == bits;
1257 }
1258
1259 /**
1260 * Only set some flags in a pp_attr_table entry if the passed in physical
1261 * address is a kernel-managed address.
1262 *
1263 * @param pa The physical address for the entry to update.
1264 * @param bits The flags to set in the entry.
1265 */
1266 static inline void
ppattr_pa_set_bits(pmap_paddr_t pa,pp_attr_t bits)1267 ppattr_pa_set_bits(pmap_paddr_t pa, pp_attr_t bits)
1268 {
1269 if (pa_valid(pa)) {
1270 ppattr_set_bits(pa_index(pa), bits);
1271 }
1272 }
1273
1274 /**
1275 * Only clear some flags in a pp_attr_table entry if the passed in physical
1276 * address is a kernel-managed address.
1277 *
1278 * @param pa The physical address for the entry to update.
1279 * @param bits The flags to clear in the entry.
1280 */
1281 static inline void
ppattr_pa_clear_bits(pmap_paddr_t pa,pp_attr_t bits)1282 ppattr_pa_clear_bits(pmap_paddr_t pa, pp_attr_t bits)
1283 {
1284 if (pa_valid(pa)) {
1285 ppattr_clear_bits(pa_index(pa), bits);
1286 }
1287 }
1288
1289 /**
1290 * Only test flags in a pp_attr_table entry if the passed in physical address
1291 * is a kernel-managed page.
1292 *
1293 * @param pa The physical address for the entry to test.
1294 * @param bits The flags to check for.
1295 *
1296 * @return False if the PA isn't a kernel-managed page, otherwise true/false
1297 * depending on whether the bits are set.
1298 */
1299 static inline bool
ppattr_pa_test_bits(pmap_paddr_t pa,pp_attr_t bits)1300 ppattr_pa_test_bits(pmap_paddr_t pa, pp_attr_t bits)
1301 {
1302 return pa_valid(pa) ? ppattr_test_bits(pa_index(pa), bits) : false;
1303 }
1304
1305 /**
1306 * Set the PP_ATTR_MODIFIED flag on a specific pp_attr_table entry if the passed
1307 * in physical address is a kernel-managed page.
1308 *
1309 * @param pa The physical address for the entry to update.
1310 */
1311 static inline void
ppattr_pa_set_modify(pmap_paddr_t pa)1312 ppattr_pa_set_modify(pmap_paddr_t pa)
1313 {
1314 ppattr_pa_set_bits(pa, PP_ATTR_MODIFIED);
1315 }
1316
1317 /**
1318 * Clear the PP_ATTR_MODIFIED flag on a specific pp_attr_table entry if the
1319 * passed in physical address is a kernel-managed page.
1320 *
1321 * @param pa The physical address for the entry to update.
1322 */
1323 static inline void
ppattr_pa_clear_modify(pmap_paddr_t pa)1324 ppattr_pa_clear_modify(pmap_paddr_t pa)
1325 {
1326 ppattr_pa_clear_bits(pa, PP_ATTR_MODIFIED);
1327 }
1328
1329 /**
1330 * Set the PP_ATTR_REFERENCED flag on a specific pp_attr_table entry if the
1331 * passed in physical address is a kernel-managed page.
1332 *
1333 * @param pa The physical address for the entry to update.
1334 */
1335 static inline void
ppattr_pa_set_reference(pmap_paddr_t pa)1336 ppattr_pa_set_reference(pmap_paddr_t pa)
1337 {
1338 ppattr_pa_set_bits(pa, PP_ATTR_REFERENCED);
1339 }
1340
1341 /**
1342 * Clear the PP_ATTR_REFERENCED flag on a specific pp_attr_table entry if the
1343 * passed in physical address is a kernel-managed page.
1344 *
1345 * @param pa The physical address for the entry to update.
1346 */
1347 static inline void
ppattr_pa_clear_reference(pmap_paddr_t pa)1348 ppattr_pa_clear_reference(pmap_paddr_t pa)
1349 {
1350 ppattr_pa_clear_bits(pa, PP_ATTR_REFERENCED);
1351 }
1352
1353 #if XNU_MONITOR
1354
1355 /**
1356 * Set the PP_ATTR_MONITOR flag on a specific pp_attr_table entry if the passed
1357 * in physical address is a kernel-managed page.
1358 *
1359 * @param pa The physical address for the entry to update.
1360 */
1361 static inline void
ppattr_pa_set_monitor(pmap_paddr_t pa)1362 ppattr_pa_set_monitor(pmap_paddr_t pa)
1363 {
1364 ppattr_pa_set_bits(pa, PP_ATTR_MONITOR);
1365 }
1366
1367 /**
1368 * Clear the PP_ATTR_MONITOR flag on a specific pp_attr_table entry if the
1369 * passed in physical address is a kernel-managed page.
1370 *
1371 * @param pa The physical address for the entry to update.
1372 */
1373 static inline void
ppattr_pa_clear_monitor(pmap_paddr_t pa)1374 ppattr_pa_clear_monitor(pmap_paddr_t pa)
1375 {
1376 ppattr_pa_clear_bits(pa, PP_ATTR_MONITOR);
1377 }
1378
1379 /**
1380 * Only test for the PP_ATTR_MONITOR flag in a pp_attr_table entry if the passed
1381 * in physical address is a kernel-managed page.
1382 *
1383 * @param pa The physical address for the entry to test.
1384 *
1385 * @return False if the PA isn't a kernel-managed page, otherwise true/false
1386 * depending on whether the PP_ATTR_MONITOR is set.
1387 */
1388 static inline bool
ppattr_pa_test_monitor(pmap_paddr_t pa)1389 ppattr_pa_test_monitor(pmap_paddr_t pa)
1390 {
1391 return ppattr_pa_test_bits(pa, PP_ATTR_MONITOR);
1392 }
1393
1394 /**
1395 * Set the PP_ATTR_NO_MONITOR flag on a specific pp_attr_table entry if the
1396 * passed in physical address is a kernel-managed page.
1397 *
1398 * @param pa The physical address for the entry to update.
1399 */
1400 static inline void
ppattr_pa_set_no_monitor(pmap_paddr_t pa)1401 ppattr_pa_set_no_monitor(pmap_paddr_t pa)
1402 {
1403 ppattr_pa_set_bits(pa, PP_ATTR_NO_MONITOR);
1404 }
1405
1406 /**
1407 * Clear the PP_ATTR_NO_MONITOR flag on a specific pp_attr_table entry if the
1408 * passed in physical address is a kernel-managed page.
1409 *
1410 * @param pa The physical address for the entry to update.
1411 */
1412 static inline void
ppattr_pa_clear_no_monitor(pmap_paddr_t pa)1413 ppattr_pa_clear_no_monitor(pmap_paddr_t pa)
1414 {
1415 ppattr_pa_clear_bits(pa, PP_ATTR_NO_MONITOR);
1416 }
1417
1418 /**
1419 * Only test for the PP_ATTR_NO_MONITOR flag in a pp_attr_table entry if the
1420 * passed in physical address is a kernel-managed page.
1421 *
1422 * @param pa The physical address for the entry to test.
1423 *
1424 * @return False if the PA isn't a kernel-managed page, otherwise true/false
1425 * depending on whether the PP_ATTR_NO_MONITOR is set.
1426 */
1427 static inline bool
ppattr_pa_test_no_monitor(pmap_paddr_t pa)1428 ppattr_pa_test_no_monitor(pmap_paddr_t pa)
1429 {
1430 return ppattr_pa_test_bits(pa, PP_ATTR_NO_MONITOR);
1431 }
1432
1433 #endif /* XNU_MONITOR */
1434
1435 /**
1436 * Set the PP_ATTR_INTERNAL flag on a specific pp_attr_table entry.
1437 *
1438 * @param pai The physical address index for the entry to update.
1439 */
1440 static inline void
ppattr_set_internal(unsigned int pai)1441 ppattr_set_internal(unsigned int pai)
1442 {
1443 ppattr_set_bits(pai, PP_ATTR_INTERNAL);
1444 }
1445
1446 /**
1447 * Clear the PP_ATTR_INTERNAL flag on a specific pp_attr_table entry.
1448 *
1449 * @param pai The physical address index for the entry to update.
1450 */
1451 static inline void
ppattr_clear_internal(unsigned int pai)1452 ppattr_clear_internal(unsigned int pai)
1453 {
1454 ppattr_clear_bits(pai, PP_ATTR_INTERNAL);
1455 }
1456
1457 /**
1458 * Return true if the pp_attr_table entry has the PP_ATTR_INTERNAL flag set.
1459 *
1460 * @param pai The physical address index for the entry to test.
1461 */
1462 static inline bool
ppattr_test_internal(unsigned int pai)1463 ppattr_test_internal(unsigned int pai)
1464 {
1465 return ppattr_test_bits(pai, PP_ATTR_INTERNAL);
1466 }
1467
1468 /**
1469 * Set the PP_ATTR_REUSABLE flag on a specific pp_attr_table entry.
1470 *
1471 * @param pai The physical address index for the entry to update.
1472 */
1473 static inline void
ppattr_set_reusable(unsigned int pai)1474 ppattr_set_reusable(unsigned int pai)
1475 {
1476 ppattr_set_bits(pai, PP_ATTR_REUSABLE);
1477 }
1478
1479 /**
1480 * Clear the PP_ATTR_REUSABLE flag on a specific pp_attr_table entry.
1481 *
1482 * @param pai The physical address index for the entry to update.
1483 */
1484 static inline void
ppattr_clear_reusable(unsigned int pai)1485 ppattr_clear_reusable(unsigned int pai)
1486 {
1487 ppattr_clear_bits(pai, PP_ATTR_REUSABLE);
1488 }
1489
1490 /**
1491 * Return true if the pp_attr_table entry has the PP_ATTR_REUSABLE flag set.
1492 *
1493 * @param pai The physical address index for the entry to test.
1494 */
1495 static inline bool
ppattr_test_reusable(unsigned int pai)1496 ppattr_test_reusable(unsigned int pai)
1497 {
1498 return ppattr_test_bits(pai, PP_ATTR_REUSABLE);
1499 }
1500
1501 /**
1502 * Set the PP_ATTR_ALTACCT flag on a specific pp_attr_table entry.
1503 *
1504 * @note This is only valid when the ALTACCT flag is being tracked using the
1505 * pp_attr_table. See the descriptions above the PVE_PTEP_ALTACCT and
1506 * PP_ATTR_ALTACCT definitions for more information.
1507 *
1508 * @param pai The physical address index for the entry to update.
1509 */
1510 static inline void
ppattr_set_altacct(unsigned int pai)1511 ppattr_set_altacct(unsigned int pai)
1512 {
1513 ppattr_set_bits(pai, PP_ATTR_ALTACCT);
1514 }
1515
1516 /**
1517 * Clear the PP_ATTR_ALTACCT flag on a specific pp_attr_table entry.
1518 *
1519 * @note This is only valid when the ALTACCT flag is being tracked using the
1520 * pp_attr_table. See the descriptions above the PVE_PTEP_ALTACCT and
1521 * PP_ATTR_ALTACCT definitions for more information.
1522 *
1523 * @param pai The physical address index for the entry to update.
1524 */
1525 static inline void
ppattr_clear_altacct(unsigned int pai)1526 ppattr_clear_altacct(unsigned int pai)
1527 {
1528 ppattr_clear_bits(pai, PP_ATTR_ALTACCT);
1529 }
1530
1531 /**
1532 * Get the PP_ATTR_ALTACCT flag on a specific pp_attr_table entry.
1533 *
1534 * @note This is only valid when the ALTACCT flag is being tracked using the
1535 * pp_attr_table. See the descriptions above the PVE_PTEP_ALTACCT and
1536 * PP_ATTR_ALTACCT definitions for more information.
1537 *
1538 * @param pai The physical address index for the entry to test.
1539 *
1540 * @return True if the passed in page uses alternate accounting, false
1541 * otherwise.
1542 */
1543 static inline bool
ppattr_is_altacct(unsigned int pai)1544 ppattr_is_altacct(unsigned int pai)
1545 {
1546 return ppattr_test_bits(pai, PP_ATTR_ALTACCT);
1547 }
1548
1549 /**
1550 * Get the PP_ATTR_INTERNAL flag on a specific pp_attr_table entry.
1551 *
1552 * @note This is only valid when the INTERNAL flag is being tracked using the
1553 * pp_attr_table. See the descriptions above the PVE_PTEP_ALTACCT and
1554 * PP_ATTR_ALTACCT definitions for more information.
1555 *
1556 * @param pai The physical address index for the entry to test.
1557 *
1558 * @return True if the passed in page is "internal", false otherwise.
1559 */
1560 static inline bool
ppattr_is_internal(unsigned int pai)1561 ppattr_is_internal(unsigned int pai)
1562 {
1563 return ppattr_test_bits(pai, PP_ATTR_INTERNAL);
1564 }
1565
1566 /**
1567 * The "alternate accounting" (ALTACCT) status for a page is tracked differently
1568 * depending on whether there are one or multiple mappings to a page. This
1569 * function abstracts out the difference between single and multiple mappings to
1570 * a page and provides a single function for determining whether alternate
1571 * accounting is set for a mapping.
1572 *
1573 * @note See the descriptions above the PVE_PTEP_ALTACCT and PP_ATTR_ALTACCT
1574 * definitions for more information.
1575 *
1576 * @param pai The physical address index for the entry to test.
1577 * @param pvep Pointer to the pv_entry_t object containing that mapping.
1578 * @param idx Index of the chosen PTE pointer inside the PVE.
1579 *
1580 * @return True if the passed in page uses alternate accounting, false
1581 * otherwise.
1582 */
1583 static inline bool
ppattr_pve_is_altacct(unsigned int pai,pv_entry_t * pvep,unsigned idx)1584 ppattr_pve_is_altacct(unsigned int pai, pv_entry_t *pvep, unsigned idx)
1585 {
1586 return (pvep == PV_ENTRY_NULL) ? ppattr_is_altacct(pai) : pve_get_altacct(pvep, idx);
1587 }
1588
1589 /**
1590 * The "internal" (INTERNAL) status for a page is tracked differently
1591 * depending on whether there are one or multiple mappings to a page. This
1592 * function abstracts out the difference between single and multiple mappings to
1593 * a page and provides a single function for determining whether "internal"
1594 * is set for a mapping.
1595 *
1596 * @note See the descriptions above the PVE_PTEP_ALTACCT and PP_ATTR_ALTACCT
1597 * definitions for more information.
1598 *
1599 * @param pai The physical address index for the entry to test.
1600 * @param pvep Pointer to the pv_entry_t object containing that mapping.
1601 * @param idx Index of the chosen PTE pointer inside the PVE.
1602 *
1603 * @return True if the passed in page is "internal", false otherwise.
1604 */
1605 static inline bool
ppattr_pve_is_internal(unsigned int pai,pv_entry_t * pvep,unsigned idx)1606 ppattr_pve_is_internal(unsigned int pai, pv_entry_t *pvep, unsigned idx)
1607 {
1608 return (pvep == PV_ENTRY_NULL) ? ppattr_is_internal(pai) : pve_get_internal(pvep, idx);
1609 }
1610
1611 /**
1612 * The "alternate accounting" (ALTACCT) status for a page is tracked differently
1613 * depending on whether there are one or multiple mappings to a page. This
1614 * function abstracts out the difference between single and multiple mappings to
1615 * a page and provides a single function for setting the alternate accounting status
1616 * for a mapping.
1617 *
1618 * @note See the descriptions above the PVE_PTEP_ALTACCT and PP_ATTR_ALTACCT
1619 * definitions for more information.
1620 *
1621 * @param pai The physical address index for the entry to update.
1622 * @param pvep Pointer to the pv_entry_t object containing that mapping.
1623 * @param idx Index of the chosen PTE pointer inside the PVE.
1624 */
1625 static inline void
ppattr_pve_set_altacct(unsigned int pai,pv_entry_t * pvep,unsigned idx)1626 ppattr_pve_set_altacct(unsigned int pai, pv_entry_t *pvep, unsigned idx)
1627 {
1628 if (pvep == PV_ENTRY_NULL) {
1629 ppattr_set_altacct(pai);
1630 } else {
1631 pve_set_altacct(pvep, idx);
1632 }
1633 }
1634
1635 /**
1636 * The "internal" (INTERNAL) status for a page is tracked differently
1637 * depending on whether there are one or multiple mappings to a page. This
1638 * function abstracts out the difference between single and multiple mappings to
1639 * a page and provides a single function for setting the "internal" status
1640 * for a mapping.
1641 *
1642 * @note See the descriptions above the PVE_PTEP_ALTACCT and PP_ATTR_ALTACCT
1643 * definitions for more information.
1644 *
1645 * @param pai The physical address index for the entry to update.
1646 * @param pvep Pointer to the pv_entry_t object containing that mapping.
1647 * @param idx Index of the chosen PTE pointer inside the PVE.
1648 */
1649 static inline void
ppattr_pve_set_internal(unsigned int pai,pv_entry_t * pvep,unsigned idx)1650 ppattr_pve_set_internal(unsigned int pai, pv_entry_t *pvep, unsigned idx)
1651 {
1652 if (pvep == PV_ENTRY_NULL) {
1653 ppattr_set_internal(pai);
1654 } else {
1655 pve_set_internal(pvep, idx);
1656 }
1657 }
1658
1659 /**
1660 * The "alternate accounting" (ALTACCT) status for a page is tracked differently
1661 * depending on whether there are one or multiple mappings to a page. This
1662 * function abstracts out the difference between single and multiple mappings to
1663 * a page and provides a single function for clearing the alternate accounting status
1664 * for a mapping.
1665 *
1666 * @note See the descriptions above the PVE_PTEP_ALTACCT and PP_ATTR_ALTACCT
1667 * definitions for more information.
1668 *
1669 * @param pai The physical address index for the entry to update.
1670 * @param pvep Pointer to the pv_entry_t object containing that mapping.
1671 * @param idx Index of the chosen PTE pointer inside the PVE.
1672 */
1673 static inline void
ppattr_pve_clr_altacct(unsigned int pai,pv_entry_t * pvep,unsigned idx)1674 ppattr_pve_clr_altacct(unsigned int pai, pv_entry_t *pvep, unsigned idx)
1675 {
1676 if (pvep == PV_ENTRY_NULL) {
1677 ppattr_clear_altacct(pai);
1678 } else {
1679 pve_clr_altacct(pvep, idx);
1680 }
1681 }
1682
1683 /**
1684 * The "internal" (INTERNAL) status for a page is tracked differently
1685 * depending on whether there are one or multiple mappings to a page. This
1686 * function abstracts out the difference between single and multiple mappings to
1687 * a page and provides a single function for clearing the "internal" status
1688 * for a mapping.
1689 *
1690 * @note See the descriptions above the PVE_PTEP_ALTACCT and PP_ATTR_ALTACCT
1691 * definitions for more information.
1692 *
1693 * @param pai The physical address index for the entry to update.
1694 * @param pvep Pointer to the pv_entry_t object containing that mapping.
1695 * @param idx Index of the chosen PTE pointer inside the PVE.
1696 */
1697 static inline void
ppattr_pve_clr_internal(unsigned int pai,pv_entry_t * pvep,unsigned idx)1698 ppattr_pve_clr_internal(unsigned int pai, pv_entry_t *pvep, unsigned idx)
1699 {
1700 if (pvep == PV_ENTRY_NULL) {
1701 ppattr_clear_internal(pai);
1702 } else {
1703 pve_clr_internal(pvep, idx);
1704 }
1705 }
1706
1707 /**
1708 * Set the PP_ATTR_REFFAULT flag on a specific pp_attr_table entry.
1709 *
1710 * @param pai The physical address index for the entry to update.
1711 */
1712 static inline void
ppattr_set_reffault(unsigned int pai)1713 ppattr_set_reffault(unsigned int pai)
1714 {
1715 ppattr_set_bits(pai, PP_ATTR_REFFAULT);
1716 }
1717
1718 /**
1719 * Clear the PP_ATTR_REFFAULT flag on a specific pp_attr_table entry.
1720 *
1721 * @param pai The physical address index for the entry to update.
1722 */
1723 static inline void
ppattr_clear_reffault(unsigned int pai)1724 ppattr_clear_reffault(unsigned int pai)
1725 {
1726 ppattr_clear_bits(pai, PP_ATTR_REFFAULT);
1727 }
1728
1729 /**
1730 * Return true if the pp_attr_table entry has the PP_ATTR_REFFAULT flag set.
1731 *
1732 * @param pai The physical address index for the entry to test.
1733 */
1734 static inline bool
ppattr_test_reffault(unsigned int pai)1735 ppattr_test_reffault(unsigned int pai)
1736 {
1737 return ppattr_test_bits(pai, PP_ATTR_REFFAULT);
1738 }
1739
1740 /**
1741 * Set the PP_ATTR_MODFAULT flag on a specific pp_attr_table entry.
1742 *
1743 * @param pai The physical address index for the entry to update.
1744 */
1745 static inline void
ppattr_set_modfault(unsigned int pai)1746 ppattr_set_modfault(unsigned int pai)
1747 {
1748 ppattr_set_bits(pai, PP_ATTR_MODFAULT);
1749 }
1750
1751 /**
1752 * Clear the PP_ATTR_MODFAULT flag on a specific pp_attr_table entry.
1753 *
1754 * @param pai The physical address index for the entry to update.
1755 */
1756 static inline void
ppattr_clear_modfault(unsigned int pai)1757 ppattr_clear_modfault(unsigned int pai)
1758 {
1759 ppattr_clear_bits(pai, PP_ATTR_MODFAULT);
1760 }
1761
1762 /**
1763 * Return true if the pp_attr_table entry has the PP_ATTR_MODFAULT flag set.
1764 *
1765 * @param pai The physical address index for the entry to test.
1766 */
1767 static inline bool
ppattr_test_modfault(unsigned int pai)1768 ppattr_test_modfault(unsigned int pai)
1769 {
1770 return ppattr_test_bits(pai, PP_ATTR_MODFAULT);
1771 }
1772
1773 /**
1774 * The minimum number of pages to keep in the PPL page free list.
1775 *
1776 * We define our target as 8 pages: enough for 2 page table pages, a PTD page,
1777 * and a PV page; in essence, twice as many pages as may be necessary to satisfy
1778 * a single pmap_enter request.
1779 */
1780 #define PMAP_MIN_FREE_PPL_PAGES 8
1781
1782 /**
1783 * Flags passed to various page allocation functions, usually accessed through
1784 * the pmap_pages_alloc_zeroed() API. Each function that can take these flags as
1785 * a part of its option field, will describe these flags in its function header.
1786 */
1787
1788 /**
1789 * Instruct the allocation function to return immediately if no pages are
1790 * current available. Without this flag, the function will spin and wait for a
1791 * page to become available. This flag can be required in some circumstances
1792 * (for instance, when allocating pages from within the PPL).
1793 */
1794 #define PMAP_PAGES_ALLOCATE_NOWAIT 0x1
1795
1796 /**
1797 * Instructs an allocation function to fallback to reclaiming a userspace page
1798 * table if it failed to allocate a page from the free lists. This can be useful
1799 * when allocating from within the PPL because refilling the free lists requires
1800 * exiting and re-entering the PPL (which incurs extra latency).
1801 *
1802 * This is a quick way of allocating a page at the expense of having to
1803 * reallocate the table the next time one of its mappings is accessed.
1804 */
1805 #define PMAP_PAGE_RECLAIM_NOWAIT 0x2
1806
1807 /**
1808 * Global variables exported to the rest of the internal pmap implementation.
1809 */
1810 #if XNU_MONITOR
1811 extern uint64_t pmap_ppl_free_page_count;
1812 extern pmap_paddr_t pmap_stacks_start_pa;
1813 extern pmap_paddr_t pmap_stacks_end_pa;
1814 extern pmap_paddr_t ppl_cpu_save_area_start;
1815 extern pmap_paddr_t ppl_cpu_save_area_end;
1816 #endif /* XNU_MONITOR */
1817 extern unsigned int inuse_pmap_pages_count;
1818 extern vm_object_t pmap_object;
1819 extern uint32_t pv_alloc_initial_target;
1820 extern uint32_t pv_kern_alloc_initial_target;
1821
1822 /**
1823 * Functions exported to the rest of the internal pmap implementation.
1824 */
1825 extern void pmap_data_bootstrap(void);
1826 extern void pmap_enqueue_pages(vm_page_t);
1827 extern kern_return_t pmap_pages_alloc_zeroed(pmap_paddr_t *, unsigned, unsigned);
1828 extern void pmap_pages_free(pmap_paddr_t, unsigned);
1829
1830 #if XNU_MONITOR
1831
1832 extern void pmap_mark_page_as_ppl_page_internal(pmap_paddr_t, bool);
1833 extern void pmap_mark_page_as_ppl_page(pmap_paddr_t);
1834 extern void pmap_mark_page_as_kernel_page(pmap_paddr_t);
1835 extern pmap_paddr_t pmap_alloc_page_for_kern(unsigned int);
1836 extern void pmap_alloc_page_for_ppl(unsigned int);
1837 extern uint64_t pmap_release_ppl_pages_to_kernel(void);
1838
1839 extern uint64_t pmap_ledger_validate(const volatile void *);
1840 void pmap_ledger_retain(ledger_t ledger);
1841 void pmap_ledger_release(ledger_t ledger);
1842 extern void pmap_ledger_check_balance(pmap_t pmap);
1843
1844 kern_return_t pmap_alloc_pmap(pmap_t *pmap);
1845 void pmap_free_pmap(pmap_t pmap);
1846
1847 #endif /* XNU_MONITOR */
1848
1849 /**
1850 * The modes in which a pmap lock can be acquired. Note that shared access
1851 * doesn't necessarily mean "read-only". As long as data is atomically updated
1852 * correctly (to account for multi-cpu accesses) data can still get written with
1853 * a shared lock held. Care just needs to be taken so as to not introduce any
1854 * race conditions when there are multiple writers.
1855 *
1856 * This is here in pmap_data.h because it's a needed parameter for pv_alloc()
1857 * and pmap_enter_pv(). This header is always included in pmap_internal.h before
1858 * the rest of the pmap locking code is defined so there shouldn't be any issues
1859 * with missing types.
1860 */
1861 OS_ENUM(pmap_lock_mode, uint8_t,
1862 PMAP_LOCK_SHARED,
1863 PMAP_LOCK_EXCLUSIVE);
1864
1865 /**
1866 * Possible return values for pv_alloc(). See the pv_alloc() function header for
1867 * a description of each of these values.
1868 */
1869 typedef enum {
1870 PV_ALLOC_SUCCESS,
1871 PV_ALLOC_RETRY,
1872 PV_ALLOC_FAIL
1873 } pv_alloc_return_t;
1874
1875 extern pv_alloc_return_t pv_alloc(
1876 pmap_t, unsigned int, pmap_lock_mode_t, pv_entry_t **);
1877 extern void pv_free(pv_entry_t *);
1878 extern void pv_list_free(pv_entry_t *, pv_entry_t *, int);
1879 extern void pmap_compute_pv_targets(void);
1880 extern pv_alloc_return_t pmap_enter_pv(
1881 pmap_t, pt_entry_t *, int, unsigned int, pmap_lock_mode_t, pv_entry_t **, int *new_pve_ptep_idx);
1882 extern void pmap_remove_pv(pmap_t, pt_entry_t *, int, bool, bool *, bool *);
1883
1884 extern void ptd_bootstrap(pt_desc_t *, unsigned int);
1885 extern pt_desc_t *ptd_alloc_unlinked(void);
1886 extern pt_desc_t *ptd_alloc(pmap_t);
1887 extern void ptd_deallocate(pt_desc_t *);
1888 extern void ptd_info_init(
1889 pt_desc_t *, pmap_t, vm_map_address_t, unsigned int, pt_entry_t *);
1890
1891 extern kern_return_t pmap_ledger_credit(pmap_t, int, ledger_amount_t);
1892 extern kern_return_t pmap_ledger_debit(pmap_t, int, ledger_amount_t);
1893
1894 extern void validate_pmap_internal(const volatile struct pmap *, const char *);
1895 extern void validate_pmap_mutable_internal(const volatile struct pmap *, const char *);
1896
1897 /**
1898 * Macro function wrappers around pmap validation so that the calling function
1899 * can be printed in the panic strings for easier validation failure debugging.
1900 */
1901 #define validate_pmap(x) validate_pmap_internal(x, __func__)
1902 #define validate_pmap_mutable(x) validate_pmap_mutable_internal(x, __func__)
1903
1904 /**
1905 * This structure describes a PPL-owned I/O range.
1906 *
1907 * @note This doesn't necessarily have to represent "I/O" only, this can also
1908 * represent non-kernel-managed DRAM (e.g., iBoot carveouts). Any physical
1909 * address region that isn't considered "kernel-managed" is fair game.
1910 *
1911 * @note The layout of this structure needs to map 1-to-1 with the pmap-io-range
1912 * device tree nodes. Astris (through the LowGlobals) also depends on the
1913 * consistency of this structure.
1914 */
1915 typedef struct pmap_io_range {
1916 /* Physical address of the PPL-owned I/O range. */
1917 uint64_t addr;
1918
1919 /* Length (in bytes) of the PPL-owned I/O range. */
1920 uint64_t len;
1921
1922 /* Strong DSB required for pages in this range. */
1923 #define PMAP_IO_RANGE_STRONG_SYNC (1UL << 31)
1924
1925 /* Corresponds to memory carved out by bootloader. */
1926 #define PMAP_IO_RANGE_CARVEOUT (1UL << 30)
1927
1928 /* Pages in this range need to be included in the hibernation image */
1929 #define PMAP_IO_RANGE_NEEDS_HIBERNATING (1UL << 29)
1930
1931 /* Mark the range as 'owned' by a given subsystem */
1932 #define PMAP_IO_RANGE_OWNED (1UL << 28)
1933
1934 /**
1935 * Lower 16 bits treated as pp_attr_t, upper 16 bits contain additional
1936 * mapping flags (defined above).
1937 */
1938 uint32_t wimg;
1939
1940 /* 4 Character Code (4CC) describing what this range is. */
1941 uint32_t signature;
1942 } pmap_io_range_t;
1943
1944 /* Reminder: be sure to change all relevant device trees if you change the layout of pmap_io_range_t */
1945 _Static_assert(sizeof(pmap_io_range_t) == 24, "unexpected size for pmap_io_range_t");
1946
1947 extern pmap_io_range_t* pmap_find_io_attr(pmap_paddr_t);
1948
1949 extern void pmap_cpu_data_init_internal(unsigned int);
1950
1951 #endif /* _ARM_PMAP_PMAP_DATA_H_ */
1952