xref: /linux/arch/arm64/kernel/entry-fpsimd.S (revision 0033cd9339642f9b7bef23f96aa2e7277ab51cce)
1caab277bSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
253631b54SCatalin Marinas/*
353631b54SCatalin Marinas * FP/SIMD state saving and restoring
453631b54SCatalin Marinas *
553631b54SCatalin Marinas * Copyright (C) 2012 ARM Ltd.
653631b54SCatalin Marinas * Author: Catalin Marinas <catalin.marinas@arm.com>
753631b54SCatalin Marinas */
853631b54SCatalin Marinas
953631b54SCatalin Marinas#include <linux/linkage.h>
1053631b54SCatalin Marinas
1153631b54SCatalin Marinas#include <asm/assembler.h>
12cfc5180eSMarc Zyngier#include <asm/fpsimdmacros.h>
1353631b54SCatalin Marinas
1453631b54SCatalin Marinas/*
1553631b54SCatalin Marinas * Save the FP registers.
1653631b54SCatalin Marinas *
1753631b54SCatalin Marinas * x0 - pointer to struct fpsimd_state
1853631b54SCatalin Marinas */
190343a7e4SMark BrownSYM_FUNC_START(fpsimd_save_state)
20cfc5180eSMarc Zyngier	fpsimd_save x0, 8
2153631b54SCatalin Marinas	ret
220343a7e4SMark BrownSYM_FUNC_END(fpsimd_save_state)
2353631b54SCatalin Marinas
2453631b54SCatalin Marinas/*
2553631b54SCatalin Marinas * Load the FP registers.
2653631b54SCatalin Marinas *
2753631b54SCatalin Marinas * x0 - pointer to struct fpsimd_state
2853631b54SCatalin Marinas */
290343a7e4SMark BrownSYM_FUNC_START(fpsimd_load_state)
30cfc5180eSMarc Zyngier	fpsimd_restore x0, 8
3153631b54SCatalin Marinas	ret
320343a7e4SMark BrownSYM_FUNC_END(fpsimd_load_state)
331fc5dce7SDave Martin
341fc5dce7SDave Martin#ifdef CONFIG_ARM64_SVE
351e530f13SJulien Grall
3638ee3c5eSMark Brown/*
3738ee3c5eSMark Brown * Save the SVE state
3838ee3c5eSMark Brown *
3938ee3c5eSMark Brown * x0 - pointer to buffer for state
4038ee3c5eSMark Brown * x1 - pointer to storage for FPSR
419f584866SMark Brown * x2 - Save FFR if non-zero
4238ee3c5eSMark Brown */
430343a7e4SMark BrownSYM_FUNC_START(sve_save_state)
449f584866SMark Brown	sve_save 0, x1, x2, 3
451fc5dce7SDave Martin	ret
460343a7e4SMark BrownSYM_FUNC_END(sve_save_state)
471fc5dce7SDave Martin
4838ee3c5eSMark Brown/*
4938ee3c5eSMark Brown * Load the SVE state
5038ee3c5eSMark Brown *
5138ee3c5eSMark Brown * x0 - pointer to buffer for state
5238ee3c5eSMark Brown * x1 - pointer to storage for FPSR
539f584866SMark Brown * x2 - Restore FFR if non-zero
5438ee3c5eSMark Brown */
550343a7e4SMark BrownSYM_FUNC_START(sve_load_state)
56ddc806b5SMark Brown	sve_load 0, x1, x2, 4
571fc5dce7SDave Martin	ret
580343a7e4SMark BrownSYM_FUNC_END(sve_load_state)
591fc5dce7SDave Martin
600343a7e4SMark BrownSYM_FUNC_START(sve_get_vl)
611fc5dce7SDave Martin	_sve_rdvl	0, 1
621fc5dce7SDave Martin	ret
630343a7e4SMark BrownSYM_FUNC_END(sve_get_vl)
641e530f13SJulien Grall
65cccb78ceSMark BrownSYM_FUNC_START(sve_set_vq)
66cccb78ceSMark Brown	sve_load_vq x0, x1, x2
67cccb78ceSMark Brown	ret
68cccb78ceSMark BrownSYM_FUNC_END(sve_set_vq)
69cccb78ceSMark Brown
709c4b4c70SJulien Grall/*
71ad4711f9SMark Brown * Zero all SVE registers but the first 128-bits of each vector
72ad4711f9SMark Brown *
73ad4711f9SMark Brown * VQ must already be configured by caller, any further updates of VQ
74ad4711f9SMark Brown * will need to ensure that the register state remains valid.
75ad4711f9SMark Brown *
769f584866SMark Brown * x0 = include FFR?
779f584866SMark Brown * x1 = VQ - 1
78ad4711f9SMark Brown */
791e530f13SJulien GrallSYM_FUNC_START(sve_flush_live)
809f584866SMark Brown	cbz		x1, 1f	// A VQ-1 of 0 is 128 bits so no extra Z state
81483dbf6aSMark Brown	sve_flush_z
829f584866SMark Brown1:	sve_flush_p
839f584866SMark Brown	tbz		x0, #0, 2f
849f584866SMark Brown	sve_flush_ffr
859f584866SMark Brown2:	ret
861e530f13SJulien GrallSYM_FUNC_END(sve_flush_live)
871e530f13SJulien Grall
881fc5dce7SDave Martin#endif /* CONFIG_ARM64_SVE */
89b42990d3SMark Brown
90b42990d3SMark Brown#ifdef CONFIG_ARM64_SME
91b42990d3SMark Brown
92b42990d3SMark BrownSYM_FUNC_START(sme_get_vl)
93b42990d3SMark Brown	_sme_rdsvl	0, 1
94b42990d3SMark Brown	ret
95b42990d3SMark BrownSYM_FUNC_END(sme_get_vl)
96b42990d3SMark Brown
97af7167d6SMark BrownSYM_FUNC_START(sme_set_vq)
98af7167d6SMark Brown	sme_load_vq x0, x1, x2
99af7167d6SMark Brown	ret
100af7167d6SMark BrownSYM_FUNC_END(sme_set_vq)
101af7167d6SMark Brown
102*0033cd93SMark Brown/*
103*0033cd93SMark Brown * Save the SME state
104*0033cd93SMark Brown *
105*0033cd93SMark Brown * x0 - pointer to buffer for state
106*0033cd93SMark Brown */
107*0033cd93SMark BrownSYM_FUNC_START(za_save_state)
108*0033cd93SMark Brown	_sme_rdsvl	1, 1		// x1 = VL/8
109*0033cd93SMark Brown	sme_save_za 0, x1, 12
110*0033cd93SMark Brown	ret
111*0033cd93SMark BrownSYM_FUNC_END(za_save_state)
112*0033cd93SMark Brown
113*0033cd93SMark Brown/*
114*0033cd93SMark Brown * Load the SME state
115*0033cd93SMark Brown *
116*0033cd93SMark Brown * x0 - pointer to buffer for state
117*0033cd93SMark Brown */
118*0033cd93SMark BrownSYM_FUNC_START(za_load_state)
119*0033cd93SMark Brown	_sme_rdsvl	1, 1		// x1 = VL/8
120*0033cd93SMark Brown	sme_load_za 0, x1, 12
121*0033cd93SMark Brown	ret
122*0033cd93SMark BrownSYM_FUNC_END(za_load_state)
123*0033cd93SMark Brown
124b42990d3SMark Brown#endif /* CONFIG_ARM64_SME */
125