linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Oliver Upton <oupton@kernel.org>
To: Colton Lewis <coltonlewis@google.com>
Cc: kvm@vger.kernel.org, Paolo Bonzini <pbonzini@redhat.com>,
	Jonathan Corbet <corbet@lwn.net>,
	Russell King <linux@armlinux.org.uk>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>, Marc Zyngier <maz@kernel.org>,
	Oliver Upton <oliver.upton@linux.dev>,
	Mingwei Zhang <mizhang@google.com>,
	Joey Gouly <joey.gouly@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Zenghui Yu <yuzenghui@huawei.com>,
	Mark Rutland <mark.rutland@arm.com>,
	Shuah Khan <shuah@kernel.org>,
	Ganapatrao Kulkarni <gankulkarni@os.amperecomputing.com>,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
	linux-perf-users@vger.kernel.org,
	linux-kselftest@vger.kernel.org
Subject: Re: [PATCH v5 14/24] KVM: arm64: Write fast path PMU register handlers
Date: Tue, 16 Dec 2025 16:38:56 -0800	[thread overview]
Message-ID: <aUH7oC41XaEMsXf_@kernel.org> (raw)
In-Reply-To: <20251209205121.1871534-15-coltonlewis@google.com>

On Tue, Dec 09, 2025 at 08:51:11PM +0000, Colton Lewis wrote:
> diff --git a/arch/arm64/include/asm/arm_pmuv3.h b/arch/arm64/include/asm/arm_pmuv3.h
> index 3e25c0313263c..41ec6730ebc62 100644
> --- a/arch/arm64/include/asm/arm_pmuv3.h
> +++ b/arch/arm64/include/asm/arm_pmuv3.h
> @@ -39,6 +39,16 @@ static inline unsigned long read_pmevtypern(int n)
>  	return 0;
>  }
>  
> +static inline void write_pmxevcntr(u64 val)
> +{
> +	write_sysreg(val, pmxevcntr_el0);
> +}
> +
> +static inline u64 read_pmxevcntr(void)
> +{
> +	return read_sysreg(pmxevcntr_el0);
> +}
> +
>  static inline unsigned long read_pmmir(void)
>  {
>  	return read_cpuid(PMMIR_EL1);
> @@ -105,21 +115,41 @@ static inline void write_pmcntenset(u64 val)
>  	write_sysreg(val, pmcntenset_el0);
>  }
>  
> +static inline u64 read_pmcntenset(void)
> +{
> +	return read_sysreg(pmcntenset_el0);
> +}
> +
>  static inline void write_pmcntenclr(u64 val)
>  {
>  	write_sysreg(val, pmcntenclr_el0);
>  }
>  
> +static inline u64 read_pmcntenclr(void)
> +{
> +	return read_sysreg(pmcntenclr_el0);
> +}
> +
>  static inline void write_pmintenset(u64 val)
>  {
>  	write_sysreg(val, pmintenset_el1);
>  }
>  
> +static inline u64 read_pmintenset(void)
> +{
> +	return read_sysreg(pmintenset_el1);
> +}
> +
>  static inline void write_pmintenclr(u64 val)
>  {
>  	write_sysreg(val, pmintenclr_el1);
>  }
>  
> +static inline u64 read_pmintenclr(void)
> +{
> +	return read_sysreg(pmintenclr_el1);
> +}
> +
>  static inline void write_pmccfiltr(u64 val)
>  {
>  	write_sysreg(val, pmccfiltr_el0);
> @@ -160,11 +190,16 @@ static inline u64 read_pmovsclr(void)
>  	return read_sysreg(pmovsclr_el0);
>  }
>  
> -static inline void write_pmuserenr(u32 val)
> +static inline void write_pmuserenr(u64 val)
>  {
>  	write_sysreg(val, pmuserenr_el0);
>  }
>  
> +static inline u64 read_pmuserenr(void)
> +{
> +	return read_sysreg(pmuserenr_el0);
> +}
> +
>  static inline void write_pmuacr(u64 val)
>  {
>  	write_sysreg_s(val, SYS_PMUACR_EL1);

I wouldn't bother with adding accessors to the PMUv3 driver header, this
gets a bit confusing when the 32-bit counterpart lacks matching definitions.
Additionally, the part of KVM you're modifying is very much an
"internal" part meant to run in a not-quite-kernel context.

Considering this, I'd prefer KVM directly accessed the PMU registers to
avoid the possibility of taking some instrumented codepath in the
future.

> +	if (!kvm_vcpu_pmu_is_partitioned(vcpu)
> +	    || pmu_access_el0_disabled(vcpu))

Always put operators on the preceding line for line continuations.

Also, don't call pmu_access_el0_disabled() from here. It can potentially
do a full emulated exception entry even though the vCPU is in an
extremely inconsistent state (i.e. haven't returned to kernel context
yet). Isn't the current value for PMUSERENR_EL0 on the CPU instead of in
the vCPU's saved context anyway?

The fast-path accessors really need to be *just* accessors, reading
state from the CPU in the unfortunate situation that a TPM trap has been
forced upon us.

> +	case SYS_PMXEVCNTR_EL0:
> +		idx = FIELD_GET(PMSELR_EL0_SEL, read_pmselr());
> +
> +		if (pmu_access_event_counter_el0_disabled(vcpu))
> +			return false;
> +
> +		if (!pmu_counter_idx_valid(vcpu, idx))
> +			return false;
> +
> +		ret = handle_pmu_reg(vcpu, &p, PMEVCNTR0_EL0 + idx, rt, val,
> +				     &read_pmxevcntr, &write_pmxevcntr);
> +		break;

It is a bit odd to handle the muxing for finding the in-memory value yet
using the selector-based register for hardware.

> +	case SYS_PMEVCNTRn_EL0(0) ... SYS_PMEVCNTRn_EL0(30):
> +		idx = ((p.CRm & 3) << 3) | (p.Op2 & 7);
> +
> +		if (pmu_access_event_counter_el0_disabled(vcpu))
> +			return false;
> +
> +		if (!pmu_counter_idx_valid(vcpu, idx))
> +			return false;
> +
> +		if (p.is_write) {
> +			write_pmevcntrn(idx, val);
> +			__vcpu_assign_sys_reg(vcpu, PMEVCNTR0_EL0 + idx, val);
> +		} else {
> +			vcpu_set_reg(vcpu, rt, read_pmevcntrn(idx));
> +		}
> +
> +		ret = true;
> +		break;

Can't both of these cases share a helper once you've worked out the
index? Same for PMEVTYPERn_EL0.

> +	default:
> +		ret = false;
> +	}
> +
> +	if (ret)
> +		__kvm_skip_instr(vcpu);
> +
> +	return ret;
> +}
> +
>  static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
>  {
>  	if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
> @@ -785,6 +983,9 @@ static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code)
>  	if (kvm_handle_cntxct(vcpu))
>  		return true;
>  
> +	if (kvm_hyp_handle_pmu_regs(vcpu))
> +		return true;
> +

