blob: 5fbc2b229d54269ba7f5cccb224a4d756c18e3c9 [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
Ronald Cron312be682019-09-23 09:27:33 +020043#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
Summer Qind2ad7e72020-01-06 18:16:35 +080044struct tfm_arch_ctx_t {
David Hu50711e32019-06-12 18:32:30 +080045 uint32_t r4;
46 uint32_t r5;
47 uint32_t r6;
48 uint32_t r7;
49 uint32_t r8;
50 uint32_t r9;
51 uint32_t r10;
52 uint32_t r11;
53 uint32_t sp;
54 uint32_t sp_limit;
55 uint32_t dummy;
56 uint32_t lr;
57};
58#elif defined(__ARM_ARCH_8M_BASE__)
Summer Qind2ad7e72020-01-06 18:16:35 +080059struct tfm_arch_ctx_t {
David Hu50711e32019-06-12 18:32:30 +080060 uint32_t r8;
61 uint32_t r9;
62 uint32_t r10;
63 uint32_t r11;
64 uint32_t r4;
65 uint32_t r5;
66 uint32_t r6;
67 uint32_t r7;
68 uint32_t sp;
69 uint32_t sp_limit;
70 uint32_t dummy;
71 uint32_t lr;
72};
73#endif
74
75/* Disable NS exceptions by setting NS PRIMASK to 1 */
76#define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1)
77/* Enable NS exceptions by setting NS PRIMASK to 0 */
78#define TFM_NS_EXC_ENABLE() __TZ_set_PRIMASK_NS(0)
79
David Hu141fe8d2019-06-24 13:24:00 +080080/**
81 * \brief Check whether Secure or Non-secure stack is used to restore stack
82 * frame on exception return.
83 *
84 * \param[in] lr LR register containing the EXC_RETURN value.
85 *
86 * \retval true Secure stack is used to restore stack frame on
87 * exception return.
88 * \retval false Non-secure stack is used to restore stack frame on
89 * exception return.
90 */
91__STATIC_INLINE bool is_return_secure_stack(uint32_t lr)
92{
93 return (lr & EXC_RETURN_SECURE_STACK);
94}
95
David Hue05b6a62019-06-12 18:45:28 +080096/**
David Hub8dada52019-07-02 18:08:23 +080097 * \brief Check whether the stack frame for this exception has space allocated
98 * for Floating Point(FP) state information.
99 *
100 * \param[in] lr LR register containing the EXC_RETURN value.
101 *
102 * \retval true The stack allocates space for FP information
103 * \retval false The stack doesn't allocate space for FP information
104 */
105__STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
106{
107 return (lr & EXC_RETURN_FPU_FRAME_BASIC) ? false : true;
108}
109
110/**
David Hue05b6a62019-06-12 18:45:28 +0800111 * \brief Set PSPLIM register.
112 *
113 * \param[in] psplim Register value to be written into PSPLIM.
114 */
115__STATIC_INLINE void tfm_arch_set_psplim(uint32_t psplim)
116{
David Huf363fe92019-07-02 13:03:30 +0800117 __set_PSPLIM(psplim);
118}
119
120/**
Ken Liuc0b5f6d2020-07-25 12:05:50 +0800121 * \brief Seal the thread stack.
122 *
123 * This function must be called only when the caller is using MSP.
124 *
125 * \param[in] stk Thread stack address.
126 *
127 * \retval stack Updated thread stack address.
128 */
129__STATIC_INLINE uintptr_t tfm_arch_seal_thread_stack(uintptr_t stk)
130{
131 TFM_CORE_ASSERT((stk & 0x7) == 0);
132 stk -= TFM_STACK_SEALED_SIZE;
133
134 *((uint32_t *)stk) = TFM_STACK_SEAL_VALUE;
135 *((uint32_t *)(stk + 4)) = TFM_STACK_SEAL_VALUE;
136
137 return stk;
138}
139
140/**
Kevin Peng814df012021-05-17 15:17:23 +0800141 * \brief Get architecture context value into context struct
Ken Liu490281d2019-12-30 15:55:26 +0800142 *
Summer Qind2ad7e72020-01-06 18:16:35 +0800143 * \param[in] p_actx Pointer of context data
Ken Liu490281d2019-12-30 15:55:26 +0800144 */
Kevin Peng814df012021-05-17 15:17:23 +0800145__STATIC_INLINE void tfm_arch_get_ctx(struct tfm_arch_ctx_t *p_actx)
146{
147 p_actx->sp = __get_PSP();
148 p_actx->sp_limit = __get_PSPLIM();
149}
150
151/**
152 * \brief Set architecture context value into hardware
153 *
154 * \param[in] p_actx Pointer of context data
155 */
156__STATIC_INLINE void tfm_arch_set_ctx(struct tfm_arch_ctx_t *p_actx)
Ken Liu490281d2019-12-30 15:55:26 +0800157{
Summer Qind2ad7e72020-01-06 18:16:35 +0800158 __set_PSP(p_actx->sp);
159 __set_PSPLIM(p_actx->sp_limit);
Ken Liu490281d2019-12-30 15:55:26 +0800160}
161
162/**
Ken Liu05e13ba2020-07-25 10:31:33 +0800163 * \brief Set MSPLIM register and seal the MSP.
164 *
165 * This function assumes that the caller is using PSP when calling this
166 * function.
David Huf363fe92019-07-02 13:03:30 +0800167 *
168 * \param[in] msplim Register value to be written into MSPLIM.
169 */
Ken Liu05e13ba2020-07-25 10:31:33 +0800170__STATIC_INLINE void tfm_arch_init_secure_msp(uint32_t msplim)
David Huf363fe92019-07-02 13:03:30 +0800171{
Ken Liu05e13ba2020-07-25 10:31:33 +0800172 uint32_t mstk_adr = __get_MSP();
173
174 /*
175 * Seal the main stack and update MSP to point below the stack seal.
176 * Set MSPLIM. As the initial 'main()' code is running under privileged PSP
177 * manipulating MSP works here.
178 */
179 TFM_CORE_ASSERT((mstk_adr & 0x7) == 0);
180 mstk_adr -= TFM_STACK_SEALED_SIZE;
181
182 *((uint32_t *)mstk_adr) = TFM_STACK_SEAL_VALUE;
183 *((uint32_t *)(mstk_adr + 4)) = TFM_STACK_SEAL_VALUE;
184
185 __set_MSP(mstk_adr);
David Huf363fe92019-07-02 13:03:30 +0800186 __set_MSPLIM(msplim);
David Hue05b6a62019-06-12 18:45:28 +0800187}
188
David Hu50711e32019-06-12 18:32:30 +0800189#endif