Skip to content

Commit 217463a

Browse files
committed
KVM: SVM: Add a helper to detect VMRUN failures
Add a helper to detect VMRUN failures so that KVM can guard against its own long-standing bug, where KVM neglects to set exitcode[63:32] when synthesizing a nested VMFAIL_INVALID VM-Exit. This will allow fixing KVM's mess of treating exitcode as two separate 32-bit values without breaking KVM-on-KVM when running on an older, unfixed KVM. Cc: Jim Mattson <jmattson@google.com> Cc: Yosry Ahmed <yosry.ahmed@linux.dev> Reviewed-by: Yosry Ahmed <yosry.ahmed@linux.dev> Link: https://patch.msgid.link/20251230211347.4099600-2-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent d23051f commit 217463a

3 files changed

Lines changed: 14 additions & 11 deletions

File tree

arch/x86/kvm/svm/nested.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,7 +1167,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm)
11671167
vmcb12->control.exit_info_1 = vmcb02->control.exit_info_1;
11681168
vmcb12->control.exit_info_2 = vmcb02->control.exit_info_2;
11691169

1170-
if (vmcb12->control.exit_code != SVM_EXIT_ERR)
1170+
if (!svm_is_vmrun_failure(vmcb12->control.exit_code))
11711171
nested_save_pending_event_to_vmcb12(svm, vmcb12);
11721172

11731173
if (guest_cpu_cap_has(vcpu, X86_FEATURE_NRIPS))
@@ -1463,30 +1463,28 @@ static int nested_svm_intercept(struct vcpu_svm *svm)
14631463
u32 exit_code = svm->vmcb->control.exit_code;
14641464
int vmexit = NESTED_EXIT_HOST;
14651465

1466+
if (svm_is_vmrun_failure(exit_code))
1467+
return NESTED_EXIT_DONE;
1468+
14661469
switch (exit_code) {
14671470
case SVM_EXIT_MSR:
14681471
vmexit = nested_svm_exit_handled_msr(svm);
14691472
break;
14701473
case SVM_EXIT_IOIO:
14711474
vmexit = nested_svm_intercept_ioio(svm);
14721475
break;
1473-
case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: {
1476+
case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f:
14741477
/*
14751478
* Host-intercepted exceptions have been checked already in
14761479
* nested_svm_exit_special. There is nothing to do here,
14771480
* the vmexit is injected by svm_check_nested_events.
14781481
*/
14791482
vmexit = NESTED_EXIT_DONE;
14801483
break;
1481-
}
1482-
case SVM_EXIT_ERR: {
1483-
vmexit = NESTED_EXIT_DONE;
1484-
break;
1485-
}
1486-
default: {
1484+
default:
14871485
if (vmcb12_is_intercept(&svm->nested.ctl, exit_code))
14881486
vmexit = NESTED_EXIT_DONE;
1489-
}
1487+
break;
14901488
}
14911489

14921490
return vmexit;

arch/x86/kvm/svm/svm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3564,7 +3564,7 @@ static int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
35643564
return 1;
35653565
}
35663566

3567-
if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
3567+
if (svm_is_vmrun_failure(svm->vmcb->control.exit_code)) {
35683568
kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
35693569
kvm_run->fail_entry.hardware_entry_failure_reason
35703570
= svm->vmcb->control.exit_code;
@@ -4346,7 +4346,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
43464346

43474347
/* Track VMRUNs that have made past consistency checking */
43484348
if (svm->nested.nested_run_pending &&
4349-
svm->vmcb->control.exit_code != SVM_EXIT_ERR)
4349+
!svm_is_vmrun_failure(svm->vmcb->control.exit_code))
43504350
++vcpu->stat.nested_run;
43514351

43524352
svm->nested.nested_run_pending = 0;

arch/x86/kvm/svm/svm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,11 @@ static __always_inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu)
425425
return container_of(vcpu, struct vcpu_svm, vcpu);
426426
}
427427

428+
static inline bool svm_is_vmrun_failure(u64 exit_code)
429+
{
430+
return (u32)exit_code == (u32)SVM_EXIT_ERR;
431+
}
432+
428433
/*
429434
* Only the PDPTRs are loaded on demand into the shadow MMU. All other
430435
* fields are synchronized on VM-Exit, because accessing the VMCB is cheap.

0 commit comments

Comments
 (0)