Kernel KVM virtualization development
 help / color / mirror / Atom feed
From: Sean Christopherson <seanjc@google.com>
To: Sean Christopherson <seanjc@google.com>,
	Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	 Hao Zhang <zhanghao1@kylinos.cn>
Subject: [PATCH v4 5/6] KVM: selftests: Refactor invalid nVMX state test to prepare for RSM testcase
Date: Mon, 27 Jul 2026 17:43:50 -0700	[thread overview]
Message-ID: <20260728004351.887076-6-seanjc@google.com> (raw)
In-Reply-To: <20260728004351.887076-1-seanjc@google.com>

In the invalid nVMX guest state test, extract the creation of the VM and
initial running of the vCPU to get to L2 into helpers so that the common
code can be reused to extend the test to also cover RSM.

Eliminate the unnecessary global "vm", and opportunistically free the VM
after the testcase as there's zero reason not to.

Opportunistically assert that L2 is never resumed after the I/O exit to L1,
e.g. to guard against false passes.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 .../kvm/x86/vmx_invalid_nested_guest_state.c  | 61 +++++++++++++------
 1 file changed, 42 insertions(+), 19 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c b/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c
index fb9444ca0d7e..ab00265d6c94 100644
--- a/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c
+++ b/tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c
@@ -11,8 +11,6 @@
 
 #define ARBITRARY_IO_PORT 0x80
 
-static struct kvm_vm *vm;
-
 static void l2_guest_code(void)
 {
 	/*
@@ -21,6 +19,7 @@ static void l2_guest_code(void)
 	 */
 	asm volatile("inb $" __stringify(ARBITRARY_IO_PORT) ", %%al"
 		     ::: "rax");
+	GUEST_FAIL("L2 resumed after stuffing invalid guest state");
 }
 
 static void l1_guest_code(struct vmx_pages *vmx_pages)
@@ -46,35 +45,50 @@ static void l1_guest_code(struct vmx_pages *vmx_pages)
 	GUEST_DONE();
 }
 
-int main(int argc, char *argv[])
+static void vcpu_run_to_io(struct kvm_vcpu *vcpu, bool want_l2)
+{
+	struct kvm_run *run = vcpu->run;
+
+	vcpu_run(vcpu);
+
+	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
+
+	TEST_ASSERT(run->io.port == ARBITRARY_IO_PORT &&
+		    (!!(run->flags & KVM_RUN_X86_GUEST_MODE) == want_l2  ||
+		     !kvm_has_cap(KVM_CAP_X86_GUEST_MODE)),
+		    "Expected IN from port %d from L2, got port %d from L%u",
+		    ARBITRARY_IO_PORT, run->io.port,
+		    1 + !!(run->flags & KVM_RUN_X86_GUEST_MODE));
+}
+
+static struct kvm_vm *vm_create_and_run_l2(struct kvm_vcpu **vcpu)
 {
 	gva_t vmx_pages_gva;
-	struct kvm_sregs sregs;
-	struct kvm_vcpu *vcpu;
-	struct kvm_run *run;
-	struct ucall uc;
+	struct kvm_vm *vm;
 
-	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
-
-	vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
+	vm = vm_create_with_one_vcpu(vcpu, l1_guest_code);
 
 	/* Allocate VMX pages and shared descriptors (vmx_pages). */
 	vcpu_alloc_vmx(vm, &vmx_pages_gva);
-	vcpu_args_set(vcpu, 1, vmx_pages_gva);
-
-	vcpu_run(vcpu);
-
-	run = vcpu->run;
+	vcpu_args_set(*vcpu, 1, vmx_pages_gva);
 
 	/*
 	 * The first exit to L0 userspace should be an I/O access from L2.
 	 * Running L1 should launch L2 without triggering an exit to userspace.
 	 */
-	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
+	vcpu_run_to_io(*vcpu, true);
 
-	TEST_ASSERT(run->io.port == ARBITRARY_IO_PORT,
-		    "Expected IN from port %d from L2, got port %d",
-		    ARBITRARY_IO_PORT, run->io.port);
+	return vm;
+}
+
+static void test_invalid_l2_guest_state(void)
+{
+	struct kvm_sregs sregs;
+	struct kvm_vcpu *vcpu;
+	struct kvm_vm *vm;
+	struct ucall uc;
+
+	vm = vm_create_and_run_l2(&vcpu);
 
 	/*
 	 * Stuff invalid guest state for L2 by making TR unusable.  The next
@@ -96,4 +110,13 @@ int main(int argc, char *argv[])
 	default:
 		TEST_FAIL("Unexpected ucall: %lu", uc.cmd);
 	}
+
+	kvm_vm_free(vm);
+}
+
+int main(int argc, char *argv[])
+{
+	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
+
+	test_invalid_l2_guest_state();
 }
-- 
2.55.0.229.g6434b31f56-goog


  parent reply	other threads:[~2026-07-28  0:43 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-28  0:43 [PATCH v4 0/6] KVM: nVMX: Synthesize SHUTDOWN on RSM with bad state Sean Christopherson
2026-07-28  0:43 ` [PATCH v4 1/6] KVM: x86: Extract VMX's unhandleable emulation check to common x86 Sean Christopherson
2026-07-28  0:58   ` sashiko-bot
2026-07-28  1:01     ` Sean Christopherson
2026-07-28  0:43 ` [PATCH v4 2/6] KVM: nVMX: Synthesize SHUTDOWN on RSM if L2 requires emulation Sean Christopherson
2026-07-28  0:43 ` [PATCH v4 3/6] KVM: x86: Rework kvm_x86_ops.vcpu_pre_run() into .vcpu_needs_initialization() Sean Christopherson
2026-07-28  0:43 ` [PATCH v4 4/6] KVM: selftests: Use port 0x80 in invalid nVMX guest state test Sean Christopherson
2026-07-28  0:43 ` Sean Christopherson [this message]
2026-07-28  0:51   ` [PATCH v4 5/6] KVM: selftests: Refactor invalid nVMX state test to prepare for RSM testcase sashiko-bot
2026-07-28  0:43 ` [PATCH v4 6/6] KVM: selftests: Extend the invalid nVMX guest state test to cover RSM Sean Christopherson
2026-07-28  3:01   ` Hao Zhang

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=20260728004351.887076-6-seanjc@google.com \
    --to=seanjc@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=zhanghao1@kylinos.cn \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox