cccb78ce89
When we enable SVE usage in userspace after taking a SVE access trap we need to ensure that the portions of the register state that are not shared with the FPSIMD registers are zeroed. Currently we do this by forcing the FPSIMD registers to be saved to the task struct and converting them there. This is wasteful in the common case where the task state is loaded into the registers and we will immediately return to userspace since we can initialise the SVE state directly in registers instead of accessing multiple copies of the register state in memory. Instead in that common case do the conversion in the registers and update the task metadata so that we can return to userspace without spilling the register state to memory unless there is some other reason to do so. Signed-off-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20210312190313.24598-1-broonie@kernel.org Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
80 lines
1.5 KiB
ArmAsm
80 lines
1.5 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
|
|
|
|
SYM_FUNC_START(sve_save_state)
|
|
sve_save 0, x1, 2
|
|
ret
|
|
SYM_FUNC_END(sve_save_state)
|
|
|
|
SYM_FUNC_START(sve_load_state)
|
|
sve_load 0, x1, x2, 3, x4
|
|
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)
|
|
|
|
/*
|
|
* Load SVE state from FPSIMD state.
|
|
*
|
|
* x0 = pointer to struct fpsimd_state
|
|
* x1 = VQ - 1
|
|
*
|
|
* Each SVE vector will be loaded with the first 128-bits taken from FPSIMD
|
|
* and the rest zeroed. All the other SVE registers will be zeroed.
|
|
*/
|
|
SYM_FUNC_START(sve_load_from_fpsimd_state)
|
|
sve_load_vq x1, x2, x3
|
|
fpsimd_restore x0, 8
|
|
_for n, 0, 15, _sve_pfalse \n
|
|
_sve_wrffr 0
|
|
ret
|
|
SYM_FUNC_END(sve_load_from_fpsimd_state)
|
|
|
|
/* Zero all SVE registers but the first 128-bits of each vector */
|
|
SYM_FUNC_START(sve_flush_live)
|
|
sve_flush
|
|
ret
|
|
SYM_FUNC_END(sve_flush_live)
|
|
|
|
#endif /* CONFIG_ARM64_SVE */
|