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