0e80dc8f3970f6145dbd6bb80d61153382f5c0c7
[platform/core/security/tef-optee_os.git] / core / arch / arm / tee / entry_fast.c
1 /*
2  * Copyright (c) 2015, Linaro Limited
3  * All rights reserved.
4  * Copyright (c) 2014, STMicroelectronics International N.V.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <tee/entry_fast.h>
31 #include <optee_msg.h>
32 #include <sm/optee_smc.h>
33 #include <kernel/generic_boot.h>
34 #include <kernel/tee_l2cc_mutex.h>
35 #include <kernel/misc.h>
36 #include <mm/core_mmu.h>
37
38 static void tee_entry_get_shm_config(struct thread_smc_args *args)
39 {
40         args->a0 = OPTEE_SMC_RETURN_OK;
41         args->a1 = default_nsec_shm_paddr;
42         args->a2 = default_nsec_shm_size;
43         /* Should this be TEESMC cache attributes instead? */
44         args->a3 = core_mmu_is_shm_cached();
45 }
46
47 static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args)
48 {
49         TEE_Result ret;
50 #ifdef ARM32
51         paddr_t pa = 0;
52
53         switch (args->a1) {
54         case OPTEE_SMC_L2CC_MUTEX_GET_ADDR:
55                 ret = tee_get_l2cc_mutex(&pa);
56                 reg_pair_from_64(pa, &args->a2, &args->a3);
57                 break;
58         case OPTEE_SMC_L2CC_MUTEX_SET_ADDR:
59                 pa = reg_pair_to_64(args->a2, args->a3);
60                 ret = tee_set_l2cc_mutex(&pa);
61                 break;
62         case OPTEE_SMC_L2CC_MUTEX_ENABLE:
63                 ret = tee_enable_l2cc_mutex();
64                 break;
65         case OPTEE_SMC_L2CC_MUTEX_DISABLE:
66                 ret = tee_disable_l2cc_mutex();
67                 break;
68         default:
69                 args->a0 = OPTEE_SMC_RETURN_EBADCMD;
70                 return;
71         }
72 #else
73         ret = TEE_ERROR_NOT_SUPPORTED;
74 #endif
75         if (ret == TEE_ERROR_NOT_SUPPORTED)
76                 args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
77         else if (ret)
78                 args->a0 = OPTEE_SMC_RETURN_EBADADDR;
79         else
80                 args->a0 = OPTEE_SMC_RETURN_OK;
81 }
82
83 static void tee_entry_exchange_capabilities(struct thread_smc_args *args)
84 {
85         if (args->a1) {
86                 /*
87                  * Either unknown capability or
88                  * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, in either case we can't
89                  * deal with it.
90                  *
91                  * The memory mapping of shared memory is defined as normal
92                  * shared memory for SMP systems and normal memory for UP
93                  * systems. Currently we map all memory as shared in secure
94                  * world.
95                  */
96                 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
97                 return;
98         }
99
100         args->a0 = OPTEE_SMC_RETURN_OK;
101         args->a1 = OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM;
102 }
103
104 static void tee_entry_disable_shm_cache(struct thread_smc_args *args)
105 {
106         uint64_t cookie;
107
108         if (!thread_disable_prealloc_rpc_cache(&cookie)) {
109                 args->a0 = OPTEE_SMC_RETURN_EBUSY;
110                 return;
111         }
112
113         if (!cookie) {
114                 args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
115                 return;
116         }
117
118         args->a0 = OPTEE_SMC_RETURN_OK;
119         args->a1 = cookie >> 32;
120         args->a2 = cookie;
121 }
122
123 static void tee_entry_enable_shm_cache(struct thread_smc_args *args)
124 {
125         if (thread_enable_prealloc_rpc_cache())
126                 args->a0 = OPTEE_SMC_RETURN_OK;
127         else
128                 args->a0 = OPTEE_SMC_RETURN_EBUSY;
129 }
130
131 static void tee_entry_boot_secondary(struct thread_smc_args *args)
132 {
133 #if defined(CFG_BOOT_SECONDARY_REQUEST)
134         if (!generic_boot_core_release(args->a1, (paddr_t)(args->a3)))
135                 args->a0 = OPTEE_SMC_RETURN_OK;
136         else
137                 args->a0 = OPTEE_SMC_RETURN_EBADCMD;
138 #else
139         args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
140 #endif
141 }
142
143 void tee_entry_fast(struct thread_smc_args *args)
144 {
145         switch (args->a0) {
146
147         /* Generic functions */
148         case OPTEE_SMC_CALLS_COUNT:
149                 tee_entry_get_api_call_count(args);
150                 break;
151         case OPTEE_SMC_CALLS_UID:
152                 tee_entry_get_api_uuid(args);
153                 break;
154         case OPTEE_SMC_CALLS_REVISION:
155                 tee_entry_get_api_revision(args);
156                 break;
157         case OPTEE_SMC_CALL_GET_OS_UUID:
158                 tee_entry_get_os_uuid(args);
159                 break;
160         case OPTEE_SMC_CALL_GET_OS_REVISION:
161                 tee_entry_get_os_revision(args);
162                 break;
163
164         /* OP-TEE specific SMC functions */
165         case OPTEE_SMC_GET_SHM_CONFIG:
166                 tee_entry_get_shm_config(args);
167                 break;
168         case OPTEE_SMC_L2CC_MUTEX:
169                 tee_entry_fastcall_l2cc_mutex(args);
170                 break;
171         case OPTEE_SMC_EXCHANGE_CAPABILITIES:
172                 tee_entry_exchange_capabilities(args);
173                 break;
174         case OPTEE_SMC_DISABLE_SHM_CACHE:
175                 tee_entry_disable_shm_cache(args);
176                 break;
177         case OPTEE_SMC_ENABLE_SHM_CACHE:
178                 tee_entry_enable_shm_cache(args);
179                 break;
180         case OPTEE_SMC_BOOT_SECONDARY:
181                 tee_entry_boot_secondary(args);
182                 break;
183
184         default:
185                 args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
186                 break;
187         }
188 }
189
190 size_t tee_entry_generic_get_api_call_count(void)
191 {
192         /*
193          * All the different calls handled in this file. If the specific
194          * target has additional calls it will call this function and
195          * add the number of calls the target has added.
196          */
197         return 9;
198 }
199
200 void __weak tee_entry_get_api_call_count(struct thread_smc_args *args)
201 {
202         args->a0 = tee_entry_generic_get_api_call_count();
203 }
204
205 void __weak tee_entry_get_api_uuid(struct thread_smc_args *args)
206 {
207         args->a0 = OPTEE_MSG_UID_0;
208         args->a1 = OPTEE_MSG_UID_1;
209         args->a2 = OPTEE_MSG_UID_2;
210         args->a3 = OPTEE_MSG_UID_3;
211 }
212
213 void __weak tee_entry_get_api_revision(struct thread_smc_args *args)
214 {
215         args->a0 = OPTEE_MSG_REVISION_MAJOR;
216         args->a1 = OPTEE_MSG_REVISION_MINOR;
217 }
218
219 void __weak tee_entry_get_os_uuid(struct thread_smc_args *args)
220 {
221         args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0;
222         args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1;
223         args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2;
224         args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3;
225 }
226
227 void __weak tee_entry_get_os_revision(struct thread_smc_args *args)
228 {
229         args->a0 = CFG_OPTEE_REVISION_MAJOR;
230         args->a1 = CFG_OPTEE_REVISION_MINOR;
231 }