TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tfm_arch_v8m_base.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 "spm_ipc.h"
10 #include "tfm_hal_device_header.h"
11 #include "tfm_arch.h"
12 #include "tfm_secure_api.h"
13 #include "tfm/tfm_core_svc.h"
14 
15 #if !defined(__ARM_ARCH_8M_BASE__)
16 #error "Unsupported ARM Architecture."
17 #endif
18 
19 /*
20  * Stack status at PendSV entry:
21  *
22  * [ R0 - R3 ]<- PSP
23  * [ R12 ]
24  * [ LR_of_RA ]
25  * MSP->[ ........ ] [ RA ]
26  * [ ........ ] [ XPSR ]
27  * [ ........ ]
28  * [ ........ ]
29  *
30  * Stack status before calling pendsv_do_schedule():
31  *
32  * MSP->[ R4 - R11 ]
33  * [ PSP ]--->[ R0 - R3 ]
34  * [ PSP Limit] [ R12 ]
35  * [ R2(dummy)] [ LR_of_RA ]
36  * [ LR ] [ RA ]
37  * [ ........ ] [ XPSR ]
38  * [ ........ ] [ ........ ]
39  * [ ........ ]
40  *
41  * tfm_pendsv_do_schedule() updates stacked context into current thread and
42  * replace stacked context with context of next thread.
43  *
44  * Scheduler does not support handler mode thread so take PSP/PSP_LIMIT as
45  * thread SP/SP_LIMIT. R2 holds dummy data due to stack operation is 8 bytes
46  * aligned.
47  */
48 #if defined(__ICCARM__)
49 #pragma required = tfm_pendsv_do_schedule
50 #endif
51 
52 __attribute__((naked)) void PendSV_Handler(void)
53 {
54  __ASM volatile(
55  "mrs r0, psp \n"
56  "mrs r1, psplim \n"
57  "push {r0, r1, r2, lr} \n"
58  "push {r4-r7} \n"
59  "mov r4, r8 \n"
60  "mov r5, r9 \n"
61  "mov r6, r10 \n"
62  "mov r7, r11 \n"
63  "push {r4-r7} \n"
64  "mov r0, sp \n"
65  "bl tfm_pendsv_do_schedule \n"
66  "pop {r4-r7} \n"
67  "mov r8, r4 \n"
68  "mov r9, r5 \n"
69  "mov r10, r6 \n"
70  "mov r11, r7 \n"
71  "pop {r4-r7} \n"
72  "pop {r0-r3} \n"
73  "mov lr, r3 \n"
74  "msr psp, r0 \n"
75  "msr psplim, r1 \n"
76  "bx lr \n"
77  );
78 }
79 
80 void tfm_arch_init_actx(struct tfm_arch_ctx_t *p_actx,
81  uint32_t sp, uint32_t sp_limit)
82 {
83  p_actx->sp = sp;
84  p_actx->sp_limit = sp_limit;
85  p_actx->lr = EXC_RETURN_THREAD_S_PSP;
86 }
87 
95 {
96  /* In a baseline implementation there is no way, to find out whether this is
97  * a hard fault triggered directly, or another fault that has been
98  * escalated.
99  */
100  /* A HardFault may indicate corruption of secure state, so it is essential
101  * that Non-secure code does not regain control after one is raised.
102  * Returning from this exception could allow a pending NS exception to be
103  * taken, so the current solution is not to return.
104  */
105  while (1) {
106  ;
107  }
108 }
109 
110 #if defined(__ICCARM__)
111 uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t exc_return);
112 #pragma required = tfm_core_svc_handler
113 #endif
114 
115 __attribute__((naked)) void SVC_Handler(void)
116 {
117  __ASM volatile(
118  "MRS r2, MSP \n"
119  "MOVS r1, #4 \n"
120  "MOV r3, lr \n"
121  "MOV r0, r2 \n"
122  "TST r1, r3 \n"
123  "BEQ handler \n"
124  /* If SVC was made from thread mode, overwrite r0 with PSP */
125  "MRS r0, PSP \n"
126  "handler: \n"
127  "MOV r1, lr \n"
128  "BL tfm_core_svc_handler \n"
129  "BX r0 \n"
130  );
131 }
132 
134 {
135  uint32_t VECTKEY;
136  SCB_Type *scb = SCB;
137  uint32_t AIRCR;
138 
139  /* Set PRIS flag in AIRCR */
140  AIRCR = scb->AIRCR;
141  VECTKEY = (~AIRCR & SCB_AIRCR_VECTKEYSTAT_Msk);
142  scb->AIRCR = SCB_AIRCR_PRIS_Msk |
143  VECTKEY |
144  (AIRCR & ~SCB_AIRCR_VECTKEY_Msk);
145 
146  NVIC_SetPriority(SVCall_IRQn, 0);
147 #ifdef TFM_MULTI_CORE_TOPOLOGY
148  NVIC_SetPriority(PendSV_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
149 #else
150  /*
151  * Set secure PendSV priority to the lowest in SECURE state.
152  *
153  * IMPORTANT NOTE:
154  *
155  * Although the priority of the secure PendSV must be the lowest possible
156  * among other interrupts in the Secure state, it must be ensured that
157  * PendSV is not preempted nor masked by Non-Secure interrupts to ensure
158  * the integrity of the Secure operation.
159  * When AIRCR.PRIS is set, the Non-Secure execution can act on
160  * FAULTMASK_NS, PRIMASK_NS or BASEPRI_NS register to boost its priority
161  * number up to the value 0x80.
162  * For this reason, set the priority of the PendSV interrupt to the next
163  * priority level configurable on the platform, just below 0x80.
164  */
165  NVIC_SetPriority(PendSV_IRQn, (1 << (__NVIC_PRIO_BITS - 1)) - 1);
166 #endif
167 }
168 
169 /* There are no coprocessors in Armv8-M Baseline implementations */
171 {
172 }
173 
174 /* There is no FPCA in baseline. */
176 {
177 }
void HardFault_Handler(void)
Overwrites default Hard fault handler.
void tfm_arch_configure_coprocessors(void)
Configure coprocessors.
void PendSV_Handler(void)
void tfm_arch_init_actx(struct tfm_arch_ctx_t *p_actx, uint32_t sp, uint32_t sp_limit)
void tfm_arch_set_secure_exception_priorities(void)
#define EXC_RETURN_THREAD_S_PSP
void tfm_arch_clear_fp_status(void)
uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t lr, uint32_t *msp)
void SVC_Handler(void)