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 Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx/common.h | 12 +++++++++--- arch/x86/kvm/vmx/vmx.c | 10 ++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/vmx/common.h b/arch/x86/kvm/vmx/common.h index 40fa72f31fc7..08005676702c 100644 --- a/arch/x86/kvm/vmx/common.h +++ b/arch/x86/kvm/vmx/common.h @@ -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; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index f1d616f928a1..9d5cd358ccc5 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -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; -- 2.54.0