All of lore.kernel.org
 help / color / mirror / Atom feed
From: ma.mandourr@gmail.com
To: Sean Christopherson <seanjc@google.com>,
	Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	Mahmoud Abumandour <ma.mandourr@gmail.com>
Subject: [PATCH 2/2] KVM: selftests: Add test for nested VM-Exits while vectoring soft INTs
Date: Tue, 20 Oct 2026 21:26:03 -0700	[thread overview]
Message-ID: <20261021042603.608292-3-ma.mandourr@gmail.com> (raw)
In-Reply-To: <20261021042603.608292-1-ma.mandourr@gmail.com>

From: Mahmoud Abumandour <ma.mandourr@gmail.com>

Verify that a VM-Exit from L2 that occurs while vectoring INT3 or INTn
reports the instruction length in the VM-Exit instruction length field and
leaves L1's VM-Entry instruction length untouched.

Assisted-by: LLM
Signed-off-by: Mahmoud Abumandour <ma.mandourr@gmail.com>
---
 tools/testing/selftests/kvm/Makefile.kvm      |   1 +
 .../kvm/x86/vmx_soft_int_vectoring_test.c     | 105 ++++++++++++++++++
 2 files changed, 106 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/x86/vmx_soft_int_vectoring_test.c

diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 888a7530a280..d5f8749413f2 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -140,6 +140,7 @@ TEST_GEN_PROGS_x86 += x86/vmx_exception_with_invalid_guest_state
 TEST_GEN_PROGS_x86 += x86/vmx_msrs_test
 TEST_GEN_PROGS_x86 += x86/vmx_invalid_nested_guest_state
 TEST_GEN_PROGS_x86 += x86/vmx_nested_la57_state_test
+TEST_GEN_PROGS_x86 += x86/vmx_soft_int_vectoring_test
 TEST_GEN_PROGS_x86 += x86/apic_bus_clock_test
 TEST_GEN_PROGS_x86 += x86/xapic_ipi_test
 TEST_GEN_PROGS_x86 += x86/xapic_state_test
diff --git a/tools/testing/selftests/kvm/x86/vmx_soft_int_vectoring_test.c b/tools/testing/selftests/kvm/x86/vmx_soft_int_vectoring_test.c
new file mode 100644
index 000000000000..e74510c49938
--- /dev/null
+++ b/tools/testing/selftests/kvm/x86/vmx_soft_int_vectoring_test.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Verify that a nested VM-Exit that occurs while L2 is vectoring a software
+ * exception (INT3) or a software interrupt (INTn) reports the length of the
+ * instruction in the VM-Exit instruction length field, and doesn't modify the
+ * VM-Entry instruction length field, a VM-Entry control that only L1 writes.
+ */
+#include "kvm_util.h"
+#include "processor.h"
+#include "vmx.h"
+#include "kselftest.h"
+
+#define INTR_INFO_VALID_MASK		BIT(31)
+#define INTR_TYPE_SOFT_INTR		(4 << 8)
+#define INTR_TYPE_SOFT_EXCEPTION	(6 << 8)
+
+#define SOFT_INT_VECTOR			0x40
+
+/*
+ * Arbitrary, but a legal instruction length that differs from the lengths of
+ * INT3 and INTn, i.e. a value no VM-Exit in this test can legitimately produce.
+ */
+#define ENTRY_INSN_LEN			7
+
+static void l2_guest_code(void)
+{
+	asm volatile("int3");
+	asm volatile("int $" __stringify(SOFT_INT_VECTOR));
+	vmcall();
+}
+
+static void l1_assert_vectoring_exit(const char *insn, u32 vectoring_info,
+				     u32 insn_len)
+{
+	u64 entry_insn_len;
+
+	GUEST_ASSERT_EQ(vmread(VM_EXIT_REASON), EXIT_REASON_EXCEPTION_NMI);
+	GUEST_ASSERT_EQ(vmread(VM_EXIT_INTR_INFO) & 0xff, GP_VECTOR);
+	GUEST_ASSERT_EQ(vmread(IDT_VECTORING_INFO_FIELD),
+			INTR_INFO_VALID_MASK | vectoring_info);
+	GUEST_ASSERT_EQ(vmread(VM_EXIT_INSTRUCTION_LEN), insn_len);
+
+	entry_insn_len = vmread(VM_ENTRY_INSTRUCTION_LEN);
+	__GUEST_ASSERT(entry_insn_len == ENTRY_INSN_LEN,
+		       "VM-Exit while vectoring %s changed the VM-Entry instruction length from %u to %lu",
+		       insn, ENTRY_INSN_LEN, entry_insn_len);
+
+	/* RIP points at the INT3/INTn, skip it. */
+	vmwrite(GUEST_RIP, vmread(GUEST_RIP) + insn_len);
+}
+
+static void l1_guest_code(struct vmx_pages *vmx_pages)
+{
+	prepare_for_vmx_operation(vmx_pages);
+	load_vmcs(vmx_pages);
+	prepare_vmcs(vmx_pages, l2_guest_code);
+
+	/*
+	 * Put every IDT entry beyond the limit so that vectoring any event in
+	 * L2 generates #GP, and intercept #GP so that the VM-Exit occurs while
+	 * the original event is being vectored.
+	 */
+	vmwrite(GUEST_IDTR_LIMIT, 0);
+	vmwrite(EXCEPTION_BITMAP, BIT(GP_VECTOR));
+	vmwrite(VM_ENTRY_INSTRUCTION_LEN, ENTRY_INSN_LEN);
+
+	vmlaunch();
+	l1_assert_vectoring_exit("INT3", INTR_TYPE_SOFT_EXCEPTION | BP_VECTOR, 1);
+
+	vmresume();
+	l1_assert_vectoring_exit("INTn", INTR_TYPE_SOFT_INTR | SOFT_INT_VECTOR, 2);
+
+	vmresume();
+	GUEST_ASSERT_EQ(vmread(VM_EXIT_REASON), EXIT_REASON_VMCALL);
+	GUEST_DONE();
+}
+
+int main(int argc, char *argv[])
+{
+	gva_t vmx_pages_gva;
+	struct kvm_vcpu *vcpu;
+	struct kvm_vm *vm;
+	struct ucall uc;
+
+	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
+
+	vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
+	vcpu_alloc_vmx(vm, &vmx_pages_gva);
+	vcpu_args_set(vcpu, 1, vmx_pages_gva);
+
+	vcpu_run(vcpu);
+	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
+
+	switch (get_ucall(vcpu, &uc)) {
+	case UCALL_ABORT:
+		REPORT_GUEST_ASSERT(uc);
+	case UCALL_DONE:
+		break;
+	default:
+		TEST_FAIL("Unexpected ucall %lu", uc.cmd);
+	}
+
+	kvm_vm_free(vm);
+	return 0;
+}
-- 
2.43.0


  parent reply	other threads:[~2026-10-21  4:26 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-21  4:26 [PATCH 0/2] KVM: nVMX: Don't clobber VM-Entry instruction length on soft INTn exits ma.mandourr
2026-10-21  4:26 ` [PATCH 1/2] KVM: nVMX: Don't clobber VM-Entry instruction length when saving soft INTn ma.mandourr
2026-10-21  4:42   ` sashiko-bot
2026-10-21  4:26 ` ma.mandourr [this message]
2026-10-21  4:45   ` [PATCH 2/2] KVM: selftests: Add test for nested VM-Exits while vectoring soft INTs sashiko-bot

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=20261021042603.608292-3-ma.mandourr@gmail.com \
    --to=ma.mandourr@gmail.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.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.