All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
To: Alexandru Elisei <alexandru.elisei@arm.com>
Cc: maz@kernel.org, oupton@kernel.org, fuad.tabba@linux.dev,
	 joey.gouly@arm.com, seiden@linux.ibm.com,
	suzuki.poulose@arm.com,  yuzenghui@huawei.com,
	linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
	 will@kernel.org, mark.rutland@arm.com,
	linux-perf-users@vger.kernel.org,  catalin.marinas@arm.com,
	james.clark@linaro.org
Subject: Re: [RFC PATCH v7 20/28] KVM: arm64: Allow guest SPE physical timestamps only if kernel allows it
Date: Tue, 3 Nov 2026 17:04:13 +0000	[thread overview]
Message-ID: <auoFWWJHUcmvif7s@gremlin> (raw)
In-Reply-To: <20260903160623.315525-21-alexandru.elisei@arm.com>

On Thu, Sep 03, 2026 at 05:06:15PM +0100, Alexandru Elisei wrote:
> The SPE driver allows userspace to use physical timestamps for records only
> if the kernel allows it, do the same for a virtual machine.

This is really bare bones again. You are making a broader change of restoring
PMSCR_EL2 and gating on perf_allow_kernel() etc. - you should explain what
you're doing here.

Also you definitely need a 'why' here :>)

