Message ID | 20200321050555.4212-1-namit@vmware.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | x86: vmx: Fix "EPT violation - paging structure" test | expand |
I mistakenly forgot the kvm-unit-tests in the patch subject. Sorry for that. > On Mar 20, 2020, at 10:05 PM, Nadav Amit <namit@vmware.com> wrote: > > Running the tests with more than 4GB of memory results in the following > failure: > > FAIL: EPT violation - paging structure > > It appears that the test mistakenly used get_ept_pte() to retrieve the > guest PTE, but this function is intended for accessing EPT and not the > guest page tables. Use get_pte_level() instead of get_ept_pte(). > > Tested on bare-metal only. > > Signed-off-by: Nadav Amit <namit@vmware.com> > --- > x86/vmx_tests.c | 17 +++++++++-------- > 1 file changed, 9 insertions(+), 8 deletions(-) > > diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c > index be5c952..1f97fe3 100644 > --- a/x86/vmx_tests.c > +++ b/x86/vmx_tests.c > @@ -1312,12 +1312,14 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) > u64 guest_cr3; > u32 insn_len; > u32 exit_qual; > - static unsigned long data_page1_pte, data_page1_pte_pte, memaddr_pte; > + static unsigned long data_page1_pte, data_page1_pte_pte, memaddr_pte, > + guest_pte_addr; > > guest_rip = vmcs_read(GUEST_RIP); > guest_cr3 = vmcs_read(GUEST_CR3); > insn_len = vmcs_read(EXI_INST_LEN); > exit_qual = vmcs_read(EXI_QUALIFICATION); > + pteval_t *ptep; > switch (exit_reason.basic) { > case VMX_VMCALL: > switch (vmx_get_test_stage()) { > @@ -1364,12 +1366,11 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) > ept_sync(INVEPT_SINGLE, eptp); > break; > case 4: > - TEST_ASSERT(get_ept_pte(pml4, (unsigned long)data_page1, > - 2, &data_page1_pte)); > - data_page1_pte &= PAGE_MASK; > - TEST_ASSERT(get_ept_pte(pml4, data_page1_pte, > - 2, &data_page1_pte_pte)); > - set_ept_pte(pml4, data_page1_pte, 2, > + ptep = get_pte_level((pgd_t *)guest_cr3, data_page1, /*level=*/2); > + guest_pte_addr = virt_to_phys(ptep) & PAGE_MASK; > + > + TEST_ASSERT(get_ept_pte(pml4, guest_pte_addr, 2, &data_page1_pte_pte)); > + set_ept_pte(pml4, guest_pte_addr, 2, > data_page1_pte_pte & ~EPT_PRESENT); > ept_sync(INVEPT_SINGLE, eptp); > break; > @@ -1437,7 +1438,7 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) > (have_ad ? EPT_VLT_WR : 0) | > EPT_VLT_LADDR_VLD)) > vmx_inc_test_stage(); > - set_ept_pte(pml4, data_page1_pte, 2, > + set_ept_pte(pml4, guest_pte_addr, 2, > data_page1_pte_pte | (EPT_PRESENT)); > ept_sync(INVEPT_SINGLE, eptp); > break; > — > 2.17.1
On 21/03/20 06:05, Nadav Amit wrote: > Running the tests with more than 4GB of memory results in the following > failure: > > FAIL: EPT violation - paging structure > > It appears that the test mistakenly used get_ept_pte() to retrieve the > guest PTE, but this function is intended for accessing EPT and not the > guest page tables. Use get_pte_level() instead of get_ept_pte(). > > Tested on bare-metal only. > > Signed-off-by: Nadav Amit <namit@vmware.com> > --- > x86/vmx_tests.c | 17 +++++++++-------- > 1 file changed, 9 insertions(+), 8 deletions(-) > > diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c > index be5c952..1f97fe3 100644 > --- a/x86/vmx_tests.c > +++ b/x86/vmx_tests.c > @@ -1312,12 +1312,14 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) > u64 guest_cr3; > u32 insn_len; > u32 exit_qual; > - static unsigned long data_page1_pte, data_page1_pte_pte, memaddr_pte; > + static unsigned long data_page1_pte, data_page1_pte_pte, memaddr_pte, > + guest_pte_addr; > > guest_rip = vmcs_read(GUEST_RIP); > guest_cr3 = vmcs_read(GUEST_CR3); > insn_len = vmcs_read(EXI_INST_LEN); > exit_qual = vmcs_read(EXI_QUALIFICATION); > + pteval_t *ptep; > switch (exit_reason.basic) { > case VMX_VMCALL: > switch (vmx_get_test_stage()) { > @@ -1364,12 +1366,11 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) > ept_sync(INVEPT_SINGLE, eptp); > break; > case 4: > - TEST_ASSERT(get_ept_pte(pml4, (unsigned long)data_page1, > - 2, &data_page1_pte)); > - data_page1_pte &= PAGE_MASK; > - TEST_ASSERT(get_ept_pte(pml4, data_page1_pte, > - 2, &data_page1_pte_pte)); > - set_ept_pte(pml4, data_page1_pte, 2, > + ptep = get_pte_level((pgd_t *)guest_cr3, data_page1, /*level=*/2); > + guest_pte_addr = virt_to_phys(ptep) & PAGE_MASK; > + > + TEST_ASSERT(get_ept_pte(pml4, guest_pte_addr, 2, &data_page1_pte_pte)); > + set_ept_pte(pml4, guest_pte_addr, 2, > data_page1_pte_pte & ~EPT_PRESENT); > ept_sync(INVEPT_SINGLE, eptp); > break; > @@ -1437,7 +1438,7 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) > (have_ad ? EPT_VLT_WR : 0) | > EPT_VLT_LADDR_VLD)) > vmx_inc_test_stage(); > - set_ept_pte(pml4, data_page1_pte, 2, > + set_ept_pte(pml4, guest_pte_addr, 2, > data_page1_pte_pte | (EPT_PRESENT)); > ept_sync(INVEPT_SINGLE, eptp); > break; > Queued, thanks. Paolo
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index be5c952..1f97fe3 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -1312,12 +1312,14 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) u64 guest_cr3; u32 insn_len; u32 exit_qual; - static unsigned long data_page1_pte, data_page1_pte_pte, memaddr_pte; + static unsigned long data_page1_pte, data_page1_pte_pte, memaddr_pte, + guest_pte_addr; guest_rip = vmcs_read(GUEST_RIP); guest_cr3 = vmcs_read(GUEST_CR3); insn_len = vmcs_read(EXI_INST_LEN); exit_qual = vmcs_read(EXI_QUALIFICATION); + pteval_t *ptep; switch (exit_reason.basic) { case VMX_VMCALL: switch (vmx_get_test_stage()) { @@ -1364,12 +1366,11 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) ept_sync(INVEPT_SINGLE, eptp); break; case 4: - TEST_ASSERT(get_ept_pte(pml4, (unsigned long)data_page1, - 2, &data_page1_pte)); - data_page1_pte &= PAGE_MASK; - TEST_ASSERT(get_ept_pte(pml4, data_page1_pte, - 2, &data_page1_pte_pte)); - set_ept_pte(pml4, data_page1_pte, 2, + ptep = get_pte_level((pgd_t *)guest_cr3, data_page1, /*level=*/2); + guest_pte_addr = virt_to_phys(ptep) & PAGE_MASK; + + TEST_ASSERT(get_ept_pte(pml4, guest_pte_addr, 2, &data_page1_pte_pte)); + set_ept_pte(pml4, guest_pte_addr, 2, data_page1_pte_pte & ~EPT_PRESENT); ept_sync(INVEPT_SINGLE, eptp); break; @@ -1437,7 +1438,7 @@ static int ept_exit_handler_common(union exit_reason exit_reason, bool have_ad) (have_ad ? EPT_VLT_WR : 0) | EPT_VLT_LADDR_VLD)) vmx_inc_test_stage(); - set_ept_pte(pml4, data_page1_pte, 2, + set_ept_pte(pml4, guest_pte_addr, 2, data_page1_pte_pte | (EPT_PRESENT)); ept_sync(INVEPT_SINGLE, eptp); break;
Running the tests with more than 4GB of memory results in the following failure: FAIL: EPT violation - paging structure It appears that the test mistakenly used get_ept_pte() to retrieve the guest PTE, but this function is intended for accessing EPT and not the guest page tables. Use get_pte_level() instead of get_ept_pte(). Tested on bare-metal only. Signed-off-by: Nadav Amit <namit@vmware.com> --- x86/vmx_tests.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)