Update from upstream to 2.4.0 version
[platform/core/security/tef-optee_os.git] / core / arch / arm / tee / arch_svc.c
1 /*
2  * Copyright (c) 2014, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <arm.h>
29 #include <assert.h>
30 #include <kernel/misc.h>
31 #include <kernel/thread.h>
32 #include <kernel/trace_ta.h>
33 #include <tee/tee_svc.h>
34 #include <tee/arch_svc.h>
35 #include <tee/tee_svc_cryp.h>
36 #include <tee/tee_svc_storage.h>
37 #include <tee/se/svc.h>
38 #include <tee/svc_cache.h>
39 #include <tee_syscall_numbers.h>
40 #include <trace.h>
41 #include <util.h>
42
43 #include "arch_svc_private.h"
44
45 #if (TRACE_LEVEL == TRACE_FLOW) && defined(CFG_TEE_CORE_TA_TRACE)
46 #define TRACE_SYSCALLS
47 #endif
48
49 struct syscall_entry {
50         syscall_t fn;
51 #ifdef TRACE_SYSCALLS
52         const char *name;
53 #endif
54 };
55
56 #ifdef TRACE_SYSCALLS
57 #define SYSCALL_ENTRY(_fn) { .fn = (syscall_t)_fn, .name = #_fn }
58 #else
59 #define SYSCALL_ENTRY(_fn) { .fn = (syscall_t)_fn }
60 #endif
61
62 /*
63  * This array is ordered according to the SYSCALL ids TEE_SCN_xxx
64  */
65 static const struct syscall_entry tee_svc_syscall_table[] = {
66         SYSCALL_ENTRY(syscall_sys_return),
67         SYSCALL_ENTRY(syscall_log),
68         SYSCALL_ENTRY(syscall_panic),
69         SYSCALL_ENTRY(syscall_get_property),
70         SYSCALL_ENTRY(syscall_get_property_name_to_index),
71         SYSCALL_ENTRY(syscall_open_ta_session),
72         SYSCALL_ENTRY(syscall_close_ta_session),
73         SYSCALL_ENTRY(syscall_invoke_ta_command),
74         SYSCALL_ENTRY(syscall_check_access_rights),
75         SYSCALL_ENTRY(syscall_get_cancellation_flag),
76         SYSCALL_ENTRY(syscall_unmask_cancellation),
77         SYSCALL_ENTRY(syscall_mask_cancellation),
78         SYSCALL_ENTRY(syscall_wait),
79         SYSCALL_ENTRY(syscall_get_time),
80         SYSCALL_ENTRY(syscall_set_ta_time),
81         SYSCALL_ENTRY(syscall_cryp_state_alloc),
82         SYSCALL_ENTRY(syscall_cryp_state_copy),
83         SYSCALL_ENTRY(syscall_cryp_state_free),
84         SYSCALL_ENTRY(syscall_hash_init),
85         SYSCALL_ENTRY(syscall_hash_update),
86         SYSCALL_ENTRY(syscall_hash_final),
87         SYSCALL_ENTRY(syscall_cipher_init),
88         SYSCALL_ENTRY(syscall_cipher_update),
89         SYSCALL_ENTRY(syscall_cipher_final),
90         SYSCALL_ENTRY(syscall_cryp_obj_get_info),
91         SYSCALL_ENTRY(syscall_cryp_obj_restrict_usage),
92         SYSCALL_ENTRY(syscall_cryp_obj_get_attr),
93         SYSCALL_ENTRY(syscall_cryp_obj_alloc),
94         SYSCALL_ENTRY(syscall_cryp_obj_close),
95         SYSCALL_ENTRY(syscall_cryp_obj_reset),
96         SYSCALL_ENTRY(syscall_cryp_obj_populate),
97         SYSCALL_ENTRY(syscall_cryp_obj_copy),
98         SYSCALL_ENTRY(syscall_cryp_derive_key),
99         SYSCALL_ENTRY(syscall_cryp_random_number_generate),
100         SYSCALL_ENTRY(syscall_authenc_init),
101         SYSCALL_ENTRY(syscall_authenc_update_aad),
102         SYSCALL_ENTRY(syscall_authenc_update_payload),
103         SYSCALL_ENTRY(syscall_authenc_enc_final),
104         SYSCALL_ENTRY(syscall_authenc_dec_final),
105         SYSCALL_ENTRY(syscall_asymm_operate),
106         SYSCALL_ENTRY(syscall_asymm_verify),
107         SYSCALL_ENTRY(syscall_storage_obj_open),
108         SYSCALL_ENTRY(syscall_storage_obj_create),
109         SYSCALL_ENTRY(syscall_storage_obj_del),
110         SYSCALL_ENTRY(syscall_storage_obj_rename),
111         SYSCALL_ENTRY(syscall_storage_alloc_enum),
112         SYSCALL_ENTRY(syscall_storage_free_enum),
113         SYSCALL_ENTRY(syscall_storage_reset_enum),
114         SYSCALL_ENTRY(syscall_storage_start_enum),
115         SYSCALL_ENTRY(syscall_storage_next_enum),
116         SYSCALL_ENTRY(syscall_storage_obj_read),
117         SYSCALL_ENTRY(syscall_storage_obj_write),
118         SYSCALL_ENTRY(syscall_storage_obj_trunc),
119         SYSCALL_ENTRY(syscall_storage_obj_seek),
120         SYSCALL_ENTRY(syscall_obj_generate_key),
121         SYSCALL_ENTRY(syscall_se_service_open),
122         SYSCALL_ENTRY(syscall_se_service_close),
123         SYSCALL_ENTRY(syscall_se_service_get_readers),
124         SYSCALL_ENTRY(syscall_se_reader_get_prop),
125         SYSCALL_ENTRY(syscall_se_reader_get_name),
126         SYSCALL_ENTRY(syscall_se_reader_open_session),
127         SYSCALL_ENTRY(syscall_se_reader_close_sessions),
128         SYSCALL_ENTRY(syscall_se_session_is_closed),
129         SYSCALL_ENTRY(syscall_se_session_get_atr),
130         SYSCALL_ENTRY(syscall_se_session_open_channel),
131         SYSCALL_ENTRY(syscall_se_session_close),
132         SYSCALL_ENTRY(syscall_se_channel_select_next),
133         SYSCALL_ENTRY(syscall_se_channel_get_select_resp),
134         SYSCALL_ENTRY(syscall_se_channel_transmit),
135         SYSCALL_ENTRY(syscall_se_channel_close),
136         SYSCALL_ENTRY(syscall_cache_operation),
137 };
138
139 #ifdef TRACE_SYSCALLS
140 static void trace_syscall(size_t num)
141 {
142         if (num == TEE_SCN_RETURN || num > TEE_SCN_MAX)
143                 return;
144         FMSG("syscall #%zu (%s)", num, tee_svc_syscall_table[num].name);
145 }
146 #else
147 static void trace_syscall(size_t num __unused)
148 {
149 }
150 #endif
151
152 #ifdef ARM32
153 static void get_scn_max_args(struct thread_svc_regs *regs, size_t *scn,
154                 size_t *max_args)
155 {
156         *scn = regs->r7;
157         *max_args = regs->r6;
158 }
159 #endif /*ARM32*/
160
161 #ifdef ARM64
162 static void get_scn_max_args(struct thread_svc_regs *regs, size_t *scn,
163                 size_t *max_args)
164 {
165         if (((regs->spsr >> SPSR_MODE_RW_SHIFT) & SPSR_MODE_RW_MASK) ==
166              SPSR_MODE_RW_32) {
167                 *scn = regs->x7;
168                 *max_args = regs->x6;
169         } else {
170                 *scn = regs->x8;
171                 *max_args = 0;
172         }
173 }
174 #endif /*ARM64*/
175
176 #ifdef ARM32
177 static void set_svc_retval(struct thread_svc_regs *regs, uint32_t ret_val)
178 {
179         regs->r0 = ret_val;
180 }
181 #endif /*ARM32*/
182
183 #ifdef ARM64
184 static void set_svc_retval(struct thread_svc_regs *regs, uint64_t ret_val)
185 {
186         regs->x0 = ret_val;
187 }
188 #endif /*ARM64*/
189
190 void tee_svc_handler(struct thread_svc_regs *regs)
191 {
192         size_t scn;
193         size_t max_args;
194         syscall_t scf;
195
196         COMPILE_TIME_ASSERT(ARRAY_SIZE(tee_svc_syscall_table) ==
197                                 (TEE_SCN_MAX + 1));
198
199         thread_user_save_vfp();
200
201         /* TA has just entered kernel mode */
202         tee_ta_update_session_utime_suspend();
203
204         /* Restore foreign interrupts which are disabled on exception entry */
205         thread_restore_foreign_intr();
206
207         get_scn_max_args(regs, &scn, &max_args);
208
209         trace_syscall(scn);
210
211         if (max_args > TEE_SVC_MAX_ARGS) {
212                 DMSG("Too many arguments for SCN %zu (%zu)", scn, max_args);
213                 set_svc_retval(regs, TEE_ERROR_GENERIC);
214                 return;
215         }
216
217         if (scn > TEE_SCN_MAX)
218                 scf = syscall_not_supported;
219         else
220                 scf = tee_svc_syscall_table[scn].fn;
221
222         set_svc_retval(regs, tee_svc_do_call(regs, scf));
223
224         if (scn != TEE_SCN_RETURN) {
225                 /* We're about to switch back to user mode */
226                 tee_ta_update_session_utime_resume();
227         }
228 }
229
230 #ifdef ARM32
231 uint32_t tee_svc_sys_return_helper(uint32_t ret, bool panic,
232                         uint32_t panic_code, struct thread_svc_regs *regs)
233 {
234         if (panic) {
235                 TAMSG("TA panicked with code 0x%x usr_sp 0x%x usr_lr 0x%x",
236                       panic_code, read_mode_sp(CPSR_MODE_SYS),
237                       read_mode_lr(CPSR_MODE_SYS));
238         }
239         regs->r1 = panic;
240         regs->r2 = panic_code;
241         regs->lr = (uintptr_t)thread_unwind_user_mode;
242         regs->spsr = read_cpsr();
243         return ret;
244 }
245 #endif /*ARM32*/
246 #ifdef ARM64
247 uint32_t tee_svc_sys_return_helper(uint32_t ret, bool panic,
248                         uint32_t panic_code, struct thread_svc_regs *regs)
249 {
250         if (panic) {
251                 TAMSG("TA panicked with code 0x%x usr_sp 0x%" PRIx64 " usr_lr 0x%" PRIx64,
252                         panic_code, regs->x13, regs->x14);
253         }
254         regs->x1 = panic;
255         regs->x2 = panic_code;
256         regs->elr = (uintptr_t)thread_unwind_user_mode;
257         regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, 0);
258         regs->spsr |= read_daif();
259         /*
260          * Regs is the value of stack pointer before calling the SVC
261          * handler.  By the addition matches for the reserved space at the
262          * beginning of el0_sync_svc(). This prepares the stack when
263          * returning to thread_unwind_user_mode instead of a normal
264          * exception return.
265          */
266         regs->sp_el0 = (uint64_t)(regs + 1);
267         return ret;
268 }
269 #endif /*ARM64*/