Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+14 -11
+7 -9
arch/x86/kvm/svm/nested.c
··· 1167 1167 vmcb12->control.exit_info_1 = vmcb02->control.exit_info_1; 1168 1168 vmcb12->control.exit_info_2 = vmcb02->control.exit_info_2; 1169 1169 1170 - if (vmcb12->control.exit_code != SVM_EXIT_ERR) 1170 + if (!svm_is_vmrun_failure(vmcb12->control.exit_code)) 1171 1171 nested_save_pending_event_to_vmcb12(svm, vmcb12); 1172 1172 1173 1173 if (guest_cpu_cap_has(vcpu, X86_FEATURE_NRIPS)) ··· 1463 1463 u32 exit_code = svm->vmcb->control.exit_code; 1464 1464 int vmexit = NESTED_EXIT_HOST; 1465 1465 1466 + if (svm_is_vmrun_failure(exit_code)) 1467 + return NESTED_EXIT_DONE; 1468 + 1466 1469 switch (exit_code) { 1467 1470 case SVM_EXIT_MSR: 1468 1471 vmexit = nested_svm_exit_handled_msr(svm); ··· 1473 1470 case SVM_EXIT_IOIO: 1474 1471 vmexit = nested_svm_intercept_ioio(svm); 1475 1472 break; 1476 - case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: { 1473 + case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: 1477 1474 /* 1478 1475 * Host-intercepted exceptions have been checked already in 1479 1476 * nested_svm_exit_special. There is nothing to do here, ··· 1481 1478 */ 1482 1479 vmexit = NESTED_EXIT_DONE; 1483 1480 break; 1484 - } 1485 - case SVM_EXIT_ERR: { 1486 - vmexit = NESTED_EXIT_DONE; 1487 - break; 1488 - } 1489 - default: { 1481 + default: 1490 1482 if (vmcb12_is_intercept(&svm->nested.ctl, exit_code)) 1491 1483 vmexit = NESTED_EXIT_DONE; 1492 - } 1484 + break; 1493 1485 } 1494 1486 1495 1487 return vmexit;
+2 -2
arch/x86/kvm/svm/svm.c
··· 3564 3564 return 1; 3565 3565 } 3566 3566 3567 - if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) { 3567 + if (svm_is_vmrun_failure(svm->vmcb->control.exit_code)) { 3568 3568 kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY; 3569 3569 kvm_run->fail_entry.hardware_entry_failure_reason 3570 3570 = svm->vmcb->control.exit_code; ··· 4346 4346 4347 4347 /* Track VMRUNs that have made past consistency checking */ 4348 4348 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)) 4350 4350 ++vcpu->stat.nested_run; 4351 4351 4352 4352 svm->nested.nested_run_pending = 0;
+5
arch/x86/kvm/svm/svm.h
··· 425 425 return container_of(vcpu, struct vcpu_svm, vcpu); 426 426 } 427 427 428 + static inline bool svm_is_vmrun_failure(u64 exit_code) 429 + { 430 + return (u32)exit_code == (u32)SVM_EXIT_ERR; 431 + } 432 + 428 433 /* 429 434 * Only the PDPTRs are loaded on demand into the shadow MMU. All other 430 435 * fields are synchronized on VM-Exit, because accessing the VMCB is cheap.