blob: a532a51d545ec031f9c36cddc30c685077297036 [file] [log] [blame]
David Hu50711e32019-06-12 18:32:30 +08001/*
Antonio de Angelis00667fc2021-05-05 22:40:39 +01002 * Copyright (c) 2018-2021, 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_V8M_H__
8#define __TFM_ARCH_V8M_H__
9
10#include <stdint.h>
11#include <stdbool.h>
12
13#include "cmsis_compiler.h"
Ken Liu05e13ba2020-07-25 10:31:33 +080014#include "tfm_core_trustzone.h"
15#include "utilities.h"
David Hu50711e32019-06-12 18:32:30 +080016
Summer Qind2ad7e72020-01-06 18:16:35 +080017#define EXC_RETURN_INDICATOR (0xFF << 24)
18#define EXC_RETURN_RES1 (0x1FFFF << 7)
David Hu50711e32019-06-12 18:32:30 +080019#define EXC_RETURN_SECURE_STACK (1 << 6)
Summer Qind2ad7e72020-01-06 18:16:35 +080020#define EXC_RETURN_STACK_RULE (1 << 5)
David Hu50711e32019-06-12 18:32:30 +080021#define EXC_RETURN_FPU_FRAME_BASIC (1 << 4)
22#define EXC_RETURN_MODE_THREAD (1 << 3)
23#define EXC_RETURN_STACK_PROCESS (1 << 2)
Antonio de Angelisa4f23f82021-05-05 22:40:39 +010024#define EXC_RETURN_STACK_MAIN (0 << 2)
Summer Qind2ad7e72020-01-06 18:16:35 +080025#define EXC_RETURN_RES0 (0 << 1)
David Hu50711e32019-06-12 18:32:30 +080026#define EXC_RETURN_EXC_SECURE (1)
27
28/* Initial EXC_RETURN value in LR when a thread is loaded at the first time */
Summer Qind2ad7e72020-01-06 18:16:35 +080029#define EXC_RETURN_THREAD_S_PSP \
30 EXC_RETURN_INDICATOR | EXC_RETURN_RES1 | \
31 EXC_RETURN_SECURE_STACK | EXC_RETURN_STACK_RULE | \
32 EXC_RETURN_FPU_FRAME_BASIC | EXC_RETURN_MODE_THREAD | \
33 EXC_RETURN_STACK_PROCESS | EXC_RETURN_RES0 | \
34 EXC_RETURN_EXC_SECURE
David Hu50711e32019-06-12 18:32:30 +080035
Antonio de Angelisa4f23f82021-05-05 22:40:39 +010036#define EXC_RETURN_THREAD_S_MSP \
37 EXC_RETURN_INDICATOR | EXC_RETURN_RES1 | \
38 EXC_RETURN_SECURE_STACK | EXC_RETURN_STACK_RULE | \
39 EXC_RETURN_FPU_FRAME_BASIC | EXC_RETURN_MODE_THREAD | \
40 EXC_RETURN_STACK_MAIN | EXC_RETURN_RES0 | \
41 EXC_RETURN_EXC_SECURE
42
Mingyang Sun22a3faf2021-07-09 15:32:47 +080043/* Exception numbers */
44#define EXC_NUM_THREAD_MODE (0)
45#define EXC_NUM_SVCALL (11)
46#define EXC_NUM_PENDSV (14)
47
Kevin Peng300c68d2021-08-12 17:40:17 +080048#define VTOR_BASE (0xE000ED08)
49
Ronald Cron312be682019-09-23 09:27:33 +020050#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
Summer Qind2ad7e72020-01-06 18:16:35 +080051struct tfm_arch_ctx_t {
David Hu50711e32019-06-12 18:32:30 +080052 uint32_t r4;
53 uint32_t r5;
54 uint32_t r6;
55 uint32_t r7;
56 uint32_t r8;
57 uint32_t r9;
58 uint32_t r10;
59 uint32_t r11;
60 uint32_t sp;
61 uint32_t sp_limit;
62 uint32_t dummy;
63 uint32_t lr;
64};
65#elif defined(__ARM_ARCH_8M_BASE__)
Summer Qind2ad7e72020-01-06 18:16:35 +080066struct tfm_arch_ctx_t {
David Hu50711e32019-06-12 18:32:30 +080067 uint32_t r8;
68 uint32_t r9;
69 uint32_t r10;
70 uint32_t r11;
71 uint32_t r4;
72 uint32_t r5;
73 uint32_t r6;
74 uint32_t r7;
75 uint32_t sp;
76 uint32_t sp_limit;
77 uint32_t dummy;
78 uint32_t lr;
79};
80#endif
81
82/* Disable NS exceptions by setting NS PRIMASK to 1 */
83#define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1)
84/* Enable NS exceptions by setting NS PRIMASK to 0 */
85#define TFM_NS_EXC_ENABLE() __TZ_set_PRIMASK_NS(0)
86
David Hu141fe8d2019-06-24 13:24:00 +080087/**
88 * \brief Check whether Secure or Non-secure stack is used to restore stack
89 * frame on exception return.
90 *
91 * \param[in] lr LR register containing the EXC_RETURN value.
92 *
93 * \retval true Secure stack is used to restore stack frame on
94 * exception return.
95 * \retval false Non-secure stack is used to restore stack frame on
96 * exception return.
97 */
98__STATIC_INLINE bool is_return_secure_stack(uint32_t lr)
99{
100 return (lr & EXC_RETURN_SECURE_STACK);
101}
102
David Hue05b6a62019-06-12 18:45:28 +0800103/**
David Hub8dada52019-07-02 18:08:23 +0800104 * \brief Check whether the stack frame for this exception has space allocated
105 * for Floating Point(FP) state information.
106 *
107 * \param[in] lr LR register containing the EXC_RETURN value.
108 *
109 * \retval true The stack allocates space for FP information
110 * \retval false The stack doesn't allocate space for FP information
111 */
112__STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
113{
114 return (lr & EXC_RETURN_FPU_FRAME_BASIC) ? false : true;
115}
116
117/**
David Hue05b6a62019-06-12 18:45:28 +0800118 * \brief Set PSPLIM register.
119 *
120 * \param[in] psplim Register value to be written into PSPLIM.
121 */
122__STATIC_INLINE void tfm_arch_set_psplim(uint32_t psplim)
123{
David Huf363fe92019-07-02 13:03:30 +0800124 __set_PSPLIM(psplim);
125}
126
127/**
Kevin Peng300c68d2021-08-12 17:40:17 +0800128 * \brief Set MSP limit value.
129 *
130 * \param[in] msplim MSP limit value to be written.
131 */
132__STATIC_INLINE void tfm_arch_set_msplim(uint32_t msplim)
133{
134 __set_MSPLIM(msplim);
135}
136
137/**
Ken Liuc0b5f6d2020-07-25 12:05:50 +0800138 * \brief Seal the thread stack.
139 *
140 * This function must be called only when the caller is using MSP.
141 *
142 * \param[in] stk Thread stack address.
143 *
144 * \retval stack Updated thread stack address.
145 */
146__STATIC_INLINE uintptr_t tfm_arch_seal_thread_stack(uintptr_t stk)
147{
148 TFM_CORE_ASSERT((stk & 0x7) == 0);
149 stk -= TFM_STACK_SEALED_SIZE;
150
151 *((uint32_t *)stk) = TFM_STACK_SEAL_VALUE;
152 *((uint32_t *)(stk + 4)) = TFM_STACK_SEAL_VALUE;
153
154 return stk;
155}
156
157/**
Kevin Peng814df012021-05-17 15:17:23 +0800158 * \brief Get architecture context value into context struct
Ken Liu490281d2019-12-30 15:55:26 +0800159 *
Summer Qind2ad7e72020-01-06 18:16:35 +0800160 * \param[in] p_actx Pointer of context data
Ken Liu490281d2019-12-30 15:55:26 +0800161 */
Kevin Peng814df012021-05-17 15:17:23 +0800162__STATIC_INLINE void tfm_arch_get_ctx(struct tfm_arch_ctx_t *p_actx)
163{
164 p_actx->sp = __get_PSP();
165 p_actx->sp_limit = __get_PSPLIM();
166}
167
168/**
169 * \brief Set architecture context value into hardware
170 *
171 * \param[in] p_actx Pointer of context data
172 */
173__STATIC_INLINE void tfm_arch_set_ctx(struct tfm_arch_ctx_t *p_actx)
Ken Liu490281d2019-12-30 15:55:26 +0800174{
Summer Qind2ad7e72020-01-06 18:16:35 +0800175 __set_PSP(p_actx->sp);
176 __set_PSPLIM(p_actx->sp_limit);
Ken Liu490281d2019-12-30 15:55:26 +0800177}
178
179/**
Ken Liu05e13ba2020-07-25 10:31:33 +0800180 * \brief Set MSPLIM register and seal the MSP.
181 *
182 * This function assumes that the caller is using PSP when calling this
183 * function.
David Huf363fe92019-07-02 13:03:30 +0800184 *
185 * \param[in] msplim Register value to be written into MSPLIM.
186 */
Ken Liu05e13ba2020-07-25 10:31:33 +0800187__STATIC_INLINE void tfm_arch_init_secure_msp(uint32_t msplim)
David Huf363fe92019-07-02 13:03:30 +0800188{
Ken Liu05e13ba2020-07-25 10:31:33 +0800189 uint32_t mstk_adr = __get_MSP();
190
191 /*
192 * Seal the main stack and update MSP to point below the stack seal.
193 * Set MSPLIM. As the initial 'main()' code is running under privileged PSP
194 * manipulating MSP works here.
195 */
196 TFM_CORE_ASSERT((mstk_adr & 0x7) == 0);
197 mstk_adr -= TFM_STACK_SEALED_SIZE;
198
199 *((uint32_t *)mstk_adr) = TFM_STACK_SEAL_VALUE;
200 *((uint32_t *)(mstk_adr + 4)) = TFM_STACK_SEAL_VALUE;
201
202 __set_MSP(mstk_adr);
David Huf363fe92019-07-02 13:03:30 +0800203 __set_MSPLIM(msplim);
David Hue05b6a62019-06-12 18:45:28 +0800204}
205
David Hu50711e32019-06-12 18:32:30 +0800206#endif