Migrate to new vmx.h's EPT violation defs, which makes it easier to grok from one code base to another. Fix a few small formatting issues along the way. No functional change intended. Signed-off-by: Jon Kohler --- x86/vmx.h | 11 ----- x86/vmx_tests.c | 127 +++++++++++++++++++++++++++++------------------- 2 files changed, 77 insertions(+), 61 deletions(-) diff --git a/x86/vmx.h b/x86/vmx.h index 41346252..9b076b0c 100644 --- a/x86/vmx.h +++ b/x86/vmx.h @@ -618,17 +618,6 @@ enum Intr_type { #define EPT_ADDR_MASK GENMASK_ULL(51, 12) #define PAGE_MASK_2M (~(PAGE_SIZE_2M-1)) -#define EPT_VLT_RD (1ull << 0) -#define EPT_VLT_WR (1ull << 1) -#define EPT_VLT_FETCH (1ull << 2) -#define EPT_VLT_PERM_RD (1ull << 3) -#define EPT_VLT_PERM_WR (1ull << 4) -#define EPT_VLT_PERM_EX (1ull << 5) -#define EPT_VLT_PERM_USER_EX (1ull << 6) -#define EPT_VLT_PERMS (EPT_VLT_PERM_RD | EPT_VLT_PERM_WR | \ - EPT_VLT_PERM_EX) -#define EPT_VLT_LADDR_VLD (1ull << 7) -#define EPT_VLT_PADDR (1ull << 8) #define EPT_VLT_GUEST_USER (1ull << 9) #define EPT_VLT_GUEST_RW (1ull << 10) #define EPT_VLT_GUEST_EX (1ull << 11) diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index dbcb6cae..a09b687f 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -1443,8 +1443,9 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) check_ept_ad(pml4, guest_cr3, (unsigned long)data_page1, 0, have_ad ? EPT_ACCESS_FLAG | EPT_DIRTY_FLAG : 0); clear_ept_ad(pml4, guest_cr3, (unsigned long)data_page1); - if (exit_qual == (EPT_VLT_WR | EPT_VLT_LADDR_VLD | - EPT_VLT_PADDR)) + if (exit_qual == (EPT_VIOLATION_ACC_WRITE | + EPT_VIOLATION_GVA_IS_VALID | + EPT_VIOLATION_GVA_TRANSLATED)) vmx_inc_test_stage(); set_ept_pte(pml4, (unsigned long)data_page1, 1, data_page1_pte | (EPT_PRESENT)); @@ -1454,16 +1455,16 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) check_ept_ad(pml4, guest_cr3, (unsigned long)data_page1, 0, have_ad ? EPT_ACCESS_FLAG | EPT_DIRTY_FLAG : 0); clear_ept_ad(pml4, guest_cr3, (unsigned long)data_page1); - if (exit_qual == (EPT_VLT_RD | - (have_ad ? EPT_VLT_WR : 0) | - EPT_VLT_LADDR_VLD)) + if (exit_qual == (EPT_VIOLATION_ACC_READ | + (have_ad ? EPT_VIOLATION_ACC_WRITE : 0) | + EPT_VIOLATION_GVA_IS_VALID)) vmx_inc_test_stage(); set_ept_pte(pml4, guest_pte_addr, 2, data_page1_pte_pte | (EPT_PRESENT)); invept(INVEPT_SINGLE, eptp); break; case 5: - if (exit_qual & EPT_VLT_RD) + if (exit_qual & EPT_VIOLATION_ACC_READ) vmx_inc_test_stage(); TEST_ASSERT(get_ept_pte(pml4, (unsigned long)pci_physaddr, 1, &memaddr_pte)); @@ -1471,7 +1472,7 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) invept(INVEPT_SINGLE, eptp); break; case 6: - if (exit_qual & EPT_VLT_WR) + if (exit_qual & EPT_VIOLATION_ACC_WRITE) vmx_inc_test_stage(); TEST_ASSERT(get_ept_pte(pml4, (unsigned long)pci_physaddr, 1, &memaddr_pte)); @@ -2283,14 +2284,14 @@ do { \ (expected & flag) ? "" : "un"); \ } while (0) - DIAGNOSE(EPT_VLT_RD); - DIAGNOSE(EPT_VLT_WR); - DIAGNOSE(EPT_VLT_FETCH); - DIAGNOSE(EPT_VLT_PERM_RD); - DIAGNOSE(EPT_VLT_PERM_WR); - DIAGNOSE(EPT_VLT_PERM_EX); - DIAGNOSE(EPT_VLT_LADDR_VLD); - DIAGNOSE(EPT_VLT_PADDR); + DIAGNOSE(EPT_VIOLATION_ACC_READ); + DIAGNOSE(EPT_VIOLATION_ACC_WRITE); + DIAGNOSE(EPT_VIOLATION_ACC_INSTR); + DIAGNOSE(EPT_VIOLATION_PROT_READ); + DIAGNOSE(EPT_VIOLATION_PROT_WRITE); + DIAGNOSE(EPT_VIOLATION_PROT_EXEC); + DIAGNOSE(EPT_VIOLATION_GVA_IS_VALID); + DIAGNOSE(EPT_VIOLATION_GVA_TRANSLATED); #undef DIAGNOSE } @@ -2357,7 +2358,7 @@ static void do_ept_violation(bool leaf, enum ept_access_op op, /* Mask undefined bits (which may later be defined in certain cases). */ qual &= ~(EPT_VLT_GUEST_USER | EPT_VLT_GUEST_RW | EPT_VLT_GUEST_EX | - EPT_VLT_PERM_USER_EX); + EPT_VIOLATION_EXEC_FOR_RING3_LIN); diagnose_ept_violation_qual(expected_qual, qual); TEST_EXPECT_EQ(expected_qual, qual); @@ -2419,18 +2420,20 @@ static void ept_access_violation(unsigned long access, enum ept_access_op op, u64 expected_qual) { ept_violation(EPT_PRESENT, access, op, - expected_qual | EPT_VLT_LADDR_VLD | EPT_VLT_PADDR); + expected_qual | EPT_VIOLATION_GVA_IS_VALID | + EPT_VIOLATION_GVA_TRANSLATED); } /* * For translations that don't involve a GVA, that is physical address (paddr) - * accesses, EPT violations don't set the flag EPT_VLT_PADDR. For a typical - * guest memory access, the hardware does GVA -> GPA -> HPA. However, certain - * translations don't involve GVAs, such as when the hardware does the guest - * page table walk. For example, in translating GVA_1 -> GPA_1, the guest MMU - * might try to set an A bit on a guest PTE. If the GPA_2 that the PTE resides - * on isn't present in the EPT, then the EPT violation will be for GPA_2 and - * the EPT_VLT_PADDR bit will be clear in the exit qualification. + * accesses, EPT violations don't set the flag EPT_VIOLATION_GVA_TRANSLATED. + * For a typical guest memory access, the hardware does GVA -> GPA -> HPA. + * However, certain translations don't involve GVAs, such as when the hardware + * does the guest page table walk. For example, in translating GVA_1 -> GPA_1, + * the guest MMU might try to set an A bit on a guest PTE. If the GPA_2 that + * the PTE resides on isn't present in the EPT, then the EPT violation will be + * for GPA_2 and the EPT_VIOLATION_GVA_TRANSLATED bit will be clear in the exit + * qualification. * * Note that paddr violations can also be triggered by loading PAE page tables * with wonky addresses. We don't test that yet. @@ -2449,7 +2452,7 @@ static void ept_access_violation(unsigned long access, enum ept_access_op op, * Is a violation expected during the paddr access? * * @expected_qual Expected qualification for the EPT violation. - * EPT_VLT_PADDR should be clear. + * EPT_VIOLATION_GVA_TRANSLATED should be clear. */ static void ept_access_paddr(unsigned long ept_access, unsigned long pte_ad, enum ept_access_op op, bool expect_violation, @@ -2492,7 +2495,7 @@ static void ept_access_paddr(unsigned long ept_access, unsigned long pte_ad, if (expect_violation) { do_ept_violation(/*leaf=*/true, op, - expected_qual | EPT_VLT_LADDR_VLD, gpa); + expected_qual | EPT_VIOLATION_GVA_IS_VALID, gpa); ept_untwiddle(gpa, /*level=*/1, orig_epte); do_ept_access_op(op); } else { @@ -2611,9 +2614,10 @@ static void ept_misconfig_at_level_mkhuge_op(bool mkhuge, int level, /* * broken: * According to description of exit qual for EPT violation, - * EPT_VLT_LADDR_VLD indicates if GUEST_LINEAR_ADDRESS is valid. + * EPT_VIOLATION_GVA_IS_VALID indicates if GUEST_LINEAR_ADDRESS is + * valid. * However, I can't find anything that says GUEST_LINEAR_ADDRESS ought - * to be set for msiconfig. + * to be set for misconfig. */ TEST_EXPECT_EQ(vmcs_read(GUEST_LINEAR_ADDRESS), (unsigned long) ( @@ -2664,7 +2668,9 @@ static void ept_reserved_bit_at_level_nohuge(int level, int bit) /* Making the entry non-present turns reserved bits into ignored. */ ept_violation_at_level(level, EPT_PRESENT, 1ul << bit, OP_READ, - EPT_VLT_RD | EPT_VLT_LADDR_VLD | EPT_VLT_PADDR); + EPT_VIOLATION_ACC_READ | + EPT_VIOLATION_GVA_IS_VALID | + EPT_VIOLATION_GVA_TRANSLATED); } static void ept_reserved_bit_at_level_huge(int level, int bit) @@ -2674,7 +2680,9 @@ static void ept_reserved_bit_at_level_huge(int level, int bit) /* Making the entry non-present turns reserved bits into ignored. */ ept_violation_at_level(level, EPT_PRESENT, 1ul << bit, OP_READ, - EPT_VLT_RD | EPT_VLT_LADDR_VLD | EPT_VLT_PADDR); + EPT_VIOLATION_ACC_READ | + EPT_VIOLATION_GVA_IS_VALID | + EPT_VIOLATION_GVA_TRANSLATED); } static void ept_reserved_bit_at_level(int level, int bit) @@ -2684,7 +2692,9 @@ static void ept_reserved_bit_at_level(int level, int bit) /* Making the entry non-present turns reserved bits into ignored. */ ept_violation_at_level(level, EPT_PRESENT, 1ul << bit, OP_READ, - EPT_VLT_RD | EPT_VLT_LADDR_VLD | EPT_VLT_PADDR); + EPT_VIOLATION_ACC_READ | + EPT_VIOLATION_GVA_IS_VALID | + EPT_VIOLATION_GVA_TRANSLATED); } static void ept_reserved_bit(int bit) @@ -2787,9 +2797,9 @@ static void ept_access_test_not_present(void) { ept_access_test_setup(); /* --- */ - ept_access_violation(0, OP_READ, EPT_VLT_RD); - ept_access_violation(0, OP_WRITE, EPT_VLT_WR); - ept_access_violation(0, OP_EXEC, EPT_VLT_FETCH); + ept_access_violation(0, OP_READ, EPT_VIOLATION_ACC_READ); + ept_access_violation(0, OP_WRITE, EPT_VIOLATION_ACC_WRITE); + ept_access_violation(0, OP_EXEC, EPT_VIOLATION_ACC_INSTR); } static void ept_access_test_read_only(void) @@ -2798,8 +2808,10 @@ static void ept_access_test_read_only(void) /* r-- */ ept_access_allowed(EPT_RA, OP_READ); - ept_access_violation(EPT_RA, OP_WRITE, EPT_VLT_WR | EPT_VLT_PERM_RD); - ept_access_violation(EPT_RA, OP_EXEC, EPT_VLT_FETCH | EPT_VLT_PERM_RD); + ept_access_violation(EPT_RA, OP_WRITE, EPT_VIOLATION_ACC_WRITE | + EPT_VIOLATION_PROT_READ); + ept_access_violation(EPT_RA, OP_EXEC, EPT_VIOLATION_ACC_INSTR | + EPT_VIOLATION_PROT_READ); } static void ept_access_test_write_only(void) @@ -2816,7 +2828,9 @@ static void ept_access_test_read_write(void) ept_access_allowed(EPT_RA | EPT_WA, OP_READ); ept_access_allowed(EPT_RA | EPT_WA, OP_WRITE); ept_access_violation(EPT_RA | EPT_WA, OP_EXEC, - EPT_VLT_FETCH | EPT_VLT_PERM_RD | EPT_VLT_PERM_WR); + EPT_VIOLATION_ACC_INSTR | + EPT_VIOLATION_PROT_READ | + EPT_VIOLATION_PROT_WRITE); } @@ -2826,9 +2840,11 @@ static void ept_access_test_execute_only(void) /* --x */ if (ept_execute_only_supported()) { ept_access_violation(EPT_EA, OP_READ, - EPT_VLT_RD | EPT_VLT_PERM_EX); + EPT_VIOLATION_ACC_READ | + EPT_VIOLATION_PROT_EXEC); ept_access_violation(EPT_EA, OP_WRITE, - EPT_VLT_WR | EPT_VLT_PERM_EX); + EPT_VIOLATION_ACC_WRITE | + EPT_VIOLATION_PROT_EXEC); ept_access_allowed(EPT_EA, OP_EXEC); } else { ept_access_misconfig(EPT_EA); @@ -2841,7 +2857,9 @@ static void ept_access_test_read_execute(void) /* r-x */ ept_access_allowed(EPT_RA | EPT_EA, OP_READ); ept_access_violation(EPT_RA | EPT_EA, OP_WRITE, - EPT_VLT_WR | EPT_VLT_PERM_RD | EPT_VLT_PERM_EX); + EPT_VIOLATION_ACC_WRITE | + EPT_VIOLATION_PROT_READ | + EPT_VIOLATION_PROT_EXEC); ept_access_allowed(EPT_RA | EPT_EA, OP_EXEC); } @@ -2936,14 +2954,17 @@ static void ept_access_test_paddr_not_present_ad_disabled(void) ept_access_test_setup(); ept_disable_ad_bits(); - ept_access_violation_paddr(0, PT_AD_MASK, OP_READ, EPT_VLT_RD); - ept_access_violation_paddr(0, PT_AD_MASK, OP_WRITE, EPT_VLT_RD); - ept_access_violation_paddr(0, PT_AD_MASK, OP_EXEC, EPT_VLT_RD); + ept_access_violation_paddr(0, PT_AD_MASK, OP_READ, + EPT_VIOLATION_ACC_READ); + ept_access_violation_paddr(0, PT_AD_MASK, OP_WRITE, + EPT_VIOLATION_ACC_READ); + ept_access_violation_paddr(0, PT_AD_MASK, OP_EXEC, + EPT_VIOLATION_ACC_READ); } static void ept_access_test_paddr_not_present_ad_enabled(void) { - u64 qual = EPT_VLT_RD | EPT_VLT_WR; + u64 qual = EPT_VIOLATION_ACC_READ | EPT_VIOLATION_ACC_WRITE; ept_access_test_setup(); ept_enable_ad_bits_or_skip_test(); @@ -2961,7 +2982,8 @@ static void ept_access_test_paddr_read_only_ad_disabled(void) * translation of the GPA to host physical address) a read+write * if the A/D bits have to be set. */ - u64 qual = EPT_VLT_WR | EPT_VLT_RD | EPT_VLT_PERM_RD; + u64 qual = EPT_VIOLATION_ACC_WRITE | EPT_VIOLATION_ACC_READ | + EPT_VIOLATION_PROT_READ; ept_access_test_setup(); ept_disable_ad_bits(); @@ -2987,7 +3009,8 @@ static void ept_access_test_paddr_read_only_ad_enabled(void) * structures are considered writes as far as EPT translation * is concerned. */ - u64 qual = EPT_VLT_WR | EPT_VLT_RD | EPT_VLT_PERM_RD; + u64 qual = EPT_VIOLATION_ACC_WRITE | EPT_VIOLATION_ACC_READ | + EPT_VIOLATION_PROT_READ; ept_access_test_setup(); ept_enable_ad_bits_or_skip_test(); @@ -3029,7 +3052,8 @@ static void ept_access_test_paddr_read_execute_ad_disabled(void) * translation of the GPA to host physical address) a read+write * if the A/D bits have to be set. */ - u64 qual = EPT_VLT_WR | EPT_VLT_RD | EPT_VLT_PERM_RD | EPT_VLT_PERM_EX; + u64 qual = EPT_VIOLATION_ACC_WRITE | EPT_VIOLATION_ACC_READ | + EPT_VIOLATION_PROT_READ | EPT_VIOLATION_PROT_EXEC; ept_access_test_setup(); ept_disable_ad_bits(); @@ -3055,7 +3079,8 @@ static void ept_access_test_paddr_read_execute_ad_enabled(void) * structures are considered writes as far as EPT translation * is concerned. */ - u64 qual = EPT_VLT_WR | EPT_VLT_RD | EPT_VLT_PERM_RD | EPT_VLT_PERM_EX; + u64 qual = EPT_VIOLATION_ACC_WRITE | EPT_VIOLATION_ACC_READ | + EPT_VIOLATION_PROT_READ | EPT_VIOLATION_PROT_EXEC; ept_access_test_setup(); ept_enable_ad_bits_or_skip_test(); @@ -3089,8 +3114,10 @@ static void ept_access_test_force_2m_page(void) TEST_ASSERT_EQ(ept_2m_supported(), true); ept_allowed_at_level_mkhuge(true, 2, 0, 0, OP_READ); ept_violation_at_level_mkhuge(true, 2, EPT_PRESENT, EPT_RA, OP_WRITE, - EPT_VLT_WR | EPT_VLT_PERM_RD | - EPT_VLT_LADDR_VLD | EPT_VLT_PADDR); + EPT_VIOLATION_ACC_WRITE | + EPT_VIOLATION_PROT_READ | + EPT_VIOLATION_GVA_IS_VALID | + EPT_VIOLATION_GVA_TRANSLATED); ept_misconfig_at_level_mkhuge(true, 2, EPT_PRESENT, EPT_WA); } -- 2.43.0