On Thu, Nov 20, 2025 at 01:06:55PM -0500, Sasha Levin wrote:
From: Yosry Ahmed yosry.ahmed@linux.dev
[ Upstream commit dc55b3c3f61246e483e50c85d8d5366f9567e188 ]
The APM lists the DbgCtlMsr field as being tracked by the VMCB_LBR clean bit. Always clear the bit when MSR_IA32_DEBUGCTLMSR is updated.
The history is complicated, it was correctly cleared for L1 before commit 1d5a1b5860ed ("KVM: x86: nSVM: correctly virtualize LBR msrs when L2 is running"). At that point svm_set_msr() started to rely on svm_update_lbrv() to clear the bit, but when nested virtualization is enabled the latter does not always clear it even if MSR_IA32_DEBUGCTLMSR changed. Go back to clearing it directly in svm_set_msr().
Fixes: 1d5a1b5860ed ("KVM: x86: nSVM: correctly virtualize LBR msrs when L2 is running") Reported-by: Matteo Rizzo matteorizzo@google.com Reported-by: evn@google.com Co-developed-by: Jim Mattson jmattson@google.com Signed-off-by: Jim Mattson jmattson@google.com Signed-off-by: Yosry Ahmed yosry.ahmed@linux.dev Link: https://patch.msgid.link/20251108004524.1600006-2-yosry.ahmed@linux.dev Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini pbonzini@redhat.com [ Open coded svm_get_lbr_vmcb() call ] Signed-off-by: Sasha Levin sashal@kernel.org
arch/x86/kvm/svm/svm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index f56dcbbbf7341..00fb1c18e23a8 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3053,11 +3053,17 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) if (data & DEBUGCTL_RESERVED_BITS) return 1;
if (svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK)
if (svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK) {if (svm->vmcb->save.dbgctl == data)break; svm->vmcb->save.dbgctl = data;
else
} else {if (svm->vmcb01.ptr->save.dbgctl == data)break; svm->vmcb01.ptr->save.dbgctl = data;}
vmcb_mark_dirty(svm->vmcb, VMCB_LBR);
The patch LGTM, thanks. FWIW, the call to vmcb_mark_dirty() is the real fix, the above changes are just a microoptimization, so we can just drop it if we want to keep it simple.
svm_update_lbrv(vcpu);break; -- 2.51.0