• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 
13 #ifndef TEED_PRIVATE_H
14 #define TEED_PRIVATE_H
15 
16 #include <arch.h>
17 #include <context.h>
18 #include <interrupt_mgmt.h>
19 #include <platform_def.h>
20 #include <psci.h>
21 
22 /*
23  * Secure Payload PM state information e.g. SP is suspended, uninitialised etc
24  * and macros to access the state information in the per-cpu 'state' flags
25  */
26 #define TEE_PSTATE_OFF        0
27 #define TEE_PSTATE_ON         1
28 #define TEE_PSTATE_SUSPEND    2
29 #define TEE_PSTATE_SHIFT      0u
30 #define TEE_PSTATE_MASK       0x3u
31 #define get_tee_pstate(state) (((state) >> TEE_PSTATE_SHIFT) & TEE_PSTATE_MASK)
32 
33 #define clr_tee_pstate(state)                        \
34     do {                                              \
35         ((state) &= ~(TEE_PSTATE_MASK <<     \
36         TEE_PSTATE_SHIFT));                  \
37     } while (0)
38 
39 #define set_tee_pstate(st, pst)                      \
40     do {                                              \
41         clr_tee_pstate(st);                  \
42         (st) |= ((pst) & TEE_PSTATE_MASK) << \
43         TEE_PSTATE_SHIFT;                    \
44     } while (0)
45 
46 /* smc id added for TEE */
47 #define TEE_STD_REE_SIQ                     0xb200000a
48 #define TEE_STD_CRASH                       0xb200000b
49 #define TEE_ENTRY_DONE_AARCH32              0xb2000000
50 #define TEE_ON_DONE_AARCH32                 0xb2000001
51 #define TEE_OFF_DONE_AARCH32                0xb2000002
52 #define TEE_SUSPEND_DONE_AARCH32            0xb2000003
53 #define TEE_RESUME_DONE_AARCH32             0xb2000004
54 #define TEE_PREEMPTED_AARCH32               0xb2000005
55 #define TEE_HANDLED_S_EL1_FIQ_AARCH32       0xb2000006
56 
57 /*
58  * Function identifiers to send smc request to SP from NS and the the repsonse
59  * to NS from SP
60  */
61 #define TEE_STD_REQUEST                     0xb2000008
62 #define TEE_STD_RESPONSE                    0xb2000009
63 
64 #define CPU_INIT_DONE                            1
65 #define CPU_IDLE_STATE                           0
66 #define CPU_SUSPEND_STATE                        1
67 /*
68  * This flag is used by the TEED to determine if the TEE is servicing a yielding
69  * SMC request prior to programming the next entry into the TEE e.g. if TEE
70  * execution is preempted by a non-secure interrupt and handed control to the
71  * normal world. If another request which is distinct from what the TEE was
72  * previously doing arrives, then this flag will be help the TEED to either
73  * reject the new request or service it while ensuring that the previous context
74  * is not corrupted.
75  */
76 #define YIELD_SMC_ACTIVE_FLAG_SHIFT             2u
77 #define YIELD_SMC_ACTIVE_FLAG_MASK              1u
78 #define SMC_INACTIVE                            0
79 #define SMC_ACTIVE                              1
80 #define get_yield_smc_active_flag(state)                                  \
81         (((state) >> YIELD_SMC_ACTIVE_FLAG_SHIFT)                 \
82          & YIELD_SMC_ACTIVE_FLAG_MASK)
83 
84 #define set_yield_smc_active_flag(state)                                  \
85     do {                                                              \
86         ((state) |=                                               \
87         1u << YIELD_SMC_ACTIVE_FLAG_SHIFT);                       \
88     } while (0)
89 
90 #define clr_yield_smc_active_flag(state)                                  \
91     do {                                                              \
92         ((state) &=                                               \
93         ~(YIELD_SMC_ACTIVE_FLAG_MASK                              \
94         << YIELD_SMC_ACTIVE_FLAG_SHIFT));                         \
95     } while (0)
96 /*
97  * This flag is used by the TEED to determine if the TEE has crashed in any way
98  * and it is impossible to continue. The flag will disable forwarding any calls
99  * to secure os system.
100  */
101 #define INIT_CONTEXT_NOT_SAVED                0x0
102 #define INIT_CONTEXT_SAVED                    0x1
103 #define INVALID_PC_ADDR                       0x0
104 #define INVALID_C_RT_CTX                      0x0
105 #define STD_NO_CRASH_FLAG                     0x0
106 #define SECURE_WORLD_FLAG                     0x0
107 #define TEE_SETUP_FAIL                        0x1
108 #define STD_SMC_CRASH_FLAG_SHIFT              0x3u
109 #define STD_SMC_CRASH_FLAG_MASK               0x1u
110 #define get_std_crash_flag(state)                                              \
111         (((state) >> STD_SMC_CRASH_FLAG_SHIFT) &                       \
112         STD_SMC_CRASH_FLAG_MASK)
113 
114 #define set_std_crash_flag(state)                                              \
115     do {                                                                   \
116         ((state) |=                                                    \
117         1 << STD_SMC_CRASH_FLAG_SHIFT);                                \
118     } while (0)
119 
120 /* Secure Payload execution state information i.e. aarch32 or aarch64 */
121 #define TEE_AARCH32        MODE_RW_32
122 #define TEE_AARCH64        MODE_RW_64
123 
124 /* The SPD should know the type of Secure Payload */
125 #define TEE_TYPE_UP        PSCI_TOS_NOT_UP_MIG_CAP
126 #define TEE_TYPE_UPM    PSCI_TOS_UP_MIG_CAP
127 #define TEE_TYPE_MP        PSCI_TOS_NOT_PRESENT_MP
128 
129 /*
130  * Secure Payload migrate type information as known to the SPD. We assume that
131  * the SPD is dealing with an MP Secure Payload.
132  */
133 #define TEE_MIGRATE_INFO        TEE_TYPE_MP
134 
135 /*
136  * Number of cpus that the present on this platform. Rely on a topology
137  * tree to determine this in the future to avoid assumptions about mpidr
138  * allocation
139  */
140 #define TEED_CORE_COUNT        PLATFORM_CORE_COUNT
141 
142 /*
143  * Constants that allow assembler code to preserve callee-saved registers of the
144  * C runtime context while performing a security state switch.
145  */
146 #define TEED_C_RT_CTX_X19          0x0
147 #define TEED_C_RT_CTX_X20          0x8
148 #define TEED_C_RT_CTX_X21          0x10
149 #define TEED_C_RT_CTX_X22          0x18
150 #define TEED_C_RT_CTX_X23          0x20
151 #define TEED_C_RT_CTX_X24          0x28
152 #define TEED_C_RT_CTX_X25          0x30
153 #define TEED_C_RT_CTX_X26          0x38
154 #define TEED_C_RT_CTX_X27          0x40
155 #define TEED_C_RT_CTX_X28          0x48
156 #define TEED_C_RT_CTX_X29          0x50
157 #define TEED_C_RT_CTX_X30          0x58
158 #define TEED_C_RT_CTX_SIZE         0x60
159 #define TEED_C_RT_CTX_ENTRIES      (TEED_C_RT_CTX_SIZE >> DWORD_SHIFT)
160 
161 /*
162  * Constants that allow assembler code to preserve caller-saved registers of the
163  * SP context while performing a TEE preemption.
164  * Note: These offsets have to match with the offsets for the corresponding
165  * registers in cpu_context as we are using memcpy to copy the values from
166  * cpu_context to sp_ctx.
167  */
168 #define TEED_SP_CTX_X0             0x0
169 #define TEED_SP_CTX_X1             0x8
170 #define TEED_SP_CTX_X2             0x10
171 #define TEED_SP_CTX_X3             0x18
172 #define TEED_SP_CTX_X4             0x20
173 #define TEED_SP_CTX_X5             0x28
174 #define TEED_SP_CTX_X6             0x30
175 #define TEED_SP_CTX_X7             0x38
176 #define TEED_SP_CTX_X8             0x40
177 #define TEED_SP_CTX_X9             0x48
178 #define TEED_SP_CTX_X10            0x50
179 #define TEED_SP_CTX_X11            0x58
180 #define TEED_SP_CTX_X12            0x60
181 #define TEED_SP_CTX_X13            0x68
182 #define TEED_SP_CTX_X14            0x70
183 #define TEED_SP_CTX_X15            0x78
184 #define TEED_SP_CTX_X16            0x80
185 #define TEED_SP_CTX_X17            0x88
186 #define TEED_SP_CTX_SIZE           0x90
187 #define TEED_SP_CTX_ENTRIES        (TEED_SP_CTX_SIZE >> DWORD_SHIFT)
188 
189 #ifndef __ASSEMBLY__
190 
191 #include <stdint.h>
192 
193 /*
194  * The number of arguments to save during a SMC call for TEE.
195  * Currently only x1 and x2 are used by TEE.
196  */
197 #define TEE_NUM_ARGS              0x2
198 
199 /* AArch64 callee saved general purpose register context structure. */
200 DEFINE_REG_STRUCT(c_rt_regs, TEED_C_RT_CTX_ENTRIES);
201 
202 /*
203  * Compile time assertion to ensure that both the compiler and linker
204  * have the same double word aligned view of the size of the C runtime
205  * register context.
206  */
207 CASSERT(TEED_C_RT_CTX_SIZE == sizeof(c_rt_regs_t), \
208     assert_spd_c_rt_regs_size_mismatch);
209 
210 /* SEL1 Secure payload (SP) caller saved register context structure. */
211 DEFINE_REG_STRUCT(sp_ctx_regs, TEED_SP_CTX_ENTRIES);
212 
213 /*
214  * Compile time assertion to ensure that both the compiler and linker
215  * have the same double word aligned view of the size of the C runtime
216  * register context.
217  */
218 CASSERT(TEED_SP_CTX_SIZE == sizeof(sp_ctx_regs_t), \
219     assert_spd_sp_regs_size_mismatch);
220 
221 /*
222  * Structure which helps the SPD to maintain the per-cpu state of the SP.
223  * 'spsr_el3' - temporary copy to allow S-EL1 interrupt handling when
224  *                    the TEE has been preempted.
225  * 'elr_el3'  - temporary copy to allow S-EL1 interrupt handling when
226  *                    the TEE has been preempted.
227  * 'state'          - collection of flags to track SP state e.g. on/off
228  * 'mpidr'          - mpidr to associate a context with a cpu
229  * 'rt_context'       - stack address to restore C runtime context from after
230  *                    returning from a synchronous entry into the SP.
231  * 'cpu_context'        - space to maintain SP architectural state
232  * 'saved_tee_args' - space to store arguments for TEE arithmetic operations
233  *                    which will queried using the TEE_GET_ARGS SMC by TEE.
234  * 'sp_ctx'         - space to save the SEL1 Secure Payload(SP) caller saved
235  *                    register context after it has been preempted by an EL3
236  *                    routed NS interrupt and when a Secure Interrupt is taken
237  *                    to SP.
238  */
239 typedef struct tee_context {
240     uint64_t elr_el3;
241     uint32_t spsr_el3;
242     uint32_t state;
243     uint64_t mpidr;
244     uint64_t rt_context;
245     cpu_context_t cpu_context;
246     uint64_t saved_tee_args[TEE_NUM_ARGS];
247 } tee_context_t;
248 
249 typedef struct tee_vectors {
250     uint32_t yield_smc_entry;
251     uint32_t fast_smc_entry;
252     uint32_t cpu_on_entry;
253     uint32_t cpu_off_entry;
254     uint32_t cpu_resume_entry;
255     uint32_t cpu_suspend_entry;
256     uint32_t sel1_intr_entry;
257     uint32_t irq_return_entry;
258     uint32_t s4_resume_entry;
259     uint32_t s4_suspend_entry;
260     uint32_t system_off_entry;
261     uint32_t system_reset_entry;
262     uint32_t abort_yield_smc_entry;
263 } tee_vectors_t;
264 
265 typedef struct smc_registers {
266     u_register_t x1;
267     u_register_t x2;
268     u_register_t x3;
269     u_register_t x4;
270 } smc_registers_t;
271 
272 /* Helper macros to store and retrieve tee args from tee_context */
273 #define store_tee_args(_tee_ctx, _x1, _x2)                           \
274     do {                                                   \
275         (_tee_ctx)->saved_tee_args[0] = _x1; \
276         (_tee_ctx)->saved_tee_args[1] = _x2; \
277     } while (0)
278 
279 #define get_tee_args(_tee_ctx, _x1, _x2)                             \
280     do {                                                   \
281         _x1 = (_tee_ctx)->saved_tee_args[0]; \
282         _x2 = (_tee_ctx)->saved_tee_args[1]; \
283     } while (0)
284 
285 /* TEED power management handlers */
286 const spd_pm_ops_t *get_teed_pm(void);
287 
288 /* Forward declarations */
289 typedef struct tee_vectors tee_vectors_t;
290 tee_context_t* get_teed_sp_context(const uint32_t linear_id);
291 uint64_t get_teed_sp_context_size(void);
292 tee_context_t *get_teed_sp_context_ptr(void);
293 tee_context_t* get_teed_sp_init_context(void);
294 int64_t get_tee_init_context_saved(void);
295 void set_tee_init_context_saved(int64_t tee_init_context_saved);
296 uint64_t get_primary_cpu_mpidr(void);
297 void set_primary_cpu_mpidr(uint64_t primary_cpu_mpidr_in);
298 tee_vectors_t* get_tee_vectors_t(void);
299 void set_tee_vectors_t(tee_vectors_t *const tee_vectors_tmp);
300 uint64_t plat_arm_calc_core_pos(uint64_t mpidr);
301 
302 #endif /* __ASSEMBLY__ */
303 
304 #endif /* TEED_PRIVATE_H */
305