diff options
author | Mike Larkin <mlarkin@cvs.openbsd.org> | 2015-11-10 08:57:40 +0000 |
---|---|---|
committer | Mike Larkin <mlarkin@cvs.openbsd.org> | 2015-11-10 08:57:40 +0000 |
commit | 77e546ae9d4227c67af7a405615b766a51e93a8d (patch) | |
tree | d65e95a6501bb5c4246bed9916c366b95a8fd8e1 /sys/arch/amd64 | |
parent | 0863918b990802d849eb2d81fe9514065d591473 (diff) |
pmap changes required for vmm. Changes include addition of pm_type to
track type of pmap and various conversion and pte bit manipulation
functions for EPT.
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r-- | sys/arch/amd64/amd64/pmap.c | 95 | ||||
-rw-r--r-- | sys/arch/amd64/include/pmap.h | 10 |
2 files changed, 103 insertions, 2 deletions
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c index 286adbbff14..bb26a571a9e 100644 --- a/sys/arch/amd64/amd64/pmap.c +++ b/sys/arch/amd64/amd64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.96 2015/09/08 21:28:35 kettenis Exp $ */ +/* $OpenBSD: pmap.c,v 1.97 2015/11/10 08:57:39 mlarkin Exp $ */ /* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */ /* @@ -403,6 +403,68 @@ pmap_unmap_ptes(struct pmap *pmap, paddr_t save_cr3) } } +/* + * pmap_fix_ept + * + * Fixes up an EPT PTE for vaddr 'va' by reconfiguring the low bits to + * conform to the EPT format (separate R/W/X bits and various "must be + * 0 bits") + * + * Parameters: + * pm: The pmap in question + * va: The VA to fix up + * offs: (out) return the offset into the PD/PT for this va + * + * Return value: + * int value corresponding to the level this VA was found + */ +int +pmap_fix_ept(struct pmap *pm, vaddr_t va, int *offs) +{ + u_long mask, shift; + pd_entry_t pde, *pd; + paddr_t pdpa; + int lev; + + pdpa = pm->pm_pdirpa; + shift = L4_SHIFT; + mask = L4_MASK; + for (lev = PTP_LEVELS; lev > 0; lev--) { + pd = (pd_entry_t *)PMAP_DIRECT_MAP(pdpa); + *offs = (VA_SIGN_POS(va) & mask) >> shift; + + pd[*offs] |= EPT_R | EPT_W | EPT_X; + /* + * Levels 3-4 have bits 3:7 'must be 0' + * Level 2 has bits 3:6 'must be 0', and bit 7 is always + * 0 in our EPT format (thus, bits 3:7 == 0) + */ + switch(lev) { + case 4: + case 3: + case 2: + /* Bits 3:7 = 0 */ + pd[*offs] &= ~(0xF8); + break; + case 1: pd[*offs] |= EPT_WB; + break; + } + + pde = pd[*offs]; + + /* Large pages are different, break early if we run into one. */ + if ((pde & (PG_PS|PG_V)) != PG_V) + return (lev - 1); + + pdpa = (pd[*offs] & PG_FRAME); + /* 4096/8 == 512 == 2^9 entries per level */ + shift -= 9; + mask >>= 9; + } + + return (0); +} + int pmap_find_pte_direct(struct pmap *pm, vaddr_t va, pt_entry_t **pd, int *offs) { @@ -585,6 +647,8 @@ pmap_bootstrap(paddr_t first_avail, paddr_t max_pa) kpm->pm_stats.wired_count = kpm->pm_stats.resident_count = atop(kva_start - VM_MIN_KERNEL_ADDRESS); + kpm->pm_type = PMAP_TYPE_NORMAL; + /* * the above is just a rough estimate and not critical to the proper * operation of the system. @@ -1023,6 +1087,7 @@ pmap_create(void) pmap->pm_stats.wired_count = 0; pmap->pm_stats.resident_count = 1; /* count the PDP allocd below */ pmap->pm_cpus = 0; + pmap->pm_type = PMAP_TYPE_NORMAL; /* allocate PDP */ @@ -2392,6 +2457,34 @@ pmap_virtual_space(vaddr_t *vstartp, vaddr_t *vendp) *vendp = VM_MAX_KERNEL_ADDRESS; } +/* + * pmap_convert + * + * Converts 'pmap' to the new 'mode'. + * + * Parameters: + * pmap: the pmap to convert + * mode: the new mode (see pmap.h, PMAP_TYPE_xxx) + * + * Return value: + * always 0 + */ +int +pmap_convert(struct pmap *pmap, int mode) +{ + pt_entry_t *pte; + + pmap->pm_type = mode; + + if (mode == PMAP_TYPE_EPT) { + /* Clear low 512GB region (first PML4E) */ + pte = (pt_entry_t *)pmap->pm_pdir; + *pte = 0; + } + + return (0); +} + #ifdef MULTIPROCESSOR /* * Locking for tlb shootdown. diff --git a/sys/arch/amd64/include/pmap.h b/sys/arch/amd64/include/pmap.h index bbf24bf1f22..aaa9638984f 100644 --- a/sys/arch/amd64/include/pmap.h +++ b/sys/arch/amd64/include/pmap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.h,v 1.59 2015/08/22 07:19:03 mlarkin Exp $ */ +/* $OpenBSD: pmap.h,v 1.60 2015/11/10 08:57:39 mlarkin Exp $ */ /* $NetBSD: pmap.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */ /* @@ -274,6 +274,11 @@ LIST_HEAD(pmap_head, pmap); /* struct pmap_head: head of a pmap list */ * page list, and number of PTPs within the pmap. */ +#define PMAP_TYPE_NORMAL 1 +#define PMAP_TYPE_EPT 2 +#define PMAP_TYPE_RVI 3 +#define pmap_nested(pm) ((pm)->pm_type != PMAP_TYPE_NORMAL) + struct pmap { struct mutex pm_mtx; struct uvm_object pm_obj[PTP_LEVELS-1]; /* objects for lvl >= 1) */ @@ -285,6 +290,7 @@ struct pmap { struct pmap_statistics pm_stats; /* pmap stats (lck by object lock) */ u_int64_t pm_cpus; /* mask of CPUs using pmap */ + int pm_type; /* Type of pmap this is (PMAP_TYPE_x) */ }; /* @@ -370,6 +376,8 @@ paddr_t pmap_prealloc_lowmem_ptps(paddr_t); void pagezero(vaddr_t); +int pmap_convert(struct pmap *, int); + /* * functions for flushing the cache for vaddrs and pages. * these functions are not part of the MI pmap interface and thus |