mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] KVM: x86/pmu: Don't retry a counter whose config was rejected
@ 2026-09-18 16:00 Luka Absandze
  2026-09-18 16:16 ` Sean Christopherson
  0 siblings, 1 reply; 5+ messages in thread
From: Luka Absandze @ 2026-09-18 16:00 UTC (permalink / raw)
  To: seanjc, pbonzini
  Cc: sandipan.das, tglx, mingo, bp, dave.hansen, x86, hpa, dwmw2, kvm,
	linux-perf-users, linux-kernel, Luka Absandze

kvm_pmu_handle_event() re-arms the reprogram bit for every failed
reprogram, on the assumption that the failure is transient and a later
refresh will succeed.  That is true for contention, e.g. the -EBUSY from
x86_reserve_hardware(), but not for a configuration the host PMU driver
rejects outright.  A rejected config can never succeed on retry, so the
counter is reprogrammed on every PMU refresh for as long as the guest
leaves it enabled, and every attempt fails the same way.

Skip the re-arm for -EINVAL, one of the errnos the x86 PMU drivers use
for a config they will never accept.  Note this becomes reachable on AMD
only with the patch linked below, which starts rejecting the Merge event
(PMCxFFF) a guest programs as part of a Large Increment per Cycle pair;
on Intel it is already reachable today via the INTEL_FIXED_VLBR_EVENT
check in intel_pmu_hw_config(), where the config is likewise a function
of fixed guest state and can never start being accepted.

Link: https://lore.kernel.org/all/20260916123315.89042-1-absandze@amazon.de/
Signed-off-by: Luka Absandze <absandze@amazon.de>
---
 arch/x86/kvm/pmu.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index a7d60c8785cd..b9945a6256ed 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -680,8 +680,14 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
 		 * reprogram bit, i.e. opportunistically try again on the next
 		 * PMU refresh.  Don't make a new request as doing so can stall
 		 * the guest if reprogramming repeatedly fails.
+		 *
+		 * -EINVAL means the event's config was rejected outright and
+		 * can never succeed on retry, so don't re-arm; the guest can
+		 * still do so itself by rewriting the event selector.
 		 */
-		if (reprogram_counter(pmc))
+		int r = reprogram_counter(pmc);
+
+		if (r && r != -EINVAL)
 			set_bit(pmc->idx, pmu->reprogram_pmi);
 	}
 
-- 
2.47.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] KVM: x86/pmu: Don't retry a counter whose config was rejected
  2026-09-18 16:00 [PATCH] KVM: x86/pmu: Don't retry a counter whose config was rejected Luka Absandze
@ 2026-09-18 16:16 ` Sean Christopherson
  2026-09-18 20:21   ` Absandze, Luka
  0 siblings, 1 reply; 5+ messages in thread
From: Sean Christopherson @ 2026-09-18 16:16 UTC (permalink / raw)
  To: Luka Absandze
  Cc: pbonzini, sandipan.das, tglx, mingo, bp, dave.hansen, x86, hpa,
	dwmw2, kvm, linux-perf-users, linux-kernel

On Fri, Sep 18, 2026, Luka Absandze wrote:
> kvm_pmu_handle_event() re-arms the reprogram bit for every failed
> reprogram, on the assumption that the failure is transient and a later
> refresh will succeed.  That is true for contention, e.g. the -EBUSY from
> x86_reserve_hardware(), but not for a configuration the host PMU driver
> rejects outright.  A rejected config can never succeed on retry, so the
> counter is reprogrammed on every PMU refresh for as long as the guest
> leaves it enabled, and every attempt fails the same way.
> 
> Skip the re-arm for -EINVAL, one of the errnos the x86 PMU drivers use
> for a config they will never accept.  Note this becomes reachable on AMD
> only with the patch linked below, which starts rejecting the Merge event
> (PMCxFFF) a guest programs as part of a Large Increment per Cycle pair;
> on Intel it is already reachable today via the INTEL_FIXED_VLBR_EVENT
> check in intel_pmu_hw_config(), where the config is likewise a function
> of fixed guest state and can never start being accepted.
> 
> Link: https://lore.kernel.org/all/20260916123315.89042-1-absandze@amazon.de/
> Signed-off-by: Luka Absandze <absandze@amazon.de>
> ---
>  arch/x86/kvm/pmu.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> index a7d60c8785cd..b9945a6256ed 100644
> --- a/arch/x86/kvm/pmu.c
> +++ b/arch/x86/kvm/pmu.c
> @@ -680,8 +680,14 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
>  		 * reprogram bit, i.e. opportunistically try again on the next
>  		 * PMU refresh.  Don't make a new request as doing so can stall
>  		 * the guest if reprogramming repeatedly fails.
> +		 *
> +		 * -EINVAL means the event's config was rejected outright and
> +		 * can never succeed on retry, so don't re-arm; the guest can
> +		 * still do so itself by rewriting the event selector.
>  		 */
> -		if (reprogram_counter(pmc))
> +		int r = reprogram_counter(pmc);
> +
> +		if (r && r != -EINVAL)
>  			set_bit(pmc->idx, pmu->reprogram_pmi);

Hmm, would it instead make more sense to explicitly check for -EBUSY?  -EINVAL
isn't the only fatal error code.

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index a7d60c8785cd..5296ee8f32af 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -681,7 +681,7 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
 		 * PMU refresh.  Don't make a new request as doing so can stall
 		 * the guest if reprogramming repeatedly fails.
 		 */
-		if (reprogram_counter(pmc))
+		if (reprogram_counter(pmc) == -EBUSY)
 			set_bit(pmc->idx, pmu->reprogram_pmi);
 	}
 
Though I guess one could argue -ENOMEM is also transient?  I definitely prefer
an "allow"-list though.  And I find it easier to read if 'r' is declared outside
the loop (and less of a chance of variable shadowing; the odds of returning a
stale value are quite low given there is no return value, and probably never will
be a return value).

E.g. this? (completely untested)

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index a7d60c8785cd..03a470c49a74 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -662,7 +662,7 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
 	DECLARE_BITMAP(bitmap, X86_PMC_IDX_MAX);
 	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
 	struct kvm_pmc *pmc;
-	int bit;
+	int bit, r;
 
 	bitmap_copy(bitmap, pmu->reprogram_pmi, X86_PMC_IDX_MAX);
 
@@ -676,12 +676,14 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
 
 	kvm_for_each_pmc(pmu, pmc, bit, bitmap) {
 		/*
-		 * If reprogramming fails, e.g. due to contention, re-set the
-		 * reprogram bit, i.e. opportunistically try again on the next
-		 * PMU refresh.  Don't make a new request as doing so can stall
-		 * the guest if reprogramming repeatedly fails.
+		 * If reprogramming fails on a transient condition, e.g. due to
+		 * contention, re-set the reprogram bit, i.e. opportunistically
+		 * try again on the next PMU refresh.  Don't make a new request
+		 * as doing so can stall the guest if reprogramming repeatedly
+		 * fails.
 		 */
-		if (reprogram_counter(pmc))
+		r = reprogram_counter(pmc);
+		if (r == -EBUSY || r == -ENOMEM)
 			set_bit(pmc->idx, pmu->reprogram_pmi);
 	}
 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] KVM: x86/pmu: Don't retry a counter whose config was rejected
  2026-09-18 16:16 ` Sean Christopherson
