diff mbox series

KVM: vPMU: Don't program counter for interrupt-based event sampling w/o lapic_in_kernel

Message ID 1634894233-84041-1-git-send-email-wanpengli@tencent.com (mailing list archive)
State New, archived
Headers show
Series KVM: vPMU: Don't program counter for interrupt-based event sampling w/o lapic_in_kernel | expand

Commit Message

Wanpeng Li Oct. 22, 2021, 9:17 a.m. UTC
From: Wanpeng Li <wanpengli@tencent.com>

vPMU depends on in-kernel lapic to deliver pmi interrupt, there is a
lot of overhead when creating/maintaining perf_event object, 
locking/unlocking perf_event_ctx etc for vPMU. It silently fails to 
deliver pmi interrupt if w/o in-kernel lapic currently. Let's not 
program counter for interrupt-based event sampling w/o in-kernel 
lapic support to avoid the whole bothering. 

Signed-off-by: Wanpeng Li <wanpengli@tencent.com>
---
 arch/x86/kvm/pmu.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Comments

Sean Christopherson Oct. 25, 2021, 4:31 p.m. UTC | #1
On Fri, Oct 22, 2021, Wanpeng Li wrote:
> From: Wanpeng Li <wanpengli@tencent.com>
> 
> vPMU depends on in-kernel lapic to deliver pmi interrupt, there is a
> lot of overhead when creating/maintaining perf_event object, 
> locking/unlocking perf_event_ctx etc for vPMU. It silently fails to 
> deliver pmi interrupt if w/o in-kernel lapic currently. Let's not 
> program counter for interrupt-based event sampling w/o in-kernel 
> lapic support to avoid the whole bothering. 

This feels all kinds of wrong.  AFAIK, there's no way for KVM to enumerate to
the guest that the vPMU isn't capable of generating interrupts.  I.e. any setup
that exposes a vPMU to the guest without an in-kernel local APIC is either
inherently broken or requires a paravirtualized guest.  I don't think KVM's bugs
should be optimized.

> Signed-off-by: Wanpeng Li <wanpengli@tencent.com>
> ---
>  arch/x86/kvm/pmu.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> index 0772bad9165c..fa5cd33af10d 100644
> --- a/arch/x86/kvm/pmu.c
> +++ b/arch/x86/kvm/pmu.c
> @@ -179,6 +179,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
>  	struct kvm_pmu_event_filter *filter;
>  	int i;
>  	bool allow_event = true;
> +	bool intr = eventsel & ARCH_PERFMON_EVENTSEL_INT;
>  
>  	if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
>  		printk_once("kvm pmu: pin control bit is ignored\n");
> @@ -187,7 +188,8 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
>  
>  	pmc_pause_counter(pmc);
>  
> -	if (!(eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) || !pmc_is_enabled(pmc))
> +	if (!(eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) || !pmc_is_enabled(pmc)
> +	    || (intr && !lapic_in_kernel(pmc->vcpu)))
>  		return;
>  
>  	filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);
> @@ -233,7 +235,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
>  	pmc_reprogram_counter(pmc, type, config,
>  			      !(eventsel & ARCH_PERFMON_EVENTSEL_USR),
>  			      !(eventsel & ARCH_PERFMON_EVENTSEL_OS),
> -			      eventsel & ARCH_PERFMON_EVENTSEL_INT,
> +			      intr,
>  			      (eventsel & HSW_IN_TX),
>  			      (eventsel & HSW_IN_TX_CHECKPOINTED));
>  }
> @@ -248,7 +250,7 @@ void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int idx)
>  
>  	pmc_pause_counter(pmc);
>  
> -	if (!en_field || !pmc_is_enabled(pmc))
> +	if (!en_field || !pmc_is_enabled(pmc) || (pmi && !lapic_in_kernel(pmc->vcpu)))
>  		return;
>  
>  	filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);
> -- 
> 2.25.1
>
Paolo Bonzini Oct. 25, 2021, 4:44 p.m. UTC | #2
On 25/10/21 18:31, Sean Christopherson wrote:
>> vPMU depends on in-kernel lapic to deliver pmi interrupt, there is a
>> lot of overhead when creating/maintaining perf_event object,
>> locking/unlocking perf_event_ctx etc for vPMU. It silently fails to
>> deliver pmi interrupt if w/o in-kernel lapic currently. Let's not
>> program counter for interrupt-based event sampling w/o in-kernel
>> lapic support to avoid the whole bothering.
>
> This feels all kinds of wrong.  AFAIK, there's no way for KVM to enumerate to
> the guest that the vPMU isn't capable of generating interrupts.  I.e. any setup
> that exposes a vPMU to the guest without an in-kernel local APIC is either
> inherently broken or requires a paravirtualized guest.  I don't think KVM's bugs
> should be optimized.

Yeah, if it simplified the code it would be a different story, but here 
there's even not one but two new checks.

Paolo
diff mbox series

Patch

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 0772bad9165c..fa5cd33af10d 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -179,6 +179,7 @@  void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
 	struct kvm_pmu_event_filter *filter;
 	int i;
 	bool allow_event = true;
+	bool intr = eventsel & ARCH_PERFMON_EVENTSEL_INT;
 
 	if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
 		printk_once("kvm pmu: pin control bit is ignored\n");
@@ -187,7 +188,8 @@  void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
 
 	pmc_pause_counter(pmc);
 
-	if (!(eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) || !pmc_is_enabled(pmc))
+	if (!(eventsel & ARCH_PERFMON_EVENTSEL_ENABLE) || !pmc_is_enabled(pmc)
+	    || (intr && !lapic_in_kernel(pmc->vcpu)))
 		return;
 
 	filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);
@@ -233,7 +235,7 @@  void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
 	pmc_reprogram_counter(pmc, type, config,
 			      !(eventsel & ARCH_PERFMON_EVENTSEL_USR),
 			      !(eventsel & ARCH_PERFMON_EVENTSEL_OS),
-			      eventsel & ARCH_PERFMON_EVENTSEL_INT,
+			      intr,
 			      (eventsel & HSW_IN_TX),
 			      (eventsel & HSW_IN_TX_CHECKPOINTED));
 }
@@ -248,7 +250,7 @@  void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int idx)
 
 	pmc_pause_counter(pmc);
 
-	if (!en_field || !pmc_is_enabled(pmc))
+	if (!en_field || !pmc_is_enabled(pmc) || (pmi && !lapic_in_kernel(pmc->vcpu)))
 		return;
 
 	filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);