* Tries to create the specified 1 MB page mapping. Returns KERN_SUCCESS if * the mapping was created, and either KERN_FAILURE or KERN_RESOURCE_SHORTAGE * otherwise. Returns KERN_FAILURE if PMAP_ENTER_NOREPLACE was specified and * a mapping already exists at the specified virtual address. Returns * KERN_RESOURCE_SHORTAGE if PMAP_ENTER_NORECLAIM was specified and PV entry * allocation
| 4703 | * allocation failed. |
| 4704 | */ |
| 4705 | static int |
| 4706 | pmap_enter_pte1(pmap_t pmap, vm_offset_t va, pt1_entry_t pte1, u_int flags, |
| 4707 | vm_page_t m) |
| 4708 | { |
| 4709 | struct spglist free; |
| 4710 | pt1_entry_t opte1, *pte1p; |
| 4711 | pt2_entry_t pte2, *pte2p; |
| 4712 | vm_offset_t cur, end; |
| 4713 | vm_page_t mt; |
| 4714 | |
| 4715 | rw_assert(&pvh_global_lock, RA_WLOCKED); |
| 4716 | KASSERT((pte1 & (PTE1_NM | PTE1_RO)) == 0 || |
| 4717 | (pte1 & (PTE1_NM | PTE1_RO)) == (PTE1_NM | PTE1_RO), |
| 4718 | ("%s: pte1 has inconsistent NM and RO attributes", __func__)); |
| 4719 | PMAP_LOCK_ASSERT(pmap, MA_OWNED); |
| 4720 | pte1p = pmap_pte1(pmap, va); |
| 4721 | opte1 = pte1_load(pte1p); |
| 4722 | if (pte1_is_valid(opte1)) { |
| 4723 | if ((flags & PMAP_ENTER_NOREPLACE) != 0) { |
| 4724 | CTR3(KTR_PMAP, "%s: failure for va %#lx in pmap %p", |
| 4725 | __func__, va, pmap); |
| 4726 | return (KERN_FAILURE); |
| 4727 | } |
| 4728 | /* Break the existing mapping(s). */ |
| 4729 | SLIST_INIT(&free); |
| 4730 | if (pte1_is_section(opte1)) { |
| 4731 | /* |
| 4732 | * If the section resulted from a promotion, then a |
| 4733 | * reserved PT page could be freed. |
| 4734 | */ |
| 4735 | pmap_remove_pte1(pmap, pte1p, va, &free); |
| 4736 | } else { |
| 4737 | sched_pin(); |
| 4738 | end = va + PTE1_SIZE; |
| 4739 | for (cur = va, pte2p = pmap_pte2_quick(pmap, va); |
| 4740 | cur != end; cur += PAGE_SIZE, pte2p++) { |
| 4741 | pte2 = pte2_load(pte2p); |
| 4742 | if (!pte2_is_valid(pte2)) |
| 4743 | continue; |
| 4744 | if (pmap_remove_pte2(pmap, pte2p, cur, &free)) |
| 4745 | break; |
| 4746 | } |
| 4747 | sched_unpin(); |
| 4748 | } |
| 4749 | vm_page_free_pages_toq(&free, false); |
| 4750 | } |
| 4751 | if ((m->oflags & VPO_UNMANAGED) == 0) { |
| 4752 | /* |
| 4753 | * Abort this mapping if its PV entry could not be created. |
| 4754 | */ |
| 4755 | if (!pmap_pv_insert_pte1(pmap, va, pte1, flags)) { |
| 4756 | CTR3(KTR_PMAP, "%s: failure for va %#lx in pmap %p", |
| 4757 | __func__, va, pmap); |
| 4758 | return (KERN_RESOURCE_SHORTAGE); |
| 4759 | } |
| 4760 | if ((pte1 & PTE1_RO) == 0) { |
| 4761 | for (mt = m; mt < &m[PTE1_SIZE / PAGE_SIZE]; mt++) |
| 4762 | vm_page_aflag_set(mt, PGA_WRITEABLE); |
no test coverage detected