>
> Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
> ---
>  arch/arm64/include/asm/kvm_spe.h | 1 +
>  arch/arm64/kvm/hyp/vhe/spe-sr.c  | 5 +++--
>  arch/arm64/kvm/spe.c             | 8 ++++++++
>  3 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_spe.h b/arch/arm64/include/asm/kvm_spe.h
> index ad0ad6ace93c..8a55ea0de4e5 100644
> --- a/arch/arm64/include/asm/kvm_spe.h
> +++ b/arch/arm64/include/asm/kvm_spe.h
> @@ -15,6 +15,7 @@ struct arm_spe_pmu;
>  struct kvm_spe {
>  	struct arm_spe_pmu *spe_pmu;
>  	u64 pmblimitr_el1_res0_mask;
> +	u64 guest_pmscr_el2;
>  };
>
>  struct kvm_vcpu_spe {
> diff --git a/arch/arm64/kvm/hyp/vhe/spe-sr.c b/arch/arm64/kvm/hyp/vhe/spe-sr.c
> index 978620ad99fa..3c32a1338cc8 100644
> --- a/arch/arm64/kvm/hyp/vhe/spe-sr.c
> +++ b/arch/arm64/kvm/hyp/vhe/spe-sr.c
> @@ -107,6 +107,7 @@ static bool __kvm_spe_profiling_buffer_enabled(u64 pmblimitr, u64 pmbsr)
>   */
>  void __kvm_spe_restore_guest_state_vhe(struct kvm_vcpu *vcpu, struct kvm_cpu_context *guest_ctxt)
>  {
> +	struct kvm *kvm = vcpu->kvm;
>  	u64 pmblimitr, pmbsr;
>
>  	pmbsr = ctxt_sys_reg(guest_ctxt, PMBSR_EL1);
> @@ -120,10 +121,10 @@ void __kvm_spe_restore_guest_state_vhe(struct kvm_vcpu *vcpu, struct kvm_cpu_con
>  		write_sysreg_s(pmbsr, SYS_PMBSR_EL1);
>  	}
>
> -	__kvm_spe_restore_sampling_regs(vcpu->kvm, guest_ctxt);
> +	__kvm_spe_restore_sampling_regs(kvm, guest_ctxt);
>
>  	write_sysreg_el1(ctxt_sys_reg(guest_ctxt, PMSCR_EL1), SYS_PMSCR);
> -	write_sysreg_el2(0, SYS_PMSCR);
> +	write_sysreg_el2(kvm->arch.kvm_spe.guest_pmscr_el2, SYS_PMSCR);
>  }
>  NOKPROBE_SYMBOL(__kvm_spe_restore_guest_state_vhe);
>
> diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c
> index af1e19cb8e9a..68b751bdb384 100644
> --- a/arch/arm64/kvm/spe.c
> +++ b/arch/arm64/kvm/spe.c
> @@ -3,9 +3,11 @@
>   * Copyright (C) 2021 - ARM Ltd
>   */
>
> +#include <linux/capability.h>
>  #include <linux/cpumask.h>
>  #include <linux/kvm_host.h>
>  #include <linux/perf/arm_spe_pmu.h>
> +#include <linux/perf_event.h>
>
>  #include <asm/kvm_emulate.h>
>  #include <asm/kvm_spe.h>
> @@ -97,6 +99,12 @@ int kvm_spe_vcpu_first_run_init(struct kvm_vcpu *vcpu)
>  	if (!kvm_spe->pmblimitr_el1_res0_mask)
>  		kvm_spe_compute_pmblimitr_el1_res0_mask(kvm);
>
> +	if (kvm_vm_has_ran_once(kvm))
> +		return 0;
> +
> +	if (perf_allow_kernel())
> +		kvm_spe->guest_pmscr_el2 = PMSCR_EL2_PCT_PHYS;

Ouch, I see the bot raised that perf_allow_kernel() does the 'return 0 if
success' pattern which is just AWFUL naming.

Though I'm confused as to why you're gating on this at all? The driver needs to,
I get that, as you don't want host userspace to gain access.

But physical timestamps in the SPE buffer seems fine? What's the threat model
there? This should be explained with a comment/commit msg if there if it's
needed.

Does it expose this data to userspace in a way that is not correctly gated? Or
does the driver already handle this?

Looking at [0], I can see that there are multiple options here in PMSCR_EL2.PCT:

* PMSCR_EL2_PCT_VIRT = 0b00 - Virtual, offset by CNTVOFF_EL2 (unless EL2-owned
  then 0, but patch 19 already made it EL1-owned when guest sampling).

* PMSCR_EL2_PCT_PHYS = 0b01 - Defer to PMSCR_EL1.PCT if EL1-owned, otherwise
  phys. Define phys as the RAW physical counter (no offset).

* PMSCR_EL2_PCT_GUEST = 0b11 - Defer to PMSCR_EL1.PCT if EL1-owned.
  Virtual means raw phys minus CNTVOFF_EL2. Phys means raw phys minus
  CNTPOFF_EL2 when ECV is enabled, otherwise no offset.

And [1], [2] tells me that there are offsets to take into account (ugh)
which I see can be set via KVM_ARM_SET_COUNTER_OFFSET, and these counters will
be what is used to correlate the data with other perf counters.

As far as I can make out from the timer code, if there's no CNTPOFF_EL2
but userspace has set a physical offset, KVM traps the guest's CNTPCT
reads and applies the offset in software, i.e. in timer_set_traps():

    /*
     * We have two possibility to deal with a physical offset:
     *
     * - Either we have CNTPOFF (yay!) or the offset is 0:
     *	 we let the guest freely access the HW
     *
     * - or neither of these condition apply:
     *	 we trap accesses to the HW, but still use it
     *	 after correcting the physical offset
     */
    if (!has_cntpoff() && timer_get_offset(map->direct_ptimer))
	tpt = tpc = true;

So just accepting physical timestamps in SPE would mean they'd be offset
from the physical counter.

Where CNTPOFF_EL2 exists, PMSCR_EL2_PCT_GUEST does the right thing in
both directions - virtual minus CNTVOFF_EL2, physical minus
CNTPOFF_EL2).

But you're kinda screwed if it doesn't, so the only way for the timestamps
to be consistent with what's expected is to force a virtual offset.

So the code should look like:

    u64 pct;

    ...

    /* Without CNTPOFF_EL2 physical timestamps can't be offset, so deny them. */
    pct = has_cntpoff() ? PMSCR_EL2_PCT_GUEST : PMSCR_EL2_PCT_VIRT;
    kvm_spe->guest_pmscr_el2 = FIELD_PREP(PMSCR_EL2_PCT, pct);

I think.

> +
>  	return 0;
>  }
>
> --
> 2.43.0
>
>

--
Cheers, Lorenzo

