xref: /openbmc/linux/arch/arm64/include/asm/fpsimd.h (revision 10a33d1d)
1caab277bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
253631b54SCatalin Marinas /*
353631b54SCatalin Marinas  * Copyright (C) 2012 ARM Ltd.
453631b54SCatalin Marinas  */
553631b54SCatalin Marinas #ifndef __ASM_FP_H
653631b54SCatalin Marinas #define __ASM_FP_H
753631b54SCatalin Marinas 
82d2123bcSDave Martin #include <asm/errno.h>
9f9209e26SMark Rutland #include <asm/ptrace.h>
109a6e5948SDave Martin #include <asm/processor.h>
119a6e5948SDave Martin #include <asm/sigcontext.h>
12f9209e26SMark Rutland #include <asm/sysreg.h>
1353631b54SCatalin Marinas 
1453631b54SCatalin Marinas #ifndef __ASSEMBLY__
1553631b54SCatalin Marinas 
16ead9e430SDave Martin #include <linux/bitmap.h>
17f9209e26SMark Rutland #include <linux/build_bug.h>
18ead9e430SDave Martin #include <linux/bug.h>
197582e220SDave Martin #include <linux/cache.h>
20b4f9b390SWill Deacon #include <linux/init.h>
21bc0ee476SDave Martin #include <linux/stddef.h>
22ead9e430SDave Martin #include <linux/types.h>
23bc0ee476SDave Martin 
24b907b80dSMark Rutland #ifdef CONFIG_COMPAT
2553631b54SCatalin Marinas /* Masks for extracting the FPSR and FPCR from the FPSCR */
2653631b54SCatalin Marinas #define VFP_FPSCR_STAT_MASK	0xf800009f
2753631b54SCatalin Marinas #define VFP_FPSCR_CTRL_MASK	0x07f79f00
2853631b54SCatalin Marinas /*
2953631b54SCatalin Marinas  * The VFP state has 32x64-bit registers and a single 32-bit
3053631b54SCatalin Marinas  * control/status register.
3153631b54SCatalin Marinas  */
3253631b54SCatalin Marinas #define VFP_STATE_SIZE		((32 * 8) + 4)
3353631b54SCatalin Marinas #endif
3453631b54SCatalin Marinas 
35d158a060SMark Brown /*
36d158a060SMark Brown  * When we defined the maximum SVE vector length we defined the ABI so
37d158a060SMark Brown  * that the maximum vector length included all the reserved for future
38d158a060SMark Brown  * expansion bits in ZCR rather than those just currently defined by
39*10a33d1dSMark Brown  * the architecture.  Using this length to allocate worst size buffers
40*10a33d1dSMark Brown  * results in excessively large allocations, and this effect is even
41*10a33d1dSMark Brown  * more pronounced for SME due to ZA.  Define more suitable VLs for
42*10a33d1dSMark Brown  * these situations.
43d158a060SMark Brown  */
44*10a33d1dSMark Brown #define ARCH_SVE_VQ_MAX ((ZCR_ELx_LEN_MASK >> ZCR_ELx_LEN_SHIFT) + 1)
45*10a33d1dSMark Brown #define SME_VQ_MAX	((SMCR_ELx_LEN_MASK >> SMCR_ELx_LEN_SHIFT) + 1)
46d158a060SMark Brown 
4753631b54SCatalin Marinas struct task_struct;
4853631b54SCatalin Marinas 
4920b85472SDave Martin extern void fpsimd_save_state(struct user_fpsimd_state *state);
5020b85472SDave Martin extern void fpsimd_load_state(struct user_fpsimd_state *state);
5153631b54SCatalin Marinas 
5253631b54SCatalin Marinas extern void fpsimd_thread_switch(struct task_struct *next);
5353631b54SCatalin Marinas extern void fpsimd_flush_thread(void);
5453631b54SCatalin Marinas 
558cd969d2SDave Martin extern void fpsimd_signal_preserve_current_state(void);
56c51f9269SArd Biesheuvel extern void fpsimd_preserve_current_state(void);
57005f78cdSArd Biesheuvel extern void fpsimd_restore_current_state(void);
580abdeff5SDave Martin extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
5993ae6b01SMark Brown extern void fpsimd_kvm_prepare(void);
60c51f9269SArd Biesheuvel 
611192b93bSMark Brown struct cpu_fp_state {
621192b93bSMark Brown 	struct user_fpsimd_state *st;
631192b93bSMark Brown 	void *sve_state;
64ce514000SMark Brown 	void *sme_state;
651192b93bSMark Brown 	u64 *svcr;
661192b93bSMark Brown 	unsigned int sve_vl;
671192b93bSMark Brown 	unsigned int sme_vl;
681192b93bSMark Brown 	enum fp_type *fp_type;
691192b93bSMark Brown 	enum fp_type to_save;
701192b93bSMark Brown };
711192b93bSMark Brown 
721192b93bSMark Brown extern void fpsimd_bind_state_to_cpu(struct cpu_fp_state *fp_state);
73e6b673b7SDave Martin 
74005f78cdSArd Biesheuvel extern void fpsimd_flush_task_state(struct task_struct *target);
7554b8c7cbSJulien Grall extern void fpsimd_save_and_flush_cpu_state(void);
76005f78cdSArd Biesheuvel 
thread_sm_enabled(struct thread_struct * thread)77af7167d6SMark Brown static inline bool thread_sm_enabled(struct thread_struct *thread)
78af7167d6SMark Brown {
79ec0067a6SMark Brown 	return system_supports_sme() && (thread->svcr & SVCR_SM_MASK);
80af7167d6SMark Brown }
81af7167d6SMark Brown 
thread_za_enabled(struct thread_struct * thread)82af7167d6SMark Brown static inline bool thread_za_enabled(struct thread_struct *thread)
83af7167d6SMark Brown {
84ec0067a6SMark Brown 	return system_supports_sme() && (thread->svcr & SVCR_ZA_MASK);
85af7167d6SMark Brown }
86af7167d6SMark Brown 
8730c43e73SMark Brown /* Maximum VL that SVE/SME VL-agnostic software can transparently support */
8830c43e73SMark Brown #define VL_ARCH_MAX 0x100
897582e220SDave Martin 
909a6e5948SDave Martin /* Offset of FFR in the SVE register dump */
sve_ffr_offset(int vl)919a6e5948SDave Martin static inline size_t sve_ffr_offset(int vl)
929a6e5948SDave Martin {
939a6e5948SDave Martin 	return SVE_SIG_FFR_OFFSET(sve_vq_from_vl(vl)) - SVE_SIG_REGS_OFFSET;
949a6e5948SDave Martin }
959a6e5948SDave Martin 
sve_pffr(struct thread_struct * thread)969a6e5948SDave Martin static inline void *sve_pffr(struct thread_struct *thread)
979a6e5948SDave Martin {
98af7167d6SMark Brown 	unsigned int vl;
99af7167d6SMark Brown 
100af7167d6SMark Brown 	if (system_supports_sme() && thread_sm_enabled(thread))
101af7167d6SMark Brown 		vl = thread_get_sme_vl(thread);
102af7167d6SMark Brown 	else
103af7167d6SMark Brown 		vl = thread_get_sve_vl(thread);
104af7167d6SMark Brown 
105af7167d6SMark Brown 	return (char *)thread->sve_state + sve_ffr_offset(vl);
1069a6e5948SDave Martin }
1079a6e5948SDave Martin 
thread_zt_state(struct thread_struct * thread)108d6138b4aSMark Brown static inline void *thread_zt_state(struct thread_struct *thread)
109d6138b4aSMark Brown {
110d6138b4aSMark Brown 	/* The ZT register state is stored immediately after the ZA state */
111d6138b4aSMark Brown 	unsigned int sme_vq = sve_vq_from_vl(thread_get_sme_vl(thread));
112d6138b4aSMark Brown 	return thread->sme_state + ZA_SIG_REGS_SIZE(sme_vq);
113d6138b4aSMark Brown }
114d6138b4aSMark Brown 
1159f584866SMark Brown extern void sve_save_state(void *state, u32 *pfpsr, int save_ffr);
1161fc5dce7SDave Martin extern void sve_load_state(void const *state, u32 const *pfpsr,
117ddc806b5SMark Brown 			   int restore_ffr);
1189f584866SMark Brown extern void sve_flush_live(bool flush_ffr, unsigned long vq_minus_1);
1191fc5dce7SDave Martin extern unsigned int sve_get_vl(void);
120cccb78ceSMark Brown extern void sve_set_vq(unsigned long vq_minus_1);
121af7167d6SMark Brown extern void sme_set_vq(unsigned long vq_minus_1);
12295fcec71SMark Brown extern void sme_save_state(void *state, int zt);
12395fcec71SMark Brown extern void sme_load_state(void const *state, int zt);
124c0cda3b8SDave Martin 
125c0cda3b8SDave Martin struct arm64_cpu_capabilities;
126c0cda3b8SDave Martin extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
1275e64b862SMark Brown extern void sme_kernel_enable(const struct arm64_cpu_capabilities *__unused);
128d4913eeeSMark Brown extern void sme2_kernel_enable(const struct arm64_cpu_capabilities *__unused);
1295e64b862SMark Brown extern void fa64_kernel_enable(const struct arm64_cpu_capabilities *__unused);
1301fc5dce7SDave Martin 
13131dc52b3SDave Martin extern u64 read_zcr_features(void);
132b42990d3SMark Brown extern u64 read_smcr_features(void);
13331dc52b3SDave Martin 
134ead9e430SDave Martin /*
135ead9e430SDave Martin  * Helpers to translate bit indices in sve_vq_map to VQ values (and
136ead9e430SDave Martin  * vice versa).  This allows find_next_bit() to be used to find the
137ead9e430SDave Martin  * _maximum_ VQ not exceeding a certain value.
138ead9e430SDave Martin  */
__vq_to_bit(unsigned int vq)139ead9e430SDave Martin static inline unsigned int __vq_to_bit(unsigned int vq)
140ead9e430SDave Martin {
141ead9e430SDave Martin 	return SVE_VQ_MAX - vq;
142ead9e430SDave Martin }
143ead9e430SDave Martin 
__bit_to_vq(unsigned int bit)144ead9e430SDave Martin static inline unsigned int __bit_to_vq(unsigned int bit)
145ead9e430SDave Martin {
146ead9e430SDave Martin 	return SVE_VQ_MAX - bit;
147ead9e430SDave Martin }
148ead9e430SDave Martin 
149b5bc00ffSMark Brown 
150b5bc00ffSMark Brown struct vl_info {
151b5bc00ffSMark Brown 	enum vec_type type;
152b5bc00ffSMark Brown 	const char *name;		/* For display purposes */
153b5bc00ffSMark Brown 
154b5bc00ffSMark Brown 	/* Minimum supported vector length across all CPUs */
155b5bc00ffSMark Brown 	int min_vl;
156b5bc00ffSMark Brown 
157b5bc00ffSMark Brown 	/* Maximum supported vector length across all CPUs */
158b5bc00ffSMark Brown 	int max_vl;
159b5bc00ffSMark Brown 	int max_virtualisable_vl;
160b5bc00ffSMark Brown 
161b5bc00ffSMark Brown 	/*
162b5bc00ffSMark Brown 	 * Set of available vector lengths,
163b5bc00ffSMark Brown 	 * where length vq encoded as bit __vq_to_bit(vq):
164b5bc00ffSMark Brown 	 */
165b5bc00ffSMark Brown 	DECLARE_BITMAP(vq_map, SVE_VQ_MAX);
166b5bc00ffSMark Brown 
167b5bc00ffSMark Brown 	/* Set of vector lengths present on at least one cpu: */
168b5bc00ffSMark Brown 	DECLARE_BITMAP(vq_partial_map, SVE_VQ_MAX);
169b5bc00ffSMark Brown };
1707582e220SDave Martin 
171bc0ee476SDave Martin #ifdef CONFIG_ARM64_SVE
172bc0ee476SDave Martin 
173826a4fddSMark Brown extern void sve_alloc(struct task_struct *task, bool flush);
174bc0ee476SDave Martin extern void fpsimd_release_task(struct task_struct *task);
17543d4da2cSDave Martin extern void fpsimd_sync_to_sve(struct task_struct *task);
176e12310a0SMark Brown extern void fpsimd_force_sync_to_sve(struct task_struct *task);
17743d4da2cSDave Martin extern void sve_sync_to_fpsimd(struct task_struct *task);
17843d4da2cSDave Martin extern void sve_sync_from_fpsimd_zeropad(struct task_struct *task);
17943d4da2cSDave Martin 
18030c43e73SMark Brown extern int vec_set_vector_length(struct task_struct *task, enum vec_type type,
1817582e220SDave Martin 				 unsigned long vl, unsigned long flags);
182bc0ee476SDave Martin 
1832d2123bcSDave Martin extern int sve_set_current_vl(unsigned long arg);
1842d2123bcSDave Martin extern int sve_get_current_vl(void);
1852d2123bcSDave Martin 
sve_user_disable(void)186f9209e26SMark Rutland static inline void sve_user_disable(void)
187f9209e26SMark Rutland {
188f9209e26SMark Rutland 	sysreg_clear_set(cpacr_el1, CPACR_EL1_ZEN_EL0EN, 0);
189f9209e26SMark Rutland }
190f9209e26SMark Rutland 
sve_user_enable(void)191f9209e26SMark Rutland static inline void sve_user_enable(void)
192f9209e26SMark Rutland {
193f9209e26SMark Rutland 	sysreg_clear_set(cpacr_el1, 0, CPACR_EL1_ZEN_EL0EN);
194f9209e26SMark Rutland }
195f9209e26SMark Rutland 
19671ce1ae5SMarc Zyngier #define sve_cond_update_zcr_vq(val, reg)		\
19771ce1ae5SMarc Zyngier 	do {						\
19871ce1ae5SMarc Zyngier 		u64 __zcr = read_sysreg_s((reg));	\
19971ce1ae5SMarc Zyngier 		u64 __new = __zcr & ~ZCR_ELx_LEN_MASK;	\
20071ce1ae5SMarc Zyngier 		__new |= (val) & ZCR_ELx_LEN_MASK;	\
20171ce1ae5SMarc Zyngier 		if (__zcr != __new)			\
20271ce1ae5SMarc Zyngier 			write_sysreg_s(__new, (reg));	\
20371ce1ae5SMarc Zyngier 	} while (0)
20471ce1ae5SMarc Zyngier 
2052e0f2478SDave Martin /*
2062e0f2478SDave Martin  * Probing and setup functions.
2072e0f2478SDave Martin  * Calls to these functions must be serialised with one another.
2082e0f2478SDave Martin  */
209b5bc00ffSMark Brown enum vec_type;
210b5bc00ffSMark Brown 
211b5bc00ffSMark Brown extern void __init vec_init_vq_map(enum vec_type type);
212b5bc00ffSMark Brown extern void vec_update_vq_map(enum vec_type type);
213b5bc00ffSMark Brown extern int vec_verify_vq_map(enum vec_type type);
2142e0f2478SDave Martin extern void __init sve_setup(void);
2152e0f2478SDave Martin 
216b5bc00ffSMark Brown extern __ro_after_init struct vl_info vl_info[ARM64_VEC_MAX];
217b5bc00ffSMark Brown 
write_vl(enum vec_type type,u64 val)218b5bc00ffSMark Brown static inline void write_vl(enum vec_type type, u64 val)
219b5bc00ffSMark Brown {
220b5bc00ffSMark Brown 	u64 tmp;
221b5bc00ffSMark Brown 
222b5bc00ffSMark Brown 	switch (type) {
223b5bc00ffSMark Brown #ifdef CONFIG_ARM64_SVE
224b5bc00ffSMark Brown 	case ARM64_VEC_SVE:
225b5bc00ffSMark Brown 		tmp = read_sysreg_s(SYS_ZCR_EL1) & ~ZCR_ELx_LEN_MASK;
226b5bc00ffSMark Brown 		write_sysreg_s(tmp | val, SYS_ZCR_EL1);
227b5bc00ffSMark Brown 		break;
228b5bc00ffSMark Brown #endif
229b42990d3SMark Brown #ifdef CONFIG_ARM64_SME
230b42990d3SMark Brown 	case ARM64_VEC_SME:
231b42990d3SMark Brown 		tmp = read_sysreg_s(SYS_SMCR_EL1) & ~SMCR_ELx_LEN_MASK;
232b42990d3SMark Brown 		write_sysreg_s(tmp | val, SYS_SMCR_EL1);
233b42990d3SMark Brown 		break;
234b42990d3SMark Brown #endif
235b5bc00ffSMark Brown 	default:
236b5bc00ffSMark Brown 		WARN_ON_ONCE(1);
237b5bc00ffSMark Brown 		break;
238b5bc00ffSMark Brown 	}
239b5bc00ffSMark Brown }
240b5bc00ffSMark Brown 
vec_max_vl(enum vec_type type)241b5bc00ffSMark Brown static inline int vec_max_vl(enum vec_type type)
242b5bc00ffSMark Brown {
243b5bc00ffSMark Brown 	return vl_info[type].max_vl;
244b5bc00ffSMark Brown }
245b5bc00ffSMark Brown 
vec_max_virtualisable_vl(enum vec_type type)246b5bc00ffSMark Brown static inline int vec_max_virtualisable_vl(enum vec_type type)
247b5bc00ffSMark Brown {
248b5bc00ffSMark Brown 	return vl_info[type].max_virtualisable_vl;
249b5bc00ffSMark Brown }
250b5bc00ffSMark Brown 
sve_max_vl(void)251b5bc00ffSMark Brown static inline int sve_max_vl(void)
252b5bc00ffSMark Brown {
253b5bc00ffSMark Brown 	return vec_max_vl(ARM64_VEC_SVE);
254b5bc00ffSMark Brown }
255b5bc00ffSMark Brown 
sve_max_virtualisable_vl(void)256b5bc00ffSMark Brown static inline int sve_max_virtualisable_vl(void)
257b5bc00ffSMark Brown {
258b5bc00ffSMark Brown 	return vec_max_virtualisable_vl(ARM64_VEC_SVE);
259b5bc00ffSMark Brown }
260b5bc00ffSMark Brown 
261b5bc00ffSMark Brown /* Ensure vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX before calling this function */
vq_available(enum vec_type type,unsigned int vq)262b5bc00ffSMark Brown static inline bool vq_available(enum vec_type type, unsigned int vq)
263b5bc00ffSMark Brown {
264b5bc00ffSMark Brown 	return test_bit(__vq_to_bit(vq), vl_info[type].vq_map);
265b5bc00ffSMark Brown }
266b5bc00ffSMark Brown 
sve_vq_available(unsigned int vq)267b5bc00ffSMark Brown static inline bool sve_vq_available(unsigned int vq)
268b5bc00ffSMark Brown {
269b5bc00ffSMark Brown 	return vq_available(ARM64_VEC_SVE, vq);
270b5bc00ffSMark Brown }
271b5bc00ffSMark Brown 
2728bd7f91cSMark Brown size_t sve_state_size(struct task_struct const *task);
2738bd7f91cSMark Brown 
274bc0ee476SDave Martin #else /* ! CONFIG_ARM64_SVE */
275bc0ee476SDave Martin 
sve_alloc(struct task_struct * task,bool flush)276826a4fddSMark Brown static inline void sve_alloc(struct task_struct *task, bool flush) { }
fpsimd_release_task(struct task_struct * task)277bc0ee476SDave Martin static inline void fpsimd_release_task(struct task_struct *task) { }
sve_sync_to_fpsimd(struct task_struct * task)27843d4da2cSDave Martin static inline void sve_sync_to_fpsimd(struct task_struct *task) { }
sve_sync_from_fpsimd_zeropad(struct task_struct * task)27943d4da2cSDave Martin static inline void sve_sync_from_fpsimd_zeropad(struct task_struct *task) { }
28043d4da2cSDave Martin 
sve_max_virtualisable_vl(void)28149ed9204SMark Brown static inline int sve_max_virtualisable_vl(void)
28249ed9204SMark Brown {
28349ed9204SMark Brown 	return 0;
28449ed9204SMark Brown }
28549ed9204SMark Brown 
sve_set_current_vl(unsigned long arg)2862d2123bcSDave Martin static inline int sve_set_current_vl(unsigned long arg)
2872d2123bcSDave Martin {
2882d2123bcSDave Martin 	return -EINVAL;
2892d2123bcSDave Martin }
2902d2123bcSDave Martin 
sve_get_current_vl(void)2912d2123bcSDave Martin static inline int sve_get_current_vl(void)
2922d2123bcSDave Martin {
2932d2123bcSDave Martin 	return -EINVAL;
2942d2123bcSDave Martin }
2952d2123bcSDave Martin 
sve_max_vl(void)296b5bc00ffSMark Brown static inline int sve_max_vl(void)
297b5bc00ffSMark Brown {
298b5bc00ffSMark Brown 	return -EINVAL;
299b5bc00ffSMark Brown }
300b5bc00ffSMark Brown 
sve_vq_available(unsigned int vq)301b5bc00ffSMark Brown static inline bool sve_vq_available(unsigned int vq) { return false; }
302b5bc00ffSMark Brown 
sve_user_disable(void)303f9209e26SMark Rutland static inline void sve_user_disable(void) { BUILD_BUG(); }
sve_user_enable(void)304f9209e26SMark Rutland static inline void sve_user_enable(void) { BUILD_BUG(); }
305f9209e26SMark Rutland 
306a9f8696dSXiaofei Tan #define sve_cond_update_zcr_vq(val, reg) do { } while (0)
307a9f8696dSXiaofei Tan 
vec_init_vq_map(enum vec_type t)308b5bc00ffSMark Brown static inline void vec_init_vq_map(enum vec_type t) { }
vec_update_vq_map(enum vec_type t)309b5bc00ffSMark Brown static inline void vec_update_vq_map(enum vec_type t) { }
vec_verify_vq_map(enum vec_type t)310b5bc00ffSMark Brown static inline int vec_verify_vq_map(enum vec_type t) { return 0; }
sve_setup(void)3112e0f2478SDave Martin static inline void sve_setup(void) { }
312bc0ee476SDave Martin 
sve_state_size(struct task_struct const * task)3138bd7f91cSMark Brown static inline size_t sve_state_size(struct task_struct const *task)
3148bd7f91cSMark Brown {
3158bd7f91cSMark Brown 	return 0;
3168bd7f91cSMark Brown }
3178bd7f91cSMark Brown 
318bc0ee476SDave Martin #endif /* ! CONFIG_ARM64_SVE */
319bc0ee476SDave Martin 
320ca8a4ebcSMark Brown #ifdef CONFIG_ARM64_SME
321ca8a4ebcSMark Brown 
sme_user_disable(void)3228bd7f91cSMark Brown static inline void sme_user_disable(void)
3238bd7f91cSMark Brown {
3248bd7f91cSMark Brown 	sysreg_clear_set(cpacr_el1, CPACR_EL1_SMEN_EL0EN, 0);
3258bd7f91cSMark Brown }
3268bd7f91cSMark Brown 
sme_user_enable(void)3278bd7f91cSMark Brown static inline void sme_user_enable(void)
3288bd7f91cSMark Brown {
3298bd7f91cSMark Brown 	sysreg_clear_set(cpacr_el1, 0, CPACR_EL1_SMEN_EL0EN);
3308bd7f91cSMark Brown }
3318bd7f91cSMark Brown 
sme_smstart_sm(void)332ca8a4ebcSMark Brown static inline void sme_smstart_sm(void)
333ca8a4ebcSMark Brown {
334ca8a4ebcSMark Brown 	asm volatile(__msr_s(SYS_SVCR_SMSTART_SM_EL0, "xzr"));
335ca8a4ebcSMark Brown }
336ca8a4ebcSMark Brown 
sme_smstop_sm(void)337ca8a4ebcSMark Brown static inline void sme_smstop_sm(void)
338ca8a4ebcSMark Brown {
339ca8a4ebcSMark Brown 	asm volatile(__msr_s(SYS_SVCR_SMSTOP_SM_EL0, "xzr"));
340ca8a4ebcSMark Brown }
341ca8a4ebcSMark Brown 
sme_smstop(void)342ca8a4ebcSMark Brown static inline void sme_smstop(void)
343ca8a4ebcSMark Brown {
344ca8a4ebcSMark Brown 	asm volatile(__msr_s(SYS_SVCR_SMSTOP_SMZA_EL0, "xzr"));
345ca8a4ebcSMark Brown }
346ca8a4ebcSMark Brown 
347b42990d3SMark Brown extern void __init sme_setup(void);
348b42990d3SMark Brown 
sme_max_vl(void)349b42990d3SMark Brown static inline int sme_max_vl(void)
350b42990d3SMark Brown {
351b42990d3SMark Brown 	return vec_max_vl(ARM64_VEC_SME);
352b42990d3SMark Brown }
353b42990d3SMark Brown 
sme_max_virtualisable_vl(void)354b42990d3SMark Brown static inline int sme_max_virtualisable_vl(void)
355b42990d3SMark Brown {
356b42990d3SMark Brown 	return vec_max_virtualisable_vl(ARM64_VEC_SME);
357b42990d3SMark Brown }
358b42990d3SMark Brown 
3595d0a8d2fSMark Brown extern void sme_alloc(struct task_struct *task, bool flush);
360b42990d3SMark Brown extern unsigned int sme_get_vl(void);
3619e4ab6c8SMark Brown extern int sme_set_current_vl(unsigned long arg);
3629e4ab6c8SMark Brown extern int sme_get_current_vl(void);
3637c892383SMark Brown extern void sme_suspend_exit(void);
364b42990d3SMark Brown 
3658bd7f91cSMark Brown /*
3668bd7f91cSMark Brown  * Return how many bytes of memory are required to store the full SME
367ce514000SMark Brown  * specific state for task, given task's currently configured vector
368ce514000SMark Brown  * length.
3698bd7f91cSMark Brown  */
sme_state_size(struct task_struct const * task)370ce514000SMark Brown static inline size_t sme_state_size(struct task_struct const *task)
3718bd7f91cSMark Brown {
3728bd7f91cSMark Brown 	unsigned int vl = task_get_sme_vl(task);
373ce514000SMark Brown 	size_t size;
3748bd7f91cSMark Brown 
375ce514000SMark Brown 	size = ZA_SIG_REGS_SIZE(sve_vq_from_vl(vl));
376ce514000SMark Brown 
377d6138b4aSMark Brown 	if (system_supports_sme2())
378d6138b4aSMark Brown 		size += ZT_SIG_REG_SIZE;
379d6138b4aSMark Brown 
380ce514000SMark Brown 	return size;
3818bd7f91cSMark Brown }
3828bd7f91cSMark Brown 
383ca8a4ebcSMark Brown #else
384ca8a4ebcSMark Brown 
sme_user_disable(void)3858bd7f91cSMark Brown static inline void sme_user_disable(void) { BUILD_BUG(); }
sme_user_enable(void)3868bd7f91cSMark Brown static inline void sme_user_enable(void) { BUILD_BUG(); }
3878bd7f91cSMark Brown 
sme_smstart_sm(void)388ca8a4ebcSMark Brown static inline void sme_smstart_sm(void) { }
sme_smstop_sm(void)389ca8a4ebcSMark Brown static inline void sme_smstop_sm(void) { }
sme_smstop(void)390ca8a4ebcSMark Brown static inline void sme_smstop(void) { }
391ca8a4ebcSMark Brown 
sme_alloc(struct task_struct * task,bool flush)3925d0a8d2fSMark Brown static inline void sme_alloc(struct task_struct *task, bool flush) { }
sme_setup(void)393b42990d3SMark Brown static inline void sme_setup(void) { }
sme_get_vl(void)394b42990d3SMark Brown static inline unsigned int sme_get_vl(void) { return 0; }
sme_max_vl(void)395b42990d3SMark Brown static inline int sme_max_vl(void) { return 0; }
sme_max_virtualisable_vl(void)396b42990d3SMark Brown static inline int sme_max_virtualisable_vl(void) { return 0; }
sme_set_current_vl(unsigned long arg)3979e4ab6c8SMark Brown static inline int sme_set_current_vl(unsigned long arg) { return -EINVAL; }
sme_get_current_vl(void)3989e4ab6c8SMark Brown static inline int sme_get_current_vl(void) { return -EINVAL; }
sme_suspend_exit(void)3997c892383SMark Brown static inline void sme_suspend_exit(void) { }
400b42990d3SMark Brown 
sme_state_size(struct task_struct const * task)401ce514000SMark Brown static inline size_t sme_state_size(struct task_struct const *task)
4028bd7f91cSMark Brown {
4038bd7f91cSMark Brown 	return 0;
4048bd7f91cSMark Brown }
4058bd7f91cSMark Brown 
406ca8a4ebcSMark Brown #endif /* ! CONFIG_ARM64_SME */
407ca8a4ebcSMark Brown 
4084328825dSDave Martin /* For use by EFI runtime services calls only */
4094328825dSDave Martin extern void __efi_fpsimd_begin(void);
4104328825dSDave Martin extern void __efi_fpsimd_end(void);
4114328825dSDave Martin 
41253631b54SCatalin Marinas #endif
41353631b54SCatalin Marinas 
41453631b54SCatalin Marinas #endif
415