blob: 5bf14fa9c254cba08490d74277e6e0716faff4da [file] [log] [blame]
David Hu50711e32019-06-12 18:32:30 +08001/*
Ken Liu5385ad12023-01-04 12:37:28 +08002 * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
Chris Brandbe5bec12022-10-18 11:41:59 -07003 * Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon
4 * company) or an affiliate of Cypress Semiconductor Corporation. All rights
5 * reserved.
David Hu50711e32019-06-12 18:32:30 +08006 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10#ifndef __TFM_ARCH_H__
11#define __TFM_ARCH_H__
12
13/* This header file collects the architecture related operations. */
14
Ken Liu1d96c132019-12-31 15:51:30 +080015#include <stddef.h>
David Hu50711e32019-06-12 18:32:30 +080016#include <inttypes.h>
Michel Jaouenaf0e98d2022-11-01 10:08:20 +010017#include "fih.h"
Kevin Pengbc5e5aa2019-10-16 10:55:17 +080018#include "tfm_hal_device_header.h"
David Hu50711e32019-06-12 18:32:30 +080019#include "cmsis_compiler.h"
20
Ronald Cron312be682019-09-23 09:27:33 +020021#if defined(__ARM_ARCH_8_1M_MAIN__) || \
22 defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
David Hu50711e32019-06-12 18:32:30 +080023#include "tfm_arch_v8m.h"
David Hu40455c92019-07-02 14:31:34 +080024#elif defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7M__) || \
25 defined(__ARM_ARCH_7EM__)
26#include "tfm_arch_v6m_v7m.h"
David Hu50711e32019-06-12 18:32:30 +080027#else
28#error "Unsupported ARM Architecture."
29#endif
30
Jianliang Shen12597922023-05-24 17:02:00 +080031#define SCHEDULER_ATTEMPTED 2 /* Schedule attempt when scheduler is locked. */
Mingyang Sun620c8562021-11-10 11:44:58 +080032#define SCHEDULER_LOCKED 1
33#define SCHEDULER_UNLOCKED 0
34
David Hu50711e32019-06-12 18:32:30 +080035#define XPSR_T32 0x01000000
36
Michel Jaouenaf0e98d2022-11-01 10:08:20 +010037/* Define IRQ level */
38#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
39#define SecureFault_IRQnLVL (0)
40#define MemoryManagement_IRQnLVL (0)
41#define BusFault_IRQnLVL (0)
42#define SVCall_IRQnLVL (0)
43#elif defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
44#define MemoryManagement_IRQnLVL (0)
45#define BusFault_IRQnLVL (0)
46#define SVCall_IRQnLVL (0)
47#elif defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__)
48#define SVCall_IRQnLVL (0)
49#else
50#error "Unsupported ARM Architecture."
51#endif
52
53
Chris Brandbe5bec12022-10-18 11:41:59 -070054/* The lowest secure interrupt priority */
55#ifdef CONFIG_TFM_USE_TRUSTZONE
56/* IMPORTANT NOTE:
57 *
58 * Although the priority of the secure PendSV must be the lowest possible
59 * among other interrupts in the Secure state, it must be ensured that
60 * PendSV is not preempted nor masked by Non-Secure interrupts to ensure
61 * the integrity of the Secure operation.
62 * When AIRCR.PRIS is set, the Non-Secure execution can act on
63 * FAULTMASK_NS, PRIMASK_NS or BASEPRI_NS register to boost its priority
64 * number up to the value 0x80.
65 * For this reason, set the priority of the PendSV interrupt to the next
66 * priority level configurable on the platform, just below 0x80.
67 */
68#define PENDSV_PRIO_FOR_SCHED ((1 << (__NVIC_PRIO_BITS - 1)) - 1)
69#else
70/* If TZ is not in use, we have the full priority range available */
71#define PENDSV_PRIO_FOR_SCHED ((1 << __NVIC_PRIO_BITS) - 1)
72#endif
73
Ken Liu5d73c872021-08-19 19:23:17 +080074/* State context defined by architecture */
Ken Liu5a2b9052019-08-15 19:03:29 +080075struct tfm_state_context_t {
David Hu50711e32019-06-12 18:32:30 +080076 uint32_t r0;
77 uint32_t r1;
78 uint32_t r2;
79 uint32_t r3;
80 uint32_t r12;
Ken Liu5a2b9052019-08-15 19:03:29 +080081 uint32_t lr;
David Hu50711e32019-06-12 18:32:30 +080082 uint32_t ra;
83 uint32_t xpsr;
Ken Liu5d73c872021-08-19 19:23:17 +080084};
David Hu50711e32019-06-12 18:32:30 +080085
Ken Liu5d73c872021-08-19 19:23:17 +080086/* Context addition to state context */
87struct tfm_additional_context_t {
Ken Liu5385ad12023-01-04 12:37:28 +080088 uint32_t integ_sign; /* Integrity signature */
89 uint32_t reserved; /* Reserved */
Ken Liu5d73c872021-08-19 19:23:17 +080090 uint32_t callee[8]; /* R4-R11. NOT ORDERED!! */
91};
92
93/* Full thread context */
94struct full_context_t {
95 struct tfm_additional_context_t addi_ctx;
96 struct tfm_state_context_t stat_ctx;
97};
98
Ken Liuca4580f2022-03-09 21:27:43 +080099/*
100 * Under cross call ABI, SPM can be preempted by interrupts, the interrupt
101 * handling can set SPM API return value and makes the initial SPM API
102 * return code invalid. Use one flag to indicate if the return code has been
103 * force updated by interrupts, then SPM return code can be discarded as it
104 * is out of date.
105 */
106#define CROSS_RETCODE_EMPTY 0xEEEEEEED
107#define CROSS_RETCODE_UPDATED 0xEEEEEEEE
108
Sherry Zhangb24f54d2022-07-04 14:26:07 +0800109/* Context control.
110 * CAUTION: Assembly references this structure. DO CHECK the below functions
111 * before changing the structure:
112 'PendSV_Handler'
113 */
Ken Liu5d73c872021-08-19 19:23:17 +0800114struct context_ctrl_t {
Sherry Zhangb24f54d2022-07-04 14:26:07 +0800115 uint32_t sp; /* Stack pointer (higher address).
116 * THIS MUST BE THE FIRST MEMBER OF
117 * THE STRUCT.
118 */
119 uint32_t exc_ret; /* EXC_RETURN pattern.
120 * THIS MUST BE THE SECOND MEMBER OF
121 * THE STRUCT.
122 */
Ken Liuca4580f2022-03-09 21:27:43 +0800123 uint32_t sp_limit; /* Stack limit (lower address) */
Ken Liu63a176b2022-06-09 22:36:56 +0800124 uint32_t sp_base; /* Stack usage start (higher addr) */
Ken Liuca4580f2022-03-09 21:27:43 +0800125 uint32_t cross_frame; /* Cross call frame position. */
126 uint32_t retcode_status; /* Cross call retcode status. */
Ken Liu5d73c872021-08-19 19:23:17 +0800127};
128
129/*
130 * The context on MSP when de-privileged FLIH Function calls SVC to return.
131 * It is the same when de-privileged FLIH Function is ready to run.
132 */
133struct context_flih_ret_t {
134 uint64_t stack_seal; /* Two words stack seal */
135 struct tfm_additional_context_t addi_ctx;
Ken Liu5d73c872021-08-19 19:23:17 +0800136 uint32_t psp; /* PSP when interrupt exception ocurrs */
Kevin Pengca59ec02021-12-09 14:35:50 +0800137 uint32_t psplim; /* PSPLIM when interrupt exception ocurrs when */
Ken Liu5d73c872021-08-19 19:23:17 +0800138 struct tfm_state_context_t state_ctx; /* ctx on SVC_PREPARE_DEPRIV_FLIH */
139};
David Hu50711e32019-06-12 18:32:30 +0800140
Ken Liuca4580f2022-03-09 21:27:43 +0800141/* A customized ABI format. */
142struct cross_call_abi_frame_t {
143 uint32_t a0;
144 uint32_t a1;
145 uint32_t a2;
146 uint32_t a3;
147 uint32_t unused0;
148 uint32_t unused1;
149};
150
Ken Liubf4681f2022-02-11 11:15:03 +0800151/* Assign stack and stack limit to the context control instance. */
Ken Liu63a176b2022-06-09 22:36:56 +0800152#define ARCH_CTXCTRL_INIT(x, buf, sz) do { \
153 (x)->sp = ((uint32_t)(buf) + (uint32_t)(sz)) & ~0x7; \
154 (x)->sp_limit = ((uint32_t)(buf) + 7) & ~0x7; \
155 (x)->sp_base = (x)->sp; \
156 (x)->exc_ret = 0; \
157 (x)->cross_frame = 0; \
158 (x)->retcode_status = CROSS_RETCODE_EMPTY; \
Ken Liubf4681f2022-02-11 11:15:03 +0800159 } while (0)
160
161/* Allocate 'size' bytes in stack. */
Ken Liu63a176b2022-06-09 22:36:56 +0800162#define ARCH_CTXCTRL_ALLOCATE_STACK(x, size) \
163 ((x)->sp -= ((size) + 7) & ~0x7)
Ken Liubf4681f2022-02-11 11:15:03 +0800164
Ken Liu63a176b2022-06-09 22:36:56 +0800165/* The last allocated pointer. */
Ken Liubf4681f2022-02-11 11:15:03 +0800166#define ARCH_CTXCTRL_ALLOCATED_PTR(x) ((x)->sp)
167
168/* Prepare a exception return pattern on the stack. */
169#define ARCH_CTXCTRL_EXCRET_PATTERN(x, param, pfn, pfnlr) do { \
170 (x)->r0 = (uint32_t)(param); \
171 (x)->ra = (uint32_t)(pfn); \
172 (x)->lr = (uint32_t)(pfnlr); \
173 (x)->xpsr = XPSR_T32; \
174 } while (0)
175
Ken Liu63a176b2022-06-09 22:36:56 +0800176/*
177 * Claim a statically initialized context control instance.
178 * Make the start stack pointer at 'stack_buf[stack_size]' because
179 * the hardware acts in a 'Decrease-then-store' behaviour.
180 */
181#define ARCH_CLAIM_CTXCTRL_INSTANCE(name, stack_buf, stack_size) \
182 struct context_ctrl_t name = { \
183 .sp = (uint32_t)&stack_buf[stack_size], \
184 .sp_base = (uint32_t)&stack_buf[stack_size], \
185 .sp_limit = (uint32_t)stack_buf, \
186 .exc_ret = 0, \
187 }
188
David Hu50711e32019-06-12 18:32:30 +0800189/**
190 * \brief Get Link Register
191 * \details Returns the value of the Link Register (LR)
192 * \return LR value
193 */
TTornblomdd233d12020-11-05 11:44:28 +0100194#if !defined ( __ICCARM__ )
David Hu50711e32019-06-12 18:32:30 +0800195__attribute__ ((always_inline)) __STATIC_INLINE uint32_t __get_LR(void)
196{
197 register uint32_t result;
198
199 __ASM volatile ("MOV %0, LR\n" : "=r" (result));
200 return result;
201}
TTornblomdd233d12020-11-05 11:44:28 +0100202#endif
David Hu50711e32019-06-12 18:32:30 +0800203
Ken Liu92ede9f2021-10-20 09:35:00 +0800204__STATIC_INLINE uint32_t __save_disable_irq(void)
205{
206 uint32_t result;
207
208 __ASM volatile ("mrs %0, primask \n cpsid i" : "=r" (result) :: "memory");
209 return result;
210}
211
212__STATIC_INLINE void __restore_irq(uint32_t status)
213{
214 __ASM volatile ("msr primask, %0" :: "r" (status) : "memory");
215}
216
David Hu50711e32019-06-12 18:32:30 +0800217__attribute__ ((always_inline))
218__STATIC_INLINE uint32_t __get_active_exc_num(void)
219{
220 IPSR_Type IPSR;
221
222 /* if non-zero, exception is active. NOT banked S/NS */
223 IPSR.w = __get_IPSR();
224 return IPSR.b.ISR;
225}
226
227__attribute__ ((always_inline))
228__STATIC_INLINE void __set_CONTROL_SPSEL(uint32_t SPSEL)
229{
230 CONTROL_Type ctrl;
231
232 ctrl.w = __get_CONTROL();
233 ctrl.b.SPSEL = SPSEL;
234 __set_CONTROL(ctrl.w);
235 __ISB();
236}
237
Antonio de Angelis995e4a62022-10-19 15:46:42 +0100238
239/**
240 * \brief Whether in privileged level
241 *
242 * \retval true If current execution runs in privileged level.
243 * \retval false If current execution runs in unprivileged level.
244 */
245__STATIC_INLINE bool tfm_arch_is_priv(void)
246{
247 CONTROL_Type ctrl;
248
249 /* If in Handler mode */
250 if (__get_IPSR()) {
251 return true;
252 }
253
254 /* If in privileged Thread mode */
255 ctrl.w = __get_CONTROL();
256 if (!ctrl.b.nPRIV) {
257 return true;
258 }
259
260 return false;
261}
262
Gabor Toth4d414112021-11-10 17:44:50 +0100263#if (CONFIG_TFM_FLOAT_ABI >= 1) && CONFIG_TFM_LAZY_STACKING
Andrej Butok93ba5ca2023-05-04 16:36:49 +0200264#define ARCH_FLUSH_FP_CONTEXT() __asm volatile("vmov.f32 s0, s0 \n":::"memory")
Feder Liang42f5b562021-09-10 17:38:36 +0800265#else
266#define ARCH_FLUSH_FP_CONTEXT()
267#endif
268
Ken Liu5d73c872021-08-19 19:23:17 +0800269/* Set secure exceptions priority. */
Ken Liu50e21092020-10-14 16:42:15 +0800270void tfm_arch_set_secure_exception_priorities(void);
Jamie Fox3ede9712020-09-28 23:14:54 +0100271
Michel Jaouenaf0e98d2022-11-01 10:08:20 +0100272#ifdef TFM_FIH_PROFILE_ON
273/* Check secure exception priority */
274FIH_RET_TYPE(int32_t) tfm_arch_verify_secure_exception_priorities(void);
275#endif
276
Ken Liu5d73c872021-08-19 19:23:17 +0800277/* Configure various extensions. */
Summer Qindea1f2c2021-01-11 14:46:34 +0800278void tfm_arch_config_extensions(void);
Jamie Fox45587672020-08-17 18:31:14 +0100279
Gabor Toth4d414112021-11-10 17:44:50 +0100280#if (CONFIG_TFM_FLOAT_ABI > 0)
Ken Liu182fb402022-06-20 16:05:47 +0800281/* Clear float point data. */
Feder Liang42f5b562021-09-10 17:38:36 +0800282void tfm_arch_clear_fp_data(void);
283#endif
284
Kevin Peng300c68d2021-08-12 17:40:17 +0800285/*
286 * This function is called after SPM has initialized.
287 * It frees the stack used by SPM initialization and do Exception Return.
288 * It does not return.
289 */
Ken Liudedbf4b2021-11-02 09:07:25 +0800290void tfm_arch_free_msp_and_exc_ret(uint32_t msp_base, uint32_t exc_return);
Kevin Peng300c68d2021-08-12 17:40:17 +0800291
Ken Liu5d73c872021-08-19 19:23:17 +0800292/*
293 * This function sets return value on APIs that cause scheduling, for example
294 * psa_wait(), by manipulating the control context - this is usaully setting the
295 * R0 register of the thread context.
296 */
Ken Liuca4580f2022-03-09 21:27:43 +0800297void tfm_arch_set_context_ret_code(void *p_ctx_ctrl, uint32_t ret_code);
Ken Liu5d73c872021-08-19 19:23:17 +0800298
299/* Init a thread context on thread stack and update the control context. */
300void tfm_arch_init_context(void *p_ctx_ctrl,
Ken Liubf4681f2022-02-11 11:15:03 +0800301 uintptr_t pfn, void *param, uintptr_t pfnlr);
Ken Liu5d73c872021-08-19 19:23:17 +0800302
303/*
304 * Refresh the HW (sp, splimit) according to the given control context and
305 * returns the EXC_RETURN payload (caller might need it for following codes).
306 *
Ken Liubf4681f2022-02-11 11:15:03 +0800307 * The p_ctx_ctrl must have been initialized by 'tfm_arch_init_context'.
Ken Liu5d73c872021-08-19 19:23:17 +0800308 */
309uint32_t tfm_arch_refresh_hardware_context(void *p_ctx_ctrl);
310
Ken Liue07c3b72021-10-14 16:19:13 +0800311/*
Jianliang Shen12597922023-05-24 17:02:00 +0800312 * Release the scheduler lock and return if there are scheduling attempts during
313 * locked period. The recorded attempts are cleared after this function so do
314 * not call it a second time after unlock to query attempt status.
315 *
316 * return value:
317 * SCHEDULER_ATTEMPTED: unlocked successfully but there are recorded attempts
318 * or function get called without locked.
319 * other values: unlocked successfully without attempts detected.
320 */
321uint32_t arch_release_sched_lock(void);
322
323/*
324 * Start scheduling if scheduler is not locked, or the attempt is recorded and
325 * return without starting the scheduler.
Ken Liue07c3b72021-10-14 16:19:13 +0800326 */
327uint32_t tfm_arch_trigger_pendsv(void);
328
Ken Liue07c3b72021-10-14 16:19:13 +0800329/*
330 * Switch to a new stack area, lock scheduler and call function.
331 * If 'stk_base' is ZERO, stack won't be switched and re-use caller stack.
332 */
Ken Liuca4580f2022-03-09 21:27:43 +0800333void arch_non_preempt_call(uintptr_t fn_addr, uintptr_t frame_addr,
334 uint32_t stk_base, uint32_t stk_limit);
Ken Liue07c3b72021-10-14 16:19:13 +0800335
David Hu50711e32019-06-12 18:32:30 +0800336#endif