KVM: nVMX: pass PFERR_USER_MASK to MMU on EPT violations

For EPT, PFERR_USER_MASK refers not to the CPL of the guest,
but to the AND of the U bits encountered while walking guest
page tables; this is consistent with how MBEC differentiates
between XS and XU.  This is available through the
"advanced vmexit information for EPT violations" feature.

Tested-by: David Riley <d.riley@proxmox.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2026-04-08 11:42:07 -04:00
parent a0efd8cb22
commit 9c167cb3c1
2 changed files with 19 additions and 3 deletions

View File

@ -100,9 +100,15 @@ static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
error_code |= (exit_qualification & EPT_VIOLATION_PROT_USER_EXEC)
? PFERR_PRESENT_MASK : 0;
if (exit_qualification & EPT_VIOLATION_GVA_IS_VALID)
error_code |= (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) ?
PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK;
if (exit_qualification & EPT_VIOLATION_GVA_IS_VALID) {
if (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) {
error_code |= PFERR_GUEST_FINAL_MASK;
if (exit_qualification & EPT_VIOLATION_GVA_USER)
error_code |= PFERR_USER_MASK;
} else {
error_code |= PFERR_GUEST_PAGE_MASK;
}
}
if (vt_is_tdx_private_gpa(vcpu->kvm, gpa))
error_code |= PFERR_PRIVATE_ACCESS;

View File

@ -2790,6 +2790,16 @@ static int setup_vmcs_config(struct vmcs_config *vmcs_conf,
vmx_cap->vpid = 0;
}
/*
* Virtualizing MBEC requires advanced vmexit information in order to
* distinguish supervisor and user accesses. For simplicity and clarity
* disable MBEC entirely if advanced vmexit information is not available,
* this way mbec=1 in the kvm_intel module parameters implies availability
* to nested guests as well.
*/
if (!(vmx_cap->ept & VMX_EPT_ADVANCED_VMEXIT_INFO_BIT))
_cpu_based_2nd_exec_control &= ~SECONDARY_EXEC_MODE_BASED_EPT_EXEC;
if (!cpu_has_sgx())
_cpu_based_2nd_exec_control &= ~SECONDARY_EXEC_ENCLS_EXITING;