mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
95fcec7132
When the system supports SME2 the ZT0 register must be context switched as part of the floating point state. This register is stored immediately after ZA in memory and is only accessible when PSTATE.ZA is set so we handle it in the same functions we use to save and restore ZA. Signed-off-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20221208-arm64-sme2-v4-10-f2fa0aef982f@kernel.org Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
134 lines
2.4 KiB
ArmAsm
134 lines
2.4 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* FP/SIMD state saving and restoring
|
|
*
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
* Author: Catalin Marinas <catalin.marinas@arm.com>
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
|
|
#include <asm/assembler.h>
|
|
#include <asm/fpsimdmacros.h>
|
|
|
|
/*
|
|
* Save the FP registers.
|
|
*
|
|
* x0 - pointer to struct fpsimd_state
|
|
*/
|
|
SYM_FUNC_START(fpsimd_save_state)
|
|
fpsimd_save x0, 8
|
|
ret
|
|
SYM_FUNC_END(fpsimd_save_state)
|
|
|
|
/*
|
|
* Load the FP registers.
|
|
*
|
|
* x0 - pointer to struct fpsimd_state
|
|
*/
|
|
SYM_FUNC_START(fpsimd_load_state)
|
|
fpsimd_restore x0, 8
|
|
ret
|
|
SYM_FUNC_END(fpsimd_load_state)
|
|
|
|
#ifdef CONFIG_ARM64_SVE
|
|
|
|
/*
|
|
* Save the SVE state
|
|
*
|
|
* x0 - pointer to buffer for state
|
|
* x1 - pointer to storage for FPSR
|
|
* x2 - Save FFR if non-zero
|
|
*/
|
|
SYM_FUNC_START(sve_save_state)
|
|
sve_save 0, x1, x2, 3
|
|
ret
|
|
SYM_FUNC_END(sve_save_state)
|
|
|
|
/*
|
|
* Load the SVE state
|
|
*
|
|
* x0 - pointer to buffer for state
|
|
* x1 - pointer to storage for FPSR
|
|
* x2 - Restore FFR if non-zero
|
|
*/
|
|
SYM_FUNC_START(sve_load_state)
|
|
sve_load 0, x1, x2, 4
|
|
ret
|
|
SYM_FUNC_END(sve_load_state)
|
|
|
|
SYM_FUNC_START(sve_get_vl)
|
|
_sve_rdvl 0, 1
|
|
ret
|
|
SYM_FUNC_END(sve_get_vl)
|
|
|
|
SYM_FUNC_START(sve_set_vq)
|
|
sve_load_vq x0, x1, x2
|
|
ret
|
|
SYM_FUNC_END(sve_set_vq)
|
|
|
|
/*
|
|
* Zero all SVE registers but the first 128-bits of each vector
|
|
*
|
|
* VQ must already be configured by caller, any further updates of VQ
|
|
* will need to ensure that the register state remains valid.
|
|
*
|
|
* x0 = include FFR?
|
|
* x1 = VQ - 1
|
|
*/
|
|
SYM_FUNC_START(sve_flush_live)
|
|
cbz x1, 1f // A VQ-1 of 0 is 128 bits so no extra Z state
|
|
sve_flush_z
|
|
1: sve_flush_p
|
|
tbz x0, #0, 2f
|
|
sve_flush_ffr
|
|
2: ret
|
|
SYM_FUNC_END(sve_flush_live)
|
|
|
|
#endif /* CONFIG_ARM64_SVE */
|
|
|
|
#ifdef CONFIG_ARM64_SME
|
|
|
|
SYM_FUNC_START(sme_get_vl)
|
|
_sme_rdsvl 0, 1
|
|
ret
|
|
SYM_FUNC_END(sme_get_vl)
|
|
|
|
SYM_FUNC_START(sme_set_vq)
|
|
sme_load_vq x0, x1, x2
|
|
ret
|
|
SYM_FUNC_END(sme_set_vq)
|
|
|
|
/*
|
|
* Save the ZA and ZT state
|
|
*
|
|
* x0 - pointer to buffer for state
|
|
* x1 - number of ZT registers to save
|
|
*/
|
|
SYM_FUNC_START(sme_save_state)
|
|
_sme_rdsvl 2, 1 // x2 = VL/8
|
|
sme_save_za 0, x2, 12 // Leaves x0 pointing to the end of ZA
|
|
|
|
cbz x1, 1f
|
|
_str_zt 0
|
|
1:
|
|
ret
|
|
SYM_FUNC_END(sme_save_state)
|
|
|
|
/*
|
|
* Load the ZA and ZT state
|
|
*
|
|
* x0 - pointer to buffer for state
|
|
* x1 - number of ZT registers to save
|
|
*/
|
|
SYM_FUNC_START(sme_load_state)
|
|
_sme_rdsvl 2, 1 // x2 = VL/8
|
|
sme_load_za 0, x2, 12 // Leaves x0 pointing to the end of ZA
|
|
|
|
cbz x1, 1f
|
|
_ldr_zt 0
|
|
1:
|
|
ret
|
|
SYM_FUNC_END(sme_load_state)
|
|
|
|
#endif /* CONFIG_ARM64_SME */
|