Commit 02243533 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

KVM: arm64: Contextualise the handling of PMCR_EL0.P writes



Contrary to what the comment says in kvm_pmu_handle_pmcr(),
writing PMCR_EL0.P==1 has the following effects:

<quote>
The event counters affected by this field are:
  * All event counters in the first range.
  * If any of the following are true, all event counters in the second
    range:
    - EL2 is disabled or not implemented in the current Security state.
    - The PE is executing at EL2 or EL3.
</quote>

where the "first range" represent the counters in the [0..HPMN-1]
range, and the "second range" the counters in the [HPMN..MAX] range.

It so appears that writing P from EL2 should nuke all counters,
and not just the "guest" view. Just do that, and nuke the misleading
comment.

Reported-by: default avatarJoey Gouly <joey.gouly@arm.com>
Reviewed-by: default avatarOliver Upton <oliver.upton@linux.dev>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent c8823e51
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -608,14 +608,12 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
		kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0);

	if (val & ARMV8_PMU_PMCR_P) {
		/*
		 * Unlike other PMU sysregs, the controls in PMCR_EL0 always apply
		 * to the 'guest' range of counters and never the 'hyp' range.
		 */
		unsigned long mask = kvm_pmu_implemented_counter_mask(vcpu) &
				     ~kvm_pmu_hyp_counter_mask(vcpu) &
				     ~BIT(ARMV8_PMU_CYCLE_IDX);

		if (!vcpu_is_el2(vcpu))
			mask &= ~kvm_pmu_hyp_counter_mask(vcpu);

		for_each_set_bit(i, &mask, 32)
			kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, i), 0, true);
	}