[0]:https://support.arm.com/documentation/ddi0601/2026-09/AArch64-Registers/PMSCR-EL2--Statistical-Profiling-Control-Register--EL2-?lang=en
[1]:https://support.arm.com/documentation/ddi0601/2026-09/AArch64-Registers/CNTVOFF-EL2--Counter-timer-Virtual-Offset-Register?lang=en
[2]:https://support.arm.com/documentation/ddi0601/2026-09/AArch64-Registers/CNTPOFF-EL2--Counter-timer-Physical-Offset-Register?lang=en

  parent reply	other threads:[~2026-11-03 17:04 UTC|newest]

Thread overview: 101+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-03 16:05 [RFC PATCH v7 00/28] KVM: arm64: Add Statistical Profiling Extension (SPE) support Alexandru Elisei
2026-09-03 16:05 ` [RFC PATCH v7 01/28] arm64/sysreg: Add the nVM field to PMBLIMITR_EL1 Alexandru Elisei
2026-09-03 16:14   ` sashiko-bot
2026-10-15 13:23   ` Lorenzo Stoakes (ARM)
2026-09-03 16:05 ` [RFC PATCH v7 02/28] arm64/sysreg: Define MDCR_EL2.E2PB values Alexandru Elisei
2026-09-03 16:12   ` sashiko-bot
2026-10-15 13:52   ` Lorenzo Stoakes (ARM)
2026-09-03 16:05 ` [RFC PATCH v7 03/28] KVM: arm64: Add CONFIG_KVM_ARM_SPE Kconfig option Alexandru Elisei
2026-09-03 16:13   ` sashiko-bot
2026-10-15 14:15   ` Lorenzo Stoakes (ARM)
2026-09-03 16:05 ` [RFC PATCH v7 04/28] perf: arm_spe_pmu: Move struct arm_spe_pmu to a separate header file Alexandru Elisei
2026-09-03 16:11   ` sashiko-bot
2026-10-15 14:40   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 05/28] perf: arm_spe_pmu: Add PMBIDR_EL1 and PMSIDR_EL1 to struct arm_spe_pmu Alexandru Elisei
2026-09-03 16:11   ` sashiko-bot
2026-10-15 15:12   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 06/28] KVM: arm64: Add KVM_CAP_ARM_SPE capability Alexandru Elisei
2026-09-03 16:15   ` sashiko-bot
2026-10-15 16:51   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 07/28] KVM: arm64: Add KVM_ARM_VCPU_SPE VCPU feature Alexandru Elisei
2026-09-03 16:21   ` sashiko-bot
2026-10-16 14:23   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 08/28] HACK! KVM: arm64: Disable SPE virtualization if protected KVM is enabled Alexandru Elisei
2026-09-03 16:21   ` sashiko-bot
2026-10-16 14:30   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 09/28] HACK! KVM: arm64: Enable SPE virtualization only in VHE mode Alexandru Elisei
2026-09-03 16:15   ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 10/28] HACK! KVM: arm64: Disable SPE virtualization if nested virt is enabled Alexandru Elisei
2026-09-03 16:20   ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 11/28] KVM: arm64: Add a new VCPU device control group for SPE Alexandru Elisei
2026-09-03 16:22   ` sashiko-bot
2026-10-16 14:44   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 12/28] KVM: arm64: Add SPE VCPU device attribute to set the interrupt number Alexandru Elisei
2026-09-03 16:27   ` sashiko-bot
2026-10-20 17:20   ` Lorenzo Stoakes (ARM)
2026-10-28 16:52   ` Suzuki K Poulose
2026-09-03 16:06 ` [RFC PATCH v7 13/28] KVM: arm64: Add SPE VCPU device attribute to set the SPE device Alexandru Elisei
2026-09-03 16:39   ` sashiko-bot
2026-09-04  9:32     ` Alexandru Elisei
2026-10-28 13:11   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 14/28] KVM: arm64: Add SPE VCPU device attribute to initialize SPE Alexandru Elisei
2026-09-03 16:28   ` sashiko-bot
2026-10-28 13:45   ` Lorenzo Stoakes (ARM)
2026-10-29 18:03   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 15/28] KVM: arm64: Use PMSVer from the assigned SPE instance Alexandru Elisei
2026-09-03 16:41   ` sashiko-bot
2026-09-04 10:26     ` Alexandru Elisei
2026-10-28 16:41   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 16/28] KVM: arm64: Add SPE system registers to VCPU context Alexandru Elisei
2026-09-03 16:32   ` sashiko-bot
2026-09-04 10:28     ` Alexandru Elisei
2026-10-29 15:42   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 17/28] KVM: arm64: Apply a RES0 mask to PMBLIMITR_EL1 writes Alexandru Elisei
2026-09-03 16:37   ` sashiko-bot
2026-09-04 10:41     ` Alexandru Elisei
2026-10-29 17:23   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 18/28] KVM: arm64: config: Use functions from spe.c to test FEAT_SPE_{FnE,FDS} Alexandru Elisei
2026-09-03 16:40   ` sashiko-bot
2026-10-29 17:47   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 19/28] KVM: arm64: VHE: Context switch SPE state Alexandru Elisei
2026-09-03 16:43   ` sashiko-bot
2026-09-04 11:35     ` Alexandru Elisei
2026-11-03 14:10       ` Lorenzo Stoakes (ARM)
2026-11-03 16:00   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 20/28] KVM: arm64: Allow guest SPE physical timestamps only if kernel allows it Alexandru Elisei
2026-09-03 16:48   ` sashiko-bot
2026-09-04 13:45     ` Alexandru Elisei
2026-11-03 17:04   ` Lorenzo Stoakes (ARM) [this message]
2026-09-03 16:06 ` [RFC PATCH v7 21/28] KVM: arm64: Handle SPE maintenance interrupts Alexandru Elisei
2026-09-03 16:58   ` sashiko-bot
2026-09-04 14:04     ` Alexandru Elisei
2026-11-05 16:05   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 22/28] arm64: errata: Disable SPE in KVM Alexandru Elisei
2026-09-03 16:50   ` sashiko-bot
2026-11-03 20:12   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 23/28] KVM: arm64: Add kvm-arm.ignore_spe_errata kernel parameter Alexandru Elisei
2026-09-03 16:46   ` sashiko-bot
2026-11-03 19:37   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 24/28] arm64: errata: Don't enable guest buffer if misprogrammed Alexandru Elisei
2026-09-03 17:00   ` sashiko-bot
2026-11-05 16:51   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 25/28] KVM: arm64: at: Use callback for reading descriptor Alexandru Elisei
2026-09-03 16:51   ` sashiko-bot
2026-11-03 19:55   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 26/28] KVM: arm64: Map memory on a SPE stage 2 fault Alexandru Elisei
2026-09-03 17:08   ` sashiko-bot
2026-11-05 17:10   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 27/28] KVM: arm64: Handle dirty page logging when SPE feature is set Alexandru Elisei
2026-09-03 17:06   ` sashiko-bot
2026-09-04 14:41     ` Alexandru Elisei
2026-11-05 17:35   ` Lorenzo Stoakes (ARM)
2026-09-03 16:06 ` [RFC PATCH v7 28/28] KVM: arm64: Allow the creation of a SPE enabled VM Alexandru Elisei
2026-09-03 16:59   ` sashiko-bot
2026-09-04 14:09     ` Alexandru Elisei
2026-11-03 19:49   ` Lorenzo Stoakes (ARM)
2026-10-15 10:25 ` [RFC PATCH v7 00/28] KVM: arm64: Add Statistical Profiling Extension (SPE) support Alexandru Elisei
2026-10-15 12:50   ` Lorenzo Stoakes (ARM)
2026-10-15 13:22     ` Alexandru Elisei
2026-11-05 17:47 ` Lorenzo Stoakes (ARM)
2026-11-05 19:28   ` Lorenzo Stoakes (ARM)
2026-11-06 11:41   ` Alexandru Elisei

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=auoFWWJHUcmvif7s@gremlin \
    --to=ljs@kernel.org \
    --cc=alexandru.elisei@arm.com \
    --cc=catalin.marinas@arm.com \
    --cc=fuad.tabba@linux.dev \
    --cc=james.clark@linaro.org \
    --cc=joey.gouly@arm.com \
    --cc=kvmarm@lists.linux.dev \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=maz@kernel.org \
    --cc=oupton@kernel.org \
    --cc=seiden@linux.ibm.com \
    --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.