From: Jim Mattson <jmattson@google.com>
To: Sean Christopherson <seanjc@google.com>,
Paolo Bonzini <pbonzini@redhat.com>
Cc: Jim Mattson <jmattson@google.com>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Yosry Ahmed <yosry@kernel.org>, Like Xu <likexu@tencent.com>,
stable@vger.kernel.org
Subject: [PATCH 1/4] KVM: SVM: Always update LBR MSR intercepts on full MSR intercept recalc
Date: Tue, 20 Oct 2026 16:45:27 -0700 [thread overview]
Message-ID: <20261020234535.3182385-2-jmattson@google.com> (raw)
In-Reply-To: <20261020234535.3182385-1-jmattson@google.com>
Split the "already up-to-date" check out of the code that writes the LBR
MSR intercepts, and write the intercepts unconditionally from
svm_recalc_msr_intercepts(), so that changes to userspace MSR filters are
reflected in the MSR permissions map.
svm_recalc_msr_intercepts() is invoked in response to
KVM_REQ_RECALC_INTERCEPTS, which is raised on MSR filter updates. But
svm->lbr_msrs_intercepted tracks only the interception KVM wants, not
what is actually in the bitmap after the filter is applied. If the LBR
MSRs are passed through when userspace installs a filter that denies
them, the early return leaves them passed through, and the guest can
access them without exiting to userspace. Conversely, if a filter
forced interception when LBR virtualization was enabled, relaxing the
filter leaves the MSRs needlessly intercepted. Either way, the bitmap
remains stale until the next change to LBR_CTL.
Full intercept recalculations are rare (e.g. on RESET/INIT, EFER.SVME
toggles, and CPUID, PERF_CAPABILITIES, and MSR filter updates), and
never happen on nested VMRUN or #VMEXIT, so writing the intercepts there
does not reintroduce the redundant per-VMRUN bitmap updates that the
check was added to avoid. And because svm_recalc_msr_intercepts()
already unconditionally writes the intercepts for many other MSRs (and
thus marks Hyper-V's nested enlightenments dirty), writing the LBR MSR
intercepts there doesn't introduce any new invalidations.
Add a comment to clarify that lbr_msrs_intercepted reflects KVM's
desired interception, not necessarily the state of the bitmap.
Fixes: 3fa05f96fc08 ("KVM: SVM: Fix redundant updates of LBR MSR intercepts")
Cc: stable@vger.kernel.org
Signed-off-by: Jim Mattson <jmattson@google.com>
---
arch/x86/kvm/svm/svm.c | 28 +++++++++++++++++++++++-----
arch/x86/kvm/svm/svm.h | 6 ++++++
2 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index fe0cba4731b2..55b3ee840365 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -721,14 +721,11 @@ void *svm_alloc_permissions_map(unsigned long size, gfp_t gfp_mask)
return pm;
}
-static void svm_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu)
+static void svm_set_lbr_msr_intercepts(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
bool intercept = !(svm->vmcb->control.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR);
- if (intercept == svm->lbr_msrs_intercepted)
- return;
-
svm_set_intercept_for_msr(vcpu, MSR_IA32_LASTBRANCHFROMIP, MSR_TYPE_RW, intercept);
svm_set_intercept_for_msr(vcpu, MSR_IA32_LASTBRANCHTOIP, MSR_TYPE_RW, intercept);
svm_set_intercept_for_msr(vcpu, MSR_IA32_LASTINTFROMIP, MSR_TYPE_RW, intercept);
@@ -740,6 +737,22 @@ static void svm_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu)
svm->lbr_msrs_intercepted = intercept;
}
+static void svm_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ bool intercept = !(svm->vmcb->control.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR);
+
+ /*
+ * Skip redundant updates from svm_update_lbrv(), e.g. on every nested
+ * VMRUN and #VMEXIT. Note, svm_recalc_msr_intercepts() updates the
+ * bitmap unconditionally, as userspace MSR filters may have changed.
+ */
+ if (intercept == svm->lbr_msrs_intercepted)
+ return;
+
+ svm_set_lbr_msr_intercepts(vcpu);
+}
+
void svm_vcpu_free_msrpm(void *msrpm)
{
__free_pages(virt_to_page(msrpm), get_order(MSRPM_SIZE));
@@ -795,8 +808,13 @@ static void svm_recalc_msr_intercepts(struct kvm_vcpu *vcpu)
svm_disable_intercept_for_msr(vcpu, MSR_SYSCALL_MASK, MSR_TYPE_RW);
#endif
+ /*
+ * Unconditionally refresh the LBR MSR intercepts, as userspace MSR
+ * filters may have changed, in which case the bitmap may be stale even
+ * if KVM's desired interception hasn't changed.
+ */
if (lbrv)
- svm_recalc_lbr_msr_intercepts(vcpu);
+ svm_set_lbr_msr_intercepts(vcpu);
if (cpu_feature_enabled(X86_FEATURE_IBPB))
svm_set_intercept_for_msr(vcpu, MSR_IA32_PRED_CMD, MSR_TYPE_W,
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 84f19026d3e8..62e08d6d4706 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -364,6 +364,12 @@ struct vcpu_svm {
bool avic_irq_window;
bool x2avic_msrs_intercepted;
+
+ /*
+ * True if KVM wants the LBR MSRs to be intercepted. Note, userspace MSR
+ * filters may force interception regardless, i.e. this doesn't
+ * necessarily reflect the state of the MSR bitmap.
+ */
bool lbr_msrs_intercepted;
/* Guest GIF value, used when vGIF is not enabled */
--
2.56.0.212.g129ede20d9-goog
next prev parent reply other threads:[~2026-10-20 23:45 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 23:45 [PATCH 0/4] KVM: x86: Honor userspace MSR filter changes for passed-through LBR MSRs Jim Mattson
2026-10-20 23:45 ` Jim Mattson [this message]
2026-10-21 0:09 ` [PATCH 1/4] KVM: SVM: Always update LBR MSR intercepts on full MSR intercept recalc Yosry Ahmed
2026-10-20 23:45 ` [PATCH 2/4] KVM: VMX: Refresh " Jim Mattson
2026-10-20 23:45 ` [PATCH 3/4] KVM: selftests: Add a helper to request XSAVE permission without skipping Jim Mattson
2026-10-20 23:45 ` [PATCH 4/4] KVM: selftests: Verify MSR filter changes apply to passed-through MSRs Jim Mattson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261020234535.3182385-2-jmattson@google.com \
--to=jmattson@google.com \
--cc=kvm@vger.kernel.org \
--cc=likexu@tencent.com \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
--cc=stable@vger.kernel.org \
--cc=yosry@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®