According to section "VMRUN and TF/RF Bits in EFLAGS." in APM vol 2, "When VMRUN loads a guest value of 1 in EFLAGS.TF, that value does not cause a trace trap between the VMRUN and the first guest instruction, but rather after completion of the first guest instruction." Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> --- x86/svm_tests.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/x86/svm_tests.c b/x86/svm_tests.c index a56a197..2d06d9e 100644 --- a/x86/svm_tests.c +++ b/x86/svm_tests.c @@ -2491,6 +2491,66 @@ static void test_vmrun_canonicalization(void) TEST_CANONICAL(vmcb->save.tr.base, "TR"); } +/* + * When VMRUN loads a guest value of 1 in EFLAGS.TF, that value does not + * cause a trace trap between the VMRUN and the first guest instruction, but + * rather after completion of the first guest instruction. + * + * [APM vol 2] + */ +u64 guest_rflags_test_trap_rip; + +static void guest_rflags_test_db_handler(struct ex_regs *r) +{ + guest_rflags_test_trap_rip = r->rip; + r->rflags &= ~X86_EFLAGS_TF; +} + +extern void guest_rflags_test_guest(struct svm_test *test); +extern u64 *insn2; +extern u64 *guest_end; + +asm("guest_rflags_test_guest:\n\t" + "push %rbp\n\t" + ".global insn2\n\t" + "insn2:\n\t" + "mov %rsp,%rbp\n\t" + "vmmcall\n\t" + "vmmcall\n\t" + ".global guest_end\n\t" + "guest_end:\n\t" + "vmmcall\n\t" + "pop %rbp\n\t" + "ret"); + +static void test_guest_rflags(void) +{ + handle_exception(DB_VECTOR, guest_rflags_test_db_handler); + + /* + * Trap expected after completion of first guest instruction + */ + vmcb->save.rflags |= X86_EFLAGS_TF; + report (svm_vmrun_custom((u64)guest_rflags_test_guest) == SVM_EXIT_VMMCALL && + guest_rflags_test_trap_rip == (u64)&insn2, + "Test EFLAGS.TF on VMRUN: trap expected after completion of first guest instruction"); + /* + * No trap expected + */ + guest_rflags_test_trap_rip = 0; + vmcb->save.rip += 3; + vmcb->save.rflags |= X86_EFLAGS_TF; + report (svm_vmrun_custom(vmcb->save.rip) == SVM_EXIT_VMMCALL && + guest_rflags_test_trap_rip == 0, "Test EFLAGS.TF on VMRUN: trap not expected"); + + /* + * Let guest finish execution + */ + vmcb->save.rip += 3; + report (svm_vmrun_custom(vmcb->save.rip) == SVM_EXIT_VMMCALL && + vmcb->save.rip == (u64)&guest_end, "Test EFLAGS.TF on VMRUN: guest execution completion"); +} + static void svm_guest_state_test(void) { test_set_guest(basic_guest_main); @@ -2501,6 +2561,7 @@ static void svm_guest_state_test(void) test_dr(); test_msrpm_iopm_bitmap_addrs(); test_vmrun_canonicalization(); + test_guest_rflags(); } static void __svm_npt_rsvd_bits_test(u64 *pxe, u64 rsvd_bits, u64 efer, -- 2.27.0