[kvm-unit-tests PATCH 11/39] x86/access: Use upper half of virtual address space

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Use the upper half of the virtual address space so that 5-level paging
doesn't collide with the core infrastucture in the top-level PTE, which
hides bugs, e.g. SMEP + 5-level, and is generally a nightmare to debug.

Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
 x86/access.c | 50 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 30 insertions(+), 20 deletions(-)

diff --git a/x86/access.c b/x86/access.c
index 5bd446c..6ccdb76 100644
--- a/x86/access.c
+++ b/x86/access.c
@@ -34,7 +34,7 @@ static int invalid_mask;
 #define EFER_NX_MASK            (1ull << 11)
 
 #define PT_INDEX(address, level)       \
-	  ((address) >> (12 + ((level)-1) * 9)) & 511
+	  (((address) >> (12 + ((level)-1) * 9)) & 511)
 
 /*
  * page table access check tests
@@ -340,12 +340,21 @@ static void ac_test_reset_pt_pool(ac_pt_env_t *pt_env)
 	pt_env->pt_pool_current = 0;
 }
 
-static void ac_test_init(ac_test_t *at, void *virt, ac_pt_env_t *pt_env)
+static void ac_test_init(ac_test_t *at, unsigned long virt, ac_pt_env_t *pt_env)
 {
+	/*
+	 * The KUT infrastructure, e.g. this function, must use a different
+	 * top-level SPTE than the test, otherwise modifying SPTEs can affect
+	 * normal behavior, e.g. crash the test due to marking code SPTEs
+	 * USER when CR4.SMEP=1.
+	 */
+	assert(PT_INDEX(virt, pt_env->pt_levels) !=
+	       PT_INDEX((unsigned long)ac_test_init, pt_env->pt_levels));
+
 	set_efer_nx(1);
 	set_cr0_wp(1);
 	at->flags = 0;
-	at->virt = virt;
+	at->virt = (void *)virt;
 	at->phys = AT_CODE_DATA_PHYS;
 	at->pt_levels = pt_env->pt_levels;
 }
