| 6613 | #endif /* VM_NRESERVLEVEL > 0 */ |
| 6614 | |
| 6615 | static int |
| 6616 | pmap_enter_largepage(pmap_t pmap, vm_offset_t va, pt_entry_t newpte, int flags, |
| 6617 | int psind) |
| 6618 | { |
| 6619 | vm_page_t mp; |
| 6620 | pt_entry_t origpte, *pml4e, *pdpe, *pde, pten, PG_V; |
| 6621 | |
| 6622 | PMAP_LOCK_ASSERT(pmap, MA_OWNED); |
| 6623 | KASSERT(psind > 0 && psind < MAXPAGESIZES && pagesizes[psind] != 0, |
| 6624 | ("psind %d unexpected", psind)); |
| 6625 | KASSERT(((newpte & PG_FRAME) & (pagesizes[psind] - 1)) == 0, |
| 6626 | ("unaligned phys address %#lx newpte %#lx psind %d", |
| 6627 | newpte & PG_FRAME, newpte, psind)); |
| 6628 | KASSERT((va & (pagesizes[psind] - 1)) == 0, |
| 6629 | ("unaligned va %#lx psind %d", va, psind)); |
| 6630 | KASSERT(va < VM_MAXUSER_ADDRESS, |
| 6631 | ("kernel mode non-transparent superpage")); /* XXXKIB */ |
| 6632 | KASSERT(va + pagesizes[psind] < VM_MAXUSER_ADDRESS, |
| 6633 | ("overflowing user map va %#lx psind %d", va, psind)); /* XXXKIB */ |
| 6634 | |
| 6635 | PG_V = pmap_valid_bit(pmap); |
| 6636 | |
| 6637 | restart: |
| 6638 | if (!pmap_pkru_same(pmap, va, va + pagesizes[psind])) |
| 6639 | return (KERN_PROTECTION_FAILURE); |
| 6640 | pten = newpte; |
| 6641 | if (va < VM_MAXUSER_ADDRESS && pmap->pm_type == PT_X86) |
| 6642 | pten |= pmap_pkru_get(pmap, va); |
| 6643 | |
| 6644 | if (psind == 2) { /* 1G */ |
| 6645 | pml4e = pmap_pml4e(pmap, va); |
| 6646 | if (pml4e == NULL || (*pml4e & PG_V) == 0) { |
| 6647 | mp = pmap_allocpte_alloc(pmap, pmap_pml4e_pindex(va), |
| 6648 | NULL, va); |
| 6649 | if (mp == NULL) |
| 6650 | goto allocf; |
| 6651 | pdpe = (pdp_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(mp)); |
| 6652 | pdpe = &pdpe[pmap_pdpe_index(va)]; |
| 6653 | origpte = *pdpe; |
| 6654 | MPASS(origpte == 0); |
| 6655 | } else { |
| 6656 | pdpe = pmap_pml4e_to_pdpe(pml4e, va); |
| 6657 | KASSERT(pdpe != NULL, ("va %#lx lost pdpe", va)); |
| 6658 | origpte = *pdpe; |
| 6659 | if ((origpte & PG_V) == 0) { |
| 6660 | mp = PHYS_TO_VM_PAGE(*pml4e & PG_FRAME); |
| 6661 | mp->ref_count++; |
| 6662 | } |
| 6663 | } |
| 6664 | *pdpe = pten; |
| 6665 | } else /* (psind == 1) */ { /* 2M */ |
| 6666 | pde = pmap_pde(pmap, va); |
| 6667 | if (pde == NULL) { |
| 6668 | mp = pmap_allocpte_alloc(pmap, pmap_pdpe_pindex(va), |
| 6669 | NULL, va); |
| 6670 | if (mp == NULL) |
| 6671 | goto allocf; |
| 6672 | pde = (pd_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(mp)); |
no test coverage detected