[PATCH 01/45] KVM: nVMX/nSVM: check unconditionally whether CR3 is valid
From: Paolo Bonzini
Date: Mon Nov 02 2026 - 15:53:17 EST
nested_vmcb_check_save() checks CR3 legality only if long mode is active,
but it really needs to be checked in all cases - the check uses must be
zero bits of the host, and indeed nested_svm_load_cr3() later will
reject illegal CR3 in every mode. Move the check earlier, and thus out
of nested_svm_load_cr3().
Likewise for nested_vmx_load_cr3() and nested_vmx_check_guest_state().
Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
arch/x86/kvm/svm/nested.c | 9 +++------
arch/x86/kvm/vmx/nested.c | 8 ++------
2 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index af0ef678433d..fedddcd1cc96 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -443,7 +443,8 @@ static bool nested_vmcb_check_save(struct kvm_vcpu *vcpu,
return false;
if (CC((save->cr0 & X86_CR0_CD) == 0 && (save->cr0 & X86_CR0_NW)) ||
- CC(save->cr0 & ~0xffffffffULL))
+ CC(save->cr0 & ~0xffffffffULL) ||
+ CC(!kvm_vcpu_is_legal_cr3(vcpu, save->cr3)))
return false;
if (CC(!kvm_dr6_valid(save->dr6)) || CC(!kvm_dr7_valid(save->dr7)))
@@ -456,8 +457,7 @@ static bool nested_vmcb_check_save(struct kvm_vcpu *vcpu,
*/
if ((save->efer & EFER_LME) && (save->cr0 & X86_CR0_PG)) {
if (CC(!(save->cr4 & X86_CR4_PAE)) ||
- CC(!(save->cr0 & X86_CR0_PE)) ||
- CC(!kvm_vcpu_is_legal_cr3(vcpu, save->cr3)))
+ CC(!(save->cr0 & X86_CR0_PE)))
return false;
if (CC((save->cs.attrib & SVM_SELECTOR_L_MASK) &&
@@ -717,9 +717,6 @@ static void nested_svm_transition_tlb_flush(struct kvm_vcpu *vcpu)
static int nested_svm_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3,
bool nested_npt, bool reload_pdptrs)
{
- if (CC(!kvm_vcpu_is_legal_cr3(vcpu, cr3)))
- return -EINVAL;
-
if (reload_pdptrs && is_pae_paging(vcpu)) {
if (nested_npt)
kvm_register_mark_for_reload(vcpu, VCPU_REG_PDPTR);
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 9b0bfa2f854c..b133e53fde39 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -1235,11 +1235,6 @@ static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3,
bool nested_ept, bool reload_pdptrs,
enum vm_entry_failure_code *entry_failure_code)
{
- if (CC(!kvm_vcpu_is_legal_cr3(vcpu, cr3))) {
- *entry_failure_code = ENTRY_FAIL_DEFAULT;
- return -EINVAL;
- }
-
/*
* If PAE paging and EPT are both on, CR3 is not used by the CPU and
* must not be dereferenced.
@@ -3323,7 +3318,8 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu,
*entry_failure_code = ENTRY_FAIL_DEFAULT;
if (CC(!nested_guest_cr0_valid(vcpu, vmcs12->guest_cr0)) ||
- CC(!nested_guest_cr4_valid(vcpu, vmcs12->guest_cr4)))
+ CC(!nested_guest_cr4_valid(vcpu, vmcs12->guest_cr4)) ||
+ CC(!kvm_vcpu_is_legal_cr3(vcpu, vmcs12->guest_cr3)))
return -EINVAL;
if (CC(vmcs12->guest_cr4 & X86_CR4_CET && !(vmcs12->guest_cr0 & X86_CR0_WP)))
--
2.52.0