According to section "VMRUN and TF/RF Bits in EFLAGS." in APM vol 2, "When VMRUN loads a guest value of 1 for EFLAGS.RF, that value takes effect and suppresses any potential (guest) instruction breakpoint on the first guest instruction." Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> --- x86/svm_tests.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/x86/svm_tests.c b/x86/svm_tests.c index 7827d1e..b6bb529 100644 --- a/x86/svm_tests.c +++ b/x86/svm_tests.c @@ -2496,14 +2496,25 @@ static void test_vmrun_canonicalization(void) * cause a trace trap between the VMRUN and the first guest instruction, but * rather after completion of the first guest instruction. * + * When VMRUN loads a guest value of 1 for EFLAGS.RF, that value takes effect + * and suppresses any potential (guest) instruction breakpoint on the first + * guest instruction. + * * [APM vol 2] */ u64 guest_rflags_test_trap_rip; +u8 guest_rflags_rf_test_counter = 0; +bool guest_rflags_rf_test = false; static void guest_rflags_test_db_handler(struct ex_regs *r) { guest_rflags_test_trap_rip = r->rip; r->rflags &= ~X86_EFLAGS_TF; + + if (guest_rflags_rf_test) { + ++guest_rflags_rf_test_counter; + r->rflags |= X86_EFLAGS_RF; + } } extern void guest_rflags_test_guest(struct svm_test *test); @@ -2542,6 +2553,7 @@ static void test_guest_rflags(void) vmcb->save.rflags |= X86_EFLAGS_TF; report (__svm_vmrun(vmcb->save.rip) == SVM_EXIT_VMMCALL && guest_rflags_test_trap_rip == 0, "Test EFLAGS.TF on VMRUN: trap not expected"); + vmcb->save.rflags &= ~X86_EFLAGS_TF; /* * Let guest finish execution @@ -2549,6 +2561,32 @@ static void test_guest_rflags(void) vmcb->save.rip += 3; report (__svm_vmrun(vmcb->save.rip) == SVM_EXIT_VMMCALL && vmcb->save.rip == (u64)&guest_end, "Test EFLAGS.TF on VMRUN: guest execution completion"); + + /* + * Trap expected before first guest instruction + */ + guest_rflags_rf_test = true; + vmcb->save.dr7 |= 0x403; + write_dr0(guest_rflags_test_guest); + write_dr7(0x403); + report (__svm_vmrun((u64)guest_rflags_test_guest) == SVM_EXIT_VMMCALL && + guest_rflags_rf_test_counter == 1 && + guest_rflags_test_trap_rip == (u64)&guest_rflags_test_guest, + "Test EFLAGS.RF on guest code: trap expected before execution of first guest instruction"); + /* + * No trap expected + */ + vmcb->save.rflags |= X86_EFLAGS_RF; + guest_rflags_rf_test_counter = 0; + report (__svm_vmrun((u64)guest_rflags_test_guest) == SVM_EXIT_VMMCALL && + guest_rflags_rf_test_counter == 0, + "Test EFLAGS.RF on guest code: trap not expected"); + + /* + * Let guest finish execution + */ + report (__svm_vmrun((u64)&guest_end) == SVM_EXIT_VMMCALL, + "Test guest EFLAGS.RF: Guest execution completion"); } static void svm_guest_state_test(void) -- 2.27.0