linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Marc Zyngier <maz@kernel.org>
To: Mark Brown <broonie@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>,
	Oliver Upton <oliver.upton@linux.dev>,
	James Morse <james.morse@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Jonathan Corbet <corbet@lwn.net>, Shuah Khan <shuah@kernel.org>,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, Dave Martin <dave.martin@arm.com>,
	kvmarm@lists.linux.dev, linux-doc@vger.kernel.org,
	linux-kselftest@vger.kernel.org
Subject: Re: [PATCH v4 03/14] arm64/fpsimd: Support FEAT_FPMR
Date: Fri, 23 Feb 2024 11:07:02 +0000	[thread overview]
Message-ID: <86r0h330dl.wl-maz@kernel.org> (raw)
In-Reply-To: <20240122-arm64-2023-dpisa-v4-3-776e094861df@kernel.org>

On Mon, 22 Jan 2024 16:28:06 +0000,
Mark Brown <broonie@kernel.org> wrote:
> 
> FEAT_FPMR defines a new EL0 accessible register FPMR use to configure the
> FP8 related features added to the architecture at the same time. Detect
> support for this register and context switch it for EL0 when present.
> 
> Due to the sharing of responsibility for saving floating point state
> between the host kernel and KVM FP8 support is not yet implemented in KVM
> and a stub similar to that used for SVCR is provided for FPMR in order to
> avoid bisection issues. To make it easier to share host state with the
> hypervisor we store FPMR as a hardened usercopy field in uw (along with
> some padding).
> 
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
>  arch/arm64/include/asm/cpufeature.h |  5 +++++
>  arch/arm64/include/asm/fpsimd.h     |  2 ++
>  arch/arm64/include/asm/kvm_host.h   |  1 +
>  arch/arm64/include/asm/processor.h  |  4 ++++
>  arch/arm64/kernel/cpufeature.c      |  9 +++++++++
>  arch/arm64/kernel/fpsimd.c          | 13 +++++++++++++
>  arch/arm64/kvm/fpsimd.c             |  1 +
>  arch/arm64/tools/cpucaps            |  1 +
>  8 files changed, 36 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 21c824edf8ce..34fcdbc65d7d 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -768,6 +768,11 @@ static __always_inline bool system_supports_tpidr2(void)
>  	return system_supports_sme();
>  }
>  
> +static __always_inline bool system_supports_fpmr(void)
> +{
> +	return alternative_has_cap_unlikely(ARM64_HAS_FPMR);
> +}
> +
>  static __always_inline bool system_supports_cnp(void)
>  {
>  	return alternative_has_cap_unlikely(ARM64_HAS_CNP);
> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> index 50e5f25d3024..6cf72b0d2c04 100644
> --- a/arch/arm64/include/asm/fpsimd.h
> +++ b/arch/arm64/include/asm/fpsimd.h
> @@ -89,6 +89,7 @@ struct cpu_fp_state {
>  	void *sve_state;
>  	void *sme_state;
>  	u64 *svcr;
> +	unsigned long *fpmr;
>  	unsigned int sve_vl;
>  	unsigned int sme_vl;
>  	enum fp_type *fp_type;
> @@ -154,6 +155,7 @@ extern void cpu_enable_sve(const struct arm64_cpu_capabilities *__unused);
>  extern void cpu_enable_sme(const struct arm64_cpu_capabilities *__unused);
>  extern void cpu_enable_sme2(const struct arm64_cpu_capabilities *__unused);
>  extern void cpu_enable_fa64(const struct arm64_cpu_capabilities *__unused);
> +extern void cpu_enable_fpmr(const struct arm64_cpu_capabilities *__unused);
>  
>  extern u64 read_smcr_features(void);
>  
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 21c57b812569..7993694a54af 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -543,6 +543,7 @@ struct kvm_vcpu_arch {
>  	enum fp_type fp_type;
>  	unsigned int sve_max_vl;
>  	u64 svcr;
> +	unsigned long fpmr;

As this directly represents a register, I'd rather you use a type that
represents the size of that register unambiguously (u64).

>  
>  	/* Stage 2 paging state used by the hardware on next switch */
>  	struct kvm_s2_mmu *hw_mmu;
> diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
> index 5b0a04810b23..b453c66d3fae 100644
> --- a/arch/arm64/include/asm/processor.h
> +++ b/arch/arm64/include/asm/processor.h
> @@ -155,6 +155,8 @@ struct thread_struct {
>  	struct {
>  		unsigned long	tp_value;	/* TLS register */
>  		unsigned long	tp2_value;
> +		unsigned long	fpmr;
> +		unsigned long	pad;
>  		struct user_fpsimd_state fpsimd_state;
>  	} uw;
>  
> @@ -253,6 +255,8 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
>  	BUILD_BUG_ON(sizeof_field(struct thread_struct, uw) !=
>  		     sizeof_field(struct thread_struct, uw.tp_value) +
>  		     sizeof_field(struct thread_struct, uw.tp2_value) +
> +		     sizeof_field(struct thread_struct, uw.fpmr) +
> +		     sizeof_field(struct thread_struct, uw.pad) +
>  		     sizeof_field(struct thread_struct, uw.fpsimd_state));
>  
>  	*offset = offsetof(struct thread_struct, uw);
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index eae59ec0f4b0..0263565f617a 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -272,6 +272,7 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = {
>  };
>  
>  static const struct arm64_ftr_bits ftr_id_aa64pfr2[] = {
> +	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR2_EL1_FPMR_SHIFT, 4, 0),
>  	ARM64_FTR_END,
>  };
>  
> @@ -2767,6 +2768,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
>  		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
>  		.matches = has_lpa2,
>  	},
> +	{
> +		.desc = "FPMR",
> +		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
> +		.capability = ARM64_HAS_FPMR,
> +		.matches = has_cpuid_feature,
> +		.cpu_enable = cpu_enable_fpmr,
> +		ARM64_CPUID_FIELDS(ID_AA64PFR2_EL1, FPMR, IMP)
> +	},
>  	{},
>  };
>  
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index a5dc6f764195..8e24b5e5e192 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -359,6 +359,9 @@ static void task_fpsimd_load(void)
>  	WARN_ON(preemptible());
>  	WARN_ON(test_thread_flag(TIF_KERNEL_FPSTATE));
>  
> +	if (system_supports_fpmr())
> +		write_sysreg_s(current->thread.uw.fpmr, SYS_FPMR);
> +
>  	if (system_supports_sve() || system_supports_sme()) {
>  		switch (current->thread.fp_type) {
>  		case FP_STATE_FPSIMD:
> @@ -446,6 +449,9 @@ static void fpsimd_save_user_state(void)
>  	if (test_thread_flag(TIF_FOREIGN_FPSTATE))
>  		return;
>  
> +	if (system_supports_fpmr())
> +		*(last->fpmr) = read_sysreg_s(SYS_FPMR);
> +
>  	/*
>  	 * If a task is in a syscall the ABI allows us to only
>  	 * preserve the state shared with FPSIMD so don't bother
> @@ -688,6 +694,12 @@ static void sve_to_fpsimd(struct task_struct *task)
>  	}
>  }
>  
> +void cpu_enable_fpmr(const struct arm64_cpu_capabilities *__always_unused p)
> +{
> +	write_sysreg_s(read_sysreg_s(SYS_SCTLR_EL1) | SCTLR_EL1_EnFPM_MASK,
> +		       SYS_SCTLR_EL1);
> +}
> +
>  #ifdef CONFIG_ARM64_SVE
>  /*
>   * Call __sve_free() directly only if you know task can't be scheduled
> @@ -1680,6 +1692,7 @@ static void fpsimd_bind_task_to_cpu(void)
>  	last->sve_vl = task_get_sve_vl(current);
>  	last->sme_vl = task_get_sme_vl(current);
>  	last->svcr = &current->thread.svcr;
> +	last->fpmr = &current->thread.uw.fpmr;
>  	last->fp_type = &current->thread.fp_type;
>  	last->to_save = FP_STATE_CURRENT;
>  	current->thread.fpsimd_cpu = smp_processor_id();
> diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
> index 8c1d0d4853df..e3e611e30e91 100644
> --- a/arch/arm64/kvm/fpsimd.c
> +++ b/arch/arm64/kvm/fpsimd.c
> @@ -153,6 +153,7 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
>  		fp_state.sve_vl = vcpu->arch.sve_max_vl;
>  		fp_state.sme_state = NULL;
>  		fp_state.svcr = &vcpu->arch.svcr;
> +		fp_state.fpmr = &vcpu->arch.fpmr;
>  		fp_state.fp_type = &vcpu->arch.fp_type;

Given the number of fields you keep track of, it would make a lot more
sense if these FP-related fields were in their own little structure
and tracked by a single pointer (I don't think there is a case where
we track them independently).

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

  reply	other threads:[~2024-02-23 11:07 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-22 16:28 [PATCH v4 00/14] arm64: Support for 2023 DPISA extensions Mark Brown
2024-01-22 16:28 ` [PATCH v4 01/14] arm64/cpufeature: Hook new identification registers up to cpufeature Mark Brown
2024-01-22 16:28 ` [PATCH v4 02/14] arm64/fpsimd: Enable host kernel access to FPMR Mark Brown
2024-02-23 11:34   ` Marc Zyngier
2024-01-22 16:28 ` [PATCH v4 03/14] arm64/fpsimd: Support FEAT_FPMR Mark Brown
2024-02-23 11:07   ` Marc Zyngier [this message]
2024-03-06 16:41     ` Mark Brown
2024-01-22 16:28 ` [PATCH v4 04/14] arm64/signal: Add FPMR signal handling Mark Brown
2024-01-22 16:28 ` [PATCH v4 05/14] arm64/ptrace: Expose FPMR via ptrace Mark Brown
2024-01-22 16:28 ` [PATCH v4 06/14] arm64/hwcap: Define hwcaps for 2023 DPISA features Mark Brown
2024-01-22 16:28 ` [PATCH v4 07/14] kselftest/arm64: Handle FPMR context in generic signal frame parser Mark Brown
2024-01-22 16:28 ` [PATCH v4 08/14] kselftest/arm64: Add basic FPMR test Mark Brown
2024-01-22 16:28 ` [PATCH v4 09/14] kselftest/arm64: Add 2023 DPISA hwcap test coverage Mark Brown
2024-01-22 16:28 ` [PATCH v4 10/14] KVM: arm64: Share all userspace hardened thread data with the hypervisor Mark Brown
2024-01-22 16:28 ` [PATCH v4 11/14] KVM: arm64: Add newly allocated ID registers to register descriptions Mark Brown
2024-02-23 11:33   ` Marc Zyngier
2024-01-22 16:28 ` [PATCH v4 12/14] KVM: arm64: Support FEAT_FPMR for guests Mark Brown
2024-02-23 11:18   ` Marc Zyngier
2024-02-23 14:46     ` Mark Brown
2024-01-22 16:28 ` [PATCH v4 13/14] KVM: arm64: selftests: Document feature registers added in 2023 extensions Mark Brown
2024-01-22 16:28 ` [PATCH v4 14/14] KVM: arm64: selftests: Teach get-reg-list about FPMR Mark Brown

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=86r0h330dl.wl-maz@kernel.org \
    --to=maz@kernel.org \
    --cc=broonie@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=corbet@lwn.net \
    --cc=dave.martin@arm.com \
    --cc=james.morse@arm.com \
    --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=oliver.upton@linux.dev \
    --cc=shuah@kernel.org \
    --cc=suzuki.poulose@arm.com \
    --cc=will@kernel.org \
    /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).