| From ada33297c8f7efa38a5100d5dde191508fc0254b Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 14 Aug 2025 17:12:02 -0700 |
| Subject: KVM: VMX: Extract checking of guest's DEBUGCTL into helper |
| |
| From: Sean Christopherson <seanjc@google.com> |
| |
| [ Upstream commit 8a4351ac302cd8c19729ba2636acfd0467c22ae8 ] |
| |
| Move VMX's logic to check DEBUGCTL values into a standalone helper so that |
| the code can be used by nested VM-Enter to apply the same logic to the |
| value being loaded from vmcs12. |
| |
| KVM needs to explicitly check vmcs12->guest_ia32_debugctl on nested |
| VM-Enter, as hardware may support features that KVM does not, i.e. relying |
| on hardware to detect invalid guest state will result in false negatives. |
| Unfortunately, that means applying KVM's funky suppression of BTF and LBR |
| to vmcs12 so as not to break existing guests. |
| |
| No functional change intended. |
| |
| Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com> |
| Link: https://lore.kernel.org/r/20250610232010.162191-6-seanjc@google.com |
| Stable-dep-of: 7d0cce6cbe71 ("KVM: VMX: Wrap all accesses to IA32_DEBUGCTL with getter/setter APIs") |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| Signed-off-by: Sean Christopherson <seanjc@google.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/x86/kvm/vmx/vmx.c | 29 +++++++++++++++++------------ |
| 1 file changed, 17 insertions(+), 12 deletions(-) |
| |
| diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c |
| index 9445def2b3d2..6517b9d929bf 100644 |
| --- a/arch/x86/kvm/vmx/vmx.c |
| +++ b/arch/x86/kvm/vmx/vmx.c |
| @@ -2071,6 +2071,19 @@ static u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated |
| return debugctl; |
| } |
| |
| +static bool vmx_is_valid_debugctl(struct kvm_vcpu *vcpu, u64 data, |
| + bool host_initiated) |
| +{ |
| + u64 invalid; |
| + |
| + invalid = data & ~vmx_get_supported_debugctl(vcpu, host_initiated); |
| + if (invalid & (DEBUGCTLMSR_BTF | DEBUGCTLMSR_LBR)) { |
| + kvm_pr_unimpl_wrmsr(vcpu, MSR_IA32_DEBUGCTLMSR, data); |
| + invalid &= ~(DEBUGCTLMSR_BTF | DEBUGCTLMSR_LBR); |
| + } |
| + return !invalid; |
| +} |
| + |
| /* |
| * Writes msr value into the appropriate "register". |
| * Returns 0 on success, non-0 otherwise. |
| @@ -2139,19 +2152,12 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) |
| } |
| vmcs_writel(GUEST_SYSENTER_ESP, data); |
| break; |
| - case MSR_IA32_DEBUGCTLMSR: { |
| - u64 invalid; |
| - |
| - invalid = data & ~vmx_get_supported_debugctl(vcpu, msr_info->host_initiated); |
| - if (invalid & (DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR)) { |
| - kvm_pr_unimpl_wrmsr(vcpu, msr_index, data); |
| - data &= ~(DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR); |
| - invalid &= ~(DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR); |
| - } |
| - |
| - if (invalid) |
| + case MSR_IA32_DEBUGCTLMSR: |
| + if (!vmx_is_valid_debugctl(vcpu, data, msr_info->host_initiated)) |
| return 1; |
| |
| + data &= vmx_get_supported_debugctl(vcpu, msr_info->host_initiated); |
| + |
| if (is_guest_mode(vcpu) && get_vmcs12(vcpu)->vm_exit_controls & |
| VM_EXIT_SAVE_DEBUG_CONTROLS) |
| get_vmcs12(vcpu)->guest_ia32_debugctl = data; |
| @@ -2161,7 +2167,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) |
| (data & DEBUGCTLMSR_LBR)) |
| intel_pmu_create_guest_lbr_event(vcpu); |
| return 0; |
| - } |
| case MSR_IA32_BNDCFGS: |
| if (!kvm_mpx_supported() || |
| (!msr_info->host_initiated && |
| -- |
| 2.50.1 |
| |