aboutsummaryrefslogtreecommitdiff
path: root/core/arch/arm32/tee
diff options
context:
space:
mode:
authorJens Wiklander <jens.wiklander@linaro.org>2014-11-03 16:02:00 +0100
committerJens Wiklander <jens.wiklander@linaro.org>2014-11-27 11:16:04 +0100
commita7ec939bc1cd7bb48b396826f496b14d98069849 (patch)
treea7dfad4b1d922b60a78df556aaf8a28ba676fc4a /core/arch/arm32/tee
parent3da2f6734972851869c6c03fe8e56db737cc4b22 (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.c142
-rw-r--r--core/arch/arm32/tee/arch_svc_asm.S231
-rw-r--r--core/arch/arm32/tee/arch_svc_private.h38
-rw-r--r--core/arch/arm32/tee/sub.mk3
-rw-r--r--core/arch/arm32/tee/tee_svc_asm.S265
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