blob: 2581a3b32bfe65e059e65770e1c9d4bd1d529b28 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6#ifndef FPU_HELPERS_H
7#define FPU_HELPERS_H
8
9#include <arch_helpers.h>
10#include <assert.h>
11#include <cpuid.h>
12#include <stdbool.h>
13
14/* The FPU and SIMD register bank is 32 quadword (128 bits) Q registers. */
15#define FPU_Q_SIZE 16U
16#define FPU_Q_COUNT 32U
17
18/* These defines are needed by assembly code to access the context. */
19#define FPU_CTX_OFFSET_Q 0U
20#define FPU_CTX_OFFSET_FPSR 512U
21#define FPU_CTX_OFFSET_FPCR 520U
22
23#ifdef RMM_FPU_USE_AT_REL2
24#define FPU_ALLOW(expression) \
25 do { \
26 assert(fpu_is_my_state_saved(my_cpuid())); \
27 write_cptr_el2( \
28 (read_cptr_el2() & \
29 (~(CPTR_EL2_FPEN_MASK << CPTR_EL2_FPEN_SHIFT))) | \
30 (CPTR_EL2_FPEN_NO_TRAP_11 << CPTR_EL2_FPEN_SHIFT)); \
31 isb(); \
32 expression; \
33 write_cptr_el2( \
34 (read_cptr_el2() & \
35 (~(CPTR_EL2_FPEN_MASK << CPTR_EL2_FPEN_SHIFT))) | \
36 (CPTR_EL2_FPEN_TRAP_ALL_00 << CPTR_EL2_FPEN_SHIFT)); \
37 isb(); \
38 } while (0)
39
40#define IS_FPU_ALLOWED() \
41 (fpu_is_my_state_saved(my_cpuid()) && is_fpen_enabled())
42
43#else /* RMM_FPU_USE_AT_REL2 */
44#define FPU_ALLOW(expression) \
45 do { \
46 expression; \
47 } while (0)
48
49#define IS_FPU_ALLOWED() (true)
50
51#endif /* RMM_FPU_USE_AT_REL2 */
52
53struct fpu_state {
54 unsigned __int128 q[FPU_Q_COUNT];
55 unsigned long fpsr;
56 unsigned long fpcr;
57};
58
59/* Since we use these offsets in assembly code make sure they are correct. */
60COMPILER_ASSERT(__builtin_offsetof(struct fpu_state, q) ==
61 FPU_CTX_OFFSET_Q);
62COMPILER_ASSERT(__builtin_offsetof(struct fpu_state, fpsr) ==
63 FPU_CTX_OFFSET_FPSR);
64COMPILER_ASSERT(__builtin_offsetof(struct fpu_state, fpcr) ==
65 FPU_CTX_OFFSET_FPCR);
66
67/*
68 * Save/restore FPU context to/from the `fpu_state` passed as parameter. The FPU
69 * instruction trap needs to be disabled before calling these functions.
70 * Can be used for context switching.
71 */
72void fpu_save_state(struct fpu_state *fpu);
73void fpu_restore_state(struct fpu_state *fpu);
74
75/*
76 * Save/restore FPU state to/from a per-cpu buffer allocated within the
77 * library. The FPU instruction trap is disabled by this function during the
78 * access to the FPU registers.
79 * These functions are expected to be called before FPU is used by RMM to save
80 * the incoming FPU context.
81 */
82void fpu_save_my_state(void);
83void fpu_restore_my_state(void);
84
85/*
86 * Return true iff an fpu state is saved in the per-cpu buffer in this library.
87 *
88 * After calling 'fpu_save_my_state' this function returns true. After calling
89 * 'fpu_restore_my_state' this function returns false.
90 */
91bool fpu_is_my_state_saved(unsigned int cpu_id);
92
93#endif /* FPU_HELPERS_H */