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