summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2018-02-16 09:44:25 +0000
committerPatrick Mooney <pmooney@pfmooney.com>2018-03-08 19:43:16 +0000
commit2773630b0f4d38c9bd840ac5c03dbdbb2ba2ad61 (patch)
tree386ac068290b518a6d8e8a1b1aaa7049e3f6a55e
parentecbf093fc1011c08dd6f9c033e92ac8120773be3 (diff)
downloadillumos-joyent-2773630b0f4d38c9bd840ac5c03dbdbb2ba2ad61.tar.gz
OS-6636 EPT misconfiguration under VMWare Fusion
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Approved by: Patrick Mooney <patrick.mooney@joyent.com>
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c49
1 files changed, 29 insertions, 20 deletions
diff --git a/usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c b/usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c
index 0ad4ee2284..7a24c8633c 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c
@@ -76,27 +76,34 @@ typedef struct eptable_map eptable_map_t;
((tbl)->ept_vaddr + \
((idx) << LEVEL_SHIFT((tbl)->ept_level)))
-#define EPT_R (0x1 << 0)
-#define EPT_W (0x1 << 1)
-#define EPT_X (0x1 << 2)
-#define EPT_RWX (EPT_R|EPT_W|EPT_X)
-#define EPT_MAP (0x1 << 7)
+#define EPT_R (0x1 << 0)
+#define EPT_W (0x1 << 1)
+#define EPT_X (0x1 << 2)
+#define EPT_RWX (EPT_R|EPT_W|EPT_X)
+#define EPT_LGPG (0x1 << 7)
#define EPT_PAT(attr) (((attr) & 0x7) << 3)
#define EPT_PADDR (0x000ffffffffff000ull)
#define EPT_IS_ABSENT(pte) (((pte) & EPT_RWX) == 0)
-#define EPT_IS_TABLE(pte) (((pte) & EPT_MAP) == 0)
#define EPT_PTE_PFN(pte) mmu_btop((pte) & EPT_PADDR)
#define EPT_PTE_PROT(pte) ((pte) & EPT_RWX)
+#define EPT_MAPS_PAGE(lvl, pte) \
+ ((lvl) == 0 || ((pte) & EPT_LGPG))
#define EPT_PTE_ASSIGN_TABLE(pfn) \
((pfn_to_pa(pfn) & EPT_PADDR) | EPT_RWX)
-#define EPT_PTE_ASSIGN_PAGE(pfn, prot, attr) \
- ((pfn_to_pa(pfn) & EPT_PADDR) | EPT_MAP | \
- ((prot) & EPT_RWX) | \
- EPT_PAT(attr))
+
+/*
+ * We only assign EPT_LGPG for levels higher than 0: although this bit is
+ * defined as being ignored at level 0, some versions of VMWare fail to honor
+ * this and report such a PTE as an EPT mis-configuration.
+ */
+#define EPT_PTE_ASSIGN_PAGE(lvl, pfn, prot, attr) \
+ ((pfn_to_pa(pfn) & EPT_PADDR) | \
+ (((lvl) != 0) ? EPT_LGPG : 0) | \
+ EPT_PAT(attr) | ((prot) & EPT_RWX))
struct vmspace_mapping {
list_node_t vmsm_node;
@@ -584,7 +591,7 @@ eptable_walk(eptable_map_t *map, uintptr_t va, level_t tgtlvl, uint_t *idxp,
entry = EPT_PTE_ASSIGN_TABLE(newept->ept_pfn);
ptes[idx] = entry;
ept->ept_valid_cnt++;
- } else if (EPT_IS_TABLE(entry)) {
+ } else if (!EPT_MAPS_PAGE(lvl, entry)) {
/* Do lookup in next level of page table */
newept = eptable_hash_lookup(map, masked_va, lvl - 1);
@@ -597,7 +604,7 @@ eptable_walk(eptable_map_t *map, uintptr_t va, level_t tgtlvl, uint_t *idxp,
* for non-PAGESIZE pages is not yet present, this is a
* surprise.
*/
- panic("unexpected parge page in pte %p", &ptes[idx]);
+ panic("unexpected large page in pte %p", &ptes[idx]);
}
ept = newept;
lvl--;
@@ -632,10 +639,11 @@ eptable_mapin(eptable_map_t *map, uintptr_t va, pfn_t pfn, uint_t lvl,
entry = ptes[idx];
if (!EPT_IS_ABSENT(entry)) {
- if (EPT_IS_TABLE(entry)) {
- panic("unexpected table entry %lx in %p[%d]",
+ if (!EPT_MAPS_PAGE(lvl, entry)) {
+ panic("unexpected PT link %lx in %p[%d]",
entry, ept, idx);
}
+
/*
* XXXJOY: Just clean the entry for now. Assume(!) that
* invalidation is going to occur anyways.
@@ -646,7 +654,7 @@ eptable_mapin(eptable_map_t *map, uintptr_t va, pfn_t pfn, uint_t lvl,
map->em_wired -= (pgsize >> PAGESHIFT);
}
- entry = EPT_PTE_ASSIGN_PAGE(pfn, prot, attr);
+ entry = EPT_PTE_ASSIGN_PAGE(lvl, pfn, prot, attr);
ptes[idx] = entry;
ept->ept_valid_cnt++;
map->em_wired += (pgsize >> PAGESHIFT);
@@ -680,10 +688,11 @@ eptable_mapout(eptable_map_t *map, uintptr_t va)
pfn_t oldpfn;
const size_t pagesize = LEVEL_SIZE((uint_t)ept->ept_level);
- if (EPT_IS_TABLE(entry)) {
- panic("unexpected table entry %lx in %p[%d]",
+ if (!EPT_MAPS_PAGE(ept->ept_level, entry)) {
+ panic("unexpected PT link %lx in %p[%d]",
entry, ept, idx);
}
+
/*
* XXXJOY: Just clean the entry for now. Assume(!) that
* invalidation is going to occur anyways.
@@ -701,7 +710,7 @@ eptable_mapout(eptable_map_t *map, uintptr_t va)
ptes = (x86pte_t *)next->ept_kva;
entry = ptes[idx];
- ASSERT(EPT_IS_TABLE(entry));
+ ASSERT(!EPT_MAPS_PAGE(next->ept_level, entry));
ASSERT(EPT_PTE_PFN(entry) == ept->ept_pfn);
ptes[idx] = (x86pte_t)0;
@@ -737,8 +746,8 @@ eptable_find(eptable_map_t *map, uintptr_t va, pfn_t *pfn, uint_t *prot)
entry = ptes[idx];
if (!EPT_IS_ABSENT(entry)) {
- if (EPT_IS_TABLE(entry)) {
- panic("unexpected table entry %lx in %p[%d]",
+ if (!EPT_MAPS_PAGE(ept->ept_level, entry)) {
+ panic("unexpected PT link %lx in %p[%d]",
entry, ept, idx);
}