162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2012 ARM Ltd.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#ifndef __ASM_FP_H
662306a36Sopenharmony_ci#define __ASM_FP_H
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <asm/errno.h>
962306a36Sopenharmony_ci#include <asm/ptrace.h>
1062306a36Sopenharmony_ci#include <asm/processor.h>
1162306a36Sopenharmony_ci#include <asm/sigcontext.h>
1262306a36Sopenharmony_ci#include <asm/sysreg.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#ifndef __ASSEMBLY__
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <linux/bitmap.h>
1762306a36Sopenharmony_ci#include <linux/build_bug.h>
1862306a36Sopenharmony_ci#include <linux/bug.h>
1962306a36Sopenharmony_ci#include <linux/cache.h>
2062306a36Sopenharmony_ci#include <linux/init.h>
2162306a36Sopenharmony_ci#include <linux/stddef.h>
2262306a36Sopenharmony_ci#include <linux/types.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
2562306a36Sopenharmony_ci/* Masks for extracting the FPSR and FPCR from the FPSCR */
2662306a36Sopenharmony_ci#define VFP_FPSCR_STAT_MASK	0xf800009f
2762306a36Sopenharmony_ci#define VFP_FPSCR_CTRL_MASK	0x07f79f00
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * The VFP state has 32x64-bit registers and a single 32-bit
3062306a36Sopenharmony_ci * control/status register.
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci#define VFP_STATE_SIZE		((32 * 8) + 4)
3362306a36Sopenharmony_ci#endif
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/*
3662306a36Sopenharmony_ci * When we defined the maximum SVE vector length we defined the ABI so
3762306a36Sopenharmony_ci * that the maximum vector length included all the reserved for future
3862306a36Sopenharmony_ci * expansion bits in ZCR rather than those just currently defined by
3962306a36Sopenharmony_ci * the architecture.  Using this length to allocate worst size buffers
4062306a36Sopenharmony_ci * results in excessively large allocations, and this effect is even
4162306a36Sopenharmony_ci * more pronounced for SME due to ZA.  Define more suitable VLs for
4262306a36Sopenharmony_ci * these situations.
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_ci#define ARCH_SVE_VQ_MAX ((ZCR_ELx_LEN_MASK >> ZCR_ELx_LEN_SHIFT) + 1)
4562306a36Sopenharmony_ci#define SME_VQ_MAX	((SMCR_ELx_LEN_MASK >> SMCR_ELx_LEN_SHIFT) + 1)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistruct task_struct;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ciextern void fpsimd_save_state(struct user_fpsimd_state *state);
5062306a36Sopenharmony_ciextern void fpsimd_load_state(struct user_fpsimd_state *state);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ciextern void fpsimd_thread_switch(struct task_struct *next);
5362306a36Sopenharmony_ciextern void fpsimd_flush_thread(void);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ciextern void fpsimd_signal_preserve_current_state(void);
5662306a36Sopenharmony_ciextern void fpsimd_preserve_current_state(void);
5762306a36Sopenharmony_ciextern void fpsimd_restore_current_state(void);
5862306a36Sopenharmony_ciextern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
5962306a36Sopenharmony_ciextern void fpsimd_kvm_prepare(void);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistruct cpu_fp_state {
6262306a36Sopenharmony_ci	struct user_fpsimd_state *st;
6362306a36Sopenharmony_ci	void *sve_state;
6462306a36Sopenharmony_ci	void *sme_state;
6562306a36Sopenharmony_ci	u64 *svcr;
6662306a36Sopenharmony_ci	unsigned int sve_vl;
6762306a36Sopenharmony_ci	unsigned int sme_vl;
6862306a36Sopenharmony_ci	enum fp_type *fp_type;
6962306a36Sopenharmony_ci	enum fp_type to_save;
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ciextern void fpsimd_bind_state_to_cpu(struct cpu_fp_state *fp_state);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ciextern void fpsimd_flush_task_state(struct task_struct *target);
7562306a36Sopenharmony_ciextern void fpsimd_save_and_flush_cpu_state(void);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic inline bool thread_sm_enabled(struct thread_struct *thread)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	return system_supports_sme() && (thread->svcr & SVCR_SM_MASK);
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic inline bool thread_za_enabled(struct thread_struct *thread)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	return system_supports_sme() && (thread->svcr & SVCR_ZA_MASK);
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/* Maximum VL that SVE/SME VL-agnostic software can transparently support */
8862306a36Sopenharmony_ci#define VL_ARCH_MAX 0x100
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/* Offset of FFR in the SVE register dump */
9162306a36Sopenharmony_cistatic inline size_t sve_ffr_offset(int vl)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	return SVE_SIG_FFR_OFFSET(sve_vq_from_vl(vl)) - SVE_SIG_REGS_OFFSET;
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic inline void *sve_pffr(struct thread_struct *thread)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	unsigned int vl;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	if (system_supports_sme() && thread_sm_enabled(thread))
10162306a36Sopenharmony_ci		vl = thread_get_sme_vl(thread);
10262306a36Sopenharmony_ci	else
10362306a36Sopenharmony_ci		vl = thread_get_sve_vl(thread);
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	return (char *)thread->sve_state + sve_ffr_offset(vl);
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistatic inline void *thread_zt_state(struct thread_struct *thread)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	/* The ZT register state is stored immediately after the ZA state */
11162306a36Sopenharmony_ci	unsigned int sme_vq = sve_vq_from_vl(thread_get_sme_vl(thread));
11262306a36Sopenharmony_ci	return thread->sme_state + ZA_SIG_REGS_SIZE(sme_vq);
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ciextern void sve_save_state(void *state, u32 *pfpsr, int save_ffr);
11662306a36Sopenharmony_ciextern void sve_load_state(void const *state, u32 const *pfpsr,
11762306a36Sopenharmony_ci			   int restore_ffr);
11862306a36Sopenharmony_ciextern void sve_flush_live(bool flush_ffr, unsigned long vq_minus_1);
11962306a36Sopenharmony_ciextern unsigned int sve_get_vl(void);
12062306a36Sopenharmony_ciextern void sve_set_vq(unsigned long vq_minus_1);
12162306a36Sopenharmony_ciextern void sme_set_vq(unsigned long vq_minus_1);
12262306a36Sopenharmony_ciextern void sme_save_state(void *state, int zt);
12362306a36Sopenharmony_ciextern void sme_load_state(void const *state, int zt);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistruct arm64_cpu_capabilities;
12662306a36Sopenharmony_ciextern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
12762306a36Sopenharmony_ciextern void sme_kernel_enable(const struct arm64_cpu_capabilities *__unused);
12862306a36Sopenharmony_ciextern void sme2_kernel_enable(const struct arm64_cpu_capabilities *__unused);
12962306a36Sopenharmony_ciextern void fa64_kernel_enable(const struct arm64_cpu_capabilities *__unused);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ciextern u64 read_zcr_features(void);
13262306a36Sopenharmony_ciextern u64 read_smcr_features(void);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci/*
13562306a36Sopenharmony_ci * Helpers to translate bit indices in sve_vq_map to VQ values (and
13662306a36Sopenharmony_ci * vice versa).  This allows find_next_bit() to be used to find the
13762306a36Sopenharmony_ci * _maximum_ VQ not exceeding a certain value.
13862306a36Sopenharmony_ci */
13962306a36Sopenharmony_cistatic inline unsigned int __vq_to_bit(unsigned int vq)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	return SVE_VQ_MAX - vq;
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic inline unsigned int __bit_to_vq(unsigned int bit)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	return SVE_VQ_MAX - bit;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cistruct vl_info {
15162306a36Sopenharmony_ci	enum vec_type type;
15262306a36Sopenharmony_ci	const char *name;		/* For display purposes */
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	/* Minimum supported vector length across all CPUs */
15562306a36Sopenharmony_ci	int min_vl;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	/* Maximum supported vector length across all CPUs */
15862306a36Sopenharmony_ci	int max_vl;
15962306a36Sopenharmony_ci	int max_virtualisable_vl;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	/*
16262306a36Sopenharmony_ci	 * Set of available vector lengths,
16362306a36Sopenharmony_ci	 * where length vq encoded as bit __vq_to_bit(vq):
16462306a36Sopenharmony_ci	 */
16562306a36Sopenharmony_ci	DECLARE_BITMAP(vq_map, SVE_VQ_MAX);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	/* Set of vector lengths present on at least one cpu: */
16862306a36Sopenharmony_ci	DECLARE_BITMAP(vq_partial_map, SVE_VQ_MAX);
16962306a36Sopenharmony_ci};
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci#ifdef CONFIG_ARM64_SVE
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ciextern void sve_alloc(struct task_struct *task, bool flush);
17462306a36Sopenharmony_ciextern void fpsimd_release_task(struct task_struct *task);
17562306a36Sopenharmony_ciextern void fpsimd_sync_to_sve(struct task_struct *task);
17662306a36Sopenharmony_ciextern void fpsimd_force_sync_to_sve(struct task_struct *task);
17762306a36Sopenharmony_ciextern void sve_sync_to_fpsimd(struct task_struct *task);
17862306a36Sopenharmony_ciextern void sve_sync_from_fpsimd_zeropad(struct task_struct *task);
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ciextern int vec_set_vector_length(struct task_struct *task, enum vec_type type,
18162306a36Sopenharmony_ci				 unsigned long vl, unsigned long flags);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ciextern int sve_set_current_vl(unsigned long arg);
18462306a36Sopenharmony_ciextern int sve_get_current_vl(void);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic inline void sve_user_disable(void)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	sysreg_clear_set(cpacr_el1, CPACR_EL1_ZEN_EL0EN, 0);
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic inline void sve_user_enable(void)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	sysreg_clear_set(cpacr_el1, 0, CPACR_EL1_ZEN_EL0EN);
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci#define sve_cond_update_zcr_vq(val, reg)		\
19762306a36Sopenharmony_ci	do {						\
19862306a36Sopenharmony_ci		u64 __zcr = read_sysreg_s((reg));	\
19962306a36Sopenharmony_ci		u64 __new = __zcr & ~ZCR_ELx_LEN_MASK;	\
20062306a36Sopenharmony_ci		__new |= (val) & ZCR_ELx_LEN_MASK;	\
20162306a36Sopenharmony_ci		if (__zcr != __new)			\
20262306a36Sopenharmony_ci			write_sysreg_s(__new, (reg));	\
20362306a36Sopenharmony_ci	} while (0)
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci/*
20662306a36Sopenharmony_ci * Probing and setup functions.
20762306a36Sopenharmony_ci * Calls to these functions must be serialised with one another.
20862306a36Sopenharmony_ci */
20962306a36Sopenharmony_cienum vec_type;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ciextern void __init vec_init_vq_map(enum vec_type type);
21262306a36Sopenharmony_ciextern void vec_update_vq_map(enum vec_type type);
21362306a36Sopenharmony_ciextern int vec_verify_vq_map(enum vec_type type);
21462306a36Sopenharmony_ciextern void __init sve_setup(void);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ciextern __ro_after_init struct vl_info vl_info[ARM64_VEC_MAX];
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cistatic inline void write_vl(enum vec_type type, u64 val)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	u64 tmp;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	switch (type) {
22362306a36Sopenharmony_ci#ifdef CONFIG_ARM64_SVE
22462306a36Sopenharmony_ci	case ARM64_VEC_SVE:
22562306a36Sopenharmony_ci		tmp = read_sysreg_s(SYS_ZCR_EL1) & ~ZCR_ELx_LEN_MASK;
22662306a36Sopenharmony_ci		write_sysreg_s(tmp | val, SYS_ZCR_EL1);
22762306a36Sopenharmony_ci		break;
22862306a36Sopenharmony_ci#endif
22962306a36Sopenharmony_ci#ifdef CONFIG_ARM64_SME
23062306a36Sopenharmony_ci	case ARM64_VEC_SME:
23162306a36Sopenharmony_ci		tmp = read_sysreg_s(SYS_SMCR_EL1) & ~SMCR_ELx_LEN_MASK;
23262306a36Sopenharmony_ci		write_sysreg_s(tmp | val, SYS_SMCR_EL1);
23362306a36Sopenharmony_ci		break;
23462306a36Sopenharmony_ci#endif
23562306a36Sopenharmony_ci	default:
23662306a36Sopenharmony_ci		WARN_ON_ONCE(1);
23762306a36Sopenharmony_ci		break;
23862306a36Sopenharmony_ci	}
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_cistatic inline int vec_max_vl(enum vec_type type)
24262306a36Sopenharmony_ci{
24362306a36Sopenharmony_ci	return vl_info[type].max_vl;
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic inline int vec_max_virtualisable_vl(enum vec_type type)
24762306a36Sopenharmony_ci{
24862306a36Sopenharmony_ci	return vl_info[type].max_virtualisable_vl;
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic inline int sve_max_vl(void)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	return vec_max_vl(ARM64_VEC_SVE);
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic inline int sve_max_virtualisable_vl(void)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	return vec_max_virtualisable_vl(ARM64_VEC_SVE);
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci/* Ensure vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX before calling this function */
26262306a36Sopenharmony_cistatic inline bool vq_available(enum vec_type type, unsigned int vq)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	return test_bit(__vq_to_bit(vq), vl_info[type].vq_map);
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic inline bool sve_vq_available(unsigned int vq)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	return vq_available(ARM64_VEC_SVE, vq);
27062306a36Sopenharmony_ci}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cisize_t sve_state_size(struct task_struct const *task);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci#else /* ! CONFIG_ARM64_SVE */
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_cistatic inline void sve_alloc(struct task_struct *task, bool flush) { }
27762306a36Sopenharmony_cistatic inline void fpsimd_release_task(struct task_struct *task) { }
27862306a36Sopenharmony_cistatic inline void sve_sync_to_fpsimd(struct task_struct *task) { }
27962306a36Sopenharmony_cistatic inline void sve_sync_from_fpsimd_zeropad(struct task_struct *task) { }
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_cistatic inline int sve_max_virtualisable_vl(void)
28262306a36Sopenharmony_ci{
28362306a36Sopenharmony_ci	return 0;
28462306a36Sopenharmony_ci}
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_cistatic inline int sve_set_current_vl(unsigned long arg)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	return -EINVAL;
28962306a36Sopenharmony_ci}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_cistatic inline int sve_get_current_vl(void)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	return -EINVAL;
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic inline int sve_max_vl(void)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	return -EINVAL;
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_cistatic inline bool sve_vq_available(unsigned int vq) { return false; }
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistatic inline void sve_user_disable(void) { BUILD_BUG(); }
30462306a36Sopenharmony_cistatic inline void sve_user_enable(void) { BUILD_BUG(); }
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci#define sve_cond_update_zcr_vq(val, reg) do { } while (0)
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistatic inline void vec_init_vq_map(enum vec_type t) { }
30962306a36Sopenharmony_cistatic inline void vec_update_vq_map(enum vec_type t) { }
31062306a36Sopenharmony_cistatic inline int vec_verify_vq_map(enum vec_type t) { return 0; }
31162306a36Sopenharmony_cistatic inline void sve_setup(void) { }
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_cistatic inline size_t sve_state_size(struct task_struct const *task)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	return 0;
31662306a36Sopenharmony_ci}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci#endif /* ! CONFIG_ARM64_SVE */
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci#ifdef CONFIG_ARM64_SME
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_cistatic inline void sme_user_disable(void)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	sysreg_clear_set(cpacr_el1, CPACR_EL1_SMEN_EL0EN, 0);
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic inline void sme_user_enable(void)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	sysreg_clear_set(cpacr_el1, 0, CPACR_EL1_SMEN_EL0EN);
33062306a36Sopenharmony_ci}
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_cistatic inline void sme_smstart_sm(void)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	asm volatile(__msr_s(SYS_SVCR_SMSTART_SM_EL0, "xzr"));
33562306a36Sopenharmony_ci}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_cistatic inline void sme_smstop_sm(void)
33862306a36Sopenharmony_ci{
33962306a36Sopenharmony_ci	asm volatile(__msr_s(SYS_SVCR_SMSTOP_SM_EL0, "xzr"));
34062306a36Sopenharmony_ci}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_cistatic inline void sme_smstop(void)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	asm volatile(__msr_s(SYS_SVCR_SMSTOP_SMZA_EL0, "xzr"));
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ciextern void __init sme_setup(void);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic inline int sme_max_vl(void)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	return vec_max_vl(ARM64_VEC_SME);
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_cistatic inline int sme_max_virtualisable_vl(void)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	return vec_max_virtualisable_vl(ARM64_VEC_SME);
35762306a36Sopenharmony_ci}
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ciextern void sme_alloc(struct task_struct *task, bool flush);
36062306a36Sopenharmony_ciextern unsigned int sme_get_vl(void);
36162306a36Sopenharmony_ciextern int sme_set_current_vl(unsigned long arg);
36262306a36Sopenharmony_ciextern int sme_get_current_vl(void);
36362306a36Sopenharmony_ciextern void sme_suspend_exit(void);
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci/*
36662306a36Sopenharmony_ci * Return how many bytes of memory are required to store the full SME
36762306a36Sopenharmony_ci * specific state for task, given task's currently configured vector
36862306a36Sopenharmony_ci * length.
36962306a36Sopenharmony_ci */
37062306a36Sopenharmony_cistatic inline size_t sme_state_size(struct task_struct const *task)
37162306a36Sopenharmony_ci{
37262306a36Sopenharmony_ci	unsigned int vl = task_get_sme_vl(task);
37362306a36Sopenharmony_ci	size_t size;
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	size = ZA_SIG_REGS_SIZE(sve_vq_from_vl(vl));
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	if (system_supports_sme2())
37862306a36Sopenharmony_ci		size += ZT_SIG_REG_SIZE;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	return size;
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci#else
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_cistatic inline void sme_user_disable(void) { BUILD_BUG(); }
38662306a36Sopenharmony_cistatic inline void sme_user_enable(void) { BUILD_BUG(); }
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_cistatic inline void sme_smstart_sm(void) { }
38962306a36Sopenharmony_cistatic inline void sme_smstop_sm(void) { }
39062306a36Sopenharmony_cistatic inline void sme_smstop(void) { }
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_cistatic inline void sme_alloc(struct task_struct *task, bool flush) { }
39362306a36Sopenharmony_cistatic inline void sme_setup(void) { }
39462306a36Sopenharmony_cistatic inline unsigned int sme_get_vl(void) { return 0; }
39562306a36Sopenharmony_cistatic inline int sme_max_vl(void) { return 0; }
39662306a36Sopenharmony_cistatic inline int sme_max_virtualisable_vl(void) { return 0; }
39762306a36Sopenharmony_cistatic inline int sme_set_current_vl(unsigned long arg) { return -EINVAL; }
39862306a36Sopenharmony_cistatic inline int sme_get_current_vl(void) { return -EINVAL; }
39962306a36Sopenharmony_cistatic inline void sme_suspend_exit(void) { }
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_cistatic inline size_t sme_state_size(struct task_struct const *task)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	return 0;
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci#endif /* ! CONFIG_ARM64_SME */
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci/* For use by EFI runtime services calls only */
40962306a36Sopenharmony_ciextern void __efi_fpsimd_begin(void);
41062306a36Sopenharmony_ciextern void __efi_fpsimd_end(void);
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci#endif
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci#endif
415