blob: 9f2e1a2298ed795d4a5c33945035d924b55a1746 [file] [log] [blame]
David Hu50711e32019-06-12 18:32:30 +08001/*
Feder Liang55194382021-11-22 16:45:33 +08002 * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
David Hu50711e32019-06-12 18:32:30 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7#ifndef __TFM_ARCH_H__
8#define __TFM_ARCH_H__
9
10/* This header file collects the architecture related operations. */
11
Ken Liu1d96c132019-12-31 15:51:30 +080012#include <stddef.h>
David Hu50711e32019-06-12 18:32:30 +080013#include <inttypes.h>
Kevin Pengbc5e5aa2019-10-16 10:55:17 +080014#include "tfm_hal_device_header.h"
David Hu50711e32019-06-12 18:32:30 +080015#include "cmsis_compiler.h"
16
Ronald Cron312be682019-09-23 09:27:33 +020017#if defined(__ARM_ARCH_8_1M_MAIN__) || \
18 defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
David Hu50711e32019-06-12 18:32:30 +080019#include "tfm_arch_v8m.h"
David Hu40455c92019-07-02 14:31:34 +080020#elif defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7M__) || \
21 defined(__ARM_ARCH_7EM__)
22#include "tfm_arch_v6m_v7m.h"
David Hu50711e32019-06-12 18:32:30 +080023#else
24#error "Unsupported ARM Architecture."
25#endif
26
Mingyang Sun620c8562021-11-10 11:44:58 +080027#define SCHEDULER_LOCKED 1
28#define SCHEDULER_UNLOCKED 0
29
David Hu50711e32019-06-12 18:32:30 +080030#define XPSR_T32 0x01000000
31
Ken Liu5d73c872021-08-19 19:23:17 +080032/* State context defined by architecture */
Ken Liu5a2b9052019-08-15 19:03:29 +080033struct tfm_state_context_t {
David Hu50711e32019-06-12 18:32:30 +080034 uint32_t r0;
35 uint32_t r1;
36 uint32_t r2;
37 uint32_t r3;
38 uint32_t r12;
Ken Liu5a2b9052019-08-15 19:03:29 +080039 uint32_t lr;
David Hu50711e32019-06-12 18:32:30 +080040 uint32_t ra;
41 uint32_t xpsr;
Ken Liu5d73c872021-08-19 19:23:17 +080042};
David Hu50711e32019-06-12 18:32:30 +080043
Ken Liu5d73c872021-08-19 19:23:17 +080044/* Context addition to state context */
45struct tfm_additional_context_t {
46 uint32_t callee[8]; /* R4-R11. NOT ORDERED!! */
47};
48
49/* Full thread context */
50struct full_context_t {
51 struct tfm_additional_context_t addi_ctx;
52 struct tfm_state_context_t stat_ctx;
53};
54
Ken Liuca4580f2022-03-09 21:27:43 +080055/*
56 * Under cross call ABI, SPM can be preempted by interrupts, the interrupt
57 * handling can set SPM API return value and makes the initial SPM API
58 * return code invalid. Use one flag to indicate if the return code has been
59 * force updated by interrupts, then SPM return code can be discarded as it
60 * is out of date.
61 */
62#define CROSS_RETCODE_EMPTY 0xEEEEEEED
63#define CROSS_RETCODE_UPDATED 0xEEEEEEEE
64
Ken Liu5d73c872021-08-19 19:23:17 +080065/* Context control */
66struct context_ctrl_t {
Ken Liuca4580f2022-03-09 21:27:43 +080067 uint32_t sp; /* Stack pointer (higher address) */
68 uint32_t sp_limit; /* Stack limit (lower address) */
Ken Liu63a176b2022-06-09 22:36:56 +080069 uint32_t sp_base; /* Stack usage start (higher addr) */
Ken Liuca4580f2022-03-09 21:27:43 +080070 uint32_t exc_ret; /* EXC_RETURN pattern. */
71 uint32_t cross_frame; /* Cross call frame position. */
72 uint32_t retcode_status; /* Cross call retcode status. */
Ken Liu5d73c872021-08-19 19:23:17 +080073};
74
75/*
76 * The context on MSP when de-privileged FLIH Function calls SVC to return.
77 * It is the same when de-privileged FLIH Function is ready to run.
78 */
79struct context_flih_ret_t {
80 uint64_t stack_seal; /* Two words stack seal */
81 struct tfm_additional_context_t addi_ctx;
Ken Liu5d73c872021-08-19 19:23:17 +080082 uint32_t psp; /* PSP when interrupt exception ocurrs */
Kevin Pengca59ec02021-12-09 14:35:50 +080083 uint32_t psplim; /* PSPLIM when interrupt exception ocurrs when */
Ken Liu5d73c872021-08-19 19:23:17 +080084 struct tfm_state_context_t state_ctx; /* ctx on SVC_PREPARE_DEPRIV_FLIH */
85};
David Hu50711e32019-06-12 18:32:30 +080086
Ken Liuca4580f2022-03-09 21:27:43 +080087/* A customized ABI format. */
88struct cross_call_abi_frame_t {
89 uint32_t a0;
90 uint32_t a1;
91 uint32_t a2;
92 uint32_t a3;
93 uint32_t unused0;
94 uint32_t unused1;
95};
96
Ken Liubf4681f2022-02-11 11:15:03 +080097/* Assign stack and stack limit to the context control instance. */
Ken Liu63a176b2022-06-09 22:36:56 +080098#define ARCH_CTXCTRL_INIT(x, buf, sz) do { \
99 (x)->sp = ((uint32_t)(buf) + (uint32_t)(sz)) & ~0x7; \
100 (x)->sp_limit = ((uint32_t)(buf) + 7) & ~0x7; \
101 (x)->sp_base = (x)->sp; \
102 (x)->exc_ret = 0; \
103 (x)->cross_frame = 0; \
104 (x)->retcode_status = CROSS_RETCODE_EMPTY; \
Ken Liubf4681f2022-02-11 11:15:03 +0800105 } while (0)
106
107/* Allocate 'size' bytes in stack. */
Ken Liu63a176b2022-06-09 22:36:56 +0800108#define ARCH_CTXCTRL_ALLOCATE_STACK(x, size) \
109 ((x)->sp -= ((size) + 7) & ~0x7)
Ken Liubf4681f2022-02-11 11:15:03 +0800110
Ken Liu63a176b2022-06-09 22:36:56 +0800111/* The last allocated pointer. */
Ken Liubf4681f2022-02-11 11:15:03 +0800112#define ARCH_CTXCTRL_ALLOCATED_PTR(x) ((x)->sp)
113
114/* Prepare a exception return pattern on the stack. */
115#define ARCH_CTXCTRL_EXCRET_PATTERN(x, param, pfn, pfnlr) do { \
116 (x)->r0 = (uint32_t)(param); \
117 (x)->ra = (uint32_t)(pfn); \
118 (x)->lr = (uint32_t)(pfnlr); \
119 (x)->xpsr = XPSR_T32; \
120 } while (0)
121
Ken Liu63a176b2022-06-09 22:36:56 +0800122/*
123 * Claim a statically initialized context control instance.
124 * Make the start stack pointer at 'stack_buf[stack_size]' because
125 * the hardware acts in a 'Decrease-then-store' behaviour.
126 */
127#define ARCH_CLAIM_CTXCTRL_INSTANCE(name, stack_buf, stack_size) \
128 struct context_ctrl_t name = { \
129 .sp = (uint32_t)&stack_buf[stack_size], \
130 .sp_base = (uint32_t)&stack_buf[stack_size], \
131 .sp_limit = (uint32_t)stack_buf, \
132 .exc_ret = 0, \
133 }
134
David Hu50711e32019-06-12 18:32:30 +0800135/**
136 * \brief Get Link Register
137 * \details Returns the value of the Link Register (LR)
138 * \return LR value
139 */
TTornblomdd233d12020-11-05 11:44:28 +0100140#if !defined ( __ICCARM__ )
David Hu50711e32019-06-12 18:32:30 +0800141__attribute__ ((always_inline)) __STATIC_INLINE uint32_t __get_LR(void)
142{
143 register uint32_t result;
144
145 __ASM volatile ("MOV %0, LR\n" : "=r" (result));
146 return result;
147}
TTornblomdd233d12020-11-05 11:44:28 +0100148#endif
David Hu50711e32019-06-12 18:32:30 +0800149
Ken Liu92ede9f2021-10-20 09:35:00 +0800150__STATIC_INLINE uint32_t __save_disable_irq(void)
151{
152 uint32_t result;
153
154 __ASM volatile ("mrs %0, primask \n cpsid i" : "=r" (result) :: "memory");
155 return result;
156}
157
158__STATIC_INLINE void __restore_irq(uint32_t status)
159{
160 __ASM volatile ("msr primask, %0" :: "r" (status) : "memory");
161}
162
David Hu50711e32019-06-12 18:32:30 +0800163__attribute__ ((always_inline))
164__STATIC_INLINE uint32_t __get_active_exc_num(void)
165{
166 IPSR_Type IPSR;
167
168 /* if non-zero, exception is active. NOT banked S/NS */
169 IPSR.w = __get_IPSR();
170 return IPSR.b.ISR;
171}
172
173__attribute__ ((always_inline))
174__STATIC_INLINE void __set_CONTROL_SPSEL(uint32_t SPSEL)
175{
176 CONTROL_Type ctrl;
177
178 ctrl.w = __get_CONTROL();
179 ctrl.b.SPSEL = SPSEL;
180 __set_CONTROL(ctrl.w);
181 __ISB();
182}
183
Feder Liang55194382021-11-22 16:45:33 +0800184#if (CONFIG_TFM_FP >= 1) && CONFIG_TFM_LAZY_STACKING
Feder Liang42f5b562021-09-10 17:38:36 +0800185#define ARCH_FLUSH_FP_CONTEXT() __asm volatile("vmov s0, s0 \n":::"memory")
186#else
187#define ARCH_FLUSH_FP_CONTEXT()
188#endif
189
Ken Liu5d73c872021-08-19 19:23:17 +0800190/* Set secure exceptions priority. */
Ken Liu50e21092020-10-14 16:42:15 +0800191void tfm_arch_set_secure_exception_priorities(void);
Jamie Fox3ede9712020-09-28 23:14:54 +0100192
Ken Liu5d73c872021-08-19 19:23:17 +0800193/* Configure various extensions. */
Summer Qindea1f2c2021-01-11 14:46:34 +0800194void tfm_arch_config_extensions(void);
Jamie Fox45587672020-08-17 18:31:14 +0100195
Ken Liu5d73c872021-08-19 19:23:17 +0800196/* Clear float point status. */
Ken Liuce2692d2020-02-11 12:39:36 +0800197void tfm_arch_clear_fp_status(void);
198
Feder Liang55194382021-11-22 16:45:33 +0800199#if (CONFIG_TFM_FP >= 1)
Feder Liang42f5b562021-09-10 17:38:36 +0800200/*
201 * Clear float point data.
202 */
203void tfm_arch_clear_fp_data(void);
204#endif
205
Kevin Peng300c68d2021-08-12 17:40:17 +0800206/*
207 * This function is called after SPM has initialized.
208 * It frees the stack used by SPM initialization and do Exception Return.
209 * It does not return.
210 */
Ken Liudedbf4b2021-11-02 09:07:25 +0800211void tfm_arch_free_msp_and_exc_ret(uint32_t msp_base, uint32_t exc_return);
Kevin Peng300c68d2021-08-12 17:40:17 +0800212
Ken Liu5d73c872021-08-19 19:23:17 +0800213/*
214 * This function sets return value on APIs that cause scheduling, for example
215 * psa_wait(), by manipulating the control context - this is usaully setting the
216 * R0 register of the thread context.
217 */
Ken Liuca4580f2022-03-09 21:27:43 +0800218void tfm_arch_set_context_ret_code(void *p_ctx_ctrl, uint32_t ret_code);
Ken Liu5d73c872021-08-19 19:23:17 +0800219
220/* Init a thread context on thread stack and update the control context. */
221void tfm_arch_init_context(void *p_ctx_ctrl,
Ken Liubf4681f2022-02-11 11:15:03 +0800222 uintptr_t pfn, void *param, uintptr_t pfnlr);
Ken Liu5d73c872021-08-19 19:23:17 +0800223
224/*
225 * Refresh the HW (sp, splimit) according to the given control context and
226 * returns the EXC_RETURN payload (caller might need it for following codes).
227 *
Ken Liubf4681f2022-02-11 11:15:03 +0800228 * The p_ctx_ctrl must have been initialized by 'tfm_arch_init_context'.
Ken Liu5d73c872021-08-19 19:23:17 +0800229 */
230uint32_t tfm_arch_refresh_hardware_context(void *p_ctx_ctrl);
231
Ken Liue07c3b72021-10-14 16:19:13 +0800232/*
233 * Triggers scheduler. A return type is assigned in case
234 * SPM returns values by the context.
235 */
236uint32_t tfm_arch_trigger_pendsv(void);
237
Ken Liue07c3b72021-10-14 16:19:13 +0800238/*
239 * Switch to a new stack area, lock scheduler and call function.
240 * If 'stk_base' is ZERO, stack won't be switched and re-use caller stack.
241 */
Ken Liuca4580f2022-03-09 21:27:43 +0800242void arch_non_preempt_call(uintptr_t fn_addr, uintptr_t frame_addr,
243 uint32_t stk_base, uint32_t stk_limit);
Ken Liue07c3b72021-10-14 16:19:13 +0800244
David Hu50711e32019-06-12 18:32:30 +0800245#endif