18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2012 ARM Ltd. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#ifndef __ASM_FP_H 68c2ecf20Sopenharmony_ci#define __ASM_FP_H 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <asm/errno.h> 98c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 108c2ecf20Sopenharmony_ci#include <asm/processor.h> 118c2ecf20Sopenharmony_ci#include <asm/sigcontext.h> 128c2ecf20Sopenharmony_ci#include <asm/sysreg.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/bitmap.h> 178c2ecf20Sopenharmony_ci#include <linux/build_bug.h> 188c2ecf20Sopenharmony_ci#include <linux/bug.h> 198c2ecf20Sopenharmony_ci#include <linux/cache.h> 208c2ecf20Sopenharmony_ci#include <linux/init.h> 218c2ecf20Sopenharmony_ci#include <linux/stddef.h> 228c2ecf20Sopenharmony_ci#include <linux/types.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT 258c2ecf20Sopenharmony_ci/* Masks for extracting the FPSR and FPCR from the FPSCR */ 268c2ecf20Sopenharmony_ci#define VFP_FPSCR_STAT_MASK 0xf800009f 278c2ecf20Sopenharmony_ci#define VFP_FPSCR_CTRL_MASK 0x07f79f00 288c2ecf20Sopenharmony_ci/* 298c2ecf20Sopenharmony_ci * The VFP state has 32x64-bit registers and a single 32-bit 308c2ecf20Sopenharmony_ci * control/status register. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci#define VFP_STATE_SIZE ((32 * 8) + 4) 338c2ecf20Sopenharmony_ci#endif 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistruct task_struct; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ciextern void fpsimd_save_state(struct user_fpsimd_state *state); 388c2ecf20Sopenharmony_ciextern void fpsimd_load_state(struct user_fpsimd_state *state); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ciextern void fpsimd_thread_switch(struct task_struct *next); 418c2ecf20Sopenharmony_ciextern void fpsimd_flush_thread(void); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ciextern void fpsimd_signal_preserve_current_state(void); 448c2ecf20Sopenharmony_ciextern void fpsimd_preserve_current_state(void); 458c2ecf20Sopenharmony_ciextern void fpsimd_restore_current_state(void); 468c2ecf20Sopenharmony_ciextern void fpsimd_update_current_state(struct user_fpsimd_state const *state); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ciextern void fpsimd_bind_task_to_cpu(void); 498c2ecf20Sopenharmony_ciextern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state, 508c2ecf20Sopenharmony_ci void *sve_state, unsigned int sve_vl); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciextern void fpsimd_flush_task_state(struct task_struct *target); 538c2ecf20Sopenharmony_ciextern void fpsimd_save_and_flush_cpu_state(void); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* Maximum VL that SVE VL-agnostic software can transparently support */ 568c2ecf20Sopenharmony_ci#define SVE_VL_ARCH_MAX 0x100 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* Offset of FFR in the SVE register dump */ 598c2ecf20Sopenharmony_cistatic inline size_t sve_ffr_offset(int vl) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci return SVE_SIG_FFR_OFFSET(sve_vq_from_vl(vl)) - SVE_SIG_REGS_OFFSET; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic inline void *sve_pffr(struct thread_struct *thread) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci return (char *)thread->sve_state + sve_ffr_offset(thread->sve_vl); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ciextern void sve_save_state(void *state, u32 *pfpsr); 708c2ecf20Sopenharmony_ciextern void sve_load_state(void const *state, u32 const *pfpsr, 718c2ecf20Sopenharmony_ci unsigned long vq_minus_1); 728c2ecf20Sopenharmony_ciextern void sve_flush_live(void); 738c2ecf20Sopenharmony_ciextern void sve_load_from_fpsimd_state(struct user_fpsimd_state const *state, 748c2ecf20Sopenharmony_ci unsigned long vq_minus_1); 758c2ecf20Sopenharmony_ciextern unsigned int sve_get_vl(void); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistruct arm64_cpu_capabilities; 788c2ecf20Sopenharmony_ciextern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ciextern u64 read_zcr_features(void); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ciextern int __ro_after_init sve_max_vl; 838c2ecf20Sopenharmony_ciextern int __ro_after_init sve_max_virtualisable_vl; 848c2ecf20Sopenharmony_ciextern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/* 878c2ecf20Sopenharmony_ci * Helpers to translate bit indices in sve_vq_map to VQ values (and 888c2ecf20Sopenharmony_ci * vice versa). This allows find_next_bit() to be used to find the 898c2ecf20Sopenharmony_ci * _maximum_ VQ not exceeding a certain value. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_cistatic inline unsigned int __vq_to_bit(unsigned int vq) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci return SVE_VQ_MAX - vq; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic inline unsigned int __bit_to_vq(unsigned int bit) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci return SVE_VQ_MAX - bit; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* Ensure vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX before calling this function */ 1028c2ecf20Sopenharmony_cistatic inline bool sve_vq_available(unsigned int vq) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci return test_bit(__vq_to_bit(vq), sve_vq_map); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM64_SVE 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ciextern size_t sve_state_size(struct task_struct const *task); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ciextern void sve_alloc(struct task_struct *task); 1128c2ecf20Sopenharmony_ciextern void fpsimd_release_task(struct task_struct *task); 1138c2ecf20Sopenharmony_ciextern void fpsimd_sync_to_sve(struct task_struct *task); 1148c2ecf20Sopenharmony_ciextern void sve_sync_to_fpsimd(struct task_struct *task); 1158c2ecf20Sopenharmony_ciextern void sve_sync_from_fpsimd_zeropad(struct task_struct *task); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ciextern int sve_set_vector_length(struct task_struct *task, 1188c2ecf20Sopenharmony_ci unsigned long vl, unsigned long flags); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ciextern int sve_set_current_vl(unsigned long arg); 1218c2ecf20Sopenharmony_ciextern int sve_get_current_vl(void); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic inline void sve_user_disable(void) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci sysreg_clear_set(cpacr_el1, CPACR_EL1_ZEN_EL0EN, 0); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic inline void sve_user_enable(void) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci sysreg_clear_set(cpacr_el1, 0, CPACR_EL1_ZEN_EL0EN); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* 1348c2ecf20Sopenharmony_ci * Probing and setup functions. 1358c2ecf20Sopenharmony_ci * Calls to these functions must be serialised with one another. 1368c2ecf20Sopenharmony_ci */ 1378c2ecf20Sopenharmony_ciextern void __init sve_init_vq_map(void); 1388c2ecf20Sopenharmony_ciextern void sve_update_vq_map(void); 1398c2ecf20Sopenharmony_ciextern int sve_verify_vq_map(void); 1408c2ecf20Sopenharmony_ciextern void __init sve_setup(void); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci#else /* ! CONFIG_ARM64_SVE */ 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic inline void sve_alloc(struct task_struct *task) { } 1458c2ecf20Sopenharmony_cistatic inline void fpsimd_release_task(struct task_struct *task) { } 1468c2ecf20Sopenharmony_cistatic inline void sve_sync_to_fpsimd(struct task_struct *task) { } 1478c2ecf20Sopenharmony_cistatic inline void sve_sync_from_fpsimd_zeropad(struct task_struct *task) { } 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic inline int sve_set_current_vl(unsigned long arg) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci return -EINVAL; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic inline int sve_get_current_vl(void) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci return -EINVAL; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic inline void sve_user_disable(void) { BUILD_BUG(); } 1608c2ecf20Sopenharmony_cistatic inline void sve_user_enable(void) { BUILD_BUG(); } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic inline void sve_init_vq_map(void) { } 1638c2ecf20Sopenharmony_cistatic inline void sve_update_vq_map(void) { } 1648c2ecf20Sopenharmony_cistatic inline int sve_verify_vq_map(void) { return 0; } 1658c2ecf20Sopenharmony_cistatic inline void sve_setup(void) { } 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci#endif /* ! CONFIG_ARM64_SVE */ 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci/* For use by EFI runtime services calls only */ 1708c2ecf20Sopenharmony_ciextern void __efi_fpsimd_begin(void); 1718c2ecf20Sopenharmony_ciextern void __efi_fpsimd_end(void); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci#endif 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci#endif 176