@@ -571,12 +580,13 @@ static void __ac_setup_specific_pages(ac_test_t *at, ac_pt_env_t *pt_env, bool r
 		pt_element_t pte;
 
 		/*
-		 * Reuse existing page tables along the path to the test code and data
-		 * (which is in the bottom 2MB).
+		 * Reuse existing page tables along the highest index, some
+		 * tests rely on sharing upper level paging structures between
+		 * two separate sub-tests.
 		 */
-		if (skip && i >= 2 && index == 0) {
+		if (skip && i >= 2 && index == 511 && (*ptep & PT_PRESENT_MASK))
 			goto next;
-		}
+
 		skip = false;
 		if (reuse && *ptep) {
 			switch (i) {
@@ -863,8 +873,8 @@ static int corrupt_hugepage_triger(ac_pt_env_t *pt_env)
 {
 	ac_test_t at1, at2;
 
-	ac_test_init(&at1, (void *)(0x123400000000), pt_env);
-	ac_test_init(&at2, (void *)(0x666600000000), pt_env);
+	ac_test_init(&at1, 0xffff923400000000ul, pt_env);
+	ac_test_init(&at2, 0xffffe66600000000ul, pt_env);
 
 	at2.flags = AC_CPU_CR0_WP_MASK | AC_PDE_PSE_MASK | AC_PDE_PRESENT_MASK;
 	ac_test_setup_pte(&at2, pt_env);
@@ -901,8 +911,8 @@ static int check_pfec_on_prefetch_pte(ac_pt_env_t *pt_env)
 {
 	ac_test_t at1, at2;
 
-	ac_test_init(&at1, (void *)(0x123406001000), pt_env);
-	ac_test_init(&at2, (void *)(0x123406003000), pt_env);
+	ac_test_init(&at1, 0xffff923406001000ul, pt_env);
+	ac_test_init(&at2, 0xffff923406003000ul, pt_env);
 
 	at1.flags = AC_PDE_PRESENT_MASK | AC_PTE_PRESENT_MASK;
 	ac_setup_specific_pages(&at1, pt_env, 30 * 1024 * 1024, 30 * 1024 * 1024);
@@ -946,8 +956,8 @@ static int check_large_pte_dirty_for_nowp(ac_pt_env_t *pt_env)
 {
 	ac_test_t at1, at2;
 
-	ac_test_init(&at1, (void *)(0x123403000000), pt_env);
-	ac_test_init(&at2, (void *)(0x666606000000), pt_env);
+	ac_test_init(&at1, 0xffff923403000000ul, pt_env);
+	ac_test_init(&at2, 0xffffe66606000000ul, pt_env);
 
 	at2.flags = AC_PDE_PRESENT_MASK | AC_PDE_PSE_MASK;
 	ac_test_setup_pte(&at2, pt_env);
@@ -985,7 +995,7 @@ static int check_smep_andnot_wp(ac_pt_env_t *pt_env)
 		return 1;
 	}
 
-	ac_test_init(&at1, (void *)(0x123406001000), pt_env);
+	ac_test_init(&at1, 0xffff923406001000ul, pt_env);
 
 	at1.flags = AC_PDE_PRESENT_MASK | AC_PTE_PRESENT_MASK |
 		    AC_PDE_USER_MASK | AC_PTE_USER_MASK |
@@ -1028,7 +1038,7 @@ err:
 
 static int check_effective_sp_permissions(ac_pt_env_t *pt_env)
 {
-	unsigned long ptr1 = 0x123480000000;
+	unsigned long ptr1 = 0xffff923480000000;
 	unsigned long ptr2 = ptr1 + SZ_2M;
 	unsigned long ptr3 = ptr1 + SZ_1G;
 	unsigned long ptr4 = ptr3 + SZ_2M;
@@ -1047,22 +1057,22 @@ static int check_effective_sp_permissions(ac_pt_env_t *pt_env)
 	 * pud1 and pud2 point to the same pmd page.
 	 */
 
-	ac_test_init(&at1, (void *)(ptr1), pt_env);
+	ac_test_init(&at1, ptr1, pt_env);
 	at1.flags = AC_PDE_PRESENT_MASK | AC_PTE_PRESENT_MASK |
 		    AC_PDE_USER_MASK | AC_PTE_USER_MASK |
 		    AC_PDE_ACCESSED_MASK | AC_PTE_ACCESSED_MASK |
 		    AC_PTE_WRITABLE_MASK | AC_ACCESS_USER_MASK;
 	__ac_setup_specific_pages(&at1, pt_env, false, pmd, 0);
 
-	ac_test_init(&at2, (void *)(ptr2), pt_env);
+	ac_test_init(&at2, ptr2, pt_env);
 	at2.flags = at1.flags | AC_PDE_WRITABLE_MASK | AC_PTE_DIRTY_MASK | AC_ACCESS_WRITE_MASK;
 	__ac_setup_specific_pages(&at2, pt_env, true, pmd, 0);
 
-	ac_test_init(&at3, (void *)(ptr3), pt_env);
+	ac_test_init(&at3, ptr3, pt_env);
 	at3.flags = AC_PDPTE_NO_WRITABLE_MASK | at1.flags;
 	__ac_setup_specific_pages(&at3, pt_env, true, pmd, 0);
 
-	ac_test_init(&at4, (void *)(ptr4), pt_env);
+	ac_test_init(&at4, ptr4, pt_env);
 	at4.flags = AC_PDPTE_NO_WRITABLE_MASK | at2.flags;
 	__ac_setup_specific_pages(&at4, pt_env, true, pmd, 0);
 
@@ -1139,7 +1149,7 @@ int ac_test_run(int pt_levels)
 	}
 
 	ac_env_int(&pt_env, pt_levels);
-	ac_test_init(&at, (void *)(0x123400000000), &pt_env);
+	ac_test_init(&at, 0xffff923400000000ul, &pt_env);
 
 	if (this_cpu_has(X86_FEATURE_PKU)) {
 		set_cr4_pke(1);
-- 
2.34.0.rc2.393.gf8c9666880-goog




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux