2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach_assert.h>
32 #include <vm/vm_map.h>
33 #include <kern/ledger.h>
34 #include <i386/pmap_internal.h>
36 void pmap_remove_range(
42 void pmap_remove_range_options(
49 void pmap_reusable_range(
56 uint32_t pmap_update_clear_pte_count
;
59 * The Intel platform can nest at the PDE level, so NBPDE (i.e. 2MB) at a time,
60 * on a NBPDE boundary.
63 /* These symbols may be referenced directly by VM */
64 uint64_t pmap_nesting_size_min
= NBPDE
;
65 uint64_t pmap_nesting_size_max
= 0 - (uint64_t)NBPDE
;
68 * kern_return_t pmap_nest(grand, subord, va_start, size)
70 * grand = the pmap that we will nest subord into
71 * subord = the pmap that goes into the grand
72 * va_start = start of range in pmap to be inserted
73 * nstart = start of range in pmap nested pmap
74 * size = Size of nest area (up to 16TB)
76 * Inserts a pmap into another. This is used to implement shared segments.
78 * Note that we depend upon higher level VM locks to insure that things don't change while
79 * we are doing this. For example, VM should not be doing any pmap enters while it is nesting
80 * or do 2 nests at once.
84 * This routine can nest subtrees either at the PDPT level (1GiB) or at the
85 * PDE level (2MiB). We currently disallow disparate offsets for the "subord"
86 * container and the "grand" parent. A minor optimization to consider for the
87 * future: make the "subord" truly a container rather than a full-fledged
88 * pagetable hierarchy which can be unnecessarily sparse (DRK).
91 kern_return_t
pmap_nest(pmap_t grand
, pmap_t subord
, addr64_t va_start
, addr64_t nstart
, uint64_t size
) {
92 vm_map_offset_t vaddr
, nvaddr
;
93 pd_entry_t
*pde
,*npde
;
97 assert(!is_ept_pmap(grand
));
98 assert(!is_ept_pmap(subord
));
100 if ((size
& (pmap_nesting_size_min
-1)) ||
101 (va_start
& (pmap_nesting_size_min
-1)) ||
102 (nstart
& (pmap_nesting_size_min
-1)) ||
103 ((size
>> 28) > 65536)) /* Max size we can nest is 16TB */
104 return KERN_INVALID_VALUE
;
107 panic("pmap_nest: size is invalid - %016llX\n", size
);
110 if (va_start
!= nstart
)
111 panic("pmap_nest: va_start(0x%llx) != nstart(0x%llx)\n", va_start
, nstart
);
113 PMAP_TRACE(PMAP_CODE(PMAP__NEST
) | DBG_FUNC_START
,
114 (uintptr_t) grand
, (uintptr_t) subord
,
115 (uintptr_t) (va_start
>>32), (uintptr_t) va_start
, 0);
117 nvaddr
= (vm_map_offset_t
)nstart
;
118 num_pde
= size
>> PDESHIFT
;
122 subord
->pm_shared
= TRUE
;
124 for (i
= 0; i
< num_pde
;) {
125 if (((nvaddr
& PDPTMASK
) == 0) && (num_pde
- i
) >= NPDEPG
&& cpu_64bit
) {
127 npde
= pmap64_pdpt(subord
, nvaddr
);
129 while (0 == npde
|| ((*npde
& INTEL_PTE_VALID
) == 0)) {
131 pmap_expand_pdpt(subord
, nvaddr
, PMAP_EXPAND_OPTIONS_NONE
);
133 npde
= pmap64_pdpt(subord
, nvaddr
);
135 *npde
|= INTEL_PDPTE_NESTED
;
137 i
+= (uint32_t)NPDEPG
;
140 npde
= pmap_pde(subord
, nvaddr
);
142 while (0 == npde
|| ((*npde
& INTEL_PTE_VALID
) == 0)) {
144 pmap_expand(subord
, nvaddr
, PMAP_EXPAND_OPTIONS_NONE
);
146 npde
= pmap_pde(subord
, nvaddr
);
155 vaddr
= (vm_map_offset_t
)va_start
;
159 for (i
= 0;i
< num_pde
;) {
162 if (((vaddr
& PDPTMASK
) == 0) && ((num_pde
- i
) >= NPDEPG
) && cpu_64bit
) {
163 npde
= pmap64_pdpt(subord
, vaddr
);
165 panic("pmap_nest: no PDPT, subord %p nstart 0x%llx", subord
, vaddr
);
167 pde
= pmap64_pdpt(grand
, vaddr
);
170 pmap_expand_pml4(grand
, vaddr
, PMAP_EXPAND_OPTIONS_NONE
);
172 pde
= pmap64_pdpt(grand
, vaddr
);
175 panic("pmap_nest: no PDPT, grand %p vaddr 0x%llx", grand
, vaddr
);
176 pmap_store_pte(pde
, tpde
);
178 i
+= (uint32_t) NPDEPG
;
181 npde
= pmap_pde(subord
, nstart
);
183 panic("pmap_nest: no npde, subord %p nstart 0x%llx", subord
, nstart
);
186 pde
= pmap_pde(grand
, vaddr
);
187 if ((0 == pde
) && cpu_64bit
) {
189 pmap_expand_pdpt(grand
, vaddr
, PMAP_EXPAND_OPTIONS_NONE
);
191 pde
= pmap_pde(grand
, vaddr
);
195 panic("pmap_nest: no pde, grand %p vaddr 0x%llx", grand
, vaddr
);
197 pmap_store_pte(pde
, tpde
);
204 PMAP_TRACE(PMAP_CODE(PMAP__NEST
) | DBG_FUNC_END
, 0, 0, 0, 0, 0);
210 * kern_return_t pmap_unnest(grand, vaddr)
212 * grand = the pmap that we will un-nest subord from
213 * vaddr = start of range in pmap to be unnested
215 * Removes a pmap from another. This is used to implement shared segments.
218 kern_return_t
pmap_unnest(pmap_t grand
, addr64_t vaddr
, uint64_t size
) {
223 addr64_t va_start
, va_end
;
224 uint64_t npdpt
= PMAP_INVALID_PDPTNUM
;
226 PMAP_TRACE(PMAP_CODE(PMAP__UNNEST
) | DBG_FUNC_START
,
228 (uintptr_t) (vaddr
>>32), (uintptr_t) vaddr
, 0, 0);
230 if ((size
& (pmap_nesting_size_min
-1)) ||
231 (vaddr
& (pmap_nesting_size_min
-1))) {
232 panic("pmap_unnest(%p,0x%llx,0x%llx): unaligned...\n",
236 assert(!is_ept_pmap(grand
));
238 /* align everything to PDE boundaries */
239 va_start
= vaddr
& ~(NBPDE
-1);
240 va_end
= (vaddr
+ size
+ NBPDE
- 1) & ~(NBPDE
-1);
241 size
= va_end
- va_start
;
245 num_pde
= size
>> PDESHIFT
;
248 for (i
= 0; i
< num_pde
; ) {
249 if ((pdptnum(grand
, vaddr
) != npdpt
) && cpu_64bit
) {
250 npdpt
= pdptnum(grand
, vaddr
);
251 pde
= pmap64_pdpt(grand
, vaddr
);
252 if (pde
&& (*pde
& INTEL_PDPTE_NESTED
)) {
253 pmap_store_pte(pde
, (pd_entry_t
)0);
254 i
+= (uint32_t) NPDEPG
;
259 pde
= pmap_pde(grand
, (vm_map_offset_t
)vaddr
);
261 panic("pmap_unnest: no pde, grand %p vaddr 0x%llx\n", grand
, vaddr
);
262 pmap_store_pte(pde
, (pd_entry_t
)0);
267 PMAP_UPDATE_TLBS(grand
, va_start
, va_end
);
271 PMAP_TRACE(PMAP_CODE(PMAP__UNNEST
) | DBG_FUNC_END
, 0, 0, 0, 0, 0);
280 __unused
uint64_t size
,
281 __unused
unsigned int options
) {
282 return pmap_unnest(grand
, vaddr
, size
);
285 /* Invoked by the Mach VM to determine the platform specific unnest region */
287 boolean_t
pmap_adjust_unnest_parameters(pmap_t p
, vm_map_offset_t
*s
, vm_map_offset_t
*e
) {
289 boolean_t rval
= FALSE
;
296 pdpte
= pmap64_pdpt(p
, *s
);
297 if (pdpte
&& (*pdpte
& INTEL_PDPTE_NESTED
)) {
302 pdpte
= pmap64_pdpt(p
, *e
);
303 if (pdpte
&& (*pdpte
& INTEL_PDPTE_NESTED
)) {
304 *e
= ((*e
+ NBPDPT
) & ~(NBPDPT
-1));
314 * pmap_find_phys returns the (4K) physical page number containing a
315 * given virtual address in a given pmap.
316 * Note that pmap_pte may return a pde if this virtual address is
317 * mapped by a large page and this is taken into account in order
318 * to return the correct page number in this case.
321 pmap_find_phys(pmap_t pmap
, addr64_t va
)
330 is_ept
= is_ept_pmap(pmap
);
332 mp_disable_preemption();
334 /* This refcount test is a band-aid--several infrastructural changes
335 * are necessary to eliminate invocation of this routine from arbitrary
339 if (!pmap
->ref_count
)
342 pdep
= pmap_pde(pmap
, va
);
344 if ((pdep
!= PD_ENTRY_NULL
) && ((pde
= *pdep
) & PTE_VALID_MASK(is_ept
))) {
346 ppn
= (ppnum_t
) i386_btop(pte_to_pa(pde
));
347 ppn
+= (ppnum_t
) ptenum(va
);
350 ptp
= pmap_pte(pmap
, va
);
351 if ((PT_ENTRY_NULL
!= ptp
) && (((pte
= *ptp
) & PTE_VALID_MASK(is_ept
)) != 0)) {
352 ppn
= (ppnum_t
) i386_btop(pte_to_pa(pte
));
357 mp_enable_preemption();
363 * Update cache attributes for all extant managed mappings.
364 * Assumes PV for this page is locked, and that the page
365 * is managed. We assume that this physical page may be mapped in
366 * both EPT and normal Intel PTEs, so we convert the attributes
367 * to the corresponding format for each pmap.
369 * We assert that the passed set of attributes is a subset of the
370 * PHYS_CACHEABILITY_MASK.
373 pmap_update_cache_attributes_locked(ppnum_t pn
, unsigned attributes
) {
374 pv_rooted_entry_t pv_h
, pv_e
;
375 pv_hashed_entry_t pvh_e
, nexth
;
376 vm_map_offset_t vaddr
;
380 unsigned ept_attributes
;
382 assert(IS_MANAGED_PAGE(pn
));
383 assert(((~PHYS_CACHEABILITY_MASK
) & attributes
) == 0);
385 /* We don't support the PTA bit for EPT PTEs */
386 if (attributes
& INTEL_PTE_NCACHE
)
387 ept_attributes
= INTEL_EPT_NCACHE
;
389 ept_attributes
= INTEL_EPT_WB
;
391 pv_h
= pai_to_pvh(pn
);
392 /* TODO: translate the PHYS_* bits to PTE bits, while they're
393 * currently identical, they may not remain so
394 * Potential optimization (here and in page_protect),
395 * parallel shootdowns, check for redundant
396 * attribute modifications.
400 * Alter attributes on all mappings
402 if (pv_h
->pmap
!= PMAP_NULL
) {
404 pvh_e
= (pv_hashed_entry_t
)pv_e
;
409 ptep
= pmap_pte(pmap
, vaddr
);
412 panic("pmap_update_cache_attributes_locked: Missing PTE, pmap: %p, pn: 0x%x vaddr: 0x%llx kernel_pmap: %p", pmap
, pn
, vaddr
, kernel_pmap
);
414 is_ept
= is_ept_pmap(pmap
);
416 nexth
= (pv_hashed_entry_t
)queue_next(&pvh_e
->qlink
);
418 pmap_update_pte(ptep
, PHYS_CACHEABILITY_MASK
, attributes
);
420 pmap_update_pte(ptep
, INTEL_EPT_CACHE_MASK
, ept_attributes
);
422 PMAP_UPDATE_TLBS(pmap
, vaddr
, vaddr
+ PAGE_SIZE
);
424 } while ((pv_e
= (pv_rooted_entry_t
)nexth
) != pv_h
);
428 void x86_filter_TLB_coherency_interrupts(boolean_t dofilter
) {
429 assert(ml_get_interrupts_enabled() == 0 || get_preemption_level() != 0);
432 CPU_CR3_MARK_INACTIVE();
434 CPU_CR3_MARK_ACTIVE();
436 if (current_cpu_datap()->cpu_tlb_invalid
)
437 process_pmap_updates();
443 * Insert the given physical page (p) at
444 * the specified virtual address (v) in the
445 * target physical map with the protection requested.
447 * If specified, the page will be wired down, meaning
448 * that the related pte cannot be reclaimed.
450 * NB: This is the only routine which MAY NOT lazy-evaluate
451 * or lose information. That is, this routine must actually
452 * insert this page into the given map NOW.
457 register pmap_t pmap
,
458 vm_map_offset_t vaddr
,
461 vm_prot_t fault_type
,
465 (void) pmap_enter_options(pmap
, vaddr
, pn
, prot
, fault_type
, flags
, wired
, PMAP_EXPAND_OPTIONS_NONE
, NULL
);
471 register pmap_t pmap
,
472 vm_map_offset_t vaddr
,
475 __unused vm_prot_t fault_type
,
478 unsigned int options
,
482 pv_rooted_entry_t pv_h
;
484 pv_hashed_entry_t pvh_e
;
485 pv_hashed_entry_t pvh_new
;
488 pmap_paddr_t pa
= (pmap_paddr_t
) i386_ptob(pn
);
489 boolean_t need_tlbflush
= FALSE
;
492 boolean_t old_pa_locked
;
493 /* 2MiB mappings are confined to x86_64 by VM */
494 boolean_t superpage
= flags
& VM_MEM_SUPERPAGE
;
495 vm_object_t delpage_pm_obj
= NULL
;
496 uint64_t delpage_pde_index
= 0;
498 kern_return_t kr_expand
;
503 if (pmap
== PMAP_NULL
)
504 return KERN_INVALID_ARGUMENT
;
506 is_ept
= is_ept_pmap(pmap
);
508 /* N.B. We can be supplied a zero page frame in the NOENTER case, it's an
509 * unused value for that scenario.
511 assert(pn
!= vm_page_fictitious_addr
);
513 if (pn
== vm_page_guard_addr
)
514 return KERN_INVALID_ARGUMENT
;
516 PMAP_TRACE(PMAP_CODE(PMAP__ENTER
) | DBG_FUNC_START
,
518 (uint32_t) (vaddr
>> 32), (uint32_t) vaddr
,
521 if ((prot
& VM_PROT_EXECUTE
) || !nx_enabled
|| !pmap
->nx_enabled
)
526 if (__improbable(set_NX
&& (pmap
== kernel_pmap
) && ((pmap_disable_kstack_nx
&& (flags
& VM_MEM_STACK
)) || (pmap_disable_kheap_nx
&& !(flags
& VM_MEM_STACK
))))) {
531 * Must allocate a new pvlist entry while we're unlocked;
532 * zalloc may cause pageout (which will lock the pmap system).
533 * If we determine we need a pvlist entry, we will unlock
534 * and allocate one. Then we will retry, throughing away
535 * the allocated entry later (if we no longer need it).
538 pvh_new
= PV_HASHED_ENTRY_NULL
;
540 pvh_e
= PV_HASHED_ENTRY_NULL
;
545 * Expand pmap to include this pte. Assume that
546 * pmap is always expanded to include enough hardware
547 * pages to map one VM page.
550 while ((pte
= pmap64_pde(pmap
, vaddr
)) == PD_ENTRY_NULL
) {
551 /* need room for another pde entry */
553 kr_expand
= pmap_expand_pdpt(pmap
, vaddr
, options
);
554 if (kr_expand
!= KERN_SUCCESS
)
559 while ((pte
= pmap_pte(pmap
, vaddr
)) == PT_ENTRY_NULL
) {
561 * Must unlock to expand the pmap
562 * going to grow pde level page(s)
565 kr_expand
= pmap_expand(pmap
, vaddr
, options
);
566 if (kr_expand
!= KERN_SUCCESS
)
571 if (options
& PMAP_EXPAND_OPTIONS_NOENTER
) {
576 if (superpage
&& *pte
&& !(*pte
& PTE_PS
)) {
578 * There is still an empty page table mapped that
579 * was used for a previous base page mapping.
580 * Remember the PDE and the PDE index, so that we
581 * can free the page at the end of this function.
583 delpage_pde_index
= pdeidx(pmap
, vaddr
);
584 delpage_pm_obj
= pmap
->pm_obj
;
588 old_pa
= pte_to_pa(*pte
);
589 pai
= pa_index(old_pa
);
590 old_pa_locked
= FALSE
;
593 (*pte
& PTE_COMPRESSED
)) {
594 /* one less "compressed" */
595 OSAddAtomic64(-1, &pmap
->stats
.compressed
);
596 /* marker will be cleared below */
600 * if we have a previous managed page, lock the pv entry now. after
601 * we lock it, check to see if someone beat us to the lock and if so
604 if ((0 != old_pa
) && IS_MANAGED_PAGE(pai
)) {
606 old_pa_locked
= TRUE
;
607 old_pa
= pte_to_pa(*pte
);
609 UNLOCK_PVH(pai
); /* another path beat us to it */
610 old_pa_locked
= FALSE
;
615 * Special case if the incoming physical page is already mapped
619 pt_entry_t old_attributes
=
620 *pte
& ~(PTE_REF(is_ept
) | PTE_MOD(is_ept
));
623 * May be changing its wired attribute or protection
626 template = pa_to_pte(pa
);
628 /* ?: WORTH ASSERTING THAT AT LEAST ONE RWX (implicit valid) PASSED FOR EPT? */
630 template |= INTEL_PTE_VALID
;
632 template |= INTEL_EPT_IPTA
;
635 template |= pmap_get_cache_attributes(pa_index(pa
), is_ept
);
638 * We don't support passing VM_MEM_NOT_CACHEABLE flags for EPT PTEs
640 if (!is_ept
&& (VM_MEM_NOT_CACHEABLE
==
641 (flags
& (VM_MEM_NOT_CACHEABLE
| VM_WIMG_USE_DEFAULT
)))) {
642 if (!(flags
& VM_MEM_GUARDED
))
643 template |= INTEL_PTE_PTA
;
644 template |= INTEL_PTE_NCACHE
;
646 if (pmap
!= kernel_pmap
&& !is_ept
)
647 template |= INTEL_PTE_USER
;
649 if (prot
& VM_PROT_READ
)
650 template |= PTE_READ(is_ept
);
652 if (prot
& VM_PROT_WRITE
) {
653 template |= PTE_WRITE(is_ept
);
654 if (is_ept
&& !pmap_ept_support_ad
) {
655 template |= PTE_MOD(is_ept
);
657 assert(IS_MANAGED_PAGE(pai
));
658 pmap_phys_attributes
[pai
] |= PHYS_MODIFIED
;
662 if (prot
& VM_PROT_EXECUTE
) {
664 template = pte_set_ex(template, is_ept
);
668 template = pte_remove_ex(template, is_ept
);
671 template |= PTE_WIRED
;
672 if (!iswired(old_attributes
)) {
673 OSAddAtomic(+1, &pmap
->stats
.wired_count
);
674 pmap_ledger_credit(pmap
, task_ledgers
.wired_mem
, PAGE_SIZE
);
677 if (iswired(old_attributes
)) {
678 assert(pmap
->stats
.wired_count
>= 1);
679 OSAddAtomic(-1, &pmap
->stats
.wired_count
);
680 pmap_ledger_debit(pmap
, task_ledgers
.wired_mem
, PAGE_SIZE
);
684 if (superpage
) /* this path can not be used */
685 template |= PTE_PS
; /* to change the page size! */
687 if (old_attributes
== template)
688 goto dont_update_pte
;
690 /* Determine delta, PV locked */
692 ((old_attributes
^ template) != PTE_WIRED
);
694 if (need_tlbflush
== TRUE
&& !(old_attributes
& PTE_WRITE(is_ept
))) {
695 if ((old_attributes
^ template) == PTE_WRITE(is_ept
))
696 need_tlbflush
= FALSE
;
699 /* For hardware that doesn't have EPT AD support, we always set REFMOD for EPT PTEs */
700 if (is_ept
&& !pmap_ept_support_ad
) {
701 template |= PTE_REF(is_ept
);
703 assert(IS_MANAGED_PAGE(pai
));
704 pmap_phys_attributes
[pai
] |= PHYS_REFERENCED
;
708 /* store modified PTE and preserve RC bits */
709 pt_entry_t npte
, opte
;;
712 npte
= template | (opte
& (PTE_REF(is_ept
) | PTE_MOD(is_ept
)));
713 } while (!pmap_cmpx_pte(pte
, opte
, npte
));
717 old_pa_locked
= FALSE
;
723 * Outline of code from here:
724 * 1) If va was mapped, update TLBs, remove the mapping
725 * and remove old pvlist entry.
726 * 2) Add pvlist entry for new mapping
727 * 3) Enter new mapping.
729 * If the old physical page is not managed step 1) is skipped
730 * (except for updating the TLBs), and the mapping is
731 * overwritten at step 3). If the new physical page is not
732 * managed, step 2) is skipped.
735 if (old_pa
!= (pmap_paddr_t
) 0) {
738 * Don't do anything to pages outside valid memory here.
739 * Instead convince the code that enters a new mapping
740 * to overwrite the old one.
743 /* invalidate the PTE */
744 pmap_update_pte(pte
, PTE_VALID_MASK(is_ept
), 0);
745 /* propagate invalidate everywhere */
746 PMAP_UPDATE_TLBS(pmap
, vaddr
, vaddr
+ PAGE_SIZE
);
747 /* remember reference and change */
749 oattr
= (char) (old_pte
& (PTE_MOD(is_ept
) | PTE_REF(is_ept
)));
750 /* completely invalidate the PTE */
751 pmap_store_pte(pte
, 0);
753 if (IS_MANAGED_PAGE(pai
)) {
754 pmap_assert(old_pa_locked
== TRUE
);
755 pmap_ledger_debit(pmap
, task_ledgers
.phys_mem
, PAGE_SIZE
);
756 pmap_ledger_debit(pmap
, task_ledgers
.phys_footprint
, PAGE_SIZE
);
757 assert(pmap
->stats
.resident_count
>= 1);
758 OSAddAtomic(-1, &pmap
->stats
.resident_count
);
759 if (pmap
!= kernel_pmap
) {
760 if (IS_REUSABLE_PAGE(pai
)) {
761 assert(pmap
->stats
.reusable
> 0);
762 OSAddAtomic(-1, &pmap
->stats
.reusable
);
763 } else if (IS_INTERNAL_PAGE(pai
)) {
764 assert(pmap
->stats
.internal
> 0);
765 OSAddAtomic(-1, &pmap
->stats
.internal
);
767 assert(pmap
->stats
.external
> 0);
768 OSAddAtomic(-1, &pmap
->stats
.external
);
772 assert(pmap
->stats
.wired_count
>= 1);
773 OSAddAtomic(-1, &pmap
->stats
.wired_count
);
774 pmap_ledger_debit(pmap
, task_ledgers
.wired_mem
,
779 pmap_phys_attributes
[pai
] |= oattr
;
781 pmap_phys_attributes
[pai
] |= ept_refmod_to_physmap(oattr
);
785 * Remove the mapping from the pvlist for
786 * this physical page.
787 * We'll end up with either a rooted pv or a
790 pvh_e
= pmap_pv_remove(pmap
, vaddr
, (ppnum_t
*) &pai
, &old_pte
);
795 * old_pa is not managed.
796 * Do removal part of accounting.
799 if (pmap
!= kernel_pmap
) {
801 assert(pmap
->stats
.device
> 0);
802 OSAddAtomic(-1, &pmap
->stats
.device
);
806 assert(pmap
->stats
.wired_count
>= 1);
807 OSAddAtomic(-1, &pmap
->stats
.wired_count
);
808 pmap_ledger_debit(pmap
, task_ledgers
.wired_mem
, PAGE_SIZE
);
814 * if we had a previously managed paged locked, unlock it now
818 old_pa_locked
= FALSE
;
821 pai
= pa_index(pa
); /* now working with new incoming phys page */
822 if (IS_MANAGED_PAGE(pai
)) {
825 * Step 2) Enter the mapping in the PV list for this
828 pv_h
= pai_to_pvh(pai
);
832 if (pv_h
->pmap
== PMAP_NULL
) {
834 * No mappings yet, use rooted pv
838 queue_init(&pv_h
->qlink
);
840 if (options
& PMAP_OPTIONS_INTERNAL
) {
841 pmap_phys_attributes
[pai
] |= PHYS_INTERNAL
;
843 pmap_phys_attributes
[pai
] &= ~PHYS_INTERNAL
;
845 if (options
& PMAP_OPTIONS_REUSABLE
) {
846 pmap_phys_attributes
[pai
] |= PHYS_REUSABLE
;
848 pmap_phys_attributes
[pai
] &= ~PHYS_REUSABLE
;
852 * Add new pv_hashed_entry after header.
854 if ((PV_HASHED_ENTRY_NULL
== pvh_e
) && pvh_new
) {
856 pvh_new
= PV_HASHED_ENTRY_NULL
;
857 } else if (PV_HASHED_ENTRY_NULL
== pvh_e
) {
858 PV_HASHED_ALLOC(&pvh_e
);
859 if (PV_HASHED_ENTRY_NULL
== pvh_e
) {
861 * the pv list is empty. if we are on
862 * the kernel pmap we'll use one of
863 * the special private kernel pv_e's,
864 * else, we need to unlock
865 * everything, zalloc a pv_e, and
866 * restart bringing in the pv_e with
869 if (kernel_pmap
== pmap
) {
870 PV_HASHED_KERN_ALLOC(&pvh_e
);
874 pmap_pv_throttle(pmap
);
875 pvh_new
= (pv_hashed_entry_t
) zalloc(pv_hashed_list_zone
);
881 if (PV_HASHED_ENTRY_NULL
== pvh_e
)
882 panic("Mapping alias chain exhaustion, possibly induced by numerous kernel virtual double mappings");
887 pv_hash_add(pvh_e
, pv_h
);
890 * Remember that we used the pvlist entry.
892 pvh_e
= PV_HASHED_ENTRY_NULL
;
896 * only count the mapping
897 * for 'managed memory'
899 pmap_ledger_credit(pmap
, task_ledgers
.phys_mem
, PAGE_SIZE
);
900 pmap_ledger_credit(pmap
, task_ledgers
.phys_footprint
, PAGE_SIZE
);
901 OSAddAtomic(+1, &pmap
->stats
.resident_count
);
902 if (pmap
->stats
.resident_count
> pmap
->stats
.resident_max
) {
903 pmap
->stats
.resident_max
= pmap
->stats
.resident_count
;
905 if (pmap
!= kernel_pmap
) {
906 if (IS_REUSABLE_PAGE(pai
)) {
907 OSAddAtomic(+1, &pmap
->stats
.reusable
);
908 PMAP_STATS_PEAK(pmap
->stats
.reusable
);
909 } else if (IS_INTERNAL_PAGE(pai
)) {
910 OSAddAtomic(+1, &pmap
->stats
.internal
);
911 PMAP_STATS_PEAK(pmap
->stats
.internal
);
913 OSAddAtomic(+1, &pmap
->stats
.external
);
914 PMAP_STATS_PEAK(pmap
->stats
.external
);
917 } else if (last_managed_page
== 0) {
918 /* Account for early mappings created before "managed pages"
919 * are determined. Consider consulting the available DRAM map.
921 pmap_ledger_credit(pmap
, task_ledgers
.phys_mem
, PAGE_SIZE
);
922 pmap_ledger_credit(pmap
, task_ledgers
.phys_footprint
, PAGE_SIZE
);
923 OSAddAtomic(+1, &pmap
->stats
.resident_count
);
924 if (pmap
!= kernel_pmap
) {
926 OSAddAtomic(+1, &pmap
->stats
.device
);
927 PMAP_STATS_PEAK(pmap
->stats
.device
);
932 * Step 3) Enter the mapping.
934 * Build a template to speed up entering -
935 * only the pfn changes.
937 template = pa_to_pte(pa
);
940 template |= INTEL_PTE_VALID
;
942 template |= INTEL_EPT_IPTA
;
947 * DRK: It may be worth asserting on cache attribute flags that diverge
948 * from the existing physical page attributes.
951 template |= pmap_get_cache_attributes(pa_index(pa
), is_ept
);
954 * We don't support passing VM_MEM_NOT_CACHEABLE flags for EPT PTEs
956 if (!is_ept
&& (flags
& VM_MEM_NOT_CACHEABLE
)) {
957 if (!(flags
& VM_MEM_GUARDED
))
958 template |= INTEL_PTE_PTA
;
959 template |= INTEL_PTE_NCACHE
;
961 if (pmap
!= kernel_pmap
&& !is_ept
)
962 template |= INTEL_PTE_USER
;
963 if (prot
& VM_PROT_READ
)
964 template |= PTE_READ(is_ept
);
965 if (prot
& VM_PROT_WRITE
) {
966 template |= PTE_WRITE(is_ept
);
967 if (is_ept
&& !pmap_ept_support_ad
) {
968 template |= PTE_MOD(is_ept
);
969 if (IS_MANAGED_PAGE(pai
))
970 pmap_phys_attributes
[pai
] |= PHYS_MODIFIED
;
973 if (prot
& VM_PROT_EXECUTE
) {
975 template = pte_set_ex(template, is_ept
);
979 template = pte_remove_ex(template, is_ept
);
981 template |= INTEL_PTE_WIRED
;
982 OSAddAtomic(+1, & pmap
->stats
.wired_count
);
983 pmap_ledger_credit(pmap
, task_ledgers
.wired_mem
, PAGE_SIZE
);
986 template |= INTEL_PTE_PS
;
988 /* For hardware that doesn't have EPT AD support, we always set REFMOD for EPT PTEs */
989 if (is_ept
&& !pmap_ept_support_ad
) {
990 template |= PTE_REF(is_ept
);
991 if (IS_MANAGED_PAGE(pai
))
992 pmap_phys_attributes
[pai
] |= PHYS_REFERENCED
;
995 pmap_store_pte(pte
, template);
998 * if this was a managed page we delayed unlocking the pv until here
999 * to prevent pmap_page_protect et al from finding it until the pte
1002 if (IS_MANAGED_PAGE(pai
)) {
1006 if (need_tlbflush
== TRUE
) {
1007 if (options
& PMAP_OPTIONS_NOFLUSH
)
1008 PMAP_UPDATE_TLBS_DELAYED(pmap
, vaddr
, vaddr
+ PAGE_SIZE
, (pmap_flush_context
*)arg
);
1010 PMAP_UPDATE_TLBS(pmap
, vaddr
, vaddr
+ PAGE_SIZE
);
1012 if (pvh_e
!= PV_HASHED_ENTRY_NULL
) {
1013 PV_HASHED_FREE_LIST(pvh_e
, pvh_e
, 1);
1015 if (pvh_new
!= PV_HASHED_ENTRY_NULL
) {
1016 PV_HASHED_KERN_FREE_LIST(pvh_new
, pvh_new
, 1);
1020 if (delpage_pm_obj
) {
1023 vm_object_lock(delpage_pm_obj
);
1024 m
= vm_page_lookup(delpage_pm_obj
, (delpage_pde_index
* PAGE_SIZE
));
1025 if (m
== VM_PAGE_NULL
)
1026 panic("pmap_enter: pte page not in object");
1028 vm_object_unlock(delpage_pm_obj
);
1029 OSAddAtomic(-1, &inuse_ptepages_count
);
1030 PMAP_ZINFO_PFREE(pmap
, PAGE_SIZE
);
1033 PMAP_TRACE(PMAP_CODE(PMAP__ENTER
) | DBG_FUNC_END
, 0, 0, 0, 0, 0);
1034 return KERN_SUCCESS
;
1038 * Remove a range of hardware page-table entries.
1039 * The entries given are the first (inclusive)
1040 * and last (exclusive) entries for the VM pages.
1041 * The virtual address is the va for the first pte.
1043 * The pmap must be locked.
1044 * If the pmap is not the kernel pmap, the range must lie
1045 * entirely within one pte-page. This is NOT checked.
1046 * Assumes that the pte-page exists.
1052 vm_map_offset_t start_vaddr
,
1056 pmap_remove_range_options(pmap
, start_vaddr
, spte
, epte
,
1057 PMAP_OPTIONS_REMOVE
);
1061 pmap_remove_range_options(
1063 vm_map_offset_t start_vaddr
,
1069 pv_hashed_entry_t pvh_et
= PV_HASHED_ENTRY_NULL
;
1070 pv_hashed_entry_t pvh_eh
= PV_HASHED_ENTRY_NULL
;
1071 pv_hashed_entry_t pvh_e
;
1073 int num_removed
, num_unwired
, num_found
, num_invalid
;
1074 int num_device
, num_external
, num_internal
, num_reusable
;
1075 uint64_t num_compressed
;
1078 vm_map_offset_t vaddr
;
1079 boolean_t is_ept
= is_ept_pmap(pmap
);
1090 /* invalidate the PTEs first to "freeze" them */
1091 for (cpte
= spte
, vaddr
= start_vaddr
;
1093 cpte
++, vaddr
+= PAGE_SIZE_64
) {
1094 pt_entry_t p
= *cpte
;
1098 if (pmap
!= kernel_pmap
&&
1099 (options
& PMAP_OPTIONS_REMOVE
) &&
1100 (p
& PTE_COMPRESSED
)) {
1101 /* one less "compressed" */
1104 /* XXX probably does not need to be atomic! */
1105 pmap_update_pte(cpte
, PTE_COMPRESSED
, 0);
1116 if (!IS_MANAGED_PAGE(pai
)) {
1118 * Outside range of managed physical memory.
1119 * Just remove the mappings.
1121 pmap_store_pte(cpte
, 0);
1126 if ((p
& PTE_VALID_MASK(is_ept
)) == 0)
1129 /* invalidate the PTE */
1130 pmap_update_pte(cpte
, PTE_VALID_MASK(is_ept
), 0);
1133 if (num_found
== 0) {
1134 /* nothing was changed: we're done */
1138 /* propagate the invalidates to other CPUs */
1140 PMAP_UPDATE_TLBS(pmap
, start_vaddr
, vaddr
);
1142 for (cpte
= spte
, vaddr
= start_vaddr
;
1144 cpte
++, vaddr
+= PAGE_SIZE_64
) {
1146 pa
= pte_to_pa(*cpte
);
1154 pa
= pte_to_pa(*cpte
);
1160 if (IS_REUSABLE_PAGE(pai
)) {
1162 } else if (IS_INTERNAL_PAGE(pai
)) {
1169 * Get the modify and reference bits, then
1170 * nuke the entry in the page table
1172 /* remember reference and change */
1173 pmap_phys_attributes
[pai
] |=
1174 (char) (*cpte
& (PHYS_MODIFIED
| PHYS_REFERENCED
));
1177 * Remove the mapping from the pvlist for this physical page.
1179 pvh_e
= pmap_pv_remove(pmap
, vaddr
, (ppnum_t
*) &pai
, cpte
);
1181 /* completely invalidate the PTE */
1182 pmap_store_pte(cpte
, 0);
1186 if (pvh_e
!= PV_HASHED_ENTRY_NULL
) {
1187 pvh_e
->qlink
.next
= (queue_entry_t
) pvh_eh
;
1190 if (pvh_et
== PV_HASHED_ENTRY_NULL
) {
1197 if (pvh_eh
!= PV_HASHED_ENTRY_NULL
) {
1198 PV_HASHED_FREE_LIST(pvh_eh
, pvh_et
, pvh_cnt
);
1205 if (pmap
->stats
.resident_count
< num_removed
)
1206 panic("pmap_remove_range: resident_count");
1208 pmap_ledger_debit(pmap
, task_ledgers
.phys_mem
, machine_ptob(num_removed
));
1209 pmap_ledger_debit(pmap
, task_ledgers
.phys_footprint
, machine_ptob(num_removed
));
1210 assert(pmap
->stats
.resident_count
>= num_removed
);
1211 OSAddAtomic(-num_removed
, &pmap
->stats
.resident_count
);
1213 if (pmap
!= kernel_pmap
) {
1215 assert(pmap
->stats
.device
>= num_device
);
1217 OSAddAtomic(-num_device
, &pmap
->stats
.device
);
1219 assert(pmap
->stats
.external
>= num_external
);
1221 OSAddAtomic(-num_external
, &pmap
->stats
.external
);
1222 assert(pmap
->stats
.internal
>= num_internal
);
1224 OSAddAtomic(-num_internal
, &pmap
->stats
.internal
);
1225 assert(pmap
->stats
.reusable
>= num_reusable
);
1227 OSAddAtomic(-num_reusable
, &pmap
->stats
.reusable
);
1228 assert(pmap
->stats
.compressed
>= num_compressed
);
1230 OSAddAtomic64(-num_compressed
, &pmap
->stats
.compressed
);
1234 if (pmap
->stats
.wired_count
< num_unwired
)
1235 panic("pmap_remove_range: wired_count");
1237 assert(pmap
->stats
.wired_count
>= num_unwired
);
1238 OSAddAtomic(-num_unwired
, &pmap
->stats
.wired_count
);
1239 pmap_ledger_debit(pmap
, task_ledgers
.wired_mem
, machine_ptob(num_unwired
));
1246 * Remove the given range of addresses
1247 * from the specified map.
1249 * It is assumed that the start and end are properly
1250 * rounded to the hardware page size.
1258 pmap_remove_options(map
, s64
, e64
, PMAP_OPTIONS_REMOVE
);
1262 pmap_remove_options(
1269 pt_entry_t
*spte
, *epte
;
1276 if (map
== PMAP_NULL
|| s64
== e64
)
1279 is_ept
= is_ept_pmap(map
);
1281 PMAP_TRACE(PMAP_CODE(PMAP__REMOVE
) | DBG_FUNC_START
,
1283 (uint32_t) (s64
>> 32), s64
,
1284 (uint32_t) (e64
>> 32), e64
);
1291 * Check that address range in the kernel does not overlap the stacks.
1292 * We initialize local static min/max variables once to avoid making
1293 * 2 function calls for every remove. Note also that these functions
1294 * both return 0 before kernel stacks have been initialized, and hence
1295 * the panic is not triggered in this case.
1297 if (map
== kernel_pmap
) {
1298 static vm_offset_t kernel_stack_min
= 0;
1299 static vm_offset_t kernel_stack_max
= 0;
1301 if (kernel_stack_min
== 0) {
1302 kernel_stack_min
= min_valid_stack_address();
1303 kernel_stack_max
= max_valid_stack_address();
1305 if ((kernel_stack_min
<= s64
&& s64
< kernel_stack_max
) ||
1306 (kernel_stack_min
< e64
&& e64
<= kernel_stack_max
))
1307 panic("pmap_remove() attempted in kernel stack");
1312 * The values of kernel_stack_min and kernel_stack_max are no longer
1313 * relevant now that we allocate kernel stacks in the kernel map,
1314 * so the old code above no longer applies. If we wanted to check that
1315 * we weren't removing a mapping of a page in a kernel stack we'd
1316 * mark the PTE with an unused bit and check that here.
1321 deadline
= rdtsc64() + max_preemption_latency_tsc
;
1324 l64
= (s64
+ pde_mapped_size
) & ~(pde_mapped_size
- 1);
1327 pde
= pmap_pde(map
, s64
);
1329 if (pde
&& (*pde
& PTE_VALID_MASK(is_ept
))) {
1330 if (*pde
& PTE_PS
) {
1332 * If we're removing a superpage, pmap_remove_range()
1333 * must work on level 2 instead of level 1; and we're
1334 * only passing a single level 2 entry instead of a
1338 epte
= spte
+1; /* excluded */
1340 spte
= pmap_pte(map
, (s64
& ~(pde_mapped_size
- 1)));
1341 spte
= &spte
[ptenum(s64
)];
1342 epte
= &spte
[intel_btop(l64
- s64
)];
1344 pmap_remove_range_options(map
, s64
, spte
, epte
,
1349 if (s64
< e64
&& rdtsc64() >= deadline
) {
1351 /* TODO: Rapid release/reacquisition can defeat
1352 * the "backoff" intent here; either consider a
1353 * fair spinlock, or a scheme whereby each lock
1354 * attempt marks the processor as within a spinlock
1355 * acquisition, and scan CPUs here to determine
1356 * if a backoff is necessary, to avoid sacrificing
1357 * performance in the common case.
1360 deadline
= rdtsc64() + max_preemption_latency_tsc
;
1366 PMAP_TRACE(PMAP_CODE(PMAP__REMOVE
) | DBG_FUNC_END
,
1376 pmap_page_protect_options(pn
, prot
, 0, NULL
);
1380 * Routine: pmap_page_protect_options
1383 * Lower the permission for all mappings to a given
1387 pmap_page_protect_options(
1390 unsigned int options
,
1393 pv_hashed_entry_t pvh_eh
= PV_HASHED_ENTRY_NULL
;
1394 pv_hashed_entry_t pvh_et
= PV_HASHED_ENTRY_NULL
;
1395 pv_hashed_entry_t nexth
;
1397 pv_rooted_entry_t pv_h
;
1398 pv_rooted_entry_t pv_e
;
1399 pv_hashed_entry_t pvh_e
;
1404 pt_entry_t new_pte_value
;
1408 assert(pn
!= vm_page_fictitious_addr
);
1409 if (pn
== vm_page_guard_addr
)
1412 pai
= ppn_to_pai(pn
);
1414 if (!IS_MANAGED_PAGE(pai
)) {
1416 * Not a managed page.
1420 PMAP_TRACE(PMAP_CODE(PMAP__PAGE_PROTECT
) | DBG_FUNC_START
,
1424 * Determine the new protection.
1428 case VM_PROT_READ
| VM_PROT_EXECUTE
:
1432 return; /* nothing to do */
1438 pv_h
= pai_to_pvh(pai
);
1444 * Walk down PV list, if any, changing or removing all mappings.
1446 if (pv_h
->pmap
== PMAP_NULL
)
1450 pvh_e
= (pv_hashed_entry_t
) pv_e
; /* cheat */
1453 vm_map_offset_t vaddr
;
1455 if ((options
& PMAP_OPTIONS_COMPRESSOR_IFF_MODIFIED
) &&
1456 (pmap_phys_attributes
[pai
] & PHYS_MODIFIED
)) {
1457 /* page was modified, so it will be compressed */
1458 options
&= ~PMAP_OPTIONS_COMPRESSOR_IFF_MODIFIED
;
1459 options
|= PMAP_OPTIONS_COMPRESSOR
;
1463 is_ept
= is_ept_pmap(pmap
);
1465 pte
= pmap_pte(pmap
, vaddr
);
1467 pmap_assert2((pa_index(pte_to_pa(*pte
)) == pn
),
1468 "pmap_page_protect: PTE mismatch, pn: 0x%x, pmap: %p, vaddr: 0x%llx, pte: 0x%llx", pn
, pmap
, vaddr
, *pte
);
1471 panic("pmap_page_protect() "
1472 "pmap=%p pn=0x%x vaddr=0x%llx\n",
1475 nexth
= (pv_hashed_entry_t
) queue_next(&pvh_e
->qlink
);
1478 * Remove the mapping if new protection is NONE
1482 /* Remove per-pmap wired count */
1483 if (iswired(*pte
)) {
1484 OSAddAtomic(-1, &pmap
->stats
.wired_count
);
1485 pmap_ledger_debit(pmap
, task_ledgers
.wired_mem
, PAGE_SIZE
);
1488 if (pmap
!= kernel_pmap
&&
1489 (options
& PMAP_OPTIONS_COMPRESSOR
) &&
1490 IS_INTERNAL_PAGE(pai
)) {
1491 /* mark this PTE as having been "reclaimed" */
1492 new_pte_value
= PTE_COMPRESSED
;
1497 if (options
& PMAP_OPTIONS_NOREFMOD
) {
1498 pmap_store_pte(pte
, new_pte_value
);
1500 if (options
& PMAP_OPTIONS_NOFLUSH
)
1501 PMAP_UPDATE_TLBS_DELAYED(pmap
, vaddr
, vaddr
+ PAGE_SIZE
, (pmap_flush_context
*)arg
);
1503 PMAP_UPDATE_TLBS(pmap
, vaddr
, vaddr
+ PAGE_SIZE
);
1506 * Remove the mapping, collecting dirty bits.
1508 pmap_update_pte(pte
, PTE_VALID_MASK(is_ept
), 0);
1510 PMAP_UPDATE_TLBS(pmap
, vaddr
, vaddr
+PAGE_SIZE
);
1512 PMAP_OPTIONS_COMPRESSOR_IFF_MODIFIED
) &&
1513 ! (pmap_phys_attributes
[pai
] &
1515 (*pte
& PHYS_MODIFIED
)) {
1517 * Page is actually "modified" and
1518 * will be compressed. Start
1519 * accounting for it as "compressed".
1521 options
&= ~PMAP_OPTIONS_COMPRESSOR_IFF_MODIFIED
;
1522 options
|= PMAP_OPTIONS_COMPRESSOR
;
1523 new_pte_value
= PTE_COMPRESSED
;
1526 pmap_phys_attributes
[pai
] |=
1527 *pte
& (PHYS_MODIFIED
|PHYS_REFERENCED
);
1529 pmap_phys_attributes
[pai
] |=
1530 ept_refmod_to_physmap((*pte
& (INTEL_EPT_REF
| INTEL_EPT_MOD
))) & (PHYS_MODIFIED
| PHYS_REFERENCED
);
1532 pmap_store_pte(pte
, new_pte_value
);
1535 if (new_pte_value
== PTE_COMPRESSED
) {
1536 /* one more "compressed" page */
1537 OSAddAtomic64(+1, &pmap
->stats
.compressed
);
1538 PMAP_STATS_PEAK(pmap
->stats
.compressed
);
1539 pmap
->stats
.compressed_lifetime
++;
1543 if (pmap
->stats
.resident_count
< 1)
1544 panic("pmap_page_protect: resident_count");
1546 pmap_ledger_debit(pmap
, task_ledgers
.phys_mem
, PAGE_SIZE
);
1547 assert(pmap
->stats
.resident_count
>= 1);
1548 OSAddAtomic(-1, &pmap
->stats
.resident_count
);
1549 if (options
& PMAP_OPTIONS_COMPRESSOR
) {
1551 * This removal is only being done so we can send this page to
1552 * the compressor; therefore it mustn't affect total task footprint.
1554 pmap_ledger_credit(pmap
, task_ledgers
.internal_compressed
, PAGE_SIZE
);
1556 pmap_ledger_debit(pmap
, task_ledgers
.phys_footprint
, PAGE_SIZE
);
1559 if (pmap
!= kernel_pmap
) {
1560 if (IS_REUSABLE_PAGE(pai
)) {
1561 assert(pmap
->stats
.reusable
> 0);
1562 OSAddAtomic(-1, &pmap
->stats
.reusable
);
1563 } else if (IS_INTERNAL_PAGE(pai
)) {
1564 assert(pmap
->stats
.internal
> 0);
1565 OSAddAtomic(-1, &pmap
->stats
.internal
);
1567 assert(pmap
->stats
.external
> 0);
1568 OSAddAtomic(-1, &pmap
->stats
.external
);
1573 * Deal with the pv_rooted_entry.
1578 * Fix up head later.
1580 pv_h
->pmap
= PMAP_NULL
;
1583 * Delete this entry.
1585 pv_hash_remove(pvh_e
);
1586 pvh_e
->qlink
.next
= (queue_entry_t
) pvh_eh
;
1589 if (pvh_et
== PV_HASHED_ENTRY_NULL
)
1595 * Write-protect, after opportunistic refmod collect
1598 pmap_phys_attributes
[pai
] |=
1599 *pte
& (PHYS_MODIFIED
|PHYS_REFERENCED
);
1601 pmap_phys_attributes
[pai
] |=
1602 ept_refmod_to_physmap((*pte
& (INTEL_EPT_REF
| INTEL_EPT_MOD
))) & (PHYS_MODIFIED
| PHYS_REFERENCED
);
1604 pmap_update_pte(pte
, PTE_WRITE(is_ept
), 0);
1606 if (options
& PMAP_OPTIONS_NOFLUSH
)
1607 PMAP_UPDATE_TLBS_DELAYED(pmap
, vaddr
, vaddr
+ PAGE_SIZE
, (pmap_flush_context
*)arg
);
1609 PMAP_UPDATE_TLBS(pmap
, vaddr
, vaddr
+PAGE_SIZE
);
1612 } while ((pv_e
= (pv_rooted_entry_t
) nexth
) != pv_h
);
1616 * If pv_head mapping was removed, fix it up.
1618 if (pv_h
->pmap
== PMAP_NULL
) {
1619 pvh_e
= (pv_hashed_entry_t
) queue_next(&pv_h
->qlink
);
1621 if (pvh_e
!= (pv_hashed_entry_t
) pv_h
) {
1622 pv_hash_remove(pvh_e
);
1623 pv_h
->pmap
= pvh_e
->pmap
;
1624 pv_h
->va
= pvh_e
->va
;
1625 pvh_e
->qlink
.next
= (queue_entry_t
) pvh_eh
;
1628 if (pvh_et
== PV_HASHED_ENTRY_NULL
)
1633 if (pvh_eh
!= PV_HASHED_ENTRY_NULL
) {
1634 PV_HASHED_FREE_LIST(pvh_eh
, pvh_et
, pvh_cnt
);
1639 PMAP_TRACE(PMAP_CODE(PMAP__PAGE_PROTECT
) | DBG_FUNC_END
,
1645 * Clear specified attribute bits.
1648 phys_attribute_clear(
1651 unsigned int options
,
1654 pv_rooted_entry_t pv_h
;
1655 pv_hashed_entry_t pv_e
;
1659 char attributes
= 0;
1660 boolean_t is_internal
, is_reusable
, is_ept
;
1661 int ept_bits_to_clear
;
1662 boolean_t ept_keep_global_mod
= FALSE
;
1664 if ((bits
& PHYS_MODIFIED
) &&
1665 (options
& PMAP_OPTIONS_NOFLUSH
) &&
1667 panic("phys_attribute_clear(0x%x,0x%x,0x%x,%p): "
1668 "should not clear 'modified' without flushing TLBs\n",
1669 pn
, bits
, options
, arg
);
1672 /* We only support converting MOD and REF bits for EPT PTEs in this function */
1673 assert((bits
& ~(PHYS_REFERENCED
| PHYS_MODIFIED
)) == 0);
1675 ept_bits_to_clear
= (unsigned)physmap_refmod_to_ept(bits
& (PHYS_MODIFIED
| PHYS_REFERENCED
));
1678 assert(pn
!= vm_page_fictitious_addr
);
1679 if (pn
== vm_page_guard_addr
)
1682 pai
= ppn_to_pai(pn
);
1684 if (!IS_MANAGED_PAGE(pai
)) {
1686 * Not a managed page.
1691 PMAP_TRACE(PMAP_CODE(PMAP__ATTRIBUTE_CLEAR
) | DBG_FUNC_START
,
1694 pv_h
= pai_to_pvh(pai
);
1700 * Walk down PV list, clearing all modify or reference bits.
1701 * We do not have to lock the pv_list because we have
1704 if (pv_h
->pmap
!= PMAP_NULL
) {
1706 * There are some mappings.
1709 is_internal
= IS_INTERNAL_PAGE(pai
);
1710 is_reusable
= IS_REUSABLE_PAGE(pai
);
1712 pv_e
= (pv_hashed_entry_t
)pv_h
;
1719 is_ept
= is_ept_pmap(pmap
);
1724 pte
= pmap_pte(pmap
, va
);
1725 /* grab ref/mod bits from this PTE */
1726 pte_bits
= (*pte
& (PTE_REF(is_ept
) | PTE_MOD(is_ept
)));
1727 /* propagate to page's global attributes */
1729 attributes
|= pte_bits
;
1731 attributes
|= ept_refmod_to_physmap(pte_bits
);
1732 if (!pmap_ept_support_ad
&& (pte_bits
& INTEL_EPT_MOD
)) {
1733 ept_keep_global_mod
= TRUE
;
1736 /* which bits to clear for this PTE? */
1740 pte_bits
&= ept_bits_to_clear
;
1745 * Clear modify and/or reference bits.
1748 pmap_update_pte(pte
, bits
, 0);
1750 /* Ensure all processors using this translation
1751 * invalidate this TLB entry. The invalidation
1752 * *must* follow the PTE update, to ensure that
1753 * the TLB shadow of the 'D' bit (in particular)
1754 * is synchronized with the updated PTE.
1756 if (! (options
& PMAP_OPTIONS_NOFLUSH
)) {
1757 /* flush TLBS now */
1758 PMAP_UPDATE_TLBS(pmap
,
1762 /* delayed TLB flush: add "pmap" info */
1763 PMAP_UPDATE_TLBS_DELAYED(
1767 (pmap_flush_context
*)arg
);
1769 /* no TLB flushing at all */
1773 /* update pmap "reusable" stats */
1774 if ((options
& PMAP_OPTIONS_CLEAR_REUSABLE
) &&
1776 pmap
!= kernel_pmap
) {
1777 /* one less "reusable" */
1778 assert(pmap
->stats
.reusable
> 0);
1779 OSAddAtomic(-1, &pmap
->stats
.reusable
);
1781 /* one more "internal" */
1782 OSAddAtomic(+1, &pmap
->stats
.internal
);
1783 PMAP_STATS_PEAK(pmap
->stats
.internal
);
1785 /* one more "external" */
1786 OSAddAtomic(+1, &pmap
->stats
.external
);
1787 PMAP_STATS_PEAK(pmap
->stats
.external
);
1789 } else if ((options
& PMAP_OPTIONS_SET_REUSABLE
) &&
1791 pmap
!= kernel_pmap
) {
1792 /* one more "reusable" */
1793 OSAddAtomic(+1, &pmap
->stats
.reusable
);
1794 PMAP_STATS_PEAK(pmap
->stats
.reusable
);
1796 /* one less "internal" */
1797 assert(pmap
->stats
.internal
> 0);
1798 OSAddAtomic(-1, &pmap
->stats
.internal
);
1800 /* one less "external" */
1801 assert(pmap
->stats
.external
> 0);
1802 OSAddAtomic(-1, &pmap
->stats
.external
);
1806 pv_e
= (pv_hashed_entry_t
)queue_next(&pv_e
->qlink
);
1808 } while (pv_e
!= (pv_hashed_entry_t
)pv_h
);
1810 /* Opportunistic refmod collection, annulled
1811 * if both REF and MOD are being cleared.
1814 pmap_phys_attributes
[pai
] |= attributes
;
1816 if (ept_keep_global_mod
) {
1818 * If the hardware doesn't support AD bits for EPT PTEs and someone is
1819 * requesting that we clear the modified bit for a phys page, we need
1820 * to ensure that there are no EPT mappings for the page with the
1821 * modified bit set. If there are, we cannot clear the global modified bit.
1823 bits
&= ~PHYS_MODIFIED
;
1825 pmap_phys_attributes
[pai
] &= ~(bits
);
1827 /* update this page's "reusable" status */
1828 if (options
& PMAP_OPTIONS_CLEAR_REUSABLE
) {
1829 pmap_phys_attributes
[pai
] &= ~PHYS_REUSABLE
;
1830 } else if (options
& PMAP_OPTIONS_SET_REUSABLE
) {
1831 pmap_phys_attributes
[pai
] |= PHYS_REUSABLE
;
1836 PMAP_TRACE(PMAP_CODE(PMAP__ATTRIBUTE_CLEAR
) | DBG_FUNC_END
,
1841 * Check specified attribute bits.
1844 phys_attribute_test(
1848 pv_rooted_entry_t pv_h
;
1849 pv_hashed_entry_t pv_e
;
1857 assert(pn
!= vm_page_fictitious_addr
);
1858 assert((bits
& ~(PHYS_MODIFIED
| PHYS_REFERENCED
)) == 0);
1859 if (pn
== vm_page_guard_addr
)
1862 pai
= ppn_to_pai(pn
);
1864 if (!IS_MANAGED_PAGE(pai
)) {
1866 * Not a managed page.
1872 * Fast check... if bits already collected
1873 * no need to take any locks...
1874 * if not set, we need to recheck after taking
1875 * the lock in case they got pulled in while
1876 * we were waiting for the lock
1878 if ((pmap_phys_attributes
[pai
] & bits
) == bits
)
1881 pv_h
= pai_to_pvh(pai
);
1885 attributes
= pmap_phys_attributes
[pai
] & bits
;
1889 * Walk down PV list, checking the mappings until we
1890 * reach the end or we've found the desired attributes.
1892 if (attributes
!= bits
&&
1893 pv_h
->pmap
!= PMAP_NULL
) {
1895 * There are some mappings.
1897 pv_e
= (pv_hashed_entry_t
)pv_h
;
1902 is_ept
= is_ept_pmap(pmap
);
1905 * pick up modify and/or reference bits from mapping
1908 pte
= pmap_pte(pmap
, va
);
1910 attributes
|= (int)(*pte
& bits
);
1912 attributes
|= (int)(ept_refmod_to_physmap((*pte
& (INTEL_EPT_REF
| INTEL_EPT_MOD
))) & (PHYS_MODIFIED
| PHYS_REFERENCED
));
1916 pv_e
= (pv_hashed_entry_t
)queue_next(&pv_e
->qlink
);
1918 } while ((attributes
!= bits
) &&
1919 (pv_e
!= (pv_hashed_entry_t
)pv_h
));
1921 pmap_phys_attributes
[pai
] |= attributes
;
1924 return (attributes
);
1928 * Routine: pmap_change_wiring
1929 * Function: Change the wiring attribute for a map/virtual-address
1931 * In/out conditions:
1932 * The mapping must already exist in the pmap.
1937 vm_map_offset_t vaddr
,
1944 if ((pte
= pmap_pte(map
, vaddr
)) == PT_ENTRY_NULL
)
1945 panic("pmap_change_wiring: pte missing");
1947 if (wired
&& !iswired(*pte
)) {
1949 * wiring down mapping
1951 pmap_ledger_credit(map
, task_ledgers
.wired_mem
, PAGE_SIZE
);
1952 OSAddAtomic(+1, &map
->stats
.wired_count
);
1953 pmap_update_pte(pte
, 0, PTE_WIRED
);
1955 else if (!wired
&& iswired(*pte
)) {
1959 assert(map
->stats
.wired_count
>= 1);
1960 OSAddAtomic(-1, &map
->stats
.wired_count
);
1961 pmap_ledger_debit(map
, task_ledgers
.wired_mem
, PAGE_SIZE
);
1962 pmap_update_pte(pte
, PTE_WIRED
, 0);
1969 * "Backdoor" direct map routine for early mappings.
1970 * Useful for mapping memory outside the range
1971 * Sets A, D and NC if requested
1977 vm_map_offset_t start_addr
,
1978 vm_map_offset_t end_addr
,
1982 pt_entry_t
template;
1985 vm_offset_t base
= virt
;
1986 template = pa_to_pte(start_addr
)
1992 if ((flags
& (VM_MEM_NOT_CACHEABLE
| VM_WIMG_USE_DEFAULT
)) == VM_MEM_NOT_CACHEABLE
) {
1993 template |= INTEL_PTE_NCACHE
;
1994 if (!(flags
& (VM_MEM_GUARDED
)))
1995 template |= INTEL_PTE_PTA
;
1998 #if defined(__x86_64__)
1999 if ((prot
& VM_PROT_EXECUTE
) == 0)
2000 template |= INTEL_PTE_NX
;
2003 if (prot
& VM_PROT_WRITE
)
2004 template |= INTEL_PTE_WRITE
;
2006 while (start_addr
< end_addr
) {
2008 pte
= pmap_pte(kernel_pmap
, (vm_map_offset_t
)virt
);
2009 if (pte
== PT_ENTRY_NULL
) {
2010 panic("pmap_map_bd: Invalid kernel address\n");
2012 pmap_store_pte(pte
, template);
2014 pte_increment_pa(template);
2016 start_addr
+= PAGE_SIZE
;
2019 PMAP_UPDATE_TLBS(kernel_pmap
, base
, base
+ end_addr
- start_addr
);
2024 pmap_query_resident(
2028 unsigned int *compressed_count_p
)
2031 pt_entry_t
*spte
, *epte
;
2034 unsigned int result
;
2036 unsigned int compressed_count
;
2040 if (pmap
== PMAP_NULL
|| pmap
== kernel_pmap
|| s64
== e64
) {
2041 if (compressed_count_p
) {
2042 *compressed_count_p
= 0;
2047 is_ept
= is_ept_pmap(pmap
);
2049 PMAP_TRACE(PMAP_CODE(PMAP__QUERY_RESIDENT
) | DBG_FUNC_START
,
2051 (uint32_t) (s64
>> 32), s64
,
2052 (uint32_t) (e64
>> 32), e64
);
2055 compressed_count
= 0;
2059 deadline
= rdtsc64() + max_preemption_latency_tsc
;
2062 l64
= (s64
+ pde_mapped_size
) & ~(pde_mapped_size
- 1);
2065 pde
= pmap_pde(pmap
, s64
);
2067 if (pde
&& (*pde
& PTE_VALID_MASK(is_ept
))) {
2068 if (*pde
& PTE_PS
) {
2069 /* superpage: not supported */
2071 spte
= pmap_pte(pmap
,
2072 (s64
& ~(pde_mapped_size
- 1)));
2073 spte
= &spte
[ptenum(s64
)];
2074 epte
= &spte
[intel_btop(l64
- s64
)];
2076 for (; spte
< epte
; spte
++) {
2077 if (pte_to_pa(*spte
) != 0) {
2079 } else if (*spte
& PTE_COMPRESSED
) {
2088 if (s64
< e64
&& rdtsc64() >= deadline
) {
2091 deadline
= rdtsc64() + max_preemption_latency_tsc
;
2097 PMAP_TRACE(PMAP_CODE(PMAP__QUERY_RESIDENT
) | DBG_FUNC_END
,
2100 if (compressed_count_p
) {
2101 *compressed_count_p
= compressed_count
;
2109 __unused pmap_t pmap
,
2111 __unused
char *procname
)
2114 #endif /* MACH_ASSERT */