* [PATCH v2 0/3] KVM: nVMX: Don't clobber VM-Entry instruction length on soft INTn exits
@ 2026-10-23 0:37 ma.mandourr
2026-10-23 0:37 ` [PATCH v2 1/3] KVM: nVMX: Fill VM-Exit instruction length before saving pending event ma.mandourr
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: ma.mandourr @ 2026-10-23 0:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, ma.mandourr
From: Mahmoud Abumandour <ma.mandourr@gmail.com>
KVM writes the length of a soft INTn that L2 was vectoring at the time of a
nested VM-Exit into vmcs12's VM-Entrty instruction length instead of the VM-Exit
instruction length.
Patch 1 did not exist in v1, but Sashiko pointed out that prepare_vmcs12()
overwrites the VM-exit instruction length that vmcs12_save_pending_event() saves
for soft events.
The selftest patch was written with the help of an LLM (Claude Opus 5.5).
v2:
- New Patch 1
- Same Patch 2 from v1 (with commit message changes)
- Patch 3 now extends nested_exceptions_test instead of adding a new test
(suggested by Sashiko).
v1: https://lore.kernel.org/all/20261021042603.608292-1-ma.mandourr@gmail.com
Mahmoud Abumandour (3):
KVM: nVMX: Fill VM-Exit instruction length before saving pending event
KVM: nVMX: Don't clobber VM-Entry instruction length when saving soft
INTn
KVM: selftests: Verify nested VM-Exits while vectoring INT3 and INTn
arch/x86/kvm/vmx/nested.c | 6 ++-
.../kvm/x86/nested_exceptions_test.c | 39 +++++++++++++++++++
2 files changed, 43 insertions(+), 2 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/3] KVM: nVMX: Fill VM-Exit instruction length before saving pending event
2026-10-23 0:37 [PATCH v2 0/3] KVM: nVMX: Don't clobber VM-Entry instruction length on soft INTn exits ma.mandourr
@ 2026-10-23 0:37 ` ma.mandourr
2026-10-23 0:37 ` [PATCH v2 2/3] KVM: nVMX: Don't clobber VM-Entry instruction length when saving soft INTn ma.mandourr
2026-10-23 0:37 ` [PATCH v2 3/3] KVM: selftests: Verify nested VM-Exits while vectoring INT3 and INTn ma.mandourr
2 siblings, 0 replies; 4+ messages in thread
From: ma.mandourr @ 2026-10-23 0:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, ma.mandourr
From: Mahmoud Abumandour <ma.mandourr@gmail.com>
Fill vmcs12's VM-Exit instruction length before calling
vmcs12_save_pending_event(), so that the length it saves for a software
exception isn't overwritten. Commit c3634d25fbee ("KVM: nVMX: Leave most
VM-Exit info fields unmodified on failed VM-Entry") moved the assignment
after the call.
L1 sees no difference since both lengths are read from vmcs02's VM-Exit
instruction length.
Link: https://lore.kernel.org/all/sashiko-outbox-179791@kernel.org
Signed-off-by: Mahmoud Abumandour <ma.mandourr@gmail.com>
---
arch/x86/kvm/vmx/nested.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 9b0bfa2f854c..6f7c00083beb 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -4764,6 +4764,9 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
* instead of reading the real value. */
vmcs12->vm_entry_intr_info_field &= ~INTR_INFO_VALID_MASK;
+ /* vmcs12_save_pending_event() may override this. */
+ vmcs12->vm_exit_instruction_len = exit_insn_len;
+
/*
* Transfer the event that L0 or L1 may wanted to inject into
* L2 to IDT_VECTORING_INFO_FIELD.
@@ -4772,7 +4775,6 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
vm_exit_reason, exit_intr_info);
vmcs12->vm_exit_intr_info = exit_intr_info;
- vmcs12->vm_exit_instruction_len = exit_insn_len;
vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
/*
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 2/3] KVM: nVMX: Don't clobber VM-Entry instruction length when saving soft INTn
2026-10-23 0:37 [PATCH v2 0/3] KVM: nVMX: Don't clobber VM-Entry instruction length on soft INTn exits ma.mandourr
2026-10-23 0:37 ` [PATCH v2 1/3] KVM: nVMX: Fill VM-Exit instruction length before saving pending event ma.mandourr
@ 2026-10-23 0:37 ` ma.mandourr
2026-10-23 0:37 ` [PATCH v2 3/3] KVM: selftests: Verify nested VM-Exits while vectoring INT3 and INTn ma.mandourr
2 siblings, 0 replies; 4+ messages in thread
From: ma.mandourr @ 2026-10-23 0:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, ma.mandourr
From: Mahmoud Abumandour <ma.mandourr@gmail.com>
When a nested VM-Exit occurs while L2 is vectoring a software interrupt,
save the INTn's length in vmcs12's VM-Exit instruction length, as is
done for software exceptions, instead of VM-Entry instruction length.
Fixes: 5f3d5799974b ("KVM: nVMX: Rework event injection and recovery")
Signed-off-by: Mahmoud Abumandour <ma.mandourr@gmail.com>
---
arch/x86/kvm/vmx/nested.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 6f7c00083beb..4286b0503046 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -4016,7 +4016,7 @@ static void vmcs12_save_pending_event(struct kvm_vcpu *vcpu,
if (vcpu->arch.interrupt.soft) {
idt_vectoring |= INTR_TYPE_SOFT_INTR;
- vmcs12->vm_entry_instruction_len =
+ vmcs12->vm_exit_instruction_len =
vcpu->arch.event_exit_inst_len;
} else
idt_vectoring |= INTR_TYPE_EXT_INTR;
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 3/3] KVM: selftests: Verify nested VM-Exits while vectoring INT3 and INTn
2026-10-23 0:37 [PATCH v2 0/3] KVM: nVMX: Don't clobber VM-Entry instruction length on soft INTn exits ma.mandourr
2026-10-23 0:37 ` [PATCH v2 1/3] KVM: nVMX: Fill VM-Exit instruction length before saving pending event ma.mandourr
2026-10-23 0:37 ` [PATCH v2 2/3] KVM: nVMX: Don't clobber VM-Entry instruction length when saving soft INTn ma.mandourr
@ 2026-10-23 0:37 ` ma.mandourr
2 siblings, 0 replies; 4+ messages in thread
From: ma.mandourr @ 2026-10-23 0:37 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, ma.mandourr
From: Mahmoud Abumandour <ma.mandourr@gmail.com>
Verify that a VM-Exit while L2 is vectoring INT3 or INTn through the
empty IDT reports the event and its instruction length, and leaves the
VM-Entry instruction length alone. Only VMX is tested, as both lengths
are VMX fields.
Assisted-by: LLM
Signed-off-by: Mahmoud Abumandour <ma.mandourr@gmail.com>
---
.../kvm/x86/nested_exceptions_test.c | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/tools/testing/selftests/kvm/x86/nested_exceptions_test.c b/tools/testing/selftests/kvm/x86/nested_exceptions_test.c
index f47432526ea1..9311af590566 100644
--- a/tools/testing/selftests/kvm/x86/nested_exceptions_test.c
+++ b/tools/testing/selftests/kvm/x86/nested_exceptions_test.c
@@ -40,12 +40,25 @@
#define GP_ERROR_CODE_INTEL ((SS_VECTOR * 8) | ERROR_CODE_IDT_FLAG | ERROR_CODE_EXT_FLAG)
#define GP_ERROR_CODE_ZHAOXIN ((SS_VECTOR * 8) | ERROR_CODE_IDT_FLAG)
+/* No "External event" flag, as INT3 and INTn are software events. */
+#define GP_ERROR_CODE_SOFT_INT(vector) (((vector) * 8) | ERROR_CODE_IDT_FLAG)
+
/*
* Intel and AMD both shove '0' into the error code on #DF, regardless of what
* led to the double fault.
*/
#define DF_ERROR_CODE 0
+/* Arbitrary, any vector #GPs with the empty IDT. */
+#define INTN_VECTOR 0x40
+
+#define INTR_INFO_VALID_MASK BIT(31)
+#define INTR_TYPE_SOFT_INTR (4 << 8)
+#define INTR_TYPE_SOFT_EXCEPTION (6 << 8)
+
+/* Arbitrary, but not the length of INT3 or INTn. */
+#define VM_ENTRY_INSN_LEN 7
+
#define INTERCEPT_SS (BIT_ULL(SS_VECTOR))
#define INTERCEPT_SS_DF (INTERCEPT_SS | BIT_ULL(DF_VECTOR))
#define INTERCEPT_SS_GP_DF (INTERCEPT_SS_DF | BIT_ULL(GP_VECTOR))
@@ -70,6 +83,16 @@ static void l2_ss_injected_tf_test(void)
GUEST_SYNC(FAKE_TRIPLE_FAULT_VECTOR);
}
+static void l2_int3_test(void)
+{
+ asm volatile("int3");
+}
+
+static void l2_intn_test(void)
+{
+ asm volatile("int $" __stringify(INTN_VECTOR));
+}
+
static void svm_run_l2(struct svm_test_data *svm, void *l2_code, int vector,
u32 error_code)
{
@@ -127,6 +150,18 @@ static void vmx_run_l2(void *l2_code, int vector, u32 error_code)
GUEST_ASSERT(!vmread(GUEST_INTERRUPTIBILITY_INFO));
}
+static void vmx_run_l2_soft_int(void *l2_code, u32 type, int vector,
+ u32 insn_len)
+{
+ vmwrite(VM_ENTRY_INSTRUCTION_LEN, VM_ENTRY_INSN_LEN);
+ vmx_run_l2(l2_code, GP_VECTOR, GP_ERROR_CODE_SOFT_INT(vector));
+
+ GUEST_ASSERT_EQ(vmread(IDT_VECTORING_INFO_FIELD),
+ INTR_INFO_VALID_MASK | type | vector);
+ GUEST_ASSERT_EQ(vmread(VM_EXIT_INSTRUCTION_LEN), insn_len);
+ GUEST_ASSERT_EQ(vmread(VM_ENTRY_INSTRUCTION_LEN), VM_ENTRY_INSN_LEN);
+}
+
static void l1_vmx_code(struct vmx_pages *vmx)
{
prepare_for_vmx_operation(vmx);
@@ -146,6 +181,10 @@ static void l1_vmx_code(struct vmx_pages *vmx)
vmx_run_l2(l2_ss_injected_gp_test, GP_VECTOR,
host_cpu_is_zhaoxin ? GP_ERROR_CODE_ZHAOXIN : GP_ERROR_CODE_INTEL);
+ /* INT3 and INTn also #GP, due to the empty IDT. */
+ vmx_run_l2_soft_int(l2_int3_test, INTR_TYPE_SOFT_EXCEPTION, BP_VECTOR, 1);
+ vmx_run_l2_soft_int(l2_intn_test, INTR_TYPE_SOFT_INTR, INTN_VECTOR, 2);
+
vmwrite(EXCEPTION_BITMAP, INTERCEPT_SS_DF);
vmx_run_l2(l2_ss_injected_df_test, DF_VECTOR, DF_ERROR_CODE);
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-23 0:37 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-23 0:37 [PATCH v2 0/3] KVM: nVMX: Don't clobber VM-Entry instruction length on soft INTn exits ma.mandourr
2026-10-23 0:37 ` [PATCH v2 1/3] KVM: nVMX: Fill VM-Exit instruction length before saving pending event ma.mandourr
2026-10-23 0:37 ` [PATCH v2 2/3] KVM: nVMX: Don't clobber VM-Entry instruction length when saving soft INTn ma.mandourr
2026-10-23 0:37 ` [PATCH v2 3/3] KVM: selftests: Verify nested VM-Exits while vectoring INT3 and INTn ma.mandourr
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®