diff options
author | Jens Wiklander <jens.wiklander@linaro.org> | 2014-11-03 16:02:00 +0100 |
---|---|---|
committer | Jens Wiklander <jens.wiklander@linaro.org> | 2014-11-27 11:16:04 +0100 |
commit | a7ec939bc1cd7bb48b396826f496b14d98069849 (patch) | |
tree | a7dfad4b1d922b60a78df556aaf8a28ba676fc4a /core/arch/arm32/tee | |
parent | 3da2f6734972851869c6c03fe8e56db737cc4b22 (diff) |
Clean syscall handling
* Implements a svc handler suitable to supply as a handler for
thread_svc_handler.
* Removes hardcoded call to tee_svc_sycall in
thread_svc_handler.
* Removes duplicated code for unwinding of stack after
tee_svc_enter_user_mode() replacing it with a single
tee_svc_unwind_enter_user_mode()
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Tested-by: Jens Wiklander <jens.wiklander@linaro.org> (QEMU virt and FVP)
Reviewed-by: Etienne Carriere <etienne.carriere@st.com>
Reviewed-by: Pascal Brand <pascal.brand@linaro.org>
Tested-by: Pascal Brand <pascal.brand@linaro.org> (STM platform)
Diffstat (limited to 'core/arch/arm32/tee')
-rw-r--r-- | core/arch/arm32/tee/arch_svc.c | 142 | ||||
-rw-r--r-- | core/arch/arm32/tee/arch_svc_asm.S | 231 | ||||
-rw-r--r-- | core/arch/arm32/tee/arch_svc_private.h | 38 | ||||
-rw-r--r-- | core/arch/arm32/tee/sub.mk | 3 | ||||
-rw-r--r-- | core/arch/arm32/tee/tee_svc_asm.S | 265 |
5 files changed, 413 insertions, 266 deletions
diff --git a/core/arch/arm32/tee/arch_svc.c b/core/arch/arm32/tee/arch_svc.c new file mode 100644 index 0000000..daa9aa8 --- /dev/null +++ b/core/arch/arm32/tee/arch_svc.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arm32.h> +#include <kernel/thread.h> +#include <tee/tee_svc.h> +#include <tee/arch_svc.h> +#include <tee/tee_svc_cryp.h> +#include <tee/tee_svc_storage.h> +#include <tee_syscall_numbers.h> +#include <util.h> +#include "arch_svc_private.h" +#include <assert.h> +#include <trace.h> +#include <kernel/misc.h> +#include <kernel/trace_ta.h> + +static const tee_svc_func tee_svc_syscall_table[] = { + (tee_svc_func)tee_svc_sys_return, + (tee_svc_func)tee_svc_sys_log, + (tee_svc_func)tee_svc_sys_panic, + (tee_svc_func)tee_svc_sys_dummy, + (tee_svc_func)tee_svc_sys_dummy_7args, + (tee_svc_func)tee_svc_sys_get_property, + (tee_svc_func)tee_svc_open_ta_session, + (tee_svc_func)tee_svc_close_ta_session, + (tee_svc_func)tee_svc_invoke_ta_command, + (tee_svc_func)tee_svc_check_access_rights, + (tee_svc_func)tee_svc_get_cancellation_flag, + (tee_svc_func)tee_svc_unmask_cancellation, + (tee_svc_func)tee_svc_mask_cancellation, + (tee_svc_func)tee_svc_wait, + (tee_svc_func)tee_svc_get_time, + (tee_svc_func)tee_svc_set_ta_time, + (tee_svc_func)tee_svc_cryp_state_alloc, + (tee_svc_func)tee_svc_cryp_state_copy, + (tee_svc_func)tee_svc_cryp_state_free, + (tee_svc_func)tee_svc_hash_init, + (tee_svc_func)tee_svc_hash_update, + (tee_svc_func)tee_svc_hash_final, + (tee_svc_func)tee_svc_cipher_init, + (tee_svc_func)tee_svc_cipher_update, + (tee_svc_func)tee_svc_cipher_final, + (tee_svc_func)tee_svc_cryp_obj_get_info, + (tee_svc_func)tee_svc_cryp_obj_restrict_usage, + (tee_svc_func)tee_svc_cryp_obj_get_attr, + (tee_svc_func)tee_svc_cryp_obj_alloc, + (tee_svc_func)tee_svc_cryp_obj_close, + (tee_svc_func)tee_svc_cryp_obj_reset, + (tee_svc_func)tee_svc_cryp_obj_populate, + (tee_svc_func)tee_svc_cryp_obj_copy, + (tee_svc_func)tee_svc_cryp_derive_key, + (tee_svc_func)tee_svc_cryp_random_number_generate, + (tee_svc_func)tee_svc_authenc_init, + (tee_svc_func)tee_svc_authenc_update_aad, + (tee_svc_func)tee_svc_authenc_update_payload, + (tee_svc_func)tee_svc_authenc_enc_final, + (tee_svc_func)tee_svc_authenc_dec_final, + (tee_svc_func)tee_svc_asymm_operate, + (tee_svc_func)tee_svc_asymm_verify, + (tee_svc_func)tee_svc_storage_obj_open, + (tee_svc_func)tee_svc_storage_obj_create, + (tee_svc_func)tee_svc_storage_obj_del, + (tee_svc_func)tee_svc_storage_obj_rename, + (tee_svc_func)tee_svc_storage_alloc_enum, + (tee_svc_func)tee_svc_storage_free_enum, + (tee_svc_func)tee_svc_storage_reset_enum, + (tee_svc_func)tee_svc_storage_start_enum, + (tee_svc_func)tee_svc_storage_next_enum, + (tee_svc_func)tee_svc_storage_obj_read, + (tee_svc_func)tee_svc_storage_obj_write, + (tee_svc_func)tee_svc_storage_obj_trunc, + (tee_svc_func)tee_svc_storage_obj_seek, + (tee_svc_func)tee_svc_obj_generate_key, +}; + +void tee_svc_handler(struct thread_svc_regs *regs) +{ + const uint32_t scn = regs->r7; + tee_svc_func scf; + + COMPILE_TIME_ASSERT(ARRAY_SIZE(tee_svc_syscall_table) == + (TEE_SCN_MAX + 1)); + + /* Restore IRQ which are disabled on exception entry */ + thread_restore_irq(); + +#if (CFG_TRACE_LEVEL == TRACE_FLOW) + tee_svc_trace_syscall(scn); +#endif + + if (regs->r6 > TEE_SVC_MAX_ARGS) { + DMSG("Too many arguments for SCN %u (%u)", scn, regs->r6); + regs->r0 = TEE_ERROR_GENERIC; + return; + } + + if (scn > TEE_SCN_MAX) + scf = tee_svc_sys_nocall; + else + scf = tee_svc_syscall_table[scn]; + + regs->r0 = tee_svc_do_call(regs, scf); +} + +uint32_t tee_svc_sys_return_helper(uint32_t ret, bool panic, + uint32_t panic_code, struct thread_svc_regs *regs) +{ + if (panic) { + TAMSG("TA panicked with code 0x%x usr_sp 0x%x usr_lr 0x%x", + panic_code, read_usr_sp(), read_usr_lr()); + } + regs->r1 = panic; + regs->r2 = panic_code; + regs->lr = (uintptr_t)tee_svc_unwind_enter_user_mode; + regs->spsr = read_cpsr(); + return ret; +} diff --git a/core/arch/arm32/tee/arch_svc_asm.S b/core/arch/arm32/tee/arch_svc_asm.S new file mode 100644 index 0000000..3a81129 --- /dev/null +++ b/core/arch/arm32/tee/arch_svc_asm.S @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "tee_syscall_numbers.h" +#include "trace_levels.h" +#include <asm.S> +#include <arm32.h> +#include <tee_api_defines.h> +#include <kernel/thread.h> + +.section .text +.balign 4 +.code 32 + +/* + * Below are low level routines handling entry and return from user mode. + * + * tee_svc_enter_user_mode() saves all that registers user mode can change + * so kernel mode can restore needed registers when resuming execution + * after the call to tee_svc_enter_user_mode() has returned. + * tee_svc_enter_user_mode() doesn't return directly since it enters user + * mode instead, it's tee_svc_unwind_enter_user_mode() that does the + * returning by restoring the registers saved by tee_svc_enter_user_mode(). + * + * There's three ways for tee_svc_enter_user_mode() to return to caller, + * user TA calls utee_return, user TA calls utee_panic or through an abort. + * + * Calls to utee_return or utee_panic are handled as: + * thread_svc_handler() -> tee_svc_handler() -> tee_svc_do_call() which + * calls tee_svc_sys_return() or tee_svc_sys_panic(). + * + * These function calls returns normally except thread_svc_handler() which + * which is an exception handling routine so it reads return address and + * SPSR to restore from the stack. tee_svc_sys_return() and tee_svc_sys_panic() + * changes return address and SPSR used by thread_svc_handler() to instead of + * returning into user mode as with other syscalls it returns into + * tee_svc_unwind_enter_user_mode() in kernel mode instead. When + * thread_svc_handler() returns the stack pointer at the point where + * tee_svc_enter_user_mode() left it so this is where + * tee_svc_unwind_enter_user_mode() can operate. + * + * Aborts are handled in a similar way but by thread_abort_handler() + * instead, when the pager sees that it's an abort from user mode that + * can't be handled it updates SPSR and return address used by + * thread_abort_handler() to return into tee_svc_unwind_enter_user_mode() + * instead. + */ + +/* + * TEE_Result tee_svc_enter_user_mode( + * uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, + * tee_uaddr_t sp, tee_uaddr_t user_func, + * uint32_t *panicked, uint32_t *panic_code); + */ +FUNC tee_svc_enter_user_mode , : + /* + * Save all registers to allow tee_svc_sys_return() to + * resume execution as if this function would have returned. + * This is also used in tee_svc_sys_panic(). + * + * If stack usage of this function is changed + * tee_svc_unwind_enter_user_mode() has to be updated. + */ + push {r4-r12,lr} + + ldr r4, [sp, #(10 * 0x4)] /* user stack pointer */ + ldr r5, [sp, #(11 * 0x4)] /* user function */ + + /* + * Save old user sp and set new user sp. + */ + cps #CPSR_MODE_SYS + mov r6, sp + mov sp, r4 + cps #CPSR_MODE_SVC + push {r6} + + /* + * Set the saved Processors Status Register to user mode to allow + * entry of user mode through movs below. Also update thumbstate + * since movs doesn't do that automatically. + */ + mrs r6, cpsr + bic r6, #CPSR_MODE_MASK + orr r6, #CPSR_MODE_USR + tst r5, #1 /* If it's odd we should switch to thumb mode */ + orrne r6, #CPSR_T /* Enable thumb mode */ + biceq r6, #CPSR_T /* Disable thumb mode */ + bicne r6, #CPSR_IT_MASK1 /* Clear IT state for thumb mode */ + bicne r6, #CPSR_IT_MASK2 /* Clear IT state for thumb mode */ + msr spsr_cxsf, r6 + + /* + * Don't allow return from this function, return is done through + * tee_svc_unwind_enter_user_mode() below. + */ + mov lr, #0 + /* Call the user function with its arguments */ + movs pc, r5 +END_FUNC tee_svc_enter_user_mode + +/* + * uint32_t tee_svc_unwind_enter_user_mode(uint32_t ret, bool panic, + * uint32_t panic_code); + * + * This is the function that exception handlers can return into + * to resume execution in kernel mode instead of user mode. + * + * This function is closely coupled with tee_svc_enter_user_mode() since + * it need to restore registers saved by tee_svc_enter_user_mode() and when + * it returns make it look like tee_svc_enter_user_mode() just returned. + * It is expected that the stack pointer is where tee_svc_enter_user_mode() + * left it. The stack will be unwound and we'll return to where + * tee_svc_enter_user_mode() was expected to return to. + */ +FUNC tee_svc_unwind_enter_user_mode , : + ldr ip, [sp, #(13 * 0x4)] /* &ctx->panicked */ + str r1, [ip] + ldr ip, [sp, #(14 * 0x4)] /* &ctx->panic_code */ + str r2, [ip] + + /* Restore old user sp */ + pop {r4} + cps #CPSR_MODE_SYS + mov sp, r4 + cps #CPSR_MODE_SVC + + pop {r4-r12,pc} /* Match the push in tee_svc_enter_user_mode()*/ +END_FUNC tee_svc_unwind_enter_user_mode + +/* + * uint32_t tee_svc_do_call(struct thread_svc_regs *regs, tee_svc_func func); + * + * Called from tee_svc_handler() + */ +FUNC tee_svc_do_call , : + push {r7-r9, lr} + mov r7, sp + mov r8, r0 + mov r9, r1 + ldr r5, [r8, #THREAD_SVC_REG_R5_OFFS] + ldr r6, [r8, #THREAD_SVC_REG_R6_OFFS] + + /* + * Copy eventual arguments passed on the user stack. + * + * r5 holds the address of the first word + * r6 holds the number of words + * + * tee_svc_handler() who calls this function has already checked + * that we don't copy too much data. + */ + cmp r6, #0 + beq .Lno_args + sub sp, sp, r6, lsl #2 + mov r0, #0 /* Let tee_svc_copy_from_user() lookup the session */ + mov r1, sp + mov r2, r5 + mov r3, r6, lsl #2 + ldr lr, =tee_svc_copy_from_user + blx lr + + /* If copy failed return the error */ + cmp r0, #0 + bne .Lret + +.Lno_args: + /* Load arguments to function */ + add lr, r8, #THREAD_SVC_REG_R0_OFFS + ldm lr, {r0-r3} + blx r9 +.Lret: + mov sp, r7 + pop {r7-r9, pc} +END_FUNC tee_svc_do_call + +/* + * User space sees this function as: + * void tee_svc_sys_return(uint32_t ret) __noreturn; + * + * But internally the function depends on being called from + * tee_svc_do_call() with pointer to the struct thread_svc_regs saved by + * thread_svc_handler() in r8. The argument ret is already in r0 so we + * don't touch that and let it propagate as return value of the called + * tee_svc_unwind_enter_user_mode(). + */ +FUNC tee_svc_sys_return , : + mov r1, #0 /* panic = false */ + mov r2, #0 /* panic_code = 0 */ + mov r3, r8 + b tee_svc_sys_return_helper +END_FUNC tee_svc_sys_return + +/* + * User space sees this function as: + * void tee_svc_sys_panic(uint32_t code) __noreturn; + * + * But internally the function depends on being called from + * tee_svc_do_call() with pointer to the struct thread_svc_regs saved by + * thread_svc_handler() in r8. + */ +FUNC tee_svc_sys_panic , : + mov r1, #1 /* panic = true */ + mov r2, r0 /* panic_code = 0 */ + mov r3, r8 + ldr r0, =TEE_ERROR_TARGET_DEAD + b tee_svc_sys_return_helper +END_FUNC tee_svc_sys_panic diff --git a/core/arch/arm32/tee/arch_svc_private.h b/core/arch/arm32/tee/arch_svc_private.h new file mode 100644 index 0000000..d01ab62 --- /dev/null +++ b/core/arch/arm32/tee/arch_svc_private.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ARCH_SVC_PRIVATE_H +#define ARCH_SVC_PRIVATE_H + +#include <tee_api_types.h> + +/* void argument but in reality it can be any number of arguments */ +typedef TEE_Result (*tee_svc_func)(void); + +/* Helper function for tee_svc_handler() */ +uint32_t tee_svc_do_call(struct thread_svc_regs *regs, tee_svc_func func); + +#endif /*ARCH_SVC_PRIVATE_H*/ diff --git a/core/arch/arm32/tee/sub.mk b/core/arch/arm32/tee/sub.mk index 672849a..6d26879 100644 --- a/core/arch/arm32/tee/sub.mk +++ b/core/arch/arm32/tee/sub.mk @@ -1,5 +1,6 @@ srcs-y += arch_tee_fs.c srcs-y += tee_rpmb.c -srcs-y += tee_svc_asm.S +srcs-y += arch_svc_asm.S +srcs-y += arch_svc.c srcs-y += entry.c srcs-y += init.c diff --git a/core/arch/arm32/tee/tee_svc_asm.S b/core/arch/arm32/tee/tee_svc_asm.S deleted file mode 100644 index 41321bc..0000000 --- a/core/arch/arm32/tee/tee_svc_asm.S +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2014, STMicroelectronics International N.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include "tee_syscall_numbers.h" -#include "trace_levels.h" - -.global tee_svc_enter_user_mode -.global tee_svc_sys_return -.global tee_svc_syscall - -.set SPSR_T_BIT, (1 << 5) -.set SPSR_IT_MASK, 0x0600FC00 -.set SPSR_IT_MASK1, 0x06000000 -.set SPSR_IT_MASK2, 0x0000FC00 - -.section .text -.balign 4 -.code 32 - -/* - * Function called from the vector table when a svc exception is received. - * This function handles entry and exit from a system call. - */ -.func tee_svc_syscall -tee_svc_syscall: - push {r4 - r12, lr} - mov r8, sp - - /* Restore IRQ which are disabled on exception entry */ - push {r0-r3} - blx thread_restore_irq - pop {r0-r3} - - /* - * Copy eventual arguments passed on the user stack. - * - * r5 holds the address of the first word - * r6 holds the number of words - * - * TODO figure out how to avoid stack overflow because of too much data - * passed on the stack. - */ - sub sp, sp, r6, lsl #2 - cmp r6, #0 - beq .Lno_args - push {r0} - push {r1-r3} - mov r0, #0 - mov r2, r5 - add r1, sp, #(4 * 4) - mov r3, r6, lsl #2 - ldr lr, =tee_svc_copy_from_user - blx lr - - /* If copy failed return the error */ - cmp r0, #0 - pop {r1-r3} - addne sp, sp, #4 - popeq {r0} - bne .Lret -.Lno_args: - - /* - * Find the system call and call the function. - * - * System call number is passed in r7. - */ -#if (CFG_TRACE_LEVEL == TRACE_FLOW) - push {r0-r3} - mov r0, r7 - blx tee_svc_trace_syscall - pop {r0-r3} -#endif - ldr r12, =tee_svc_syscall_table - cmp r7, #TEE_SCN_MAX - /* Either syscall function should return to cleanup (.Lret) */ - ldr lr, =.Lret - ldrls pc, [r12, r7, lsl #2] /* if valid syscall number */ - ldr pc, =tee_svc_sys_nocall /* if invalid syscall number */ -.Lret: - mov sp, r8 - pop {r4 - r12, lr} - movs pc, lr -.endfunc - - - -@ TEE_Result tee_svc_enter_user_mode( -@ uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, -@ tee_uaddr_t sp, tee_uaddr_t user_func, -@ uint32_t *panicked, uint32_t *panic_code); -.func tee_svc_enter_user_mode -tee_svc_enter_user_mode: - /* - * Save all registers to allow tee_svc_sys_return() to - * resume execution as if this function would have returned. - * This is also used in tee_svc_sys_panic(). - * - * If stack usage of this function is changed tee_svc_sys_return() - * and tee_svc_sys_panic() has to be updated. - */ - push {r4-r12,lr} - - ldr r4, [sp, #(10 * 0x4)] /* user stack pointer */ - ldr r5, [sp, #(11 * 0x4)] /* user function */ - - /* Save user sp */ - stmfd sp, {sp}^ /* store r13 user mode */ - nop - sub sp, sp, #4 /* update stack pointer */ - - /* Switch from Supervisor mode to System mode */ - mrs r6, cpsr - mrs r7, cpsr - orr r6, #0xF - msr cpsr, r6 - - /* Setup user stack */ - mov sp, r4 - - /* Switch back to Supervisor mode to have a spsr to modify */ - msr cpsr, r7 - - /* - * Set the saved Processors Status Register to user mode to allow entry - * of user mode through movs below. Also update thumbstate since movs - * doesn't do that automatically. - */ - bic r6, #0xF - tst r5, #1 /* If it's odd we should switch to thumb mode */ - orrne r6, #SPSR_T_BIT /* Enable thumb mode */ - biceq r6, #SPSR_T_BIT /* Disable thumb mode */ - bicne r6, #SPSR_IT_MASK1 /* Clear IT state for thumb mode */ - bicne r6, #SPSR_IT_MASK2 /* Clear IT state for thumb mode */ - msr spsr_cxsf, r6 - - /* - * Don't allow return from this function, return is done through - * tee_svc_sys_return() below. - */ - mov lr, #0 - /* Call the user function with its arguments */ - movs pc, r5 -.endfunc - -@ tee_svc_sys_return(uint32_t ret, uint32_t param_types, void *params); -.func tee_svc_sys_return -tee_svc_sys_return: - mov sp, r8 /* Restore sp in case extra parameters was passed */ - pop {r4-r12,lr} /* Match the push in tee_svc_syscall() */ - - /* Restore user sp */ - ldmfd sp, {sp}^ /* store r13 user mode */ - nop - add sp, sp, #4 /* update stack pointer */ - - pop {r4-r12,pc} /* Match the push in tee_svc_enter_user_mode() */ -.endfunc - -@ void tee_svc_sys_panic(uint32_t code); -.func tee_svc_sys_panic -tee_svc_sys_panic: - mov sp, r8 /* Restore sp in case extra parameters was passed */ - pop {r4-r12,lr} /* Match the push in tee_svc_syscall() */ - -.global tee_svc_user_ta_panic_from_pager -tee_svc_user_ta_panic_from_pager: - ldr r1, [sp, #(13 * 0x4)] /* &session->panicked */ - mov r2, #1 /* true */ - str r2, [r1] /* update session->panicked */ - - ldr r1, [sp, #(14 * 0x4)] /* &session->panic_code */ - str r0, [r1] /* update session->panic_code */ - - /* Restore user sp */ - ldmfd sp, {sp}^ /* store r13 user mode */ - nop - add sp, sp, #4 /* update stack pointer */ - - pop {r4-r12,pc} /* Match the push in tee_svc_enter_user_mode() */ -.endfunc - - - .section .rodata -.balign 4 -tee_svc_syscall_table: -.word tee_svc_sys_return -.word tee_svc_sys_log -.word tee_svc_sys_panic -.word tee_svc_sys_dummy -.word tee_svc_sys_dummy_7args -.word tee_svc_sys_get_property -.word tee_svc_open_ta_session -.word tee_svc_close_ta_session -.word tee_svc_invoke_ta_command -.word tee_svc_check_access_rights -.word tee_svc_get_cancellation_flag -.word tee_svc_unmask_cancellation -.word tee_svc_mask_cancellation -.word tee_svc_wait -.word tee_svc_get_time -.word tee_svc_set_ta_time -.word tee_svc_cryp_state_alloc -.word tee_svc_cryp_state_copy -.word tee_svc_cryp_state_free -.word tee_svc_hash_init -.word tee_svc_hash_update -.word tee_svc_hash_final -.word tee_svc_cipher_init -.word tee_svc_cipher_update -.word tee_svc_cipher_final -.word tee_svc_cryp_obj_get_info -.word tee_svc_cryp_obj_restrict_usage -.word tee_svc_cryp_obj_get_attr -.word tee_svc_cryp_obj_alloc -.word tee_svc_cryp_obj_close -.word tee_svc_cryp_obj_reset -.word tee_svc_cryp_obj_populate -.word tee_svc_cryp_obj_copy -.word tee_svc_cryp_derive_key -.word tee_svc_cryp_random_number_generate -.word tee_svc_authenc_init -.word tee_svc_authenc_update_aad -.word tee_svc_authenc_update_payload -.word tee_svc_authenc_enc_final -.word tee_svc_authenc_dec_final -.word tee_svc_asymm_operate -.word tee_svc_asymm_verify -.word tee_svc_storage_obj_open -.word tee_svc_storage_obj_create -.word tee_svc_storage_obj_del -.word tee_svc_storage_obj_rename -.word tee_svc_storage_alloc_enum -.word tee_svc_storage_free_enum -.word tee_svc_storage_reset_enum -.word tee_svc_storage_start_enum -.word tee_svc_storage_next_enum -.word tee_svc_storage_obj_read -.word tee_svc_storage_obj_write -.word tee_svc_storage_obj_trunc -.word tee_svc_storage_obj_seek -.word tee_svc_obj_generate_key |