From: Oliver Upton <oupton@kernel.org>
To: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Cc: Marc Zyngier <maz@kernel.org>, 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>, Kees Cook <kees@kernel.org>,
"Gustavo A. R. Silva" <gustavoars@kernel.org>,
Paolo Bonzini <pbonzini@redhat.com>,
Jonathan Corbet <corbet@lwn.net>, Shuah Khan <shuah@kernel.org>,
Shuah Khan <skhan@linuxfoundation.org>,
linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org,
devel@daynix.com, kvm@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kselftest@vger.kernel.org
Subject: Re: [PATCH v8 5/7] KVM: arm64: PMU: Implement fixed-counters-only emulation
Date: Mon, 6 Jul 2026 11:23:57 -0700 [thread overview]
Message-ID: <akvyvclUQ2b2YHiU@kernel.org> (raw)
In-Reply-To: <20260706-hybrid-v8-5-de459617b59d@rsg.ci.i.u-tokyo.ac.jp>
On Mon, Jul 06, 2026 at 07:03:28PM +0900, Akihiko Odaki wrote:
> Add internal state for PMUv3 emulation without programmable event
> counters. When fixed-counters-only mode is active, KVM reports no
> programmable counters and hides PMCEID, avoiding event-counter state
> whose behavior can depend on the selected hardware PMU.
>
> The cycle counter still uses a host perf event. Unlike the normal PMU
> path, fixed-counters-only mode may create that event from the hardware
> PMU attached to the VCPU's current pCPU. If the VCPU later loads on a
> pCPU that is not covered by the existing event's PMU, request a PMU
> reload so the cycle counter can be recreated against the new pCPU's PMU.
> Keep this affinity check limited to fixed-counters-only VMs; the normal
> programmable-counter mode continues to use the VM-wide PMU and does not
> need per-load reload decisions.
>
> Add a separate internal flag for explicit userspace PMU selection. The
> UAPI wiring added later will use it to keep explicit PMU selection and
> fixed-counters-only mode mutually exclusive while still allowing
> fixed-counters-only mode to replace the default PMU selected during
> KVM_ARM_VCPU_INIT.
>
> The UAPI wiring that sets the fixed-counters-only flag and records
> explicit PMU selection is added later in the series.
>
> Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> ---
> arch/arm64/include/asm/kvm_host.h | 4 ++++
> arch/arm64/kvm/arm.c | 1 +
> arch/arm64/kvm/pmu-emul.c | 43 +++++++++++++++++++++++++++++++++++++--
> include/kvm/arm_pmu.h | 2 ++
> 4 files changed, 48 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 0c39d9db7d57..aa07b05b8231 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -353,6 +353,10 @@ struct kvm_arch {
> #define KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS 10
> /* Unhandled SEAs are taken to userspace */
> #define KVM_ARCH_FLAG_EXIT_SEA 11
> + /* PMUv3 is emulated with an explicitly specified hardware PMU */
> +#define KVM_ARCH_FLAG_PMU_V3_EXPLICIT 12
> + /* PMUv3 is emulated without progammable event counters */
> +#define KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY 13
> unsigned long flags;
>
> /* VM-wide vCPU feature set */
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 68767bb08285..1cc7754d5ace 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -687,6 +687,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
> if (has_vhe())
> kvm_vcpu_load_vhe(vcpu);
> kvm_arch_vcpu_load_fp(vcpu);
> + kvm_vcpu_load_pmu(vcpu);
> kvm_vcpu_pmu_restore_guest(vcpu);
> if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
> kvm_make_request(KVM_REQ_RECORD_STEAL, vcpu);
> diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
> index e70628653e4b..40cad183376c 100644
> --- a/arch/arm64/kvm/pmu-emul.c
> +++ b/arch/arm64/kvm/pmu-emul.c
> @@ -96,6 +96,11 @@ u64 kvm_pmu_evtyper_mask(struct kvm *kvm)
> return mask;
> }
>
> +static bool kvm_pmu_fixed_counters_only(struct kvm *kvm)
> +{
> + return test_bit(KVM_ARCH_FLAG_PMU_V3_FIXED_COUNTERS_ONLY, &kvm->arch.flags);
> +}
> +
> /**
> * kvm_pmc_is_64bit - determine if counter is 64bit
> * @pmc: counter context
> @@ -343,7 +348,11 @@ u64 kvm_pmu_implemented_counter_mask(struct kvm_vcpu *vcpu)
>
> static void kvm_pmc_enable_perf_event(struct kvm_pmc *pmc)
> {
> - if (!pmc->perf_event) {
> + struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
> +
> + if (!pmc->perf_event ||
> + (kvm_pmu_fixed_counters_only(vcpu->kvm) &&
> + !cpumask_test_cpu(vcpu->cpu, &to_arm_pmu(pmc->perf_event->pmu)->supported_cpus))) {
> kvm_pmu_create_perf_event(pmc);
> return;
> }
> @@ -720,6 +729,12 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
> int eventsel;
> u64 evtreg;
>
> + if (kvm_pmu_fixed_counters_only(vcpu->kvm)) {
> + arm_pmu = kvm_pmu_probe_armpmu(vcpu->cpu);
> + if (WARN_ON_ONCE(!arm_pmu))
> + return;
> + }
> +
> evtreg = kvm_pmc_read_evtreg(pmc);
>
> kvm_pmu_stop_counter(pmc);
> @@ -748,7 +763,7 @@ static void kvm_pmu_create_perf_event(struct kvm_pmc *pmc)
> * Don't create an event if we're running on hardware that requires
> * PMUv3 event translation and we couldn't find a valid mapping.
> */
> - eventsel = kvm_map_pmu_event(vcpu->kvm->arch.arm_pmu, eventsel);
> + eventsel = kvm_map_pmu_event(arm_pmu, eventsel);
> if (eventsel < 0)
> return;
>
> @@ -878,6 +893,9 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
> u64 val, mask = 0;
> int base, i, nr_events;
>
> + if (kvm_pmu_fixed_counters_only(vcpu->kvm))
> + return 0;
> +
Even if we advertise bits in PMCEID, does it matter? There's no PMC that
the guest could use to count it.
I understand it isn't aesthetic but I really want to minimize the
special-casing that has to be done for this feature.
> +void kvm_vcpu_load_pmu(struct kvm_vcpu *vcpu)
> +{
> + /*
> + * ARMV8_PMU_INSTR_IDX will need the same check once
> + * FEAT_PMUv3_ICNTR is supported.
> + */
> + struct kvm_pmc *pmc = kvm_vcpu_idx_to_pmc(vcpu, ARMV8_PMU_CYCLE_IDX);
> + struct arm_pmu *cpu_pmu;
> +
> + if (!kvm_pmu_fixed_counters_only(vcpu->kvm) ||
> + !kvm_pmu_counter_is_enabled(pmc) || !pmc->perf_event)
> + return;
> +
> + cpu_pmu = to_arm_pmu(pmc->perf_event->pmu);
> + if (!cpumask_test_cpu(vcpu->cpu, &cpu_pmu->supported_cpus))
> + kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
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);
}
Thanks,
Oliver
next prev parent reply other threads:[~2026-07-06 18:23 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-06 10:03 [PATCH v8 0/7] KVM: arm64: PMU: Use multiple host PMUs Akihiko Odaki
2026-07-06 10:03 ` [PATCH v8 1/7] KVM: arm64: Disallow vPMU when pPMUs do not cover all CPUs Akihiko Odaki
2026-07-06 17:04 ` Oliver Upton
2026-07-07 11:08 ` Akihiko Odaki
2026-07-06 10:03 ` [PATCH v8 2/7] KVM: arm64: PMU: Protect the list of PMUs with RCU Akihiko Odaki
2026-07-06 10:03 ` [PATCH v8 3/7] KVM: arm64: PMU: Pass the pPMU to kvm_map_pmu_event() Akihiko Odaki
2026-07-06 10:03 ` [PATCH v8 4/7] KVM: arm64: PMU: Pass the target CPU to kvm_pmu_probe_armpmu() Akihiko Odaki
2026-07-06 10:03 ` [PATCH v8 5/7] KVM: arm64: PMU: Implement fixed-counters-only emulation Akihiko Odaki
2026-07-06 10:53 ` sashiko-bot
2026-07-06 18:23 ` Oliver Upton [this message]
2026-07-07 11:23 ` Akihiko Odaki
2026-07-07 12:52 ` Akihiko Odaki
2026-07-06 10:03 ` [PATCH v8 6/7] KVM: arm64: PMU: Introduce FIXED_COUNTERS_ONLY Akihiko Odaki
2026-07-06 11:13 ` sashiko-bot
2026-07-06 17:58 ` Oliver Upton
2026-07-07 11:36 ` Akihiko Odaki
2026-07-06 10:03 ` [PATCH v8 7/7] KVM: arm64: selftests: Test PMU_V3_FIXED_COUNTERS_ONLY Akihiko Odaki
2026-07-06 18:28 ` [PATCH v8 0/7] KVM: arm64: PMU: Use multiple host PMUs Oliver Upton
2026-07-07 7:58 ` Marc Zyngier
2026-07-07 8:10 ` Oliver Upton
2026-07-07 9:41 ` 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=akvyvclUQ2b2YHiU@kernel.org \
--to=oupton@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=corbet@lwn.net \
--cc=devel@daynix.com \
--cc=gustavoars@kernel.org \
--cc=joey.gouly@arm.com \
--cc=kees@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=maz@kernel.org \
--cc=odaki@rsg.ci.i.u-tokyo.ac.jp \
--cc=pbonzini@redhat.com \
--cc=shuah@kernel.org \
--cc=skhan@linuxfoundation.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.