xref: /xnu-8019.80.24/osfmk/arm/pmap/pmap_data.h (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
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 
514 /**
515  * Set the ALTACCT bit for a specific PTE pointer.
516  *
517  * @param pvep A pointer to the current pv_entry mapping in the linked list of
518  *             mappings.
519  * @param idx Index of the chosen PTE pointer inside the PVE.
520  */
521 static inline void
pve_set_altacct(pv_entry_t * pvep,unsigned idx)522 pve_set_altacct(pv_entry_t *pvep, unsigned idx)
523 {
524 	assert(idx < PTE_PER_PVE);
525 	pvep->pve_ptep[idx] = (pt_entry_t *)((uintptr_t)pvep->pve_ptep[idx] | PVE_PTEP_ALTACCT);
526 }
527 
528 /**
529  * Set the ALTACCT bit for a specific PTE pointer.
530  *
531  * @param pvep A pointer to the current pv_entry mapping in the linked list of
532  *             mappings.
533  * @param idx Index of the chosen PTE pointer inside the PVE.
534  */
535 static inline void
pve_clr_altacct(pv_entry_t * pvep,unsigned idx)536 pve_clr_altacct(pv_entry_t *pvep, unsigned idx)
537 {
538 	assert(idx < PTE_PER_PVE);
539 	pvep->pve_ptep[idx] = (pt_entry_t *)((uintptr_t)pvep->pve_ptep[idx] & ~PVE_PTEP_ALTACCT);
540 }
541 
542 /**
543  * Return the ALTACCT bit for a specific PTE pointer.
544  *
545  * @param pvep A pointer to the current pv_entry mapping in the linked list of
546  *             mappings.
547  * @param idx Index of the chosen PTE pointer inside the PVE.
548  */
549 static inline bool
pve_get_altacct(pv_entry_t * pvep,unsigned idx)550 pve_get_altacct(pv_entry_t *pvep, unsigned idx)
551 {
552 	assert(idx < PTE_PER_PVE);
553 	return (uintptr_t)pvep->pve_ptep[idx] & PVE_PTEP_ALTACCT;
554 }
555 
556 /**
557  * Return the next mapping (pv_entry) in a linked list of mappings. This applies
558  * to pv_head_table entries of type PVH_TYPE_PVEP.
559  *
560  * @param pvep A pointer to the current pv_entry mapping in the linked list of
561  *             mappings.
562  *
563  * @return The next virtual mapping for a physical page, or PV_ENTRY_NULL if the
564  *         end of the list has been reached.
565  */
566 static inline pv_entry_t *
pve_next(pv_entry_t * pvep)567 pve_next(pv_entry_t *pvep)
568 {
569 	return pvep->pve_next;
570 }
571 
572 /**
573  * Return a pointer to the pve_next field in a pv_entry. This value is used
574  * when adding and removing entries to a PVE list.
575  *
576  * @param pvep The pv_entry whose pve_next field is being accessed.
577  *
578  * @return Pointer to the pve_next field.
579  */
580 static inline pv_entry_t **
pve_next_ptr(pv_entry_t * pvep)581 pve_next_ptr(pv_entry_t *pvep)
582 {
583 	return &pvep->pve_next;
584 }
585 
586 /**
587  * Return a pointer to the page table entry for this mapping.
588  *
589  * @param pvep The pv_entry whose pve_ptep field is to be returned.
590  * @param idx Index of the chosen PTE pointer inside the PVE.
591  *
592  * @return Pointer to the page table entry.
593  */
594 static inline pt_entry_t *
pve_get_ptep(pv_entry_t * pvep,unsigned idx)595 pve_get_ptep(pv_entry_t *pvep, unsigned idx)
596 {
597 	assert(idx < PTE_PER_PVE);
598 	return (pt_entry_t *)((uintptr_t)pvep->pve_ptep[idx] & ~PVE_PTEP_ALTACCT);
599 }
600 
601 /**
602  * Update the page table entry for a specific physical to virtual mapping.
603  *
604  * @param pvep The pv_entry to update.
605  * @param idx Index of the chosen PTE pointer inside the PVE.
606  * @param ptep_new The new page table entry.
607  */
608 static inline void
pve_set_ptep(pv_entry_t * pvep,unsigned idx,pt_entry_t * ptep_new)609 pve_set_ptep(pv_entry_t *pvep, unsigned idx, pt_entry_t *ptep_new)
610 {
611 	assert(idx < PTE_PER_PVE);
612 	pvep->pve_ptep[idx] = ptep_new;
613 }
614 
615 /**
616  * Initialize all fields in a PVE to NULL.
617  *
618  * @param pvep The pv_entry to initialize.
619  */
620 static inline void
pve_init(pv_entry_t * pvep)621 pve_init(pv_entry_t *pvep)
622 {
623 	pvep->pve_next = PV_ENTRY_NULL;
624 	for (int i = 0; i < PTE_PER_PVE; i++) {
625 		pvep->pve_ptep[i] = PT_ENTRY_NULL;
626 	}
627 }
628 
629 /**
630  * Find PTE pointer in PVE and return its index.
631  *
632  * @param pvep The PVE to search.
633  * @param ptep PTE to search for.
634  *
635  * @return Index of the found entry, or -1 if no entry exists.
636  */
637 static inline int
pve_find_ptep_index(pv_entry_t * pvep,pt_entry_t * ptep)638 pve_find_ptep_index(pv_entry_t *pvep, pt_entry_t *ptep)
639 {
640 	for (int i = 0; i < PTE_PER_PVE; i++) {
641 		if (pve_get_ptep(pvep, i) == ptep) {
642 			return i;
643 		}
644 	}
645 
646 	return -1;
647 }
648 
649 /**
650  * Checks if no PTEs are currently associated with this PVE.
651  *
652  * @param pvep The PVE to search.
653  *
654  * @return True if no PTEs are currently associated with this PVE, or false.
655  */
656 static inline bool
pve_is_empty(pv_entry_t * pvep)657 pve_is_empty(pv_entry_t *pvep)
658 {
659 	for (int i = 0; i < PTE_PER_PVE; i++) {
660 		if (pve_get_ptep(pvep, i) != PT_ENTRY_NULL) {
661 			return false;
662 		}
663 	}
664 
665 	return true;
666 }
667 
668 /**
669  * Prepend a new pv_entry node to a PVE list.
670  *
671  * @note This function will clobber any existing flags stored in the PVH
672  *       pointer. It's up to the caller to preserve flags if that functionality
673  *       is needed (either by ensuring `pvep` contains those flags, or by
674  *       manually setting the flags after this call).
675  *
676  * @param pvh The linked list of mappings to update.
677  * @param pvep The new mapping to add to the linked list.
678  */
679 static inline void
pve_add(pv_entry_t ** pvh,pv_entry_t * pvep)680 pve_add(pv_entry_t **pvh, pv_entry_t *pvep)
681 {
682 	assert(pvh_test_type(pvh, PVH_TYPE_PVEP));
683 
684 	pvep->pve_next = pvh_pve_list(pvh);
685 	pvh_update_head(pvh, pvep, PVH_TYPE_PVEP);
686 }
687 
688 /**
689  * Remove an entry from a PVE list of mappings.
690  *
691  * @note This function will clobber any existing flags stored in the PVH
692  *       pointer. It's up to the caller to preserve flags if that functionality
693  *       is needed (either by ensuring `pvep` contains those flags, or by
694  *       manually setting the flags after this call).
695  *
696  * @param pvh The pv_head_table entry of the PVE list to remove a mapping from.
697  *            This is the first entry in the list of pv_entry_t mappings.
698  * @param pvepp A pointer to the pv_entry_t* that's being removed. If this entry
699  *              is the first in the linked list of mappings, then this should be
700  *              identical to the pv_head_table entry. If the mapping isn't the
701  *              first, then this is a pointer to the pve_next field in the
702  *              previous mapping.
703  * @param pvep The entry that should be removed. Should be identical to a
704  *             dereference of the pvepp parameter (unless it's the pv_head_table
705  *             entry).
706  */
707 static inline void
pve_remove(pv_entry_t ** pvh,pv_entry_t ** pvepp,pv_entry_t * pvep)708 pve_remove(pv_entry_t **pvh, pv_entry_t **pvepp, pv_entry_t *pvep)
709 {
710 	assert(pvh_test_type(pvh, PVH_TYPE_PVEP));
711 
712 	if (pvepp == pvh) {
713 		if (pve_next(pvep) == PV_ENTRY_NULL) {
714 			/* The last mapping to this page is being removed. */
715 			pvh_update_head(pvh, PV_ENTRY_NULL, PVH_TYPE_NULL);
716 		} else {
717 			/**
718 			 * There are still mappings left, make the next one the new head of
719 			 * the list. This effectively removes the first entry from the list.
720 			 */
721 			pvh_update_head(pvh, pve_next(pvep), PVH_TYPE_PVEP);
722 		}
723 	} else {
724 		/**
725 		 * Move the previous entry's next field to the entry after the one being
726 		 * removed. This will clobber the ALTACCT bit.
727 		 */
728 		*pvepp = pve_next(pvep);
729 	}
730 }
731 
732 /**
733  * PVH_TYPE_PTDP Types and Helper Functions.
734  *
735  * The following are types and methods used to manipulate page table descriptor
736  * (PTD) objects. This is the type of pv_head_table entry used when a page is
737  * being used as a page table.
738  */
739 
740 /**
741  * When the pmap layer allocates memory, it always does so in chunks of the VM
742  * page size (which are represented by the PAGE_SIZE/PAGE_SHIFT macros). The VM
743  * page size might not match up with the hardware page size for a given address
744  * space (this is especially true on systems that support more than one page
745  * size).
746  *
747  * The pv_head_table is allocated to have one entry per VM page, not hardware
748  * page (which can change depending on the address space). Because of that, a
749  * single VM-page-sized region (single pv_head_table entry) can potentially hold
750  * up to four page tables. Only one page table descriptor (PTD) is allocated per
751  * pv_head_table entry (per VM page), so on some systems, one PTD might have to
752  * keep track of up to four different page tables.
753  */
754 #if (__ARM_VMSA__ == 7)
755 
756 #define PT_INDEX_MAX 1
757 
758 #else /* (__ARM_VMSA__ == 7) */
759 
760 #if __ARM_MIXED_PAGE_SIZE__
761 #define PT_INDEX_MAX (ARM_PGBYTES / 4096)
762 #elif (ARM_PGSHIFT == 14)
763 #define PT_INDEX_MAX 1
764 #elif (ARM_PGSHIFT == 12)
765 #define PT_INDEX_MAX 4
766 #else
767 #error Unsupported ARM_PGSHIFT
768 #endif /* __ARM_MIXED_PAGE_SIZE__ || ARM_PGSHIFT == 14 || ARM_PGSHIFT == 12 */
769 
770 #endif /* (__ARM_VMSA__ == 7) */
771 
772 /**
773  * Page table descriptor (PTD) info structure.
774  *
775  * Contains information about a page table. These pieces of data are separate
776  * from the PTD itself because in address spaces where the VM page size doesn't
777  * match the underlying hardware page size, one PTD could represent multiple
778  * page tables (and so will need multiple PTD info structures).
779  *
780  * These fields are also in their own struct so that they can be allocated
781  * separately from the associated pt_desc_t object. This allows us to allocate
782  * the counts in this structure in a way that ensures they don't fall within the
783  * same cache line as the main pt_desc_t object. This is important because the
784  * fields in this structure are atomically updated which could cause false
785  * sharing cache performance issues with the "va" field in pt_desc_t if all of
786  * the fields were within the same structure.
787  */
788 typedef struct {
789 	/**
790 	 * Pre-defined sentinel values for ptd_info_t.refcnt. If these refcnt values
791 	 * change, make sure to update the showpte LLDB macro to reflect the
792 	 * changes.
793 	 */
794 	#define PT_DESC_REFCOUNT                0x4000U
795 	#define PT_DESC_IOMMU_GRANTED_REFCOUNT  0x8000U
796 	#define PT_DESC_IOMMU_ACCEPTED_REFCOUNT 0x8001U
797 
798 	/*
799 	 * For non-leaf pagetables, should always be PT_DESC_REFCOUNT.
800 	 * For leaf pagetables, should reflect the number of non-empty PTEs.
801 	 * For IOMMU pages, should always be either PT_DESC_IOMMU_GRANTED_REFCOUNT
802 	 * or PT_DESC_IOMMU_ACCEPTED_REFCOUNT.
803 	 */
804 	unsigned short refcnt;
805 
806 	/*
807 	 * For non-leaf pagetables, should be 0.
808 	 * For leaf pagetables, should reflect the number of wired entries.
809 	 * For IOMMU pages, may optionally reflect a driver-defined refcount (IOMMU
810 	 * operations are implicitly wired).
811 	 */
812 	unsigned short wiredcnt;
813 } ptd_info_t;
814 
815 /**
816  * Page Table Descriptor (PTD).
817  *
818  * Provides a per-table data structure and a way of keeping track of all page
819  * tables in the system.
820  *
821  * This structure is also used as a convenient way of keeping track of IOMMU
822  * pages (which may or may not be used as page tables). In that case the "iommu"
823  * field will point to the owner of the page, ptd_info[0].refcnt will be
824  * PT_DESC_IOMMU_GRANTED_REFCOUNT or PT_DESC_IOMMU_ACCEPTED_REFCOUNT, and
825  * ptd_info[0].wiredcnt can be used as an arbitrary refcnt controlled by the
826  * IOMMU driver.
827  */
828 typedef struct pt_desc {
829 	/**
830 	 * This queue chain provides a mechanism for keeping a list of pages
831 	 * being used as page tables. This is used to potentially reclaim userspace
832 	 * page tables as a fast way of "allocating" a page.
833 	 *
834 	 * Refer to osfmk/kern/queue.h for more information about queue chains.
835 	 */
836 	queue_chain_t pt_page;
837 
838 	/* Each page table is either owned by a pmap or a specific IOMMU. */
839 	union {
840 		struct pmap *pmap;
841 	};
842 
843 	/**
844 	 * The following fields contain per-page-table properties, and as such,
845 	 * might have multiple elements each. This is due to a single PTD
846 	 * potentially representing multiple page tables (in address spaces where
847 	 * the VM page size differs from the hardware page size). Use the
848 	 * ptd_get_index() function to get the correct index for a specific page
849 	 * table.
850 	 */
851 
852 	/**
853 	 * The first address of the virtual address space this page table is
854 	 * translating for, or a value set by an IOMMU driver if this PTD is being
855 	 * used to track an IOMMU page.
856 	 */
857 	vm_offset_t va[PT_INDEX_MAX];
858 
859 	/**
860 	 * ptd_info_t's are allocated separately so as to reduce false sharing
861 	 * with the va field. This is desirable because ptd_info_t's are updated
862 	 * atomically from all CPUs.
863 	 */
864 	ptd_info_t *ptd_info;
865 } pt_desc_t;
866 
867 /**
868  * Convert a pv_head_table entry/pointer into a page table descriptor pointer.
869  * This should only be done if the type of this entry is PVH_TYPE_PTDP.
870  *
871  * @param pvh The pv_head_table entry/pointer to convert into a safe to
872  *            dereference pt_desc_t*.
873  *
874  * @return Return back a safe to derefence pointer to the page table descriptor
875  *         for this physical page by masking off the TYPE bits and adding any
876  *         missing flags to the upper portion of the pointer.
877  */
878 static inline pt_desc_t*
pvh_ptd(pv_entry_t ** pvh)879 pvh_ptd(pv_entry_t **pvh)
880 {
881 	return (pt_desc_t *)(((*(vm_offset_t *)pvh) & PVH_LIST_MASK) | PVH_HIGH_FLAGS);
882 }
883 
884 /**
885  * Given an arbitrary page table entry, return back the page table descriptor
886  * (PTD) object for the page table that contains that entry.
887  *
888  * @param ptep Pointer to a PTE whose page table descriptor object to return.
889  *
890  * @return The PTD object for the passed in page table.
891  */
892 static inline pt_desc_t *
ptep_get_ptd(const pt_entry_t * ptep)893 ptep_get_ptd(const pt_entry_t *ptep)
894 {
895 	assert(ptep != NULL);
896 
897 	const vm_offset_t pt_base_va = (vm_offset_t)ptep;
898 	pv_entry_t **pvh = pai_to_pvh(pa_index(ml_static_vtop(pt_base_va)));
899 
900 	if (__improbable(!pvh_test_type(pvh, PVH_TYPE_PTDP))) {
901 		panic("%s: invalid PV head 0x%llx for PTE 0x%p", __func__, (uint64_t)(*pvh), ptep);
902 	}
903 
904 	return pvh_ptd(pvh);
905 }
906 
907 /**
908  * Given an arbitrary page table entry, return back the pmap that owns that
909  * page table.
910  *
911  * @note This won't work correctly for page tables owned by IOMMUs, because
912  *       those table aren't owned by any specific pmap.
913  *
914  * @param ptep Pointer to a page table entry whose owner we're trying to return.
915  *
916  * @return The pmap that owns the given page table entry.
917  */
918 static inline struct pmap *
ptep_get_pmap(const pt_entry_t * ptep)919 ptep_get_pmap(const pt_entry_t *ptep)
920 {
921 	return ptep_get_ptd(ptep)->pmap;
922 }
923 
924 
925 /**
926  * Given an arbitrary translation table entry, get the page table descriptor
927  * (PTD) object for the page table pointed to by the TTE.
928  *
929  * @param tte The translation table entry to parse. For instance, if this is an
930  *            L2 TTE, then the PTD for the L3 table this entry points to will be
931  *            returned.
932  *
933  * @return The page table descriptor (PTD) for the page table pointed to by this
934  *         TTE.
935  */
936 static inline pt_desc_t *
tte_get_ptd(const tt_entry_t tte)937 tte_get_ptd(const tt_entry_t tte)
938 {
939 	const vm_offset_t pt_base_va = (vm_offset_t)(tte & ~PAGE_MASK);
940 	pv_entry_t **pvh = pai_to_pvh(pa_index(pt_base_va));
941 
942 	if (__improbable(!pvh_test_type(pvh, PVH_TYPE_PTDP))) {
943 		panic("%s: invalid PV head 0x%llx for TTE 0x%llx", __func__, (uint64_t)(*pvh), (uint64_t)tte);
944 	}
945 
946 	return pvh_ptd(pvh);
947 }
948 
949 /**
950  * In address spaces where the VM page size doesn't match the underlying
951  * hardware page size, one PTD could represent multiple page tables. This
952  * function returns the correct index value depending on which page table is
953  * being accessed. That index value can then be used to access the
954  * per-page-table properties stored within a PTD.
955  *
956  * @note See the description above the PT_INDEX_MAX definition for a more
957  *       detailed explanation of why multiple page tables can be represented
958  *       by a single PTD object in the pv_head_table.
959  *
960  * @param ptd The page table descriptor that's being accessed.
961  * @param ttep Pointer to the translation table entry that's being accessed.
962  *
963  * @return The correct index value for a specific, hardware-sized page
964  *         table.
965  */
966 static inline unsigned
ptd_get_index(__unused const pt_desc_t * ptd,__unused const tt_entry_t * ttep)967 ptd_get_index(__unused const pt_desc_t *ptd, __unused const tt_entry_t *ttep)
968 {
969 #if PT_INDEX_MAX == 1
970 	return 0;
971 #else
972 	assert(ptd != NULL);
973 
974 	const uint64_t pmap_page_shift = pt_attr_leaf_shift(pmap_get_pt_attr(ptd->pmap));
975 	const vm_offset_t ttep_page = (vm_offset_t)ttep >> pmap_page_shift;
976 
977 	/**
978 	 * Use the difference between the VM page shift and the hardware page shift
979 	 * to get the index of the correct page table. In practice, this equates to
980 	 * masking out the bottom two bits of the L3 table index in address spaces
981 	 * where the VM page size is greater than the hardware page size. In address
982 	 * spaces where they're identical, the index will always be zero.
983 	 */
984 	const unsigned int ttep_index = ttep_page & ((1U << (PAGE_SHIFT - pmap_page_shift)) - 1);
985 	assert(ttep_index < PT_INDEX_MAX);
986 
987 	return ttep_index;
988 #endif
989 }
990 
991 /**
992  * In address spaces where the VM page size doesn't match the underlying
993  * hardware page size, one PTD could represent multiple page tables. This
994  * function returns the correct ptd_info_t structure depending on which page
995  * table is being accessed.
996  *
997  * @note See the description above the PT_INDEX_MAX definition for a more
998  *       detailed explanation of why multiple page tables can be represented
999  *       by a single PTD object in the pv_head_table.
1000  *
1001  * @param ptd The page table descriptor that's being accessed.
1002  * @param ttep Pointer to the translation table entry that's being accessed.
1003  *
1004  * @return The correct ptd_info_t structure for a specific, hardware-sized page
1005  *         table.
1006  */
1007 static inline ptd_info_t *
ptd_get_info(pt_desc_t * ptd,const tt_entry_t * ttep)1008 ptd_get_info(pt_desc_t *ptd, const tt_entry_t *ttep)
1009 {
1010 	assert((ptd != NULL) && (ptd->ptd_info[0].refcnt < PT_DESC_IOMMU_GRANTED_REFCOUNT));
1011 
1012 	return &ptd->ptd_info[ptd_get_index(ptd, ttep)];
1013 }
1014 
1015 /**
1016  * Given a pointer to a page table entry, return back the ptd_info structure
1017  * for the page table that contains that entry.
1018  *
1019  * @param ptep Pointer to a PTE whose ptd_info object to return.
1020  *
1021  * @return The ptd_info object for the page table that contains the passed in
1022  *         page table entry.
1023  */
1024 static inline ptd_info_t *
ptep_get_info(const pt_entry_t * ptep)1025 ptep_get_info(const pt_entry_t *ptep)
1026 {
1027 	return ptd_get_info(ptep_get_ptd(ptep), ptep);
1028 }
1029 
1030 /**
1031  * Return the virtual address mapped by the passed in leaf page table entry,
1032  * using an already-retrieved pagetable descriptor.
1033  *
1034  * @param ptdp pointer to the descriptor for the pagetable containing ptep
1035  * @param ptep Pointer to a PTE to parse
1036  */
1037 static inline vm_map_address_t
ptd_get_va(const pt_desc_t * ptdp,const pt_entry_t * ptep)1038 ptd_get_va(const pt_desc_t *ptdp, const pt_entry_t *ptep)
1039 {
1040 	const pt_attr_t * const pt_attr = pmap_get_pt_attr(ptdp->pmap);
1041 
1042 	vm_map_address_t va = ptdp->va[ptd_get_index(ptdp, ptep)];
1043 	vm_offset_t ptep_index = ((vm_offset_t)ptep & pt_attr_leaf_offmask(pt_attr)) / sizeof(*ptep);
1044 
1045 	va += (ptep_index << pt_attr_leaf_shift(pt_attr));
1046 
1047 	return va;
1048 }
1049 
1050 /**
1051  * Return the virtual address that is being mapped by the passed in leaf page
1052  * table entry.
1053  *
1054  * @param ptep Pointer to a PTE to parse.
1055  */
1056 static inline vm_map_address_t
ptep_get_va(const pt_entry_t * ptep)1057 ptep_get_va(const pt_entry_t *ptep)
1058 {
1059 	return ptd_get_va(ptep_get_ptd(ptep), ptep);
1060 }
1061 
1062 /**
1063  * Physical Page Attribute Table (pp_attr_table) defines and helper functions.
1064  */
1065 
1066 /* How many bits to use for flags on a per-VM-page basis. */
1067 typedef uint16_t pp_attr_t;
1068 
1069 /* See the definition of pp_attr_table for more information. */
1070 extern volatile pp_attr_t* pp_attr_table;
1071 
1072 /**
1073  * Flags stored in the pp_attr_table on a per-physical-page basis.
1074  *
1075  * Please update the pv_walk LLDB macro if these flags are changed or added to.
1076  */
1077 
1078 /**
1079  * The bottom 6-bits are used to store the default WIMG (cacheability and memory
1080  * type) setting for this physical page. This can be changed by calling
1081  * pmap_set_cache_attributes().
1082  *
1083  * If a default WIMG setting isn't set for a page, then the default is Normal,
1084  * Cached memory (VM_WIMG_DEFAULT).
1085  */
1086 #define PP_ATTR_WIMG_MASK 0x003F
1087 #define PP_ATTR_WIMG(x) ((x) & PP_ATTR_WIMG_MASK)
1088 
1089 /**
1090  * The reference and modify bits keep track of whether a page has been accessed
1091  * or modified since the last time the bits were cleared. These bits are used to
1092  * enforce policy decisions in the VM layer.
1093  */
1094 #define PP_ATTR_REFERENCED 0x0040
1095 #define PP_ATTR_MODIFIED   0x0080
1096 
1097 /**
1098  * This physical page is being used as anonymous memory that's internally
1099  * managed by the VM and is not connected to an external pager. This flag is
1100  * only set/cleared on the first CPU mapping of a page (see PVH_FLAG_CPU). Any
1101  * subsequent mappings won't set/clear this flag until all mappings are removed
1102  * and a new CPU mapping is added.
1103  */
1104 #define PP_ATTR_INTERNAL 0x0100
1105 
1106 /**
1107  * This flag is used to keep track of pages that are still resident but are not
1108  * considered dirty and can be reclaimed under memory pressure. These pages do
1109  * not count as a part of the memory footprint, so the footprint ledger does not
1110  * need to be updated for these pages. This is hinted to the VM by the
1111  * `madvise(MADV_FREE_REUSABLE)` system call.
1112  */
1113 #define PP_ATTR_REUSABLE 0x0200
1114 
1115 /**
1116  * This flag denotes that a page is utilizing "alternate accounting". This means
1117  * that the pmap doesn't need to keep track of these pages with regards to the
1118  * footprint ledger because the VM is already accounting for them in a different
1119  * way. These include IOKit mappings (VM adds their entire virtual size to the
1120  * footprint), and purgeable pages (VM counts them only when non-volatile and
1121  * only for one "owner"), among others.
1122  *
1123  * Note that alternate accounting status is tracked on a per-mapping basis (not
1124  * per-page). Because of that the ALTACCT flag in the pp_attr_table is only used
1125  * when there's a single mapping to a page. When there are multiple mappings,
1126  * the status of this flag is tracked in the pv_head_table (see PVE_PTEP_ALTACCT
1127  * above).
1128  */
1129 #define PP_ATTR_ALTACCT 0x0400
1130 
1131 /**
1132  * This bit was originally used on x86 to keep track of what pages to not
1133  * encrypt during the hibernation process as a performance optimization when
1134  * encryption was done in software. This doesn't apply to the ARM
1135  * hibernation process because all pages are automatically encrypted using
1136  * hardware acceleration. Despite that, the pmap still keeps track of this flag
1137  * as a debugging aid on internal builds.
1138  *
1139  * TODO: This bit can probably be reclaimed:
1140  * rdar://70740650 (PMAP Cleanup: Potentially reclaim the PP_ATTR_NOENCRYPT bit on ARM)
1141  */
1142 #define PP_ATTR_NOENCRYPT 0x0800
1143 
1144 /**
1145  * These bits denote that a physical page is expecting the next access or
1146  * modification to set the PP_ATTR_REFERENCED and PP_ATTR_MODIFIED flags
1147  * respectively.
1148  */
1149 #define PP_ATTR_REFFAULT 0x1000
1150 #define PP_ATTR_MODFAULT 0x2000
1151 
1152 #if XNU_MONITOR
1153 /**
1154  * Denotes that a page is owned by the PPL. This is modified/checked with the
1155  * PVH lock held, to avoid ownership related races. This does not need to be a
1156  * PP_ATTR bit (as we have the lock), but for now this is a convenient place to
1157  * put the bit.
1158  */
1159 #define PP_ATTR_MONITOR 0x4000
1160 
1161 /**
1162  * Denotes that a page *cannot* be owned by the PPL. This is required in order
1163  * to temporarily 'pin' kernel pages that are used to store PPL output
1164  * parameters. Otherwise a malicious or buggy caller could pass PPL-owned memory
1165  * for these parameters and in so doing stage a write gadget against the PPL.
1166  */
1167 #define PP_ATTR_NO_MONITOR 0x8000
1168 
1169 /**
1170  * All of the bits owned by the PPL; kernel requests to set or clear these bits
1171  * are illegal.
1172  */
1173 #define PP_ATTR_PPL_OWNED_BITS (PP_ATTR_MONITOR | PP_ATTR_NO_MONITOR)
1174 #endif /* XNU_MONITOR */
1175 
1176 /**
1177  * Atomically set some flags in a pp_attr_table entry.
1178  *
1179  * @param pai The physical address index for the entry to update.
1180  * @param bits The flags to set in the entry.
1181  */
1182 static inline void
ppattr_set_bits(unsigned int pai,pp_attr_t bits)1183 ppattr_set_bits(unsigned int pai, pp_attr_t bits)
1184 {
1185 	volatile pp_attr_t *ppattr = &pp_attr_table[pai];
1186 	os_atomic_or(ppattr, bits, acq_rel);
1187 }
1188 
1189 /**
1190  * Atomically clear some flags in a pp_attr_table entry.
1191  *
1192  * @param pai The physical address index for the entry to update.
1193  * @param bits The flags to clear in the entry.
1194  */
1195 static inline void
ppattr_clear_bits(unsigned int pai,pp_attr_t bits)1196 ppattr_clear_bits(unsigned int pai, pp_attr_t bits)
1197 {
1198 	volatile pp_attr_t *ppattr = &pp_attr_table[pai];
1199 	os_atomic_andnot(ppattr, bits, acq_rel);
1200 }
1201 
1202 /**
1203  * Return true if the pp_attr_table entry contains the passed in bits.
1204  *
1205  * @param pai The physical address index for the entry to test.
1206  * @param bits The flags to check for.
1207  */
1208 static inline bool
ppattr_test_bits(unsigned int pai,pp_attr_t bits)1209 ppattr_test_bits(unsigned int pai, pp_attr_t bits)
1210 {
1211 	const volatile pp_attr_t *ppattr = &pp_attr_table[pai];
1212 	return (*ppattr & bits) == bits;
1213 }
1214 
1215 /**
1216  * Only set some flags in a pp_attr_table entry if the passed in physical
1217  * address is a kernel-managed address.
1218  *
1219  * @param pa The physical address for the entry to update.
1220  * @param bits The flags to set in the entry.
1221  */
1222 static inline void
ppattr_pa_set_bits(pmap_paddr_t pa,pp_attr_t bits)1223 ppattr_pa_set_bits(pmap_paddr_t pa, pp_attr_t bits)
1224 {
1225 	if (pa_valid(pa)) {
1226 		ppattr_set_bits(pa_index(pa), bits);
1227 	}
1228 }
1229 
1230 /**
1231  * Only clear some flags in a pp_attr_table entry if the passed in physical
1232  * address is a kernel-managed address.
1233  *
1234  * @param pa The physical address for the entry to update.
1235  * @param bits The flags to clear in the entry.
1236  */
1237 static inline void
ppattr_pa_clear_bits(pmap_paddr_t pa,pp_attr_t bits)1238 ppattr_pa_clear_bits(pmap_paddr_t pa, pp_attr_t bits)
1239 {
1240 	if (pa_valid(pa)) {
1241 		ppattr_clear_bits(pa_index(pa), bits);
1242 	}
1243 }
1244 
1245 /**
1246  * Only test flags in a pp_attr_table entry if the passed in physical address
1247  * is a kernel-managed page.
1248  *
1249  * @param pa The physical address for the entry to test.
1250  * @param bits The flags to check for.
1251  *
1252  * @return False if the PA isn't a kernel-managed page, otherwise true/false
1253  *         depending on whether the bits are set.
1254  */
1255 static inline bool
ppattr_pa_test_bits(pmap_paddr_t pa,pp_attr_t bits)1256 ppattr_pa_test_bits(pmap_paddr_t pa, pp_attr_t bits)
1257 {
1258 	return pa_valid(pa) ? ppattr_test_bits(pa_index(pa), bits) : false;
1259 }
1260 
1261 /**
1262  * Set the PP_ATTR_MODIFIED flag on a specific pp_attr_table entry if the passed
1263  * in physical address is a kernel-managed page.
1264  *
1265  * @param pa The physical address for the entry to update.
1266  */
1267 static inline void
ppattr_pa_set_modify(pmap_paddr_t pa)1268 ppattr_pa_set_modify(pmap_paddr_t pa)
1269 {
1270 	ppattr_pa_set_bits(pa, PP_ATTR_MODIFIED);
1271 }
1272 
1273 /**
1274  * Clear the PP_ATTR_MODIFIED flag on a specific pp_attr_table entry if the
1275  * passed in physical address is a kernel-managed page.
1276  *
1277  * @param pa The physical address for the entry to update.
1278  */
1279 static inline void
ppattr_pa_clear_modify(pmap_paddr_t pa)1280 ppattr_pa_clear_modify(pmap_paddr_t pa)
1281 {
1282 	ppattr_pa_clear_bits(pa, PP_ATTR_MODIFIED);
1283 }
1284 
1285 /**
1286  * Set the PP_ATTR_REFERENCED flag on a specific pp_attr_table entry if the
1287  * passed in physical address is a kernel-managed page.
1288  *
1289  * @param pa The physical address for the entry to update.
1290  */
1291 static inline void
ppattr_pa_set_reference(pmap_paddr_t pa)1292 ppattr_pa_set_reference(pmap_paddr_t pa)
1293 {
1294 	ppattr_pa_set_bits(pa, PP_ATTR_REFERENCED);
1295 }
1296 
1297 /**
1298  * Clear the PP_ATTR_REFERENCED flag on a specific pp_attr_table entry if the
1299  * passed in physical address is a kernel-managed page.
1300  *
1301  * @param pa The physical address for the entry to update.
1302  */
1303 static inline void
ppattr_pa_clear_reference(pmap_paddr_t pa)1304 ppattr_pa_clear_reference(pmap_paddr_t pa)
1305 {
1306 	ppattr_pa_clear_bits(pa, PP_ATTR_REFERENCED);
1307 }
1308 
1309 #if XNU_MONITOR
1310 
1311 /**
1312  * Set the PP_ATTR_MONITOR flag on a specific pp_attr_table entry if the passed
1313  * in physical address is a kernel-managed page.
1314  *
1315  * @param pa The physical address for the entry to update.
1316  */
1317 static inline void
ppattr_pa_set_monitor(pmap_paddr_t pa)1318 ppattr_pa_set_monitor(pmap_paddr_t pa)
1319 {
1320 	ppattr_pa_set_bits(pa, PP_ATTR_MONITOR);
1321 }
1322 
1323 /**
1324  * Clear the PP_ATTR_MONITOR 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  */
1329 static inline void
ppattr_pa_clear_monitor(pmap_paddr_t pa)1330 ppattr_pa_clear_monitor(pmap_paddr_t pa)
1331 {
1332 	ppattr_pa_clear_bits(pa, PP_ATTR_MONITOR);
1333 }
1334 
1335 /**
1336  * Only test for the PP_ATTR_MONITOR flag in a pp_attr_table entry if the passed
1337  * in physical address is a kernel-managed page.
1338  *
1339  * @param pa The physical address for the entry to test.
1340  *
1341  * @return False if the PA isn't a kernel-managed page, otherwise true/false
1342  *         depending on whether the PP_ATTR_MONITOR is set.
1343  */
1344 static inline bool
ppattr_pa_test_monitor(pmap_paddr_t pa)1345 ppattr_pa_test_monitor(pmap_paddr_t pa)
1346 {
1347 	return ppattr_pa_test_bits(pa, PP_ATTR_MONITOR);
1348 }
1349 
1350 /**
1351  * Set the PP_ATTR_NO_MONITOR flag on a specific pp_attr_table entry if the
1352  * passed in physical address is a kernel-managed page.
1353  *
1354  * @param pa The physical address for the entry to update.
1355  */
1356 static inline void
ppattr_pa_set_no_monitor(pmap_paddr_t pa)1357 ppattr_pa_set_no_monitor(pmap_paddr_t pa)
1358 {
1359 	ppattr_pa_set_bits(pa, PP_ATTR_NO_MONITOR);
1360 }
1361 
1362 /**
1363  * Clear the PP_ATTR_NO_MONITOR flag on a specific pp_attr_table entry if the
1364  * passed in physical address is a kernel-managed page.
1365  *
1366  * @param pa The physical address for the entry to update.
1367  */
1368 static inline void
ppattr_pa_clear_no_monitor(pmap_paddr_t pa)1369 ppattr_pa_clear_no_monitor(pmap_paddr_t pa)
1370 {
1371 	ppattr_pa_clear_bits(pa, PP_ATTR_NO_MONITOR);
1372 }
1373 
1374 /**
1375  * Only test for the PP_ATTR_NO_MONITOR flag in a pp_attr_table entry if the
1376  * passed in physical address is a kernel-managed page.
1377  *
1378  * @param pa The physical address for the entry to test.
1379  *
1380  * @return False if the PA isn't a kernel-managed page, otherwise true/false
1381  *         depending on whether the PP_ATTR_NO_MONITOR is set.
1382  */
1383 static inline bool
ppattr_pa_test_no_monitor(pmap_paddr_t pa)1384 ppattr_pa_test_no_monitor(pmap_paddr_t pa)
1385 {
1386 	return ppattr_pa_test_bits(pa, PP_ATTR_NO_MONITOR);
1387 }
1388 
1389 #endif /* XNU_MONITOR */
1390 
1391 /**
1392  * Set the PP_ATTR_INTERNAL flag on a specific pp_attr_table entry.
1393  *
1394  * @param pai The physical address index for the entry to update.
1395  */
1396 static inline void
ppattr_set_internal(unsigned int pai)1397 ppattr_set_internal(unsigned int pai)
1398 {
1399 	ppattr_set_bits(pai, PP_ATTR_INTERNAL);
1400 }
1401 
1402 /**
1403  * Clear the PP_ATTR_INTERNAL flag on a specific pp_attr_table entry.
1404  *
1405  * @param pai The physical address index for the entry to update.
1406  */
1407 static inline void
ppattr_clear_internal(unsigned int pai)1408 ppattr_clear_internal(unsigned int pai)
1409 {
1410 	ppattr_clear_bits(pai, PP_ATTR_INTERNAL);
1411 }
1412 
1413 /**
1414  * Return true if the pp_attr_table entry has the PP_ATTR_INTERNAL flag set.
1415  *
1416  * @param pai The physical address index for the entry to test.
1417  */
1418 static inline bool
ppattr_test_internal(unsigned int pai)1419 ppattr_test_internal(unsigned int pai)
1420 {
1421 	return ppattr_test_bits(pai, PP_ATTR_INTERNAL);
1422 }
1423 
1424 /**
1425  * Set the PP_ATTR_REUSABLE flag on a specific pp_attr_table entry.
1426  *
1427  * @param pai The physical address index for the entry to update.
1428  */
1429 static inline void
ppattr_set_reusable(unsigned int pai)1430 ppattr_set_reusable(unsigned int pai)
1431 {
1432 	ppattr_set_bits(pai, PP_ATTR_REUSABLE);
1433 }
1434 
1435 /**
1436  * Clear the PP_ATTR_REUSABLE 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_clear_reusable(unsigned int pai)1441 ppattr_clear_reusable(unsigned int pai)
1442 {
1443 	ppattr_clear_bits(pai, PP_ATTR_REUSABLE);
1444 }
1445 
1446 /**
1447  * Return true if the pp_attr_table entry has the PP_ATTR_REUSABLE flag set.
1448  *
1449  * @param pai The physical address index for the entry to test.
1450  */
1451 static inline bool
ppattr_test_reusable(unsigned int pai)1452 ppattr_test_reusable(unsigned int pai)
1453 {
1454 	return ppattr_test_bits(pai, PP_ATTR_REUSABLE);
1455 }
1456 
1457 /**
1458  * Set the PP_ATTR_ALTACCT flag on a specific pp_attr_table entry.
1459  *
1460  * @note This is only valid when the ALTACCT flag is being tracked using the
1461  *       pp_attr_table. See the descriptions above the PVE_PTEP_ALTACCT and
1462  *       PP_ATTR_ALTACCT definitions for more information.
1463  *
1464  * @param pai The physical address index for the entry to update.
1465  */
1466 static inline void
ppattr_set_altacct(unsigned int pai)1467 ppattr_set_altacct(unsigned int pai)
1468 {
1469 	ppattr_set_bits(pai, PP_ATTR_ALTACCT);
1470 }
1471 
1472 /**
1473  * Clear the PP_ATTR_ALTACCT flag on a specific pp_attr_table entry.
1474  *
1475  * @note This is only valid when the ALTACCT flag is being tracked using the
1476  *       pp_attr_table. See the descriptions above the PVE_PTEP_ALTACCT and
1477  *       PP_ATTR_ALTACCT definitions for more information.
1478  *
1479  * @param pai The physical address index for the entry to update.
1480  */
1481 static inline void
ppattr_clear_altacct(unsigned int pai)1482 ppattr_clear_altacct(unsigned int pai)
1483 {
1484 	ppattr_clear_bits(pai, PP_ATTR_ALTACCT);
1485 }
1486 
1487 /**
1488  * Get the PP_ATTR_ALTACCT flag on a specific pp_attr_table entry.
1489  *
1490  * @note This is only valid when the ALTACCT flag is being tracked using the
1491  *       pp_attr_table. See the descriptions above the PVE_PTEP_ALTACCT and
1492  *       PP_ATTR_ALTACCT definitions for more information.
1493  *
1494  * @param pai The physical address index for the entry to test.
1495  *
1496  * @return True if the passed in page uses alternate accounting, false
1497  *         otherwise.
1498  */
1499 static inline bool
ppattr_is_altacct(unsigned int pai)1500 ppattr_is_altacct(unsigned int pai)
1501 {
1502 	return ppattr_test_bits(pai, PP_ATTR_ALTACCT);
1503 }
1504 
1505 /**
1506  * The "alternate accounting" (ALTACCT) status for a page is tracked differently
1507  * depending on whether there are one or multiple mappings to a page. This
1508  * function abstracts out the difference between single and multiple mappings to
1509  * a page and provides a single function for determining whether alternate
1510  * accounting is set for a mapping.
1511  *
1512  * @note See the descriptions above the PVE_PTEP_ALTACCT and PP_ATTR_ALTACCT
1513  *       definitions for more information.
1514  *
1515  * @param pai The physical address index for the entry to test.
1516  * @param pvep Pointer to the pv_entry_t object containing that mapping.
1517  * @param idx Index of the chosen PTE pointer inside the PVE.
1518  *
1519  * @return True if the passed in page uses alternate accounting, false
1520  *         otherwise.
1521  */
1522 static inline bool
ppattr_pve_is_altacct(unsigned int pai,pv_entry_t * pvep,unsigned idx)1523 ppattr_pve_is_altacct(unsigned int pai, pv_entry_t *pvep, unsigned idx)
1524 {
1525 	return (pvep == PV_ENTRY_NULL) ? ppattr_is_altacct(pai) : pve_get_altacct(pvep, idx);
1526 }
1527 
1528 /**
1529  * The "alternate accounting" (ALTACCT) status for a page is tracked differently
1530  * depending on whether there are one or multiple mappings to a page. This
1531  * function abstracts out the difference between single and multiple mappings to
1532  * a page and provides a single function for setting the alternate accounting status
1533  * for a mapping.
1534  *
1535  * @note See the descriptions above the PVE_PTEP_ALTACCT and PP_ATTR_ALTACCT
1536  *       definitions for more information.
1537  *
1538  * @param pai The physical address index for the entry to update.
1539  * @param pvep Pointer to the pv_entry_t object containing that mapping.
1540  * @param idx Index of the chosen PTE pointer inside the PVE.
1541  */
1542 static inline void
ppattr_pve_set_altacct(unsigned int pai,pv_entry_t * pvep,unsigned idx)1543 ppattr_pve_set_altacct(unsigned int pai, pv_entry_t *pvep, unsigned idx)
1544 {
1545 	if (pvep == PV_ENTRY_NULL) {
1546 		ppattr_set_altacct(pai);
1547 	} else {
1548 		pve_set_altacct(pvep, idx);
1549 	}
1550 }
1551 
1552 /**
1553  * The "alternate accounting" (ALTACCT) status for a page is tracked differently
1554  * depending on whether there are one or multiple mappings to a page. This
1555  * function abstracts out the difference between single and multiple mappings to
1556  * a page and provides a single function for clearing the alternate accounting status
1557  * for a mapping.
1558  *
1559  * @note See the descriptions above the PVE_PTEP_ALTACCT and PP_ATTR_ALTACCT
1560  *       definitions for more information.
1561  *
1562  * @param pai The physical address index for the entry to update.
1563  * @param pvep Pointer to the pv_entry_t object containing that mapping.
1564  * @param idx Index of the chosen PTE pointer inside the PVE.
1565  */
1566 static inline void
ppattr_pve_clr_altacct(unsigned int pai,pv_entry_t * pvep,unsigned idx)1567 ppattr_pve_clr_altacct(unsigned int pai, pv_entry_t *pvep, unsigned idx)
1568 {
1569 	if (pvep == PV_ENTRY_NULL) {
1570 		ppattr_clear_altacct(pai);
1571 	} else {
1572 		pve_clr_altacct(pvep, idx);
1573 	}
1574 }
1575 
1576 /**
1577  * Set the PP_ATTR_REFFAULT flag on a specific pp_attr_table entry.
1578  *
1579  * @param pai The physical address index for the entry to update.
1580  */
1581 static inline void
ppattr_set_reffault(unsigned int pai)1582 ppattr_set_reffault(unsigned int pai)
1583 {
1584 	ppattr_set_bits(pai, PP_ATTR_REFFAULT);
1585 }
1586 
1587 /**
1588  * Clear the PP_ATTR_REFFAULT flag on a specific pp_attr_table entry.
1589  *
1590  * @param pai The physical address index for the entry to update.
1591  */
1592 static inline void
ppattr_clear_reffault(unsigned int pai)1593 ppattr_clear_reffault(unsigned int pai)
1594 {
1595 	ppattr_clear_bits(pai, PP_ATTR_REFFAULT);
1596 }
1597 
1598 /**
1599  * Return true if the pp_attr_table entry has the PP_ATTR_REFFAULT flag set.
1600  *
1601  * @param pai The physical address index for the entry to test.
1602  */
1603 static inline bool
ppattr_test_reffault(unsigned int pai)1604 ppattr_test_reffault(unsigned int pai)
1605 {
1606 	return ppattr_test_bits(pai, PP_ATTR_REFFAULT);
1607 }
1608 
1609 /**
1610  * Set the PP_ATTR_MODFAULT flag on a specific pp_attr_table entry.
1611  *
1612  * @param pai The physical address index for the entry to update.
1613  */
1614 static inline void
ppattr_set_modfault(unsigned int pai)1615 ppattr_set_modfault(unsigned int pai)
1616 {
1617 	ppattr_set_bits(pai, PP_ATTR_MODFAULT);
1618 }
1619 
1620 /**
1621  * Clear the PP_ATTR_MODFAULT flag on a specific pp_attr_table entry.
1622  *
1623  * @param pai The physical address index for the entry to update.
1624  */
1625 static inline void
ppattr_clear_modfault(unsigned int pai)1626 ppattr_clear_modfault(unsigned int pai)
1627 {
1628 	ppattr_clear_bits(pai, PP_ATTR_MODFAULT);
1629 }
1630 
1631 /**
1632  * Return true if the pp_attr_table entry has the PP_ATTR_MODFAULT flag set.
1633  *
1634  * @param pai The physical address index for the entry to test.
1635  */
1636 static inline bool
ppattr_test_modfault(unsigned int pai)1637 ppattr_test_modfault(unsigned int pai)
1638 {
1639 	return ppattr_test_bits(pai, PP_ATTR_MODFAULT);
1640 }
1641 
1642 /**
1643  * The minimum number of pages to keep in the PPL page free list.
1644  *
1645  * We define our target as 8 pages: enough for 2 page table pages, a PTD page,
1646  * and a PV page; in essence, twice as many pages as may be necessary to satisfy
1647  * a single pmap_enter request.
1648  */
1649 #define PMAP_MIN_FREE_PPL_PAGES 8
1650 
1651 /**
1652  * Flags passed to various page allocation functions, usually accessed through
1653  * the pmap_pages_alloc_zeroed() API. Each function that can take these flags as
1654  * a part of its option field, will describe these flags in its function header.
1655  */
1656 
1657 /**
1658  * Instruct the allocation function to return immediately if no pages are
1659  * current available. Without this flag, the function will spin and wait for a
1660  * page to become available. This flag can be required in some circumstances
1661  * (for instance, when allocating pages from within the PPL).
1662  */
1663 #define PMAP_PAGES_ALLOCATE_NOWAIT 0x1
1664 
1665 /**
1666  * Instructs an allocation function to fallback to reclaiming a userspace page
1667  * table if it failed to allocate a page from the free lists. This can be useful
1668  * when allocating from within the PPL because refilling the free lists requires
1669  * exiting and re-entering the PPL (which incurs extra latency).
1670  *
1671  * This is a quick way of allocating a page at the expense of having to
1672  * reallocate the table the next time one of its mappings is accessed.
1673  */
1674 #define PMAP_PAGE_RECLAIM_NOWAIT 0x2
1675 
1676 /**
1677  * Global variables exported to the rest of the internal pmap implementation.
1678  */
1679 #if XNU_MONITOR
1680 extern uint64_t pmap_ppl_free_page_count;
1681 extern pmap_paddr_t pmap_stacks_start_pa;
1682 extern pmap_paddr_t pmap_stacks_end_pa;
1683 extern pmap_paddr_t ppl_cpu_save_area_start;
1684 extern pmap_paddr_t ppl_cpu_save_area_end;
1685 #endif /* XNU_MONITOR */
1686 extern unsigned int inuse_pmap_pages_count;
1687 extern vm_object_t pmap_object;
1688 extern uint32_t pv_alloc_initial_target;
1689 extern uint32_t pv_kern_alloc_initial_target;
1690 
1691 /**
1692  * Functions exported to the rest of the internal pmap implementation.
1693  */
1694 extern void pmap_data_bootstrap(void);
1695 extern void pmap_enqueue_pages(vm_page_t);
1696 extern kern_return_t pmap_pages_alloc_zeroed(pmap_paddr_t *, unsigned, unsigned);
1697 extern void pmap_pages_free(pmap_paddr_t, unsigned);
1698 
1699 #if XNU_MONITOR
1700 
1701 extern void pmap_mark_page_as_ppl_page_internal(pmap_paddr_t, bool);
1702 extern void pmap_mark_page_as_ppl_page(pmap_paddr_t);
1703 extern void pmap_mark_page_as_kernel_page(pmap_paddr_t);
1704 extern pmap_paddr_t pmap_alloc_page_for_kern(unsigned int);
1705 extern void pmap_alloc_page_for_ppl(unsigned int);
1706 extern uint64_t pmap_release_ppl_pages_to_kernel(void);
1707 
1708 extern uint64_t pmap_ledger_validate(const volatile void *);
1709 void pmap_ledger_retain(ledger_t ledger);
1710 void pmap_ledger_release(ledger_t ledger);
1711 extern void pmap_ledger_check_balance(pmap_t pmap);
1712 
1713 kern_return_t pmap_alloc_pmap(pmap_t *pmap);
1714 void pmap_free_pmap(pmap_t pmap);
1715 
1716 #endif /* XNU_MONITOR */
1717 
1718 /**
1719  * The modes in which a pmap lock can be acquired. Note that shared access
1720  * doesn't necessarily mean "read-only". As long as data is atomically updated
1721  * correctly (to account for multi-cpu accesses) data can still get written with
1722  * a shared lock held. Care just needs to be taken so as to not introduce any
1723  * race conditions when there are multiple writers.
1724  *
1725  * This is here in pmap_data.h because it's a needed parameter for pv_alloc()
1726  * and pmap_enter_pv(). This header is always included in pmap_internal.h before
1727  * the rest of the pmap locking code is defined so there shouldn't be any issues
1728  * with missing types.
1729  */
1730 OS_ENUM(pmap_lock_mode, uint8_t,
1731     PMAP_LOCK_SHARED,
1732     PMAP_LOCK_EXCLUSIVE);
1733 
1734 /**
1735  * Possible return values for pv_alloc(). See the pv_alloc() function header for
1736  * a description of each of these values.
1737  */
1738 typedef enum {
1739 	PV_ALLOC_SUCCESS,
1740 	PV_ALLOC_RETRY,
1741 	PV_ALLOC_FAIL
1742 } pv_alloc_return_t;
1743 
1744 extern pv_alloc_return_t pv_alloc(
1745 	pmap_t, unsigned int, pmap_lock_mode_t, pv_entry_t **);
1746 extern void pv_free(pv_entry_t *);
1747 extern void pv_list_free(pv_entry_t *, pv_entry_t *, int);
1748 extern void pmap_compute_pv_targets(void);
1749 extern pv_alloc_return_t pmap_enter_pv(
1750 	pmap_t, pt_entry_t *, int, unsigned int, pmap_lock_mode_t, pv_entry_t **, int *new_pve_ptep_idx);
1751 extern bool pmap_remove_pv(pmap_t, pt_entry_t *, int, bool);
1752 
1753 extern void ptd_bootstrap(pt_desc_t *, unsigned int);
1754 extern pt_desc_t *ptd_alloc_unlinked(void);
1755 extern pt_desc_t *ptd_alloc(pmap_t);
1756 extern void ptd_deallocate(pt_desc_t *);
1757 extern void ptd_info_init(
1758 	pt_desc_t *, pmap_t, vm_map_address_t, unsigned int, pt_entry_t *);
1759 
1760 extern kern_return_t pmap_ledger_credit(pmap_t, int, ledger_amount_t);
1761 extern kern_return_t pmap_ledger_debit(pmap_t, int, ledger_amount_t);
1762 
1763 extern void validate_pmap_internal(const volatile struct pmap *, const char *);
1764 extern void validate_pmap_mutable_internal(const volatile struct pmap *, const char *);
1765 
1766 /**
1767  * Macro function wrappers around pmap validation so that the calling function
1768  * can be printed in the panic strings for easier validation failure debugging.
1769  */
1770 #define validate_pmap(x) validate_pmap_internal(x, __func__)
1771 #define validate_pmap_mutable(x) validate_pmap_mutable_internal(x, __func__)
1772 
1773 /**
1774  * This structure describes a PPL-owned I/O range.
1775  *
1776  * @note This doesn't necessarily have to represent "I/O" only, this can also
1777  *       represent non-kernel-managed DRAM (e.g., iBoot carveouts). Any physical
1778  *       address region that isn't considered "kernel-managed" is fair game.
1779  *
1780  * @note The layout of this structure needs to map 1-to-1 with the pmap-io-range
1781  *       device tree nodes. Astris (through the LowGlobals) also depends on the
1782  *       consistency of this structure.
1783  */
1784 typedef struct pmap_io_range {
1785 	/* Physical address of the PPL-owned I/O range. */
1786 	uint64_t addr;
1787 
1788 	/* Length (in bytes) of the PPL-owned I/O range. */
1789 	uint64_t len;
1790 
1791 	/* Strong DSB required for pages in this range. */
1792 	#define PMAP_IO_RANGE_STRONG_SYNC (1UL << 31)
1793 
1794 	/* Corresponds to memory carved out by bootloader. */
1795 	#define PMAP_IO_RANGE_CARVEOUT (1UL << 30)
1796 
1797 	/* Pages in this range need to be included in the hibernation image */
1798 	#define PMAP_IO_RANGE_NEEDS_HIBERNATING (1UL << 29)
1799 
1800 	/**
1801 	 * Lower 16 bits treated as pp_attr_t, upper 16 bits contain additional
1802 	 * mapping flags (defined above).
1803 	 */
1804 	uint32_t wimg;
1805 
1806 	/* 4 Character Code (4CC) describing what this range is. */
1807 	uint32_t signature;
1808 } __attribute__((packed)) pmap_io_range_t;
1809 
1810 extern pmap_io_range_t* pmap_find_io_attr(pmap_paddr_t);
1811 
1812 extern void pmap_cpu_data_init_internal(unsigned int);
1813 
1814 #endif /* _ARM_PMAP_PMAP_DATA_H_ */
1815