summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2015-11-10 08:57:40 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2015-11-10 08:57:40 +0000
commit77e546ae9d4227c67af7a405615b766a51e93a8d (patch)
treed65e95a6501bb5c4246bed9916c366b95a8fd8e1 /sys/arch
parent0863918b990802d849eb2d81fe9514065d591473 (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')
-rw-r--r--sys/arch/amd64/amd64/pmap.c95
-rw-r--r--sys/arch/amd64/include/pmap.h10
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