Since the whole partitioned PMU feature is constrained to VHE-only you
should call this from kvm_hyp_handle_sysreg_vhe().

> +
> +bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags)
> +{
> +	u64 reg = __vcpu_sys_reg(vcpu, PMUSERENR_EL0);
> +	bool enabled = (reg & flags) || vcpu_mode_priv(vcpu);
> +
> +	if (!enabled)
> +		kvm_inject_undefined(vcpu);
> +
> +	return !enabled;
> +}
> +
> +bool pmu_access_el0_disabled(struct kvm_vcpu *vcpu)
> +{
> +	return check_pmu_access_disabled(vcpu, ARMV8_PMU_USERENR_EN);
> +}
> +
> +bool pmu_counter_idx_valid(struct kvm_vcpu *vcpu, u64 idx)
> +{
> +	u64 pmcr, val;
> +
> +	pmcr = kvm_vcpu_read_pmcr(vcpu);
> +	val = FIELD_GET(ARMV8_PMU_PMCR_N, pmcr);
> +	if (idx >= val && idx != ARMV8_PMU_CYCLE_IDX) {
> +		kvm_inject_undefined(vcpu);
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +bool pmu_access_cycle_counter_el0_disabled(struct kvm_vcpu *vcpu)
> +{
> +	return check_pmu_access_disabled(vcpu, ARMV8_PMU_USERENR_CR | ARMV8_PMU_USERENR_EN);
> +}
> +
> +bool pmu_access_event_counter_el0_disabled(struct kvm_vcpu *vcpu)
> +{
> +	return check_pmu_access_disabled(vcpu, ARMV8_PMU_USERENR_ER | ARMV8_PMU_USERENR_EN);
> +}

Refactorings need to happen in a separate patch.

Thanks,
Oliver

  reply	other threads:[~2025-12-17  0:38 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-09 20:50 [PATCH v5 00/24] ARM64 PMU Partitioning Colton Lewis
2025-12-09 20:50 ` [PATCH v5 01/24] arm64: cpufeature: Add cpucap for HPMN0 Colton Lewis
2025-12-10 10:54   ` Suzuki K Poulose
2025-12-12 19:22     ` Colton Lewis
2025-12-09 20:50 ` [PATCH v5 02/24] KVM: arm64: Move arm_{psci,hypercalls}.h to an internal KVM path Colton Lewis
2025-12-09 20:51 ` [PATCH v5 03/24] KVM: arm64: Include KVM headers to get forward declarations Colton Lewis
2025-12-09 20:51 ` [PATCH v5 04/24] KVM: arm64: Move ARM specific headers in include/kvm to arch directory Colton Lewis
2025-12-09 20:51 ` [PATCH v5 05/24] KVM: arm64: Reorganize PMU includes Colton Lewis
2025-12-09 20:51 ` [PATCH v5 06/24] KVM: arm64: Reorganize PMU functions Colton Lewis
2025-12-09 20:51 ` [PATCH v5 07/24] perf: arm_pmuv3: Introduce method to partition the PMU Colton Lewis
2025-12-09 20:51 ` [PATCH v5 08/24] perf: arm_pmuv3: Generalize counter bitmasks Colton Lewis
2025-12-09 20:51 ` [PATCH v5 09/24] perf: arm_pmuv3: Keep out of guest counter partition Colton Lewis
2025-12-10 20:21   ` kernel test robot
2025-12-12 20:29     ` Colton Lewis
2025-12-09 20:51 ` [PATCH v5 10/24] KVM: arm64: Set up FGT for Partitioned PMU Colton Lewis
2025-12-09 21:08   ` Oliver Upton
2025-12-12 20:51     ` Colton Lewis
2025-12-17  0:13       ` Oliver Upton
2025-12-09 20:51 ` [PATCH v5 11/24] KVM: arm64: Writethrough trapped PMEVTYPER register Colton Lewis
2025-12-10 18:31   ` kernel test robot
2025-12-12 20:27     ` Colton Lewis
2025-12-09 20:51 ` [PATCH v5 12/24] KVM: arm64: Use physical PMSELR for PMXEVTYPER if partitioned Colton Lewis
2025-12-09 21:14   ` Oliver Upton
2025-12-12 20:54     ` Colton Lewis
2025-12-09 20:51 ` [PATCH v5 13/24] KVM: arm64: Writethrough trapped PMOVS register Colton Lewis
2025-12-09 21:19   ` Oliver Upton
2025-12-12 21:06     ` Colton Lewis
2025-12-09 20:51 ` [PATCH v5 14/24] KVM: arm64: Write fast path PMU register handlers Colton Lewis
2025-12-17  0:38   ` Oliver Upton [this message]
2025-12-09 20:51 ` [PATCH v5 15/24] KVM: arm64: Setup MDCR_EL2 to handle a partitioned PMU Colton Lewis
2025-12-09 21:33   ` Oliver Upton
2025-12-12 21:22     ` Colton Lewis
2025-12-09 20:51 ` [PATCH v5 16/24] KVM: arm64: Account for partitioning in PMCR_EL0 access Colton Lewis
2025-12-09 21:37   ` Oliver Upton
2025-12-12 21:31     ` Colton Lewis
2025-12-09 20:51 ` [PATCH v5 17/24] KVM: arm64: Context swap Partitioned PMU guest registers Colton Lewis
2025-12-09 21:55   ` Oliver Upton
2025-12-12 21:57     ` Colton Lewis
2025-12-09 20:51 ` [PATCH v5 18/24] KVM: arm64: Enforce PMU event filter at vcpu_load() Colton Lewis
2025-12-09 22:00   ` Oliver Upton
2025-12-12 21:59     ` Colton Lewis
2025-12-17  0:57   ` Oliver Upton
2025-12-09 20:51 ` [PATCH v5 19/24] KVM: arm64: Implement lazy PMU context swaps Colton Lewis
2025-12-09 22:06   ` Oliver Upton
2025-12-12 22:25     ` Colton Lewis
2025-12-15 18:06       ` Oliver Upton
2025-12-09 20:51 ` [PATCH v5 20/24] perf: arm_pmuv3: Handle IRQs for Partitioned PMU guest counters Colton Lewis
2025-12-09 22:45   ` Oliver Upton
2025-12-12 22:36     ` Colton Lewis
2025-12-09 20:51 ` [PATCH v5 21/24] KVM: arm64: Inject recorded guest interrupts Colton Lewis
2025-12-09 22:52   ` Oliver Upton
2025-12-12 22:55     ` Colton Lewis
2025-12-15 17:50       ` Oliver Upton
2025-12-09 20:51 ` [PATCH v5 22/24] KVM: arm64: Add KVM_CAP to partition the PMU Colton Lewis
2025-12-09 22:58   ` Oliver Upton
2025-12-12 22:59     ` Colton Lewis
2025-12-09 20:51 ` [PATCH v5 23/24] KVM: selftests: Add find_bit to KVM library Colton Lewis
2025-12-09 20:51 ` [PATCH v5 24/24] KVM: arm64: selftests: Add test case for partitioned PMU Colton Lewis
2025-12-09 23:00 ` [PATCH v5 00/24] ARM64 PMU Partitioning Oliver Upton

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=aUH7oC41XaEMsXf_@kernel.org \
    --to=oupton@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=coltonlewis@google.com \
    --cc=corbet@lwn.net \
    --cc=gankulkarni@os.amperecomputing.com \
    --cc=joey.gouly@arm.com \
    --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-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=mark.rutland@arm.com \
    --cc=maz@kernel.org \
    --cc=mizhang@google.com \
    --cc=oliver.upton@linux.dev \
    --cc=pbonzini@redhat.com \
    --cc=shuah@kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).