blob: e615c3ce45a7ab52887b4d17de7f6f9de39b35c0 [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
Ronald Cron312be682019-09-23 09:27:33 +020048#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
Summer Qind2ad7e72020-01-06 18:16:35 +080049struct tfm_arch_ctx_t {
David Hu50711e32019-06-12 18:32:30 +080050 uint32_t r4;
51 uint32_t r5;
52 uint32_t r6;
53 uint32_t r7;
54 uint32_t r8;
55 uint32_t r9;
56 uint32_t r10;
57 uint32_t r11;
58 uint32_t sp;
59 uint32_t sp_limit;
60 uint32_t dummy;
61 uint32_t lr;
62};
63#elif defined(__ARM_ARCH_8M_BASE__)
Summer Qind2ad7e72020-01-06 18:16:35 +080064struct tfm_arch_ctx_t {
David Hu50711e32019-06-12 18:32:30 +080065 uint32_t r8;
66 uint32_t r9;
67 uint32_t r10;
68 uint32_t r11;
69 uint32_t r4;
70 uint32_t r5;
71 uint32_t r6;
72 uint32_t r7;
73 uint32_t sp;
74 uint32_t sp_limit;
75 uint32_t dummy;
76 uint32_t lr;
77};
78#endif
79
80/* Disable NS exceptions by setting NS PRIMASK to 1 */
81#define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1)
82/* Enable NS exceptions by setting NS PRIMASK to 0 */
83#define TFM_NS_EXC_ENABLE() __TZ_set_PRIMASK_NS(0)
84
David Hu141fe8d2019-06-24 13:24:00 +080085/**
86 * \brief Check whether Secure or Non-secure stack is used to restore stack
87 * frame on exception return.
88 *
89 * \param[in] lr LR register containing the EXC_RETURN value.
90 *
91 * \retval true Secure stack is used to restore stack frame on
92 * exception return.
93 * \retval false Non-secure stack is used to restore stack frame on
94 * exception return.
95 */
96__STATIC_INLINE bool is_return_secure_stack(uint32_t lr)
97{
98 return (lr & EXC_RETURN_SECURE_STACK);
99}
100
David Hue05b6a62019-06-12 18:45:28 +0800101/**
David Hub8dada52019-07-02 18:08:23 +0800102 * \brief Check whether the stack frame for this exception has space allocated
103 * for Floating Point(FP) state information.
104 *
105 * \param[in] lr LR register containing the EXC_RETURN value.
106 *
107 * \retval true The stack allocates space for FP information
108 * \retval false The stack doesn't allocate space for FP information
109 */
110__STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
111{
112 return (lr & EXC_RETURN_FPU_FRAME_BASIC) ? false : true;
113}
114
115/**
David Hue05b6a62019-06-12 18:45:28 +0800116 * \brief Set PSPLIM register.
117 *
118 * \param[in] psplim Register value to be written into PSPLIM.
119 */
120__STATIC_INLINE void tfm_arch_set_psplim(uint32_t psplim)
121{
David Huf363fe92019-07-02 13:03:30 +0800122 __set_PSPLIM(psplim);
123}
124
125/**
Ken Liuc0b5f6d2020-07-25 12:05:50 +0800126 * \brief Seal the thread stack.
127 *
128 * This function must be called only when the caller is using MSP.
129 *
130 * \param[in] stk Thread stack address.
131 *
132 * \retval stack Updated thread stack address.
133 */
134__STATIC_INLINE uintptr_t tfm_arch_seal_thread_stack(uintptr_t stk)
135{
136 TFM_CORE_ASSERT((stk & 0x7) == 0);
137 stk -= TFM_STACK_SEALED_SIZE;
138
139 *((uint32_t *)stk) = TFM_STACK_SEAL_VALUE;
140 *((uint32_t *)(stk + 4)) = TFM_STACK_SEAL_VALUE;
141
142 return stk;
143}
144
145/**
Kevin Peng814df012021-05-17 15:17:23 +0800146 * \brief Get architecture context value into context struct
Ken Liu490281d2019-12-30 15:55:26 +0800147 *
Summer Qind2ad7e72020-01-06 18:16:35 +0800148 * \param[in] p_actx Pointer of context data
Ken Liu490281d2019-12-30 15:55:26 +0800149 */
Kevin Peng814df012021-05-17 15:17:23 +0800150__STATIC_INLINE void tfm_arch_get_ctx(struct tfm_arch_ctx_t *p_actx)
151{
152 p_actx->sp = __get_PSP();
153 p_actx->sp_limit = __get_PSPLIM();
154}
155
156/**
157 * \brief Set architecture context value into hardware
158 *
159 * \param[in] p_actx Pointer of context data
160 */
161__STATIC_INLINE void tfm_arch_set_ctx(struct tfm_arch_ctx_t *p_actx)
Ken Liu490281d2019-12-30 15:55:26 +0800162{
Summer Qind2ad7e72020-01-06 18:16:35 +0800163 __set_PSP(p_actx->sp);
164 __set_PSPLIM(p_actx->sp_limit);
Ken Liu490281d2019-12-30 15:55:26 +0800165}
166
167/**
Ken Liu05e13ba2020-07-25 10:31:33 +0800168 * \brief Set MSPLIM register and seal the MSP.
169 *
170 * This function assumes that the caller is using PSP when calling this
171 * function.
David Huf363fe92019-07-02 13:03:30 +0800172 *
173 * \param[in] msplim Register value to be written into MSPLIM.
174 */
Ken Liu05e13ba2020-07-25 10:31:33 +0800175__STATIC_INLINE void tfm_arch_init_secure_msp(uint32_t msplim)
David Huf363fe92019-07-02 13:03:30 +0800176{
Ken Liu05e13ba2020-07-25 10:31:33 +0800177 uint32_t mstk_adr = __get_MSP();
178
179 /*
180 * Seal the main stack and update MSP to point below the stack seal.
181 * Set MSPLIM. As the initial 'main()' code is running under privileged PSP
182 * manipulating MSP works here.
183 */
184 TFM_CORE_ASSERT((mstk_adr & 0x7) == 0);
185 mstk_adr -= TFM_STACK_SEALED_SIZE;
186
187 *((uint32_t *)mstk_adr) = TFM_STACK_SEAL_VALUE;
188 *((uint32_t *)(mstk_adr + 4)) = TFM_STACK_SEAL_VALUE;
189
190 __set_MSP(mstk_adr);
David Huf363fe92019-07-02 13:03:30 +0800191 __set_MSPLIM(msplim);
David Hue05b6a62019-06-12 18:45:28 +0800192}
193
David Hu50711e32019-06-12 18:32:30 +0800194#endif