1 /*
2  * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "compiler_ext_defs.h"
9 #include "security_defs.h"
10 #include "tfm_arch.h"
11 #include "tfm_core_trustzone.h"
12 #include "utilities.h"
13 #include "config_impl.h"
14 
15 #if defined(__ICCARM__) && (CONFIG_TFM_FP >= 1)
16 #pragma required = tfm_arch_clear_fp_data
17 #endif
18 
tfm_arch_free_msp_and_exc_ret(uint32_t msp_base,uint32_t exc_return)19 __naked void tfm_arch_free_msp_and_exc_ret(uint32_t msp_base,
20                                            uint32_t exc_return)
21 {
22     __ASM volatile(
23 #if !defined(__ICCARM__)
24         ".syntax unified                        \n"
25 #endif
26         "mov     r4, r0                         \n"
27         "mov     r5, r1                         \n"
28 #if (CONFIG_TFM_FLOAT_ABI > 0)
29         "bl      tfm_arch_clear_fp_data         \n"
30 #endif
31         "mov     sp, r4                         \n"
32         "bx      r5                             \n"
33     );
34 }
35 #if CONFIG_TFM_SPM_BACKEND_IPC == 1
tfm_arch_set_context_ret_code(void * p_ctx_ctrl,uint32_t ret_code)36 void tfm_arch_set_context_ret_code(void *p_ctx_ctrl, uint32_t ret_code)
37 {
38     struct context_ctrl_t *ctx_ctrl = (struct context_ctrl_t *)p_ctx_ctrl;
39 
40     /*
41      * If a cross call is pending (cross_frame != CROSS_RETCODE_EMPTY), write
42      * return value to the frame position.
43      * Otherwise, write the return value to the state context on stack.
44      */
45     if (ctx_ctrl->cross_frame) {
46         ((struct cross_call_abi_frame_t *)ctx_ctrl->cross_frame)->a0 = ret_code;
47         ctx_ctrl->retcode_status = CROSS_RETCODE_UPDATED;
48     } else {
49         ((struct full_context_t *)ctx_ctrl->sp)->stat_ctx.r0 = ret_code;
50     }
51 }
52 
53 /* Caution: Keep 'uint32_t' always for collecting thread return values! */
tfm_arch_trigger_pendsv(void)54 __naked uint32_t tfm_arch_trigger_pendsv(void)
55 {
56     __ASM volatile(
57 #ifndef __ICCARM__
58         ".syntax unified                               \n"
59 #endif
60         "ldr     r0, ="M2S(SCB_ICSR_ADDR)"             \n"
61         "ldr     r1, ="M2S(SCB_ICSR_PENDSVSET_BIT)"    \n"
62         "str     r1, [r0, #0]                          \n"
63         "dsb     #0xf                                  \n"
64         "isb                                           \n"
65         "bx      lr                                    \n"
66     );
67 }
68 #endif
69 
tfm_arch_init_context(void * p_ctx_ctrl,uintptr_t pfn,void * param,uintptr_t pfnlr)70 void tfm_arch_init_context(void *p_ctx_ctrl,
71                            uintptr_t pfn, void *param, uintptr_t pfnlr)
72 {
73     uintptr_t sp = ((struct context_ctrl_t *)p_ctx_ctrl)->sp;
74     uintptr_t sp_limit = ((struct context_ctrl_t *)p_ctx_ctrl)->sp_limit;
75     struct full_context_t *p_tctx =
76             (struct full_context_t *)arch_seal_thread_stack(sp);
77 
78     /* Check if enough space on stack */
79     if ((uintptr_t)p_tctx - sizeof(struct full_context_t) < sp_limit) {
80         tfm_core_panic();
81     }
82 
83     p_tctx--;
84 
85     spm_memset(p_tctx, 0, sizeof(*p_tctx));
86 
87     ARCH_CTXCTRL_EXCRET_PATTERN(&p_tctx->stat_ctx, param, pfn, pfnlr);
88 
89     ((struct context_ctrl_t *)p_ctx_ctrl)->exc_ret  = EXC_RETURN_THREAD_PSP;
90     ((struct context_ctrl_t *)p_ctx_ctrl)->sp       = (uintptr_t)p_tctx;
91 }
92 
tfm_arch_refresh_hardware_context(void * p_ctx_ctrl)93 uint32_t tfm_arch_refresh_hardware_context(void *p_ctx_ctrl)
94 {
95     struct context_ctrl_t *ctx_ctrl;
96     struct tfm_state_context_t *sc;
97 
98     ctx_ctrl  = (struct context_ctrl_t *)p_ctx_ctrl;
99     sc = &(((struct full_context_t *)(ctx_ctrl->sp))->stat_ctx);
100 
101     tfm_arch_set_psplim(ctx_ctrl->sp_limit);
102     __set_PSP((uintptr_t)sc);
103 
104     return ctx_ctrl->exc_ret;
105 }
106