1 /*
2 * Copyright (c) 2021, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 #include "tfm_arch.h"
8 #include "tfm_nspm.h"
9 #include "tfm_ns_client_ext.h"
10 #include "tfm_ns_ctx.h"
11
12 /*
13 * Definiton of NS Client Token
14 * bit[0:7] - Thread ID
15 * bit[8:15] - Group ID
16 * bit[16:23] - Context identifier
17 * bit[24:31] - Reserved, must be 0
18 */
19 #define MAKE_NS_CLIENT_TOKEN(tid, gid, idx) \
20 (uint32_t)((((uint32_t)tid & 0xff) \
21 | (((uint32_t)gid & 0xff) << 8) \
22 | (((uint32_t)idx & 0xff) << 16)) \
23 & 0x00ffffff)
24 #define IS_INVALID_TOKEN(token) ((token) & 0xff000000)
25 #define NS_CLIENT_TOKEN_TO_CTX_IDX(token) (((token) >> 16) & 0xff)
26 #define NS_CLIENT_TOKEN_TO_GID(token) (((token) >> 8) & 0xff)
27 #define NS_CLIENT_TOKEN_TO_TID(token) ((token) & 0xff)
28
29 __tz_c_veneer
tfm_nsce_init(uint32_t ctx_requested)30 uint32_t tfm_nsce_init(uint32_t ctx_requested)
31 {
32 if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
33 /* This veneer should only be called by NS RTOS in handler mode */
34 return 0; /* Return 0 if the caller is from thread mode */
35 }
36
37 /* Nothing to initialize for now */
38 if (ctx_requested == 0) {
39 /* 0 means requesting maximum available context */
40 return TFM_NS_CONTEXT_MAX;
41 } else {
42 return ((ctx_requested <= TFM_NS_CONTEXT_MAX) ?
43 ctx_requested : TFM_NS_CONTEXT_MAX);
44 }
45 }
46
47 __tz_c_veneer
tfm_nsce_acquire_ctx(uint8_t group_id,uint8_t thread_id)48 uint32_t tfm_nsce_acquire_ctx(uint8_t group_id, uint8_t thread_id)
49 {
50 uint8_t ns_ctx_idx;
51
52 if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
53 /* This veneer should only be called by NS RTOS in handler mode */
54 return TFM_NS_CLIENT_ERR_INVALID_ACCESS;
55 }
56
57 /* Try to allocate the non-secure context */
58 if (!acquire_ns_ctx(group_id, &ns_ctx_idx)) {
59 return TFM_NS_CLIENT_INVALID_TOKEN;
60 }
61
62 /* Return the token */
63 return MAKE_NS_CLIENT_TOKEN(thread_id, group_id, ns_ctx_idx);
64 }
65
66 __tz_c_veneer
tfm_nsce_release_ctx(uint32_t token)67 uint32_t tfm_nsce_release_ctx(uint32_t token)
68 {
69 /* Free the context slot assigned */
70 uint8_t ctx_idx;
71 uint8_t gid;
72 uint8_t tid;
73
74 if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
75 /* This veneer should only be called by NS RTOS in handler mode */
76 return TFM_NS_CLIENT_ERR_INVALID_ACCESS;
77 }
78
79 if (IS_INVALID_TOKEN(token)) {
80 return TFM_NS_CLIENT_ERR_INVALID_TOKEN;
81 } else {
82 /* Extract the context index, group ID and thread ID from the token */
83 ctx_idx = NS_CLIENT_TOKEN_TO_CTX_IDX(token);
84 gid = NS_CLIENT_TOKEN_TO_GID(token);
85 tid = NS_CLIENT_TOKEN_TO_TID(token);
86 }
87
88 if (!release_ns_ctx(gid, tid, ctx_idx)) {
89 return TFM_NS_CLIENT_ERR_INVALID_TOKEN;
90 } else {
91 return TFM_NS_CLIENT_ERR_SUCCESS;
92 }
93 }
94
95 __tz_c_veneer
tfm_nsce_load_ctx(uint32_t token,int32_t nsid)96 uint32_t tfm_nsce_load_ctx(uint32_t token, int32_t nsid)
97 {
98 uint8_t ctx_idx;
99 uint8_t gid;
100 uint8_t tid;
101
102 if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
103 /* This veneer should only be called by NS RTOS in handler mode */
104 return TFM_NS_CLIENT_ERR_INVALID_ACCESS;
105 }
106
107 /* Check if NSID is valid */
108 if (nsid >= 0) {
109 return TFM_NS_CLIENT_ERR_INVALID_NSID;
110 }
111
112 if (IS_INVALID_TOKEN(token)) {
113 return TFM_NS_CLIENT_ERR_INVALID_TOKEN;
114 } else {
115 /* Extract the context index, group ID and thread ID from the token */
116 ctx_idx = NS_CLIENT_TOKEN_TO_CTX_IDX(token);
117 gid = NS_CLIENT_TOKEN_TO_GID(token);
118 tid = NS_CLIENT_TOKEN_TO_TID(token);
119 }
120
121 if (!load_ns_ctx(gid, tid, nsid, ctx_idx)) {
122 return TFM_NS_CLIENT_ERR_INVALID_TOKEN;
123 } else {
124 return TFM_NS_CLIENT_ERR_SUCCESS;
125 }
126 }
127
128 __tz_c_veneer
tfm_nsce_save_ctx(uint32_t token)129 uint32_t tfm_nsce_save_ctx(uint32_t token)
130 {
131 uint8_t ctx_idx;
132 uint8_t gid;
133 uint8_t tid;
134
135 if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
136 /* This veneer should only be called by NS RTOS in handler mode */
137 return TFM_NS_CLIENT_ERR_INVALID_ACCESS;
138 }
139
140 if (IS_INVALID_TOKEN(token)) {
141 return TFM_NS_CLIENT_ERR_INVALID_TOKEN;
142 } else {
143 /* Extract the context index, group ID and thread ID from the token */
144 ctx_idx = NS_CLIENT_TOKEN_TO_CTX_IDX(token);
145 gid = NS_CLIENT_TOKEN_TO_GID(token);
146 tid = NS_CLIENT_TOKEN_TO_TID(token);
147 }
148
149 if (!save_ns_ctx(gid, tid, ctx_idx)) {
150 return TFM_NS_CLIENT_ERR_INVALID_TOKEN;
151 } else {
152 return TFM_NS_CLIENT_ERR_SUCCESS;
153 }
154 }
155