1 /*
2  * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
3  * Copyright (c) 2022, Google LLC. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #ifndef SIMD_CTX_H
9 #define SIMD_CTX_H
10 
11 /*******************************************************************************
12  * Constants that allow assembler code to access members of and the 'simd_context'
13  * structure at their correct offsets.
14  ******************************************************************************/
15 
16 #if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
17 #if CTX_INCLUDE_SVE_REGS
18 #define SIMD_VECTOR_LEN_BYTES	(SVE_VECTOR_LEN / 8) /* Length of vector in bytes */
19 #elif CTX_INCLUDE_FPREGS
20 #define SIMD_VECTOR_LEN_BYTES	U(16) /* 128 bits fixed vector length for FPU */
21 #endif /* CTX_INCLUDE_SVE_REGS */
22 
23 #define CTX_SIMD_VECTORS	U(0)
24 /* there are 32 vector registers, each of size SIMD_VECTOR_LEN_BYTES */
25 #define CTX_SIMD_FPSR		(CTX_SIMD_VECTORS + (32 * SIMD_VECTOR_LEN_BYTES))
26 #define CTX_SIMD_FPCR		(CTX_SIMD_FPSR + 8)
27 
28 #if CTX_INCLUDE_FPREGS && CTX_INCLUDE_AARCH32_REGS
29 #define CTX_SIMD_FPEXC32	(CTX_SIMD_FPCR + 8)
30 #define CTX_SIMD_PREDICATES	(CTX_SIMD_FPEXC32 + 16)
31 #else
32 #define CTX_SIMD_PREDICATES      (CTX_SIMD_FPCR + 8)
33 #endif /* CTX_INCLUDE_FPREGS && CTX_INCLUDE_AARCH32_REGS */
34 
35 /*
36  * Each predicate register is 1/8th the size of a vector register and there are 16
37  * predicate registers
38  */
39 #define CTX_SIMD_FFR		(CTX_SIMD_PREDICATES + (16 * (SIMD_VECTOR_LEN_BYTES / 8)))
40 
41 #ifndef __ASSEMBLER__
42 
43 #include <stdint.h>
44 #include <lib/cassert.h>
45 
46 /*
47  * Please don't change order of fields in this struct as that may violate
48  * alignment requirements and affect how assembly code accesses members of this
49  * struct.
50  */
51 typedef struct {
52 	uint8_t vectors[32][SIMD_VECTOR_LEN_BYTES];
53 	uint8_t fpsr[8];
54 	uint8_t fpcr[8];
55 #if CTX_INCLUDE_FPREGS && CTX_INCLUDE_AARCH32_REGS
56 	/* 16 bytes to align to next 16 byte boundary when CTX_INCLUDE_SVE_REGS is 0 */
57 	uint8_t fpexc32_el2[16];
58 #endif
59 #if CTX_INCLUDE_SVE_REGS
60 	/* FFR and each of predicates is one-eigth of the SVE vector length */
61 	uint8_t predicates[16][SIMD_VECTOR_LEN_BYTES / 8];
62 	uint8_t ffr[SIMD_VECTOR_LEN_BYTES / 8];
63 	/* SMCCCv1.3 FID[16] hint bit state recorded on EL3 entry */
64 	bool hint;
65 #endif /* CTX_INCLUDE_SVE_REGS */
66 } __aligned(16) simd_regs_t;
67 
68 CASSERT(CTX_SIMD_VECTORS == __builtin_offsetof(simd_regs_t, vectors),
69 		assert_vectors_mismatch);
70 
71 CASSERT(CTX_SIMD_FPSR == __builtin_offsetof(simd_regs_t, fpsr),
72 		assert_fpsr_mismatch);
73 
74 CASSERT(CTX_SIMD_FPCR == __builtin_offsetof(simd_regs_t, fpcr),
75 		assert_fpcr_mismatch);
76 
77 #if CTX_INCLUDE_FPREGS && CTX_INCLUDE_AARCH32_REGS
78 CASSERT(CTX_SIMD_FPEXC32 == __builtin_offsetof(simd_regs_t, fpexc32_el2),
79 		assert_fpex32_mismtatch);
80 #endif
81 
82 #if CTX_INCLUDE_SVE_REGS
83 CASSERT(CTX_SIMD_PREDICATES == __builtin_offsetof(simd_regs_t, predicates),
84 		assert_predicates_mismatch);
85 
86 CASSERT(CTX_SIMD_FFR == __builtin_offsetof(simd_regs_t, ffr),
87 		assert_ffr_mismatch);
88 #endif
89 
90 void simd_ctx_save(uint32_t security_state, bool hint_sve);
91 void simd_ctx_restore(uint32_t security_state);
92 
93 #endif /* __ASSEMBLER__ */
94 
95 #endif /* CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS */
96 
97 #endif /* SIMD_CTX_H */
98