1/* SPDX-License-Identifier: BSD-2-Clause */ 2/* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 */ 5#include "tee_syscall_numbers.h" 6#include "trace_levels.h" 7#include <arm.h> 8#include <asm.S> 9#include <generated/asm-defines.h> 10#include <kernel/thread.h> 11#include <tee_api_defines.h> 12 13/* 14 * uint32_t tee_svc_do_call(struct thread_svc_regs *regs, tee_svc_func func); 15 * 16 * Called from user_ta_handle_svc() 17 */ 18FUNC tee_svc_do_call , : 19UNWIND( .cantunwind) 20 push {r5-r9, lr} 21 mov r7, sp 22 mov r8, r0 23 mov r9, r1 24 ldr r5, [r8, #THREAD_SVC_REG_R5] 25 ldr r6, [r8, #THREAD_SVC_REG_R6] 26 27 /* 28 * Copy eventual arguments passed on the user stack. 29 * 30 * r5 holds the address of the first word 31 * r6 holds the number of words 32 * 33 * user_ta_handle_svc() who calls this function has already checked 34 * that we don't copy too much data. 35 */ 36 cmp r6, #0 37 beq .Lno_args 38 sub sp, sp, r6, lsl #2 39 bic sp, sp, #7 /* make sure it's a multiple of 8 */ 40 mov r0, sp 41 mov r1, r5 42 mov r2, r6, lsl #2 43 ldr lr, =copy_from_user 44 blx lr 45 46 /* If copy failed return the error */ 47 cmp r0, #0 48 bne .Lret 49 50.Lno_args: 51 /* Load arguments to function */ 52 add lr, r8, #THREAD_SVC_REG_R0 53 ldm lr, {r0-r3} 54 blx r9 55.Lret: 56 mov sp, r7 57 pop {r5-r9, pc} 58END_FUNC tee_svc_do_call 59 60/* 61 * syscall_sys_return() and syscall_panic() are two special cases for syscalls 62 * in the way that they do not return to the TA, instead execution is resumed 63 * as if __thread_enter_user_mode() had returned to thread_enter_user_mode(). 64 * 65 * In order to do this the functions need a way to get hold of a pointer to 66 * the struct thread_svc_regs provided by storing relevant registers on the 67 * stack in thread_svc_handler() and later load them into registers again 68 * when thread_svc_handler() is returning. 69 * 70 * tee_svc_do_call() is supplied the pointer to struct thread_svc_regs in 71 * r0. This pointer can later be retrieved from r8. 72 */ 73 74/* 75 * User space sees this function as: 76 * void syscall_sys_return(uint32_t ret) __noreturn; 77 * 78 * But internally the function depends on being called from 79 * tee_svc_do_call() with pointer to the struct thread_svc_regs saved by 80 * thread_svc_handler() in r8. 81 * 82 * The argument ret is already in r0 so we don't touch that and let it 83 * propagate as return value of the called 84 * tee_svc_unwind_enter_user_mode(). 85 */ 86FUNC syscall_sys_return , : 87 mov r1, #0 /* panic = false */ 88 mov r2, #0 /* panic_code = 0 */ 89 mov r3, r8 /* pointer to struct thread_svc_regs */ 90 b tee_svc_sys_return_helper 91END_FUNC syscall_sys_return 92 93/* 94 * User space sees this function as: 95 * void syscall_panic(uint32_t code) __noreturn; 96 * 97 * But internally the function depends on being called from 98 * tee_svc_do_call() with pointer to the struct thread_svc_regs saved by 99 * thread_svc_handler() in r8. 100 */ 101FUNC syscall_panic , : 102 mov r1, #1 /* panic = true */ 103 mov r2, r0 /* panic_code = 0 */ 104 mov r3, r8 /* pointer to struct thread_svc_regs */ 105 ldr r0, =TEE_ERROR_TARGET_DEAD 106 b tee_svc_sys_return_helper 107END_FUNC syscall_panic 108