* [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 related [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 related [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 related [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 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.