All of lore.kernel.org
 help / color / mirror / Atom feed
From: Krish Sadhukhan <krish.sadhukhan@oracle.com>
To: kvm@vger.kernel.org
Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com,
	vkuznets@redhat.com, wanpengli@tencent.com, joro@8bytes.org,
	thomas.lendacky@amd.com
Subject: [PATCH 3/3] Test: nSVM: Test effects of host EFLAGS.RF on VMRUN
Date: Mon, 26 Jul 2021 14:02:26 -0400	[thread overview]
Message-ID: <20210726180226.253738-4-krish.sadhukhan@oracle.com> (raw)
In-Reply-To: <20210726180226.253738-1-krish.sadhukhan@oracle.com>

According to section "VMRUN and TF/RF Bits in EFLAGS" in APM vol 2,

    "EFLAGS.RF suppresses any potential instruction breakpoint match on
     the VMRUN. Completion of the VMRUN instruction clears the host
     EFLAGS.RF bit."

Test that the RIP detected by the #DB handler when a #DB is triggered by
configuring the debug registers, is the RIP of the VMRUN instruction and
that setting EFLAGS.RF in the #DB handler will no more trigger any #DB
following the completion of VMRUN. Also, test that the processor clears
EFLAGS.RF on completion of VMRUN.

Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com>
---
 x86/svm_tests.c | 74 +++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 59 insertions(+), 15 deletions(-)

diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index a56a197..1f12504 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -1965,6 +1965,10 @@ static bool init_intercept_check(struct svm_test *test)
  * Setting host EFLAGS.TF causes a #DB trap after the VMRUN completes on the
  * host side (i.e., after the #VMEXIT from the guest).
  *
+ * Setting host EFLAGS.RF suppresses any potential instruction breakpoint
+ * match on the VMRUN and completion of the VMRUN instruction clears the
+ * host EFLAGS.RF bit.
+ *
  * [AMD APM]
  */
 static volatile u8 host_rflags_guest_main_flag = 0;
@@ -1972,7 +1976,8 @@ static volatile u8 host_rflags_db_handler_flag = 0;
 static volatile bool host_rflags_ss_on_vmrun = false;
 static volatile bool host_rflags_vmrun_reached = false;
 static volatile bool host_rflags_set_tf = false;
-static u64 post_vmrun_rip;
+static volatile bool host_rflags_set_rf = false;
+static u64 rip_detected;
 
 extern u64 *vmrun_rip;
 
@@ -1980,11 +1985,27 @@ static void host_rflags_db_handler(struct ex_regs *r)
 {
 	if (host_rflags_ss_on_vmrun) {
 		if (host_rflags_vmrun_reached) {
-			r->rflags &= ~X86_EFLAGS_TF;
-			post_vmrun_rip = r->rip;
+			if (!host_rflags_set_rf) {
+				r->rflags &= ~X86_EFLAGS_TF;
+				rip_detected = r->rip;
+			} else {
+				r->rflags |= X86_EFLAGS_RF;
+				++host_rflags_db_handler_flag;
+			}
 		} else {
-			if (r->rip == (u64)&vmrun_rip)
+			if (r->rip == (u64)&vmrun_rip) {
 				host_rflags_vmrun_reached = true;
+
+				if (host_rflags_set_rf) {
+					host_rflags_guest_main_flag = 0;
+					rip_detected = r->rip;
+					r->rflags &= ~X86_EFLAGS_TF;
+
+					/* Trigger #DB via debug registers */
+					write_dr0((void *)&vmrun_rip);
+					write_dr7(0x403);
+				}
+			}
 		}
 	} else {
 		r->rflags &= ~X86_EFLAGS_TF;
@@ -2007,11 +2028,15 @@ static void host_rflags_prepare_gif_clear(struct svm_test *test)
 static void host_rflags_test(struct svm_test *test)
 {
 	while (1) {
-		if (get_test_stage(test) > 0 && host_rflags_set_tf &&
-		    (!host_rflags_ss_on_vmrun) &&
-		    (!host_rflags_db_handler_flag))
-			host_rflags_guest_main_flag = 1;
-		if (get_test_stage(test) == 3)
+		if (get_test_stage(test) > 0) {
+			if ((host_rflags_set_tf && (!host_rflags_ss_on_vmrun) &&
+			    (!host_rflags_db_handler_flag)) ||
+			    (host_rflags_set_rf &&
+			    host_rflags_db_handler_flag == 1))
+				host_rflags_guest_main_flag = 1;
+		}
+
+		if (get_test_stage(test) == 4)
 			break;
 		vmmcall();
 	}
@@ -2051,26 +2076,45 @@ static bool host_rflags_finished(struct svm_test *test)
 		break;
 	case 2:
 		if (vmcb->control.exit_code != SVM_EXIT_VMMCALL ||
-		    (post_vmrun_rip - (u64)&vmrun_rip) != 3) {
+		    (rip_detected - (u64)&vmrun_rip) != 3) {
 			report(false, "Unexpected VMEXIT or RIP mismatch."
-			    " Exit reason 0x%x, VMRUN RIP: %lx, post-VMRUN"
-			    " RIP: %lx", vmcb->control.exit_code,
-			    (u64)&vmrun_rip, post_vmrun_rip);
+			    " Exit reason 0x%x, RIP actual: %lx, RIP expected: "
+			    "%lx", vmcb->control.exit_code,
+			    (u64)&vmrun_rip, rip_detected - 3);
+			return true;
+		}
+		host_rflags_set_rf = true;
+		host_rflags_guest_main_flag = 0;
+		host_rflags_vmrun_reached = false;
+		vmcb->save.rip += 3;
+		break;
+	case 3:
+		if (vmcb->control.exit_code != SVM_EXIT_VMMCALL ||
+		    rip_detected != (u64)&vmrun_rip ||
+		    host_rflags_guest_main_flag != 1 ||
+		    host_rflags_db_handler_flag > 1 ||
+		    read_rflags() & X86_EFLAGS_RF) {
+			report(false, "Unexpected VMEXIT or RIP mismatch or "
+			    "EFLAGS.RF not cleared."
+			    " Exit reason 0x%x, RIP actual: %lx, RIP expected: "
+			    "%lx", vmcb->control.exit_code,
+			    (u64)&vmrun_rip, rip_detected);
 			return true;
 		}
 		host_rflags_set_tf = false;
+		host_rflags_set_rf = false;
 		vmcb->save.rip += 3;
 		break;
 	default:
 		return true;
 	}
 	inc_test_stage(test);
-	return get_test_stage(test) == 4;
+	return get_test_stage(test) == 5;
 }
 
 static bool host_rflags_check(struct svm_test *test)
 {
-	return get_test_stage(test) == 3;
+	return get_test_stage(test) == 4;
 }
 
 #define TEST(name) { #name, .v2 = name }
-- 
2.27.0


  parent reply	other threads:[~2021-07-26 18:53 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-26 18:02 [PATCH 0/3] Test: nSVM: Test effects of host EFLAGS.RF on VMRUN Krish Sadhukhan
2021-07-26 18:02 ` [PATCH 1/3] Test: x86: Move setter/getter for Debug registers to common library Krish Sadhukhan
2021-07-26 18:02 ` [PATCH 2/3] Test: x86: Add a #define for the RF bit in EFLAGS register Krish Sadhukhan
2021-07-26 18:02 ` Krish Sadhukhan [this message]
2021-07-26 21:59 ` [PATCH 0/3] Test: nSVM: Test effects of host EFLAGS.RF on VMRUN Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210726180226.253738-4-krish.sadhukhan@oracle.com \
    --to=krish.sadhukhan@oracle.com \
    --cc=jmattson@google.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=thomas.lendacky@amd.com \
    --cc=vkuznets@redhat.com \
    --cc=wanpengli@tencent.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.