* [PATCH 1/4] KVM: SVM: Always update LBR MSR intercepts on full MSR intercept recalc [not found] <20261020234535.3182385-1-jmattson@google.com> @ 2026-10-20 23:45 ` Jim Mattson 2026-10-21 0:09 ` Yosry Ahmed 2026-10-20 23:45 ` [PATCH 2/4] KVM: VMX: Refresh " Jim Mattson 1 sibling, 1 reply; 8+ messages in thread From: Jim Mattson @ 2026-10-20 23:45 UTC (permalink / raw) To: Sean Christopherson, Paolo Bonzini Cc: Jim Mattson, kvm, linux-kernel, Yosry Ahmed, Like Xu, stable 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 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] KVM: SVM: Always update LBR MSR intercepts on full MSR intercept recalc 2026-10-20 23:45 ` [PATCH 1/4] KVM: SVM: Always update LBR MSR intercepts on full MSR intercept recalc Jim Mattson @ 2026-10-21 0:09 ` Yosry Ahmed 2026-11-04 20:55 ` Sean Christopherson 0 siblings, 1 reply; 8+ messages in thread From: Yosry Ahmed @ 2026-10-21 0:09 UTC (permalink / raw) To: Jim Mattson Cc: Sean Christopherson, Paolo Bonzini, kvm, linux-kernel, Like Xu, stable On Tue, Oct 20, 2026 at 4:45 PM Jim Mattson <jmattson@google.com> wrote: > > 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; Hmm I was going to ask if we can set svm->lbr_msrs_intercepted based on whether or not svm_set_intercept_for_msr() actually set the intercept, so that it also captures intercepts due to MSR filtering. I assume that we didn't do this because MSR filters can result in different interception status for different LBR MSRs, and we don't want to track them individually? Hmm even if we do track them individually (e.g. as a bitmap), it would add a bit of complexity here because we'll need to plumb that into svm_set_intercept_for_msr(), right? I suppose if we go with "lbr_msrs_intercepted just means KVM wants to intercept", then we should probably rename it accordingly? > } > > +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 > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] KVM: SVM: Always update LBR MSR intercepts on full MSR intercept recalc 2026-10-21 0:09 ` Yosry Ahmed @ 2026-11-04 20:55 ` Sean Christopherson 0 siblings, 0 replies; 8+ messages in thread From: Sean Christopherson @ 2026-11-04 20:55 UTC (permalink / raw) To: Yosry Ahmed Cc: Jim Mattson, Paolo Bonzini, kvm, linux-kernel, Like Xu, stable On Tue, Oct 20, 2026, Yosry Ahmed wrote: > On Tue, Oct 20, 2026 at 4:45 PM Jim Mattson <jmattson@google.com> wrote: > > 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; > > Hmm I was going to ask if we can set svm->lbr_msrs_intercepted based > on whether or not svm_set_intercept_for_msr() actually set the > intercept, so that it also captures intercepts due to MSR filtering. I > assume that we didn't do this because MSR filters can result in > different interception status for different LBR MSRs, and we don't > want to track them individually? NAK. In the past, KVM had a bitmap to do exactly that, and it was a trainwreck. > Hmm even if we do track them individually (e.g. as a bitmap), it would > add a bit of complexity here because we'll need to plumb that into > svm_set_intercept_for_msr(), right? > > I suppose if we go with "lbr_msrs_intercepted just means KVM wants to > intercept", then we should probably rename it accordingly? Probably, but that can be done on top. And I'd like to change all of these flags (all two of them?) to be consistent. > > } > > > > +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); Eww. The naming is all kinda of funky, and I strongly dislike the duplicate code. E.g. svm_set_lbr_msr_intercepts() recalcs, it's not a pure "set". I'd much rather pass a @force param, e.g. diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index e6b8c0423813..2d70fb37103e 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -728,12 +728,12 @@ 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_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu, bool force) { 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) + if (intercept == svm->lbr_msrs_intercepted && !force) return; svm_set_intercept_for_msr(vcpu, MSR_IA32_LASTBRANCHFROMIP, MSR_TYPE_RW, intercept); @@ -747,6 +747,11 @@ 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) +{ + __svm_recalc_lbr_msr_intercepts(vcpu, false); +} + void svm_vcpu_free_msrpm(void *msrpm) { __free_pages(virt_to_page(msrpm), get_order(MSRPM_SIZE)); @@ -803,7 +808,7 @@ static void svm_recalc_msr_intercepts(struct kvm_vcpu *vcpu) #endif if (lbrv) - svm_recalc_lbr_msr_intercepts(vcpu); + __svm_recalc_lbr_msr_intercepts(vcpu, true); if (cpu_feature_enabled(X86_FEATURE_IBPB)) svm_set_intercept_for_msr(vcpu, MSR_IA32_PRED_CMD, MSR_TYPE_W, ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] KVM: VMX: Refresh LBR MSR intercepts on full MSR intercept recalc [not found] <20261020234535.3182385-1-jmattson@google.com> 2026-10-20 23:45 ` [PATCH 1/4] KVM: SVM: Always update LBR MSR intercepts on full MSR intercept recalc Jim Mattson @ 2026-10-20 23:45 ` Jim Mattson 2026-11-04 20:45 ` Sean Christopherson 1 sibling, 1 reply; 8+ messages in thread From: Jim Mattson @ 2026-10-20 23:45 UTC (permalink / raw) To: Sean Christopherson, Paolo Bonzini Cc: Jim Mattson, kvm, linux-kernel, Yosry Ahmed, Like Xu, stable Re-apply the LBR MSR intercepts in vmx_recalc_msr_intercepts() if the LBRs are currently passed through, so that changes to userspace MSR filters are reflected in the MSR bitmap. Unlike SVM, which can simply rewrite the intercepts in either direction, leave the bitmap alone if the LBRs aren't passed through, as a filter can only force interception, never prevent it, i.e. the bitmap is already correct. Note, clearing msr_passthrough to force vmx_passthrough_lbr_msrs() to re-apply the intercepts on the next VM-Enter isn't an option, as doing so would leave stale passthrough bits behind if the guest LBR event is no longer active. vmx_recalc_msr_intercepts() is invoked in response to KVM_REQ_RECALC_INTERCEPTS, which is raised on MSR filter updates, but it skips the LBR MSRs, and vmx_enable_lbr_msrs_passthrough() does nothing if lbr_desc->msr_passthrough is already set. If the LBR MSRs are passed through when userspace installs a filter that denies them, they remain passed through, and the guest can access them without exiting to userspace. Conversely, if a filter forced interception when the guest LBR event became active, relaxing the filter leaves the MSRs needlessly intercepted. Either way, the bitmap remains stale until the guest LBR event is torn down and recreated. Only x2APIC MSRs are exempt from userspace filtering (see kvm_msr_allowed() and the KVM_X86_SET_MSR_FILTER documentation), and the filter is honored when LBR passthrough is first enabled, so KVM's behavior shouldn't depend on whether the filter is set before or after the guest enables LBRs. Drop the LBR MSRs from the comment claiming that they can't be filtered by userspace, and clarify that lbr_desc.msr_passthrough tracks KVM's desired interception, which may not match the MSR bitmap when userspace filters are in play. Fixes: 9254beaafd12 ("KVM: vmx/pmu: Reduce the overhead of LBR pass-through or cancellation") Cc: stable@vger.kernel.org Signed-off-by: Jim Mattson <jmattson@google.com> --- arch/x86/kvm/vmx/pmu_intel.c | 20 +++++++++++++++++++- arch/x86/kvm/vmx/pmu_intel.h | 7 ++++++- arch/x86/kvm/vmx/vmx.c | 6 ++++-- arch/x86/kvm/vmx/vmx.h | 1 + 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 70a8c4816135..b945213f0b68 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -517,7 +517,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) memset(&lbr_desc->records, 0, sizeof(lbr_desc->records)); /* - * Setting passthrough of LBR MSRs is done only in the VM-Entry loop, + * LBR MSRs are initially passed through only in the VM-Entry loop (a + * full MSR intercept recalc merely refreshes an existing passthrough), * and PMU refresh is disallowed after the vCPU has run, i.e. this code * should never be reached while KVM is passing through MSRs. */ @@ -704,6 +705,23 @@ static inline void vmx_enable_lbr_msrs_passthrough(struct kvm_vcpu *vcpu) lbr_desc->msr_passthrough = true; } +/* + * Refresh the LBR MSR intercepts if the LBRs are passed through, so that + * changes to userspace MSR filters are reflected in the MSR bitmap. There's + * nothing to do if the LBRs are intercepted, as a filter can only force + * interception, never prevent it. + */ +void vmx_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu) +{ + struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); + + if (WARN_ON_ONCE(!lbr_desc)) + return; + + if (lbr_desc->msr_passthrough) + vmx_update_intercept_for_lbr_msrs(vcpu, false); +} + /* * Higher priority host perf events (e.g. cpu pinned) could reclaim the * pmu resources (e.g. LBR) that were assigned to the guest. This is diff --git a/arch/x86/kvm/vmx/pmu_intel.h b/arch/x86/kvm/vmx/pmu_intel.h index 5d9357640aa1..b553f63e19a6 100644 --- a/arch/x86/kvm/vmx/pmu_intel.h +++ b/arch/x86/kvm/vmx/pmu_intel.h @@ -34,7 +34,12 @@ struct lbr_desc { */ struct perf_event *event; - /* True if LBRs are marked as not intercepted in the MSR bitmap */ + /* + * True if KVM wants the LBR MSRs to be passed through, i.e. not + * intercepted. Note, userspace MSR filters may force interception of + * some or all LBR MSRs regardless, i.e. this doesn't necessarily + * reflect the state of the MSR bitmap. + */ bool msr_passthrough; }; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 612ab07d4100..1c190a6303a3 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -4347,11 +4347,13 @@ static void vmx_recalc_msr_intercepts(struct kvm_vcpu *vcpu) vmx_set_intercept_for_msr(vcpu, MSR_IA32_S_CET, MSR_TYPE_RW, intercept); } + vmx_recalc_lbr_msr_intercepts(vcpu); + vmx_recalc_pmu_msr_intercepts(vcpu); /* - * x2APIC and LBR MSR intercepts are modified on-demand and cannot be - * filtered by userspace. + * x2APIC intercepts are modified on-demand and cannot be filtered by + * userspace. */ } diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index dc8517f15bc4..ec6104b66009 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -667,6 +667,7 @@ static __always_inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu) void intel_pmu_cross_mapped_check(struct kvm_pmu *pmu); int intel_pmu_create_guest_lbr_event(struct kvm_vcpu *vcpu); void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu); +void vmx_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu); struct vmcs *alloc_vmcs_cpu(bool shadow, int cpu, gfp_t flags); void free_vmcs(struct vmcs *vmcs); -- 2.56.0.212.g129ede20d9-goog ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/4] KVM: VMX: Refresh LBR MSR intercepts on full MSR intercept recalc 2026-10-20 23:45 ` [PATCH 2/4] KVM: VMX: Refresh " Jim Mattson @ 2026-11-04 20:45 ` Sean Christopherson 2026-11-04 23:49 ` Jim Mattson 0 siblings, 1 reply; 8+ messages in thread From: Sean Christopherson @ 2026-11-04 20:45 UTC (permalink / raw) To: Jim Mattson Cc: Paolo Bonzini, kvm, linux-kernel, Yosry Ahmed, Like Xu, stable On Tue, Oct 20, 2026, Jim Mattson wrote: > Re-apply the LBR MSR intercepts in vmx_recalc_msr_intercepts() if the > LBRs are currently passed through, so that changes to userspace MSR > filters are reflected in the MSR bitmap. Unlike SVM, which can simply > rewrite the intercepts in either direction, leave the bitmap alone if > the LBRs aren't passed through, as a filter can only force interception, > never prevent it, i.e. the bitmap is already correct. Note, clearing > msr_passthrough to force vmx_passthrough_lbr_msrs() to re-apply the > intercepts on the next VM-Enter isn't an option, as doing so would > leave stale passthrough bits behind if the guest LBR event is no longer > active. > > vmx_recalc_msr_intercepts() is invoked in response to > KVM_REQ_RECALC_INTERCEPTS, which is raised on MSR filter updates, but it > skips the LBR MSRs, and vmx_enable_lbr_msrs_passthrough() does nothing > if lbr_desc->msr_passthrough is already set. If the LBR MSRs are passed > through when userspace installs a filter that denies them, they remain > passed through, and the guest can access them without exiting to > userspace. Conversely, if a filter forced interception when the guest > LBR event became active, relaxing the filter leaves the MSRs needlessly > intercepted. Either way, the bitmap remains stale until the guest LBR > event is torn down and recreated. > > Only x2APIC MSRs are exempt from userspace filtering (see > kvm_msr_allowed() and the KVM_X86_SET_MSR_FILTER documentation), and the > filter is honored when LBR passthrough is first enabled, so KVM's > behavior shouldn't depend on whether the filter is set before or after > the guest enables LBRs. Drop the LBR MSRs from the comment claiming > that they can't be filtered by userspace, and clarify that > lbr_desc.msr_passthrough tracks KVM's desired interception, which may > not match the MSR bitmap when userspace filters are in play. > > Fixes: 9254beaafd12 ("KVM: vmx/pmu: Reduce the overhead of LBR pass-through or cancellation") > Cc: stable@vger.kernel.org Meh, this isn't stable material. Unlike SVM, where LBR virtualization is tied to a pile of other crud, if userspace wants to filter LBRs on Intel it should just not expose LBRs in the first place. If it weren't for SVM, and the fact that avoiding the filters is actually more work, I probably would vote to fix the docs. > Signed-off-by: Jim Mattson <jmattson@google.com> > --- > arch/x86/kvm/vmx/pmu_intel.c | 20 +++++++++++++++++++- > arch/x86/kvm/vmx/pmu_intel.h | 7 ++++++- > arch/x86/kvm/vmx/vmx.c | 6 ++++-- > arch/x86/kvm/vmx/vmx.h | 1 + > 4 files changed, 30 insertions(+), 4 deletions(-) > > diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c > index 70a8c4816135..b945213f0b68 100644 > --- a/arch/x86/kvm/vmx/pmu_intel.c > +++ b/arch/x86/kvm/vmx/pmu_intel.c > @@ -517,7 +517,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) > memset(&lbr_desc->records, 0, sizeof(lbr_desc->records)); > > /* > - * Setting passthrough of LBR MSRs is done only in the VM-Entry loop, > + * LBR MSRs are initially passed through only in the VM-Entry loop (a > + * full MSR intercept recalc merely refreshes an existing passthrough), > * and PMU refresh is disallowed after the vCPU has run, i.e. this code > * should never be reached while KVM is passing through MSRs. > */ > @@ -704,6 +705,23 @@ static inline void vmx_enable_lbr_msrs_passthrough(struct kvm_vcpu *vcpu) > lbr_desc->msr_passthrough = true; > } > > +/* > + * Refresh the LBR MSR intercepts if the LBRs are passed through, so that > + * changes to userspace MSR filters are reflected in the MSR bitmap. There's > + * nothing to do if the LBRs are intercepted, as a filter can only force > + * interception, never prevent it. Hmm, I don't love assuming that recalcs are only done for filter updates. On the other hand, taking action if lbr_desc->msr_passthrough=false is nonsensical. Rather than immediately refresh the updates, what if we just disable passthrough and let vmx_passthrough_lbr_msrs() do the actual update? void vmx_recalc_lbr_msr_intercepts(struct kvm_vcpu *vcpu) { if (WARN_ON_ONCE(!vcpu_to_lbr_desc(vcpu))) return; /* Disable passthrough to force a recalc on the next VM-Entry. */ vmx_disable_lbr_msrs_passthrough(vcpu); } ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/4] KVM: VMX: Refresh LBR MSR intercepts on full MSR intercept recalc 2026-11-04 20:45 ` Sean Christopherson @ 2026-11-04 23:49 ` Jim Mattson 2026-11-04 23:59 ` Jim Mattson 0 siblings, 1 reply; 8+ messages in thread From: Jim Mattson @ 2026-11-04 23:49 UTC (permalink / raw) To: Sean Christopherson Cc: Paolo Bonzini, kvm, linux-kernel, Yosry Ahmed, Like Xu, stable On Wed, Nov 4, 2026 at 12:45 PM Sean Christopherson <seanjc@google.com> wrote: > > On Tue, Oct 20, 2026, Jim Mattson wrote: > > Re-apply the LBR MSR intercepts in vmx_recalc_msr_intercepts() if the > > LBRs are currently passed through, so that changes to userspace MSR > > filters are reflected in the MSR bitmap. Unlike SVM, which can simply > > rewrite the intercepts in either direction, leave the bitmap alone if > > the LBRs aren't passed through, as a filter can only force interception, > > never prevent it, i.e. the bitmap is already correct. Note, clearing > > msr_passthrough to force vmx_passthrough_lbr_msrs() to re-apply the > > intercepts on the next VM-Enter isn't an option, as doing so would > > leave stale passthrough bits behind if the guest LBR event is no longer > > active. > > > > vmx_recalc_msr_intercepts() is invoked in response to > > KVM_REQ_RECALC_INTERCEPTS, which is raised on MSR filter updates, but it > > skips the LBR MSRs, and vmx_enable_lbr_msrs_passthrough() does nothing > > if lbr_desc->msr_passthrough is already set. If the LBR MSRs are passed > > through when userspace installs a filter that denies them, they remain > > passed through, and the guest can access them without exiting to > > userspace. Conversely, if a filter forced interception when the guest > > LBR event became active, relaxing the filter leaves the MSRs needlessly > > intercepted. Either way, the bitmap remains stale until the guest LBR > > event is torn down and recreated. > > > > Only x2APIC MSRs are exempt from userspace filtering (see > > kvm_msr_allowed() and the KVM_X86_SET_MSR_FILTER documentation), and the > > filter is honored when LBR passthrough is first enabled, so KVM's > > behavior shouldn't depend on whether the filter is set before or after > > the guest enables LBRs. Drop the LBR MSRs from the comment claiming > > that they can't be filtered by userspace, and clarify that > > lbr_desc.msr_passthrough tracks KVM's desired interception, which may > > not match the MSR bitmap when userspace filters are in play. > > > > Fixes: 9254beaafd12 ("KVM: vmx/pmu: Reduce the overhead of LBR pass-through or cancellation") > > Cc: stable@vger.kernel.org > > Meh, this isn't stable material. Unlike SVM, where LBR virtualization is tied > to a pile of other crud, if userspace wants to filter LBRs on Intel it should > just not expose LBRs in the first place. The functionality is not equivalent. For whatever reason, MSR filtering can be modified dynamically. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/4] KVM: VMX: Refresh LBR MSR intercepts on full MSR intercept recalc 2026-11-04 23:49 ` Jim Mattson @ 2026-11-04 23:59 ` Jim Mattson 2026-11-05 0:25 ` Sean Christopherson 0 siblings, 1 reply; 8+ messages in thread From: Jim Mattson @ 2026-11-04 23:59 UTC (permalink / raw) To: Sean Christopherson Cc: Paolo Bonzini, kvm, linux-kernel, Yosry Ahmed, Like Xu, stable On Wed, Nov 4, 2026 at 3:49 PM Jim Mattson <jmattson@google.com> wrote: > > On Wed, Nov 4, 2026 at 12:45 PM Sean Christopherson <seanjc@google.com> wrote: > > > > On Tue, Oct 20, 2026, Jim Mattson wrote: > > > Re-apply the LBR MSR intercepts in vmx_recalc_msr_intercepts() if the > > > LBRs are currently passed through, so that changes to userspace MSR > > > filters are reflected in the MSR bitmap. Unlike SVM, which can simply > > > rewrite the intercepts in either direction, leave the bitmap alone if > > > the LBRs aren't passed through, as a filter can only force interception, > > > never prevent it, i.e. the bitmap is already correct. Note, clearing > > > msr_passthrough to force vmx_passthrough_lbr_msrs() to re-apply the > > > intercepts on the next VM-Enter isn't an option, as doing so would > > > leave stale passthrough bits behind if the guest LBR event is no longer > > > active. > > > > > > vmx_recalc_msr_intercepts() is invoked in response to > > > KVM_REQ_RECALC_INTERCEPTS, which is raised on MSR filter updates, but it > > > skips the LBR MSRs, and vmx_enable_lbr_msrs_passthrough() does nothing > > > if lbr_desc->msr_passthrough is already set. If the LBR MSRs are passed > > > through when userspace installs a filter that denies them, they remain > > > passed through, and the guest can access them without exiting to > > > userspace. Conversely, if a filter forced interception when the guest > > > LBR event became active, relaxing the filter leaves the MSRs needlessly > > > intercepted. Either way, the bitmap remains stale until the guest LBR > > > event is torn down and recreated. > > > > > > Only x2APIC MSRs are exempt from userspace filtering (see > > > kvm_msr_allowed() and the KVM_X86_SET_MSR_FILTER documentation), and the > > > filter is honored when LBR passthrough is first enabled, so KVM's > > > behavior shouldn't depend on whether the filter is set before or after > > > the guest enables LBRs. Drop the LBR MSRs from the comment claiming > > > that they can't be filtered by userspace, and clarify that > > > lbr_desc.msr_passthrough tracks KVM's desired interception, which may > > > not match the MSR bitmap when userspace filters are in play. > > > > > > Fixes: 9254beaafd12 ("KVM: vmx/pmu: Reduce the overhead of LBR pass-through or cancellation") > > > Cc: stable@vger.kernel.org > > > > Meh, this isn't stable material. Unlike SVM, where LBR virtualization is tied > > to a pile of other crud, if userspace wants to filter LBRs on Intel it should > > just not expose LBRs in the first place. > > The functionality is not equivalent. For whatever reason, MSR > filtering can be modified dynamically. Oh, and, duh, MSR filtering doesn't disallow the LBRs; it just reflects them to userspace. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/4] KVM: VMX: Refresh LBR MSR intercepts on full MSR intercept recalc 2026-11-04 23:59 ` Jim Mattson @ 2026-11-05 0:25 ` Sean Christopherson 0 siblings, 0 replies; 8+ messages in thread From: Sean Christopherson @ 2026-11-05 0:25 UTC (permalink / raw) To: Jim Mattson Cc: Paolo Bonzini, kvm, linux-kernel, Yosry Ahmed, Like Xu, stable On Wed, Nov 04, 2026, Jim Mattson wrote: > On Wed, Nov 4, 2026 at 3:49 PM Jim Mattson <jmattson@google.com> wrote: > > > > On Wed, Nov 4, 2026 at 12:45 PM Sean Christopherson <seanjc@google.com> wrote: > > > > > > On Tue, Oct 20, 2026, Jim Mattson wrote: > > > > Re-apply the LBR MSR intercepts in vmx_recalc_msr_intercepts() if the > > > > LBRs are currently passed through, so that changes to userspace MSR > > > > filters are reflected in the MSR bitmap. Unlike SVM, which can simply > > > > rewrite the intercepts in either direction, leave the bitmap alone if > > > > the LBRs aren't passed through, as a filter can only force interception, > > > > never prevent it, i.e. the bitmap is already correct. Note, clearing > > > > msr_passthrough to force vmx_passthrough_lbr_msrs() to re-apply the > > > > intercepts on the next VM-Enter isn't an option, as doing so would > > > > leave stale passthrough bits behind if the guest LBR event is no longer > > > > active. > > > > > > > > vmx_recalc_msr_intercepts() is invoked in response to > > > > KVM_REQ_RECALC_INTERCEPTS, which is raised on MSR filter updates, but it > > > > skips the LBR MSRs, and vmx_enable_lbr_msrs_passthrough() does nothing > > > > if lbr_desc->msr_passthrough is already set. If the LBR MSRs are passed > > > > through when userspace installs a filter that denies them, they remain > > > > passed through, and the guest can access them without exiting to > > > > userspace. Conversely, if a filter forced interception when the guest > > > > LBR event became active, relaxing the filter leaves the MSRs needlessly > > > > intercepted. Either way, the bitmap remains stale until the guest LBR > > > > event is torn down and recreated. > > > > > > > > Only x2APIC MSRs are exempt from userspace filtering (see > > > > kvm_msr_allowed() and the KVM_X86_SET_MSR_FILTER documentation), and the > > > > filter is honored when LBR passthrough is first enabled, so KVM's > > > > behavior shouldn't depend on whether the filter is set before or after > > > > the guest enables LBRs. Drop the LBR MSRs from the comment claiming > > > > that they can't be filtered by userspace, and clarify that > > > > lbr_desc.msr_passthrough tracks KVM's desired interception, which may > > > > not match the MSR bitmap when userspace filters are in play. > > > > > > > > Fixes: 9254beaafd12 ("KVM: vmx/pmu: Reduce the overhead of LBR pass-through or cancellation") > > > > Cc: stable@vger.kernel.org > > > > > > Meh, this isn't stable material. Unlike SVM, where LBR virtualization is tied > > > to a pile of other crud, if userspace wants to filter LBRs on Intel it should > > > just not expose LBRs in the first place. > > > > The functionality is not equivalent. For whatever reason, MSR > > filtering can be modified dynamically. > > Oh, and, duh, MSR filtering doesn't disallow the LBRs; it just > reflects them to userspace. Right, but how many real world deployments actually enable vLBR *and* want to intercept accesses *and* want to do so dynamically? This isn't a particularly dangerous change by any means, but sending things to stable@ does incur some amount of downstream work. Unless there's an actual end user that's affected by this flaw, I'd much prefer not to create more work. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-11-05 0:25 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20261020234535.3182385-1-jmattson@google.com>
2026-10-20 23:45 ` [PATCH 1/4] KVM: SVM: Always update LBR MSR intercepts on full MSR intercept recalc Jim Mattson
2026-10-21 0:09 ` Yosry Ahmed
2026-11-04 20:55 ` Sean Christopherson
2026-10-20 23:45 ` [PATCH 2/4] KVM: VMX: Refresh " Jim Mattson
2026-11-04 20:45 ` Sean Christopherson
2026-11-04 23:49 ` Jim Mattson
2026-11-04 23:59 ` Jim Mattson
2026-11-05 0:25 ` Sean Christopherson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox