blob: 58576d3f7be7b123d110f2629da629dec302ae10 [file] [log] [blame]
David Hu50711e32019-06-12 18:32:30 +08001/*
Ronald Cron312be682019-09-23 09:27:33 +02002 * Copyright (c) 2018-2020, 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)
Summer Qind2ad7e72020-01-06 18:16:35 +080024#define EXC_RETURN_RES0 (0 << 1)
David Hu50711e32019-06-12 18:32:30 +080025#define EXC_RETURN_EXC_SECURE (1)
26
27/* Initial EXC_RETURN value in LR when a thread is loaded at the first time */
Summer Qind2ad7e72020-01-06 18:16:35 +080028#define EXC_RETURN_THREAD_S_PSP \
29 EXC_RETURN_INDICATOR | EXC_RETURN_RES1 | \
30 EXC_RETURN_SECURE_STACK | EXC_RETURN_STACK_RULE | \
31 EXC_RETURN_FPU_FRAME_BASIC | EXC_RETURN_MODE_THREAD | \
32 EXC_RETURN_STACK_PROCESS | EXC_RETURN_RES0 | \
33 EXC_RETURN_EXC_SECURE
David Hu50711e32019-06-12 18:32:30 +080034
Ronald Cron312be682019-09-23 09:27:33 +020035#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
Summer Qind2ad7e72020-01-06 18:16:35 +080036struct tfm_arch_ctx_t {
David Hu50711e32019-06-12 18:32:30 +080037 uint32_t r4;
38 uint32_t r5;
39 uint32_t r6;
40 uint32_t r7;
41 uint32_t r8;
42 uint32_t r9;
43 uint32_t r10;
44 uint32_t r11;
45 uint32_t sp;
46 uint32_t sp_limit;
47 uint32_t dummy;
48 uint32_t lr;
49};
50#elif defined(__ARM_ARCH_8M_BASE__)
Summer Qind2ad7e72020-01-06 18:16:35 +080051struct tfm_arch_ctx_t {
David Hu50711e32019-06-12 18:32:30 +080052 uint32_t r8;
53 uint32_t r9;
54 uint32_t r10;
55 uint32_t r11;
56 uint32_t r4;
57 uint32_t r5;
58 uint32_t r6;
59 uint32_t r7;
60 uint32_t sp;
61 uint32_t sp_limit;
62 uint32_t dummy;
63 uint32_t lr;
64};
65#endif
66
67/* Disable NS exceptions by setting NS PRIMASK to 1 */
68#define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1)
69/* Enable NS exceptions by setting NS PRIMASK to 0 */
70#define TFM_NS_EXC_ENABLE() __TZ_set_PRIMASK_NS(0)
71
David Hu141fe8d2019-06-24 13:24:00 +080072/**
73 * \brief Check whether Secure or Non-secure stack is used to restore stack
74 * frame on exception return.
75 *
76 * \param[in] lr LR register containing the EXC_RETURN value.
77 *
78 * \retval true Secure stack is used to restore stack frame on
79 * exception return.
80 * \retval false Non-secure stack is used to restore stack frame on
81 * exception return.
82 */
83__STATIC_INLINE bool is_return_secure_stack(uint32_t lr)
84{
85 return (lr & EXC_RETURN_SECURE_STACK);
86}
87
David Hue05b6a62019-06-12 18:45:28 +080088/**
David Hub8dada52019-07-02 18:08:23 +080089 * \brief Check whether the stack frame for this exception has space allocated
90 * for Floating Point(FP) state information.
91 *
92 * \param[in] lr LR register containing the EXC_RETURN value.
93 *
94 * \retval true The stack allocates space for FP information
95 * \retval false The stack doesn't allocate space for FP information
96 */
97__STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
98{
99 return (lr & EXC_RETURN_FPU_FRAME_BASIC) ? false : true;
100}
101
102/**
David Hue05b6a62019-06-12 18:45:28 +0800103 * \brief Set PSPLIM register.
104 *
105 * \param[in] psplim Register value to be written into PSPLIM.
106 */
107__STATIC_INLINE void tfm_arch_set_psplim(uint32_t psplim)
108{
David Huf363fe92019-07-02 13:03:30 +0800109 __set_PSPLIM(psplim);
110}
111
112/**
Ken Liuc0b5f6d2020-07-25 12:05:50 +0800113 * \brief Seal the thread stack.
114 *
115 * This function must be called only when the caller is using MSP.
116 *
117 * \param[in] stk Thread stack address.
118 *
119 * \retval stack Updated thread stack address.
120 */
121__STATIC_INLINE uintptr_t tfm_arch_seal_thread_stack(uintptr_t stk)
122{
123 TFM_CORE_ASSERT((stk & 0x7) == 0);
124 stk -= TFM_STACK_SEALED_SIZE;
125
126 *((uint32_t *)stk) = TFM_STACK_SEAL_VALUE;
127 *((uint32_t *)(stk + 4)) = TFM_STACK_SEAL_VALUE;
128
129 return stk;
130}
131
132/**
Summer Qind2ad7e72020-01-06 18:16:35 +0800133 * \brief Update architecture context value into hardware
Ken Liu490281d2019-12-30 15:55:26 +0800134 *
Summer Qind2ad7e72020-01-06 18:16:35 +0800135 * \param[in] p_actx Pointer of context data
Ken Liu490281d2019-12-30 15:55:26 +0800136 */
Summer Qind2ad7e72020-01-06 18:16:35 +0800137__STATIC_INLINE void tfm_arch_update_ctx(struct tfm_arch_ctx_t *p_actx)
Ken Liu490281d2019-12-30 15:55:26 +0800138{
Summer Qind2ad7e72020-01-06 18:16:35 +0800139 __set_PSP(p_actx->sp);
140 __set_PSPLIM(p_actx->sp_limit);
Ken Liu490281d2019-12-30 15:55:26 +0800141}
142
143/**
Ken Liu05e13ba2020-07-25 10:31:33 +0800144 * \brief Set MSPLIM register and seal the MSP.
145 *
146 * This function assumes that the caller is using PSP when calling this
147 * function.
David Huf363fe92019-07-02 13:03:30 +0800148 *
149 * \param[in] msplim Register value to be written into MSPLIM.
150 */
Ken Liu05e13ba2020-07-25 10:31:33 +0800151__STATIC_INLINE void tfm_arch_init_secure_msp(uint32_t msplim)
David Huf363fe92019-07-02 13:03:30 +0800152{
Ken Liu05e13ba2020-07-25 10:31:33 +0800153 uint32_t mstk_adr = __get_MSP();
154
155 /*
156 * Seal the main stack and update MSP to point below the stack seal.
157 * Set MSPLIM. As the initial 'main()' code is running under privileged PSP
158 * manipulating MSP works here.
159 */
160 TFM_CORE_ASSERT((mstk_adr & 0x7) == 0);
161 mstk_adr -= TFM_STACK_SEALED_SIZE;
162
163 *((uint32_t *)mstk_adr) = TFM_STACK_SEAL_VALUE;
164 *((uint32_t *)(mstk_adr + 4)) = TFM_STACK_SEAL_VALUE;
165
166 __set_MSP(mstk_adr);
David Huf363fe92019-07-02 13:03:30 +0800167 __set_MSPLIM(msplim);
David Hue05b6a62019-06-12 18:45:28 +0800168}
169
David Hu50711e32019-06-12 18:32:30 +0800170#endif