TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tfm_arch_v8m_main.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <inttypes.h>
9 #include "tfm_hal_device_header.h"
10 #include "region_defs.h"
11 #include "tfm_arch.h"
12 #include "tfm_memory_utils.h"
13 #include "tfm_core_utils.h"
14 #include "tfm_secure_api.h"
15 #include "spm_ipc.h"
16 #include "tfm/tfm_core_svc.h"
17 
18 #if !defined(__ARM_ARCH_8M_MAIN__) && !defined(__ARM_ARCH_8_1M_MAIN__)
19 #error "Unsupported ARM Architecture."
20 #endif
21 
22 /*
23  * Stack status at PendSV entry:
24  *
25  * [ R0 - R3 ]<- PSP
26  * [ R12 ]
27  * [ LR_of_RA ]
28  * MSP->[ ........ ] [ RA ]
29  * [ ........ ] [ XPSR ]
30  * [ ........ ]
31  * [ ........ ]
32  *
33  * Stack status before calling pendsv_do_schedule():
34  *
35  * MSP->[ R4 - R11 ]
36  * [ PSP ]--->[ R0 - R3 ]
37  * [ PSP Limit] [ R12 ]
38  * [ R2(dummy)] [ LR_of_RA ]
39  * [ LR ] [ RA ]
40  * [ ........ ] [ XPSR ]
41  * [ ........ ] [ ........ ]
42  * [ ........ ]
43  *
44  * tfm_pendsv_do_schedule() updates stacked context into current thread and
45  * replace stacked context with context of next thread.
46  *
47  * Scheduler does not support handler mode thread so take PSP/PSP_LIMIT as
48  * thread SP/SP_LIMIT. R2 holds dummy data due to stack operation is 8 bytes
49  * aligned.
50  */
51 #if defined(__ICCARM__)
52 #pragma required = tfm_pendsv_do_schedule
53 #endif
54 
55 __attribute__((naked)) void PendSV_Handler(void)
56 {
57  __ASM volatile(
58  "mrs r0, psp \n"
59  "mrs r1, psplim \n"
60  "push {r0, r1, r2, lr} \n"
61  "push {r4-r11} \n"
62  "mov r0, sp \n"
63  "bl tfm_pendsv_do_schedule \n"
64  "pop {r4-r11} \n"
65  "pop {r0, r1, r2, lr} \n"
66  "msr psp, r0 \n"
67  "msr psplim, r1 \n"
68  "bx lr \n"
69  );
70 }
71 
72 void tfm_arch_init_actx(struct tfm_arch_ctx_t *p_actx,
73  uint32_t sp, uint32_t sp_limit)
74 {
75  p_actx->sp = sp;
76  p_actx->sp_limit = sp_limit;
77  p_actx->lr = EXC_RETURN_THREAD_S_PSP;
78 }
79 
84 {
85  ERROR_MSG("Oops... Secure fault!!! You're not going anywhere!");
86  /* A SecureFault may indicate corruption of secure state, so it is essential
87  * that Non-secure code does not regain control after one is raised.
88  * Returning from this exception could allow a pending NS exception to be
89  * taken, so the current solution is not to return.
90  */
91  while (1) {
92  ;
93  }
94 }
95 
96 #if defined(__ICCARM__)
97 uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t exc_return);
98 #pragma required = tfm_core_svc_handler
99 #endif
100 
101 __attribute__((naked)) void SVC_Handler(void)
102 {
103  __ASM volatile(
104  "MRS r2, MSP \n"
105  /* Check store SP in thread mode to r0 */
106  "TST lr, #4 \n"
107  "ITE EQ \n"
108  "MOVEQ r0, r2 \n"
109  "MRSNE r0, PSP \n"
110  "MOV r1, lr \n"
111  "BL tfm_core_svc_handler \n"
112  "BX r0 \n"
113  );
114 }
115 
116 /* Reserved for future usage */
117 __attribute__((naked)) void HardFault_Handler(void)
118 {
119  /* A HardFault may indicate corruption of secure state, so it is essential
120  * that Non-secure code does not regain control after one is raised.
121  * Returning from this exception could allow a pending NS exception to be
122  * taken, so the current solution is not to return.
123  */
124  __ASM volatile("b .");
125 }
126 
127 __attribute__((naked)) void MemManage_Handler(void)
128 {
129  /* A MemManage fault may indicate corruption of secure state, so it is
130  * essential that Non-secure code does not regain control after one is
131  * raised. Returning from this exception could allow a pending NS exception
132  * to be taken, so the current solution is not to return.
133  */
134  __ASM volatile("b .");
135 }
136 
137 __attribute__((naked)) void BusFault_Handler(void)
138 {
139  /* A BusFault may indicate corruption of secure state, so it is essential
140  * that Non-secure code does not regain control after one is raised.
141  * Returning from this exception could allow a pending NS exception to be
142  * taken, so the current solution is not to return.
143  */
144  __ASM volatile("b .");
145 }
146 
147 __attribute__((naked)) void UsageFault_Handler(void)
148 {
149  __ASM volatile("b .");
150 }
151 
153 {
154  uint32_t VECTKEY;
155  SCB_Type *scb = SCB;
156  uint32_t AIRCR;
157 
158  /* Set PRIS flag in AIRCR */
159  AIRCR = scb->AIRCR;
160  VECTKEY = (~AIRCR & SCB_AIRCR_VECTKEYSTAT_Msk);
161  scb->AIRCR = SCB_AIRCR_PRIS_Msk |
162  VECTKEY |
163  (AIRCR & ~SCB_AIRCR_VECTKEY_Msk);
164  /* Set fault priority to less than 0x80 (with AIRCR.PRIS set) to prevent
165  * Non-secure from pre-empting faults that may indicate corruption of Secure
166  * state.
167  */
168  NVIC_SetPriority(MemoryManagement_IRQn, 0);
169  NVIC_SetPriority(BusFault_IRQn, 0);
170  NVIC_SetPriority(SecureFault_IRQn, 0);
171 
172  NVIC_SetPriority(SVCall_IRQn, 0);
173 #ifdef TFM_MULTI_CORE_TOPOLOGY
174  NVIC_SetPriority(PendSV_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
175 #else
176  /*
177  * Set secure PendSV priority to the lowest in SECURE state.
178  *
179  * IMPORTANT NOTE:
180  *
181  * Although the priority of the secure PendSV must be the lowest possible
182  * among other interrupts in the Secure state, it must be ensured that
183  * PendSV is not preempted nor masked by Non-Secure interrupts to ensure
184  * the integrity of the Secure operation.
185  * When AIRCR.PRIS is set, the Non-Secure execution can act on
186  * FAULTMASK_NS, PRIMASK_NS or BASEPRI_NS register to boost its priority
187  * number up to the value 0x80.
188  * For this reason, set the priority of the PendSV interrupt to the next
189  * priority level configurable on the platform, just below 0x80.
190  */
191  NVIC_SetPriority(PendSV_IRQn, (1 << (__NVIC_PRIO_BITS - 1)) - 1);
192 #endif
193 }
194 
196 {
197 #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
198  /* Configure Secure access to the FPU only if the secure image is being
199  * built with the FPU in use. This avoids introducing extra interrupt
200  * latency when the FPU is not used by the SPE.
201  */
202 #if defined (__FPU_USED) && (__FPU_USED == 1U)
203  /* Enable Secure privileged and unprivilged access to the FP Extension */
204  SCB->CPACR |= (3U << 10U*2U) /* enable CP10 full access */
205  | (3U << 11U*2U); /* enable CP11 full access */
206 
207  /* If the SPE will ever use the floating-point registers for sensitive data,
208  * then FPCCR.TS, FPCCR.CLRONRET and FPCCR.CLRONRETS must be set at
209  * initialisation and not changed again afterwards.
210  */
211  FPU->FPCCR |= FPU_FPCCR_TS_Msk
212  | FPU_FPCCR_CLRONRET_Msk
213  | FPU_FPCCR_CLRONRETS_Msk;
214 #endif
215 
216  /* Permit Non-secure access to the Floating-point Extension.
217  * Note: It is still necessary to set CPACR_NS to enable the FP Extension in
218  * the NSPE. This configuration is left to NS privileged software.
219  */
220  SCB->NSACR |= SCB_NSACR_CP10_Msk | SCB_NSACR_CP11_Msk;
221 #endif
222 }
223 
224 __attribute__((naked, noinline)) void tfm_arch_clear_fp_status(void)
225 {
226  __ASM volatile(
227  "mrs r0, control \n"
228  "bics r0, r0, #4 \n"
229  "msr control, r0 \n"
230  "isb \n"
231  "bx lr \n"
232  );
233 }
void tfm_arch_configure_coprocessors(void)
Configure coprocessors.
void HardFault_Handler(void)
void PendSV_Handler(void)
void UsageFault_Handler(void)
#define EXC_RETURN_THREAD_S_PSP
#define ERROR_MSG(msg)
Definition: utilities.h:36
void BusFault_Handler(void)
void SecureFault_Handler(void)
Overwrites default Secure fault handler.
uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t lr, uint32_t *msp)
void MemManage_Handler(void)
void tfm_arch_init_actx(struct tfm_arch_ctx_t *p_actx, uint32_t sp, uint32_t sp_limit)
void SVC_Handler(void)
void tfm_arch_clear_fp_status(void)
void tfm_arch_set_secure_exception_priorities(void)