-/* $OpenBSD: pmap.c,v 1.168 2024/06/03 20:53:00 dv Exp $ */
+/* $OpenBSD: pmap.c,v 1.169 2024/07/09 19:11:06 bluhm Exp $ */
/* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */
/*
/* pg_xo: XO PTE bits, set to PKU key1 (if cpu supports PKU) */
pt_entry_t pg_xo;
+/* pg_crypt, pg_frame, pg_lgframe: will be derived from CPUID */
+pt_entry_t pg_crypt = 0;
+pt_entry_t pg_frame = PG_FRAME;
+pt_entry_t pg_lgframe = PG_LGFRAME;
+
/*
* pmap_pg_wc: if our processor supports PAT then we set this
* to be the pte bits for Write Combining. Else we fall back to
if ((pde & (PG_PS|PG_V)) != PG_V)
return (lev - 1);
- pdpa = ((*pd)[*offs] & PG_FRAME);
+ pdpa = ((*pd)[*offs] & pg_frame);
/* 4096/8 == 512 == 2^9 entries per level */
shift -= 9;
mask >>= 9;
npte = (pa & PMAP_PA_MASK) | ((prot & PROT_WRITE) ? PG_RW : PG_RO) |
((pa & PMAP_NOCACHE) ? PG_N : 0) |
- ((pa & PMAP_WC) ? pmap_pg_wc : 0) | PG_V;
+ ((pa & PMAP_WC) ? pmap_pg_wc : 0) | PG_V |
+ ((pa & PMAP_NOCRYPT) ? 0 : pg_crypt);
/* special 1:1 mappings in the first 2MB must not be global */
if (va >= (vaddr_t)NBPD_L2)
panic("%s: PG_PS", __func__);
#endif
if (pmap_valid_entry(opte)) {
- if (pa & PMAP_NOCACHE && (opte & PG_N) == 0)
+ if ((pa & PMAP_NOCACHE && (opte & PG_N) == 0) ||
+ (pa & PMAP_NOCRYPT))
wbinvd_on_all_cpus();
/* This shouldn't happen */
pmap_tlb_shootpage(pmap_kernel(), va, 1);
vaddr_t va;
pml4e = (pt_entry_t *)(proc0.p_addr->u_pcb.pcb_cr3 + KERNBASE);
- pml4e[PDIR_SLOT_EARLY] = (pd_entry_t)early_pte_pages | PG_V | PG_RW;
+ pml4e[PDIR_SLOT_EARLY] = (pd_entry_t)early_pte_pages | PG_V | PG_RW |
+ pg_crypt;
off = pa & PAGE_MASK_L2;
curpa = pa & L2_FRAME;
pte = (pt_entry_t *)PMAP_DIRECT_MAP(early_pte_pages);
memset(pte, 0, 3 * NBPG);
- pte[0] = (early_pte_pages + NBPG) | PG_V | PG_RW;
- pte[1] = (early_pte_pages + 2 * NBPG) | PG_V | PG_RW;
+ pte[0] = (early_pte_pages + NBPG) | PG_V | PG_RW | pg_crypt;
+ pte[1] = (early_pte_pages + 2 * NBPG) | PG_V | PG_RW | pg_crypt;
pte = (pt_entry_t *)PMAP_DIRECT_MAP(early_pte_pages + NBPG);
for (i = 0; i < 2; i++) {
/* 2 early pages of mappings */
for (j = 0; j < 512; j++) {
/* j[0..511] : 2MB mappings per page */
- pte[(i * 512) + j] = curpa | PG_V | PG_RW | PG_PS;
+ pte[(i * 512) + j] = curpa | PG_V | PG_RW | PG_PS |
+ pg_crypt;
curpa += (2 * 1024 * 1024);
}
}
if (ndmpdp > 512)
ndmpdp = 512; /* At most 512GB */
- dmpdp = kpm->pm_pdir[PDIR_SLOT_DIRECT] & PG_FRAME;
+ dmpdp = kpm->pm_pdir[PDIR_SLOT_DIRECT] & pg_frame;
dmpd = first_avail; first_avail += ndmpdp * PAGE_SIZE;
*((pd_entry_t *)va) = ((paddr_t)i << L2_SHIFT);
*((pd_entry_t *)va) |= PG_RW | PG_V | PG_PS | pg_g_kern | PG_U |
- PG_M | pg_nx;
+ PG_M | pg_nx | pg_crypt;
}
for (i = NDML2_ENTRIES; i < ndmpdp; i++) {
va = PMAP_DIRECT_MAP(pdp);
*((pd_entry_t *)va) = dmpd + (i << PAGE_SHIFT);
- *((pd_entry_t *)va) |= PG_RW | PG_V | PG_U | PG_M | pg_nx;
+ *((pd_entry_t *)va) |= PG_RW | PG_V | PG_U | PG_M | pg_nx |
+ pg_crypt;
}
kpm->pm_pdir[PDIR_SLOT_DIRECT] = dmpdp | PG_V | PG_KW | PG_U |
- PG_M | pg_nx;
+ PG_M | pg_nx | pg_crypt;
/* Map any remaining physical memory > 512GB */
for (curslot = 1 ; curslot < NUM_L4_SLOT_DIRECT ; curslot++) {
dmpd = first_avail; first_avail += PAGE_SIZE;
pml3 = (pt_entry_t *)PMAP_DIRECT_MAP(dmpd);
kpm->pm_pdir[PDIR_SLOT_DIRECT + curslot] = dmpd |
- PG_KW | PG_V | PG_U | PG_M | pg_nx;
+ PG_KW | PG_V | PG_U | PG_M | pg_nx | pg_crypt;
/* Calculate full 1GB pages in this 512GB region */
p = ((max_pa - start_cur) >> L3_SHIFT);
dmpd = first_avail; first_avail += PAGE_SIZE;
pml2 = (pt_entry_t *)PMAP_DIRECT_MAP(dmpd);
pml3[i] = dmpd |
- PG_RW | PG_V | PG_U | PG_M | pg_nx;
+ PG_RW | PG_V | PG_U | PG_M | pg_nx |
+ pg_crypt;
cur_pa = start_cur + (i << L3_SHIFT);
j = 0;
(uint64_t)i * NBPD_L3 +
(uint64_t)j * NBPD_L2;
pml2[j] |= PG_RW | PG_V | pg_g_kern |
- PG_U | PG_M | pg_nx | PG_PS;
+ PG_U | PG_M | pg_nx | PG_PS |
+ pg_crypt;
cur_pa += NBPD_L2;
j++;
}
proc0.p_addr->u_pcb.pcb_cr3 = pml4pa;
/* Fixup recursive PTE PML4E slot. We are only changing the PA */
- pml4va[PDIR_SLOT_PTE] = pml4pa | (pml4va[PDIR_SLOT_PTE] & ~PG_FRAME);
+ pml4va[PDIR_SLOT_PTE] = pml4pa | (pml4va[PDIR_SLOT_PTE] & ~pg_frame);
for (i = 0; i < NPDPG; i++) {
/* PTE slot already handled earlier */
if (i == PDIR_SLOT_PTE)
continue;
- if (pml4va[i] & PG_FRAME)
+ if (pml4va[i] & pg_frame)
pmap_randomize_level(&pml4va[i], 3);
}
panic("%s: cannot allocate page for L%d page directory",
__func__, level);
- old_pd_pa = *pde & PG_FRAME;
+ old_pd_pa = *pde & pg_frame;
old_pd_va = PMAP_DIRECT_MAP(old_pd_pa);
pmap_extract(pmap_kernel(), (vaddr_t)new_pd_va, &new_pd_pa);
memcpy(new_pd_va, (void *)old_pd_va, PAGE_SIZE);
- *pde = new_pd_pa | (*pde & ~PG_FRAME);
+ *pde = new_pd_pa | (*pde & ~pg_frame);
tlbflush();
memset((void *)old_pd_va, 0, PAGE_SIZE);
}
for (i = 0; i < NPDPG; i++)
- if (new_pd_va[i] & PG_FRAME)
+ if (new_pd_va[i] & pg_frame)
pmap_randomize_level(&new_pd_va[i], level - 1);
}
for (;;) {
newp = first_avail; first_avail += PAGE_SIZE;
memset((void *)PMAP_DIRECT_MAP(newp), 0, PAGE_SIZE);
- pdes[pl_i(0, level)] = (newp & PG_FRAME) | PG_V | PG_RW;
+ pdes[pl_i(0, level)] =
+ (newp & pg_frame) | PG_V | PG_RW | pg_crypt;
level--;
if (level <= 1)
break;
pva = normal_pdes[i - 2];
if (pmap_valid_entry(pva[index])) {
- ppa = pva[index] & PG_FRAME;
+ ppa = pva[index] & pg_frame;
ptp = NULL;
continue;
}
ptp->wire_count = 1;
pmap->pm_ptphint[i - 2] = ptp;
pa = VM_PAGE_TO_PHYS(ptp);
- pva[index] = (pd_entry_t) (pa | PG_u | PG_RW | PG_V);
+ pva[index] = (pd_entry_t) (pa | PG_u | PG_RW | PG_V | pg_crypt);
/*
* Meltdown Special case - if we are adding a new PML4e for
memset(pdir, 0, PDIR_SLOT_PTE * sizeof(pd_entry_t));
/* put in recursive PDE to map the PTEs */
- pdir[PDIR_SLOT_PTE] = pdirpa | PG_V | PG_KW | pg_nx;
+ pdir[PDIR_SLOT_PTE] = pdirpa | PG_V | PG_KW | pg_nx | pg_crypt;
npde = nkptp[PTP_LEVELS - 1];
pmap->pm_pdir = pool_get(&pmap_pdp_pool, PR_WAITOK);
pmap_pdp_ctor(pmap->pm_pdir);
- pmap->pm_pdirpa = pmap->pm_pdir[PDIR_SLOT_PTE] & PG_FRAME;
+ pmap->pm_pdirpa = pmap->pm_pdir[PDIR_SLOT_PTE] & pg_frame;
/*
* Intel CPUs need a special page table to be used during usermode
if (__predict_true(level == 0 && pmap_valid_entry(pte))) {
if (pap != NULL)
- *pap = (pte & PG_FRAME) | (va & PAGE_MASK);
+ *pap = (pte & pg_frame) | (va & PAGE_MASK);
return 1;
}
if (level == 1 && (pte & (PG_PS|PG_V)) == (PG_PS|PG_V)) {
if (pap != NULL)
- *pap = (pte & PG_LGFRAME) | (va & PAGE_MASK_L2);
+ *pap = (pte & pg_lgframe) | (va & PAGE_MASK_L2);
return 1;
}
if (ptp != NULL)
ptp->wire_count--; /* dropping a PTE */
- pg = PHYS_TO_VM_PAGE(opte & PG_FRAME);
+ pg = PHYS_TO_VM_PAGE(opte & pg_frame);
/*
* if we are not on a pv list we are done.
if (ptp != NULL)
ptp->wire_count--; /* dropping a PTE */
- pg = PHYS_TO_VM_PAGE(opte & PG_FRAME);
+ pg = PHYS_TO_VM_PAGE(opte & pg_frame);
/*
* if we are not on a pv list we are done.
if (pmap_pdes_valid(sva, &pde)) {
/* PA of the PTP */
- ptppa = pde & PG_FRAME;
+ ptppa = pde & pg_frame;
/* get PTP if non-kernel mapping */
continue;
/* PA of the PTP */
- ptppa = pde & PG_FRAME;
+ ptppa = pde & pg_frame;
/* get PTP if non-kernel mapping */
if (pmap == pmap_kernel()) {
#ifdef DIAGNOSTIC
if (pve->pv_ptp != NULL && pmap_pdes_valid(pve->pv_va, &pde) &&
- (pde & PG_FRAME) != VM_PAGE_TO_PHYS(pve->pv_ptp)) {
+ (pde & pg_frame) != VM_PAGE_TO_PHYS(pve->pv_ptp)) {
printf("%s: pg=%p: va=%lx, pv_ptp=%p\n", __func__,
pg, pve->pv_va, pve->pv_ptp);
printf("%s: PTP's phys addr: "
"actual=%lx, recorded=%lx\n", __func__,
- (unsigned long)(pde & PG_FRAME),
+ (unsigned long)(pde & pg_frame),
VM_PAGE_TO_PHYS(pve->pv_ptp));
panic("%s: mapped managed page has "
"invalid pv_ptp field", __func__);
shootself = (scr3 == 0);
/* should be ok, but just in case ... */
- sva &= PG_FRAME;
- eva &= PG_FRAME;
+ sva &= pg_frame;
+ eva &= pg_frame;
if (!(prot & PROT_READ))
set |= pg_xo;
if (!pmap_extract(pmap, (vaddr_t)ptp, &npa))
panic("%s: can't locate PDPT page", __func__);
- pd[l4idx] = (npa | PG_RW | PG_V);
+ pd[l4idx] = (npa | PG_RW | PG_V | pg_crypt);
DPRINTF("%s: allocated new PDPT page at phys 0x%llx, "
"setting PML4e[%lld] = 0x%llx\n", __func__,
if (!pmap_extract(pmap, (vaddr_t)ptp, &npa))
panic("%s: can't locate PD page", __func__);
- pd[l3idx] = (npa | PG_RW | PG_V);
+ pd[l3idx] = (npa | PG_RW | PG_V | pg_crypt);
DPRINTF("%s: allocated new PD page at phys 0x%llx, "
"setting PDPTe[%lld] = 0x%llx\n", __func__,
if (!pmap_extract(pmap, (vaddr_t)ptp, &npa))
panic("%s: can't locate PT page", __func__);
- pd[l2idx] = (npa | PG_RW | PG_V);
+ pd[l2idx] = (npa | PG_RW | PG_V | pg_crypt);
DPRINTF("%s: allocated new PT page at phys 0x%llx, "
"setting PDE[%lld] = 0x%llx\n", __func__,
"0x%llx was 0x%llx\n", __func__, (uint64_t)npa, (uint64_t)pd,
(uint64_t)prot, (uint64_t)pd[l1idx]);
- pd[l1idx] = pa | protection_codes[prot] | PG_V | PG_W;
+ pd[l1idx] = pa | protection_codes[prot] | PG_V | PG_W | pg_crypt;
/*
* Look up the corresponding U+K entry. If we're installing the
*/
level = pmap_find_pte_direct(pmap, va, &ptes, &offs);
if (__predict_true(level == 0 && pmap_valid_entry(ptes[offs]))) {
- if (((pd[l1idx] ^ ptes[offs]) & PG_FRAME) == 0) {
+ if (((pd[l1idx] ^ ptes[offs]) & pg_frame) == 0) {
pd[l1idx] |= PG_G | (ptes[offs] & (PG_N | PG_WT));
ptes[offs] |= PG_G;
} else {
struct pv_entry *pve, *opve = NULL;
int ptpdelta, wireddelta, resdelta;
int wired = (flags & PMAP_WIRED) != 0;
+ int crypt = (flags & PMAP_NOCRYPT) == 0;
int nocache = (pa & PMAP_NOCACHE) != 0;
int wc = (pa & PMAP_WC) != 0;
int error, shootself;
* want to map?
*/
- if ((opte & PG_FRAME) == pa) {
+ if ((opte & pg_frame) == pa) {
/* if this is on the PVLIST, sync R/M bit */
if (opte & PG_PVLIST) {
*/
if (opte & PG_PVLIST) {
- pg = PHYS_TO_VM_PAGE(opte & PG_FRAME);
+ pg = PHYS_TO_VM_PAGE(opte & pg_frame);
#ifdef DIAGNOSTIC
if (pg == NULL)
panic("%s: PG_PVLIST mapping with unmanaged "
npte |= (PG_u | PG_RW); /* XXXCDC: no longer needed? */
if (pmap == pmap_kernel())
npte |= pg_g_kern;
+ if (crypt)
+ npte |= pg_crypt;
/*
* If the old entry wasn't valid, we can just update it and
for (i = index; i <= endindex; i++) {
pmap_get_physpage(va, level - 1, &pa);
- pdep[i] = pa | PG_RW | PG_V | pg_nx;
+ pdep[i] = pa | PG_RW | PG_V | pg_nx | pg_crypt;
nkptp[level - 1]++;
va += nbpd[level - 1];
}