diff mbox series

[v2,36/54] KVM: x86/pmu: Switch PMI handler at KVM context switch boundary

Message ID 20240506053020.3911940-37-mizhang@google.com (mailing list archive)
State New, archived
Headers show
Series Mediated Passthrough vPMU 2.0 for x86 | expand

Commit Message

Mingwei Zhang May 6, 2024, 5:30 a.m. UTC
From: Xiong Zhang <xiong.y.zhang@linux.intel.com>

Switch PMI handler at KVM context switch boundary because KVM uses a
separate maskable interrupt vector other than the NMI handler for the host
PMU to process its own PMIs.  So invoke the perf API that allows
registration of the PMI handler.

Signed-off-by: Xiong Zhang <xiong.y.zhang@linux.intel.com>
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
---
 arch/x86/kvm/pmu.c | 4 ++++
 1 file changed, 4 insertions(+)

Comments

Sandipan Das July 10, 2024, 8:37 a.m. UTC | #1
On 5/6/2024 11:00 AM, Mingwei Zhang wrote:
> From: Xiong Zhang <xiong.y.zhang@linux.intel.com>
> 
> Switch PMI handler at KVM context switch boundary because KVM uses a
> separate maskable interrupt vector other than the NMI handler for the host
> PMU to process its own PMIs.  So invoke the perf API that allows
> registration of the PMI handler.
> 
> Signed-off-by: Xiong Zhang <xiong.y.zhang@linux.intel.com>
> Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
> ---
>  arch/x86/kvm/pmu.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> index 2ad71020a2c0..a12012a00c11 100644
> --- a/arch/x86/kvm/pmu.c
> +++ b/arch/x86/kvm/pmu.c
> @@ -1097,6 +1097,8 @@ void kvm_pmu_save_pmu_context(struct kvm_vcpu *vcpu)
>  		if (pmc->counter)
>  			wrmsrl(pmc->msr_counter, 0);
>  	}
> +
> +	x86_perf_guest_exit();
>  }
>  
>  void kvm_pmu_restore_pmu_context(struct kvm_vcpu *vcpu)
> @@ -1107,6 +1109,8 @@ void kvm_pmu_restore_pmu_context(struct kvm_vcpu *vcpu)
>  
>  	lockdep_assert_irqs_disabled();
>  
> +	x86_perf_guest_enter(kvm_lapic_get_reg(vcpu->arch.apic, APIC_LVTPC));
> +

Reading the LVTPC for a vCPU that does not have a struct kvm_lapic allocated
leads to a NULL pointer dereference. I noticed this while trying to run a
minimalistic guest like https://github.com/dpw/kvm-hello-world

Does this require a kvm_lapic_enabled() or similar check?

>  	static_call_cond(kvm_x86_pmu_restore_pmu_context)(vcpu);
>  
>  	/*
Zhang, Xiong Y July 10, 2024, 10:01 a.m. UTC | #2
> On 5/6/2024 11:00 AM, Mingwei Zhang wrote:
> > From: Xiong Zhang <xiong.y.zhang@linux.intel.com>
> >
> > Switch PMI handler at KVM context switch boundary because KVM uses a
> > separate maskable interrupt vector other than the NMI handler for the
> > host PMU to process its own PMIs.  So invoke the perf API that allows
> > registration of the PMI handler.
> >
> > Signed-off-by: Xiong Zhang <xiong.y.zhang@linux.intel.com>
> > Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
> > ---
> >  arch/x86/kvm/pmu.c | 4 ++++
> >  1 file changed, 4 insertions(+)
> >
> > diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index
> > 2ad71020a2c0..a12012a00c11 100644
> > --- a/arch/x86/kvm/pmu.c
> > +++ b/arch/x86/kvm/pmu.c
> > @@ -1097,6 +1097,8 @@ void kvm_pmu_save_pmu_context(struct kvm_vcpu
> *vcpu)
> >  		if (pmc->counter)
> >  			wrmsrl(pmc->msr_counter, 0);
> >  	}
> > +
> > +	x86_perf_guest_exit();
> >  }
> >
> >  void kvm_pmu_restore_pmu_context(struct kvm_vcpu *vcpu) @@ -1107,6
> > +1109,8 @@ void kvm_pmu_restore_pmu_context(struct kvm_vcpu *vcpu)
> >
> >  	lockdep_assert_irqs_disabled();
> >
> > +	x86_perf_guest_enter(kvm_lapic_get_reg(vcpu->arch.apic,
> > +APIC_LVTPC));
> > +
> 
> Reading the LVTPC for a vCPU that does not have a struct kvm_lapic allocated
> leads to a NULL pointer dereference. I noticed this while trying to run a
> minimalistic guest like https://github.com/dpw/kvm-hello-world
> 
> Does this require a kvm_lapic_enabled() or similar check?
> 

Intel processor has lapci_in_kernel() checking in "[RFC PATCH v3 16/54] KVM: x86/pmu: Plumb through pass-through PMU to vcpu for Intel CPUs".
+	pmu->passthrough = vcpu->kvm->arch.enable_passthrough_pmu &&
+			   lapic_in_kernel(vcpu);

AMD processor seems need this checking also. we could move this checking into common place.

Thanks

> >  	static_call_cond(kvm_x86_pmu_restore_pmu_context)(vcpu);
> >
> >  	/*
Sandipan Das July 10, 2024, 12:30 p.m. UTC | #3
On 7/10/2024 3:31 PM, Zhang, Xiong Y wrote:
> 
>> On 5/6/2024 11:00 AM, Mingwei Zhang wrote:
>>> From: Xiong Zhang <xiong.y.zhang@linux.intel.com>
>>>
>>> Switch PMI handler at KVM context switch boundary because KVM uses a
>>> separate maskable interrupt vector other than the NMI handler for the
>>> host PMU to process its own PMIs.  So invoke the perf API that allows
>>> registration of the PMI handler.
>>>
>>> Signed-off-by: Xiong Zhang <xiong.y.zhang@linux.intel.com>
>>> Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
>>> ---
>>>  arch/x86/kvm/pmu.c | 4 ++++
>>>  1 file changed, 4 insertions(+)
>>>
>>> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index
>>> 2ad71020a2c0..a12012a00c11 100644
>>> --- a/arch/x86/kvm/pmu.c
>>> +++ b/arch/x86/kvm/pmu.c
>>> @@ -1097,6 +1097,8 @@ void kvm_pmu_save_pmu_context(struct kvm_vcpu
>> *vcpu)
>>>  		if (pmc->counter)
>>>  			wrmsrl(pmc->msr_counter, 0);
>>>  	}
>>> +
>>> +	x86_perf_guest_exit();
>>>  }
>>>
>>>  void kvm_pmu_restore_pmu_context(struct kvm_vcpu *vcpu) @@ -1107,6
>>> +1109,8 @@ void kvm_pmu_restore_pmu_context(struct kvm_vcpu *vcpu)
>>>
>>>  	lockdep_assert_irqs_disabled();
>>>
>>> +	x86_perf_guest_enter(kvm_lapic_get_reg(vcpu->arch.apic,
>>> +APIC_LVTPC));
>>> +
>>
>> Reading the LVTPC for a vCPU that does not have a struct kvm_lapic allocated
>> leads to a NULL pointer dereference. I noticed this while trying to run a
>> minimalistic guest like https://github.com/dpw/kvm-hello-world
>>
>> Does this require a kvm_lapic_enabled() or similar check?
>>
> 
> Intel processor has lapci_in_kernel() checking in "[RFC PATCH v3 16/54] KVM: x86/pmu: Plumb through pass-through PMU to vcpu for Intel CPUs".
> +	pmu->passthrough = vcpu->kvm->arch.enable_passthrough_pmu &&
> +			   lapic_in_kernel(vcpu);
> 
> AMD processor seems need this checking also. we could move this checking into common place.
> 

Thanks. Adding that fixes the issue.

> 
>>>  	static_call_cond(kvm_x86_pmu_restore_pmu_context)(vcpu);
>>>
>>>  	/*
>
diff mbox series

Patch

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 2ad71020a2c0..a12012a00c11 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -1097,6 +1097,8 @@  void kvm_pmu_save_pmu_context(struct kvm_vcpu *vcpu)
 		if (pmc->counter)
 			wrmsrl(pmc->msr_counter, 0);
 	}
+
+	x86_perf_guest_exit();
 }
 
 void kvm_pmu_restore_pmu_context(struct kvm_vcpu *vcpu)
@@ -1107,6 +1109,8 @@  void kvm_pmu_restore_pmu_context(struct kvm_vcpu *vcpu)
 
 	lockdep_assert_irqs_disabled();
 
+	x86_perf_guest_enter(kvm_lapic_get_reg(vcpu->arch.apic, APIC_LVTPC));
+
 	static_call_cond(kvm_x86_pmu_restore_pmu_context)(vcpu);
 
 	/*