mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
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>
This commit is contained in:
parent
d23051f59a
commit
217463aa32
|
|
@ -1167,7 +1167,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm)
|
|||
vmcb12->control.exit_info_1 = vmcb02->control.exit_info_1;
|
||||
vmcb12->control.exit_info_2 = vmcb02->control.exit_info_2;
|
||||
|
||||
if (vmcb12->control.exit_code != SVM_EXIT_ERR)
|
||||
if (!svm_is_vmrun_failure(vmcb12->control.exit_code))
|
||||
nested_save_pending_event_to_vmcb12(svm, vmcb12);
|
||||
|
||||
if (guest_cpu_cap_has(vcpu, X86_FEATURE_NRIPS))
|
||||
|
|
@ -1463,6 +1463,9 @@ static int nested_svm_intercept(struct vcpu_svm *svm)
|
|||
u32 exit_code = svm->vmcb->control.exit_code;
|
||||
int vmexit = NESTED_EXIT_HOST;
|
||||
|
||||
if (svm_is_vmrun_failure(exit_code))
|
||||
return NESTED_EXIT_DONE;
|
||||
|
||||
switch (exit_code) {
|
||||
case SVM_EXIT_MSR:
|
||||
vmexit = nested_svm_exit_handled_msr(svm);
|
||||
|
|
@ -1470,7 +1473,7 @@ static int nested_svm_intercept(struct vcpu_svm *svm)
|
|||
case SVM_EXIT_IOIO:
|
||||
vmexit = nested_svm_intercept_ioio(svm);
|
||||
break;
|
||||
case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: {
|
||||
case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f:
|
||||
/*
|
||||
* Host-intercepted exceptions have been checked already in
|
||||
* nested_svm_exit_special. There is nothing to do here,
|
||||
|
|
@ -1478,15 +1481,10 @@ static int nested_svm_intercept(struct vcpu_svm *svm)
|
|||
*/
|
||||
vmexit = NESTED_EXIT_DONE;
|
||||
break;
|
||||
}
|
||||
case SVM_EXIT_ERR: {
|
||||
vmexit = NESTED_EXIT_DONE;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
default:
|
||||
if (vmcb12_is_intercept(&svm->nested.ctl, exit_code))
|
||||
vmexit = NESTED_EXIT_DONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return vmexit;
|
||||
|
|
|
|||
|
|
@ -3564,7 +3564,7 @@ static int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
|
||||
if (svm_is_vmrun_failure(svm->vmcb->control.exit_code)) {
|
||||
kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
|
||||
kvm_run->fail_entry.hardware_entry_failure_reason
|
||||
= svm->vmcb->control.exit_code;
|
||||
|
|
@ -4346,7 +4346,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
|
|||
|
||||
/* Track VMRUNs that have made past consistency checking */
|
||||
if (svm->nested.nested_run_pending &&
|
||||
svm->vmcb->control.exit_code != SVM_EXIT_ERR)
|
||||
!svm_is_vmrun_failure(svm->vmcb->control.exit_code))
|
||||
++vcpu->stat.nested_run;
|
||||
|
||||
svm->nested.nested_run_pending = 0;
|
||||
|
|
|
|||
|
|
@ -425,6 +425,11 @@ static __always_inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu)
|
|||
return container_of(vcpu, struct vcpu_svm, vcpu);
|
||||
}
|
||||
|
||||
static inline bool svm_is_vmrun_failure(u64 exit_code)
|
||||
{
|
||||
return (u32)exit_code == (u32)SVM_EXIT_ERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only the PDPTRs are loaded on demand into the shadow MMU. All other
|
||||
* fields are synchronized on VM-Exit, because accessing the VMCB is cheap.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user