From: Marc Zyngier <maz@kernel.org>
To: Akihiko Odaki <akihiko.odaki@daynix.com>
Cc: Oliver Upton <oliver.upton@linux.dev>,
Joey Gouly <joey.gouly@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Zenghui Yu <yuzenghui@huawei.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>, Andrew Jones <drjones@redhat.com>,
Shannon Zhao <shannon.zhao@linaro.org>,
linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
linux-kernel@vger.kernel.org, devel@daynix.com
Subject: Re: [PATCH v2 1/3] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
Date: Sun, 09 Mar 2025 18:40:00 +0000 [thread overview]
Message-ID: <867c4yoxof.wl-maz@kernel.org> (raw)
In-Reply-To: <20250307-pmc-v2-1-6c3375a5f1e4@daynix.com>
On Fri, 07 Mar 2025 10:55:28 +0000,
Akihiko Odaki <akihiko.odaki@daynix.com> wrote:
>
> Reload the perf event when setting the vPMU counter (vPMC) registers
> (PMCCNTR_EL0 and PMEVCNTR<n>_EL0). This is a change corresponding to
> commit 9228b26194d1 ("KVM: arm64: PMU: Fix GET_ONE_REG
> for vPMC regs to return the current value") but for SET_ONE_REG.
>
> Values of vPMC registers are saved in sysreg files on certain occasions.
> These saved values don't represent the current values of the vPMC
> registers if the perf events for the vPMCs count events after the save.
> The current values of those registers are the sum of the sysreg file
> value and the current perf event counter value. But, when userspace
> writes those registers (using KVM_SET_ONE_REG), KVM only updates the
> sysreg file value and leaves the current perf event counter value as is.
>
> Fix this by releasing the current perf event and trigger recreating one
> with KVM_REQ_RELOAD_PMU.
>
> Fixes: 051ff581ce70 ("arm64: KVM: Add access handler for event counter register")
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
> arch/arm64/kvm/pmu-emul.c | 16 ++++++++++++++++
> arch/arm64/kvm/sys_regs.c | 20 +++++++++++++++++++-
> include/kvm/arm_pmu.h | 1 +
> 3 files changed, 36 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
> index e3e82b66e2268d37d5e2630e47ddf085a6846e1c..1402cce5625bffa706aabe5e6121d1f3817a0aaf 100644
> --- a/arch/arm64/kvm/pmu-emul.c
> +++ b/arch/arm64/kvm/pmu-emul.c
> @@ -191,6 +191,22 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
> kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, select_idx), val, false);
> }
>
> +/**
> + * kvm_pmu_set_counter_value_user - set PMU counter value from user
> + * @vcpu: The vcpu pointer
> + * @select_idx: The counter index
> + * @val: The counter value
> + */
> +void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
> +{
> + if (!kvm_vcpu_has_pmu(vcpu))
> + return;
How can this occur? It seems to me that we only get here from a
register that has .visibility == pmu_visibility().
Or is there another way to reach this function?
> +
> + kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, select_idx));
> + __vcpu_sys_reg(vcpu, counter_index_to_reg(select_idx)) = val;
> + kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
> +}
> +
> /**
> * kvm_pmu_release_perf_event - remove the perf event
> * @pmc: The PMU counter pointer
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 42791971f75887796afab905cc12f49fead39e10..27418dac791df9a89124f867879e899db175e506 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1035,6 +1035,22 @@ static int get_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
> return 0;
> }
>
> +static int set_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
> + u64 val)
> +{
> + u64 idx;
> +
> + if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
> + /* PMCCNTR_EL0 */
> + idx = ARMV8_PMU_CYCLE_IDX;
> + else
> + /* PMEVCNTRn_EL0 */
> + idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
> +
> + kvm_pmu_set_counter_value_user(vcpu, idx, val);
> + return 0;
> +}
> +
> static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
> struct sys_reg_params *p,
> const struct sys_reg_desc *r)
> @@ -1328,6 +1344,7 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
> #define PMU_PMEVCNTR_EL0(n) \
> { PMU_SYS_REG(PMEVCNTRn_EL0(n)), \
> .reset = reset_pmevcntr, .get_user = get_pmu_evcntr, \
> + .set_user = set_pmu_evcntr, \
> .access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
>
> /* Macro to expand the PMEVTYPERn_EL0 register */
> @@ -2682,7 +2699,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
> .access = access_pmceid, .reset = NULL },
> { PMU_SYS_REG(PMCCNTR_EL0),
> .access = access_pmu_evcntr, .reset = reset_unknown,
> - .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr},
> + .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr,
> + .set_user = set_pmu_evcntr },
> { PMU_SYS_REG(PMXEVTYPER_EL0),
> .access = access_pmu_evtyper, .reset = NULL },
> { PMU_SYS_REG(PMXEVCNTR_EL0),
> diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
> index 28b380ad8dfa942c4275e0c7ed3535d309b81b2f..9c062756ebfad5ea555362154459ffe9f8311c6d 100644
> --- a/include/kvm/arm_pmu.h
> +++ b/include/kvm/arm_pmu.h
> @@ -41,6 +41,7 @@ bool kvm_supports_guest_pmuv3(void);
> #define kvm_arm_pmu_irq_initialized(v) ((v)->arch.pmu.irq_num >= VGIC_NR_SGIS)
> u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
> void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
> +void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
> u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
> u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1);
> void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);
Other than the nit above, looks good to me.
M.
--
Without deviation from the norm, progress is not possible.
next prev parent reply other threads:[~2025-03-09 18:40 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-07 10:55 [PATCH v2 0/3] KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs Akihiko Odaki
2025-03-07 10:55 ` [PATCH v2 1/3] " Akihiko Odaki
2025-03-09 18:40 ` Marc Zyngier [this message]
2025-03-07 10:55 ` [PATCH v2 2/3] KVM: arm64: PMU: Reload when user modifies registers Akihiko Odaki
2025-03-09 18:50 ` Marc Zyngier
2025-03-07 10:55 ` [PATCH v2 3/3] KVM: arm64: PMU: Set raw values from user to PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR} Akihiko Odaki
2025-03-09 19:01 ` Marc Zyngier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=867c4yoxof.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=akihiko.odaki@daynix.com \
--cc=catalin.marinas@arm.com \
--cc=devel@daynix.com \
--cc=drjones@redhat.com \
--cc=joey.gouly@arm.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=oliver.upton@linux.dev \
--cc=shannon.zhao@linaro.org \
--cc=suzuki.poulose@arm.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.