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