@ 2026-09-18 20:21   ` Absandze, Luka
  2026-09-18 21:39     ` Sean Christopherson
  0 siblings, 1 reply; 5+ messages in thread
From: Absandze, Luka @ 2026-09-18 20:21 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: pbonzini, sandipan.das, tglx, mingo, bp, dave.hansen, x86, hpa,
	dwmw2, kvm, linux-perf-users, linux-kernel

On 2026-09-18 09:16, Sean Christopherson wrote:
> Hmm, would it instead make more sense to explicitly check for -EBUSY?  -EINVAL
> isn't the only fatal error code.
> 
> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> index a7d60c8785cd..5296ee8f32af 100644
> --- a/arch/x86/kvm/pmu.c
> +++ b/arch/x86/kvm/pmu.c
> @@ -681,7 +681,7 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
>                  * PMU refresh.  Don't make a new request as doing so can stall
>                  * the guest if reprogramming repeatedly fails.
>                  */
> -               if (reprogram_counter(pmc))
> +               if (reprogram_counter(pmc) == -EBUSY)
>                         set_bit(pmc->idx, pmu->reprogram_pmi);
>         }
> 
> Though I guess one could argue -ENOMEM is also transient?

I had contemplated this, but could not convince myself at a glance that
perf and KVM agreed on what constituted a transient error.
I have now concluded I was seeing ghosts :)

> E.g. this? (completely untested)
> [diff]

Tested against the fault described in the linked patch and selftests on
AMD Zen 3 (although I don't think there's much coverage in this regard).

If no other objections, would you be fine with taking the diff you
provided into the tree or would you prefer a v2?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] KVM: x86/pmu: Don't retry a counter whose config was rejected
  2026-09-18 20:21   ` Absandze, Luka
@ 2026-09-18 21:39     ` Sean Christopherson
  2026-09-19 14:29       ` Sandipan Das
  0 siblings, 1 reply; 5+ messages in thread
From: Sean Christopherson @ 2026-09-18 21:39 UTC (permalink / raw)
  To: Luka Absandze
  Cc: pbonzini, sandipan.das, tglx, mingo, bp, dave.hansen, x86, hpa,
	dwmw2, kvm, linux-perf-users, linux-kernel

On Fri, Sep 18, 2026, Luka Absandze wrote:
> On 2026-09-18 09:16, Sean Christopherson wrote:
> > Hmm, would it instead make more sense to explicitly check for -EBUSY?  -EINVAL
> > isn't the only fatal error code.
> > 
> > diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> > index a7d60c8785cd..5296ee8f32af 100644
> > --- a/arch/x86/kvm/pmu.c
> > +++ b/arch/x86/kvm/pmu.c
> > @@ -681,7 +681,7 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
> >                  * PMU refresh.  Don't make a new request as doing so can stall
> >                  * the guest if reprogramming repeatedly fails.
> >                  */
> > -               if (reprogram_counter(pmc))
> > +               if (reprogram_counter(pmc) == -EBUSY)
> >                         set_bit(pmc->idx, pmu->reprogram_pmi);
> >         }
> > 
> > Though I guess one could argue -ENOMEM is also transient?
> 
> I had contemplated this, but could not convince myself at a glance that
> perf and KVM agreed on what constituted a transient error.
> I have now concluded I was seeing ghosts :)
> 
> > E.g. this? (completely untested)
> > [diff]
> 
> Tested against the fault described in the linked patch and selftests on
> AMD Zen 3 (although I don't think there's much coverage in this regard).
> 
> If no other objections, would you be fine with taking the diff you
> provided into the tree or would you prefer a v2?

Go ahead and send a v2, I want to see what Sashiko thinks.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] KVM: x86/pmu: Don't retry a counter whose config was rejected
  2026-09-18 21:39     ` Sean Christopherson
@ 2026-09-19 14:29       ` Sandipan Das
  0 siblings, 0 replies; 5+ messages in thread
From: Sandipan Das @ 2026-09-19 14:29 UTC (permalink / raw)
  To: Sean Christopherson, Luka Absandze
  Cc: pbonzini, tglx, mingo, bp, dave.hansen, x86, hpa, dwmw2, kvm,
	linux-perf-users, linux-kernel

On 19-09-2026 03:09, Sean Christopherson wrote:
> On Fri, Sep 18, 2026, Luka Absandze wrote:
>> On 2026-09-18 09:16, Sean Christopherson wrote:
>>> Hmm, would it instead make more sense to explicitly check for -EBUSY?  -EINVAL
>>> isn't the only fatal error code.
>>>
>>> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
>>> index a7d60c8785cd..5296ee8f32af 100644
>>> --- a/arch/x86/kvm/pmu.c
>>> +++ b/arch/x86/kvm/pmu.c
>>> @@ -681,7 +681,7 @@ void kvm_pmu_handle_event(struct kvm_vcpu *vcpu)
>>>                  * PMU refresh.  Don't make a new request as doing so can stall
>>>                  * the guest if reprogramming repeatedly fails.
>>>                  */
>>> -               if (reprogram_counter(pmc))
>>> +               if (reprogram_counter(pmc) == -EBUSY)
>>>                         set_bit(pmc->idx, pmu->reprogram_pmi);
>>>         }
>>>
>>> Though I guess one could argue -ENOMEM is also transient?
>>
>> I had contemplated this, but could not convince myself at a glance that
>> perf and KVM agreed on what constituted a transient error.
>> I have now concluded I was seeing ghosts :)
>>
>>> E.g. this? (completely untested)
>>> [diff]
>>
>> Tested against the fault described in the linked patch and selftests on
>> AMD Zen 3 (although I don't think there's much coverage in this regard).
>>
>> If no other objections, would you be fine with taking the diff you
>> provided into the tree or would you prefer a v2?
> 
> Go ahead and send a v2, I want to see what Sashiko thinks.

From a quick glance, it seems EBUSY and ENOMEM might just be sufficient.
The former occurs when a pinned event cannot be created cause all counters
are exhausted and the latter due to various event and context struct
related alloc failures.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-19 14:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-18 16:00 [PATCH] KVM: x86/pmu: Don't retry a counter whose config was rejected Luka Absandze
2026-09-18 16:16 ` Sean Christopherson
2026-09-18 20:21   ` Absandze, Luka
2026-09-18 21:39     ` Sean Christopherson
2026-09-19 14:29       ` Sandipan Das

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®