[PATCH v8 5/7] KVM: arm64: PMU: Implement fixed-counters-only emulation

Akihiko Odaki odaki at rsg.ci.i.u-tokyo.ac.jp
Wed Jul 8 02:43:32 PDT 2026


On 2026/07/08 3:02, Oliver Upton wrote:
> On Tue, Jul 07, 2026 at 09:52:49PM +0900, Akihiko Odaki wrote:
>> On 2026/07/07 20:23, Akihiko Odaki wrote:
>>> On 2026/07/07 3:23, Oliver Upton wrote:
>>>> Just detect the changing PMU implementation here, KVM_REQ_RELOAD_PMU
>>>> will need to detect the PMCs that require an update anyway. Stash the
>>>> last cpu in kvm_arch_vcpu_load() and pass it to this:
>>>>
>>>> void kvm_vcpu_load_pmu(struct kvm_vcpu *vcpu, int last_cpu)
>>>> {
>>>>      if (!kvm_pmu_fixed_counters_only(vcpu->kvm) || vcpu->cpu == last_cpu)
>>>>          return;
>>>>
>>>>      if (kvm_pmu_probe_armpmu(vcpu->cpu) !=
>>>> kvm_pmu_probe_armpmu(last_cpu))
>>>>          kvm_make_request(KVM_REQ_RELOAD_PMU);
>>>> }
>>>
>>> It is a nice way to simplify the code and to avoid hardcoding
>>> ARMV8_PMU_INSTR_IDX. I'll use the code for the next version.
>>
>> I tried this but unfortunately it doesn't seem to work. kvm_arch_vcpu_put()
>> sets vcpu->cpu to -1 so we cannot simply read it to get the last cpu in
>> kvm_arch_vcpu_load().
> 
> Urgh, there's no reason for doing that any more. Let's fix it, I want a
> straightforward way to detect pCPU migrations. There may be other
> reasons for using it in the future.
> 
> Untested, but could you give this a whirl?

It looks good to me. I'll test it and include it in the next version.

Regards,
Akihiko Odaki

> 
>  From bb5af058030aada66f5c9eafa54db604979acf55 Mon Sep 17 00:00:00 2001
> From: Oliver Upton <oupton at kernel.org>
> Date: Tue, 7 Jul 2026 09:50:00 -0700
> Subject: [PATCH] KVM: arm64: Don't clear vcpu->cpu in kvm_arch_vcpu_put()
> 
> commit e9b152cb957c ("arm/arm64: kvm: Set vcpu->cpu to -1 on vcpu_put")
> reset vcpu->cpu in order for the VGIC to determine if there was any vCPU
> running at the time of access. The VGIC has gone through an entire
> rewrite since then, and with commit 7d450e282171 ("KVM: arm/arm64:
> vgic-new: Add userland access to VGIC dist registers") the user
> accessors just grab all vCPU mutexes instead.
> 
> Drop this remaining vestige such that kvm_arch_vcpu_load() can properly
> detect a CPU migration. While at it, rework kvm_reset_vcpu() to do a
> much more pedantic check that the provided vCPU is actually what's
> running on the present CPU.
> 
> Signed-off-by: Oliver Upton <oupton at kernel.org>
> ---
>   arch/arm64/kvm/arm.c   |  1 -
>   arch/arm64/kvm/reset.c | 15 ++++++++++-----
>   2 files changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 50adfff75be8..735acc42b50b 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -749,7 +749,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
>   	kvm_arm_vmid_clear_active();
>   
>   	vcpu_clear_on_unsupported_cpu(vcpu);
> -	vcpu->cpu = -1;
>   }
>   
>   static void __kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index b963fd975aac..6aba085c0673 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c
> @@ -190,7 +190,8 @@ static void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu)
>   void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
>   {
>   	struct vcpu_reset_state reset_state;
> -	bool loaded;
> +	struct kvm_vcpu *running;
> +	bool loaded = false;
>   	u32 pstate;
>   
>   	spin_lock(&vcpu->arch.mp_state_lock);
> @@ -198,10 +199,15 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
>   	vcpu->arch.reset_state.reset = false;
>   	spin_unlock(&vcpu->arch.mp_state_lock);
>   
> -	preempt_disable();
> -	loaded = (vcpu->cpu != -1);
> -	if (loaded)
> +	guard(preempt)();
> +
> +	if ((running = kvm_get_running_vcpu())) {
> +		if (KVM_BUG_ON(running != vcpu, vcpu->kvm))
> +			return;
> +
> +		loaded = true;
>   		kvm_arch_vcpu_put(vcpu);
> +	}
>   
>   	if (!kvm_arm_vcpu_sve_finalized(vcpu)) {
>   		if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE))
> @@ -269,7 +275,6 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
>   
>   	if (loaded)
>   		kvm_arch_vcpu_load(vcpu, smp_processor_id());
> -	preempt_enable();
>   }
>   
>   u32 kvm_get_pa_bits(struct kvm *kvm)




More information about the linux-arm-kernel mailing list