当在TA 中发生系统调用时,其入口函数在optee_os-master/core/arch/arm/kernel/thread_a64.S
LOCAL_FUNC el0_svc , :
/* get pointer to current thread context in x0 */
get_thread_ctx sp, 0, 1, 2
/* load saved kernel sp */
ldr x0, [x0, #THREAD_CTX_KERN_SP]
/* Keep pointer to initial recod in x1 */
mov x1, sp
/* Switch to SP_EL0 and restore kernel sp */
msr spsel, #0
mov x2, sp /* Save SP_EL0 */
mov sp, x0
/* Call the handler */
bl tee_svc_handler
这里继续调用tee_svc_handler
void tee_svc_handler(struct thread_svc_regs *regs)
{
size_t scn;
size_t max_args;
syscall_t scf;
COMPILE_TIME_ASSERT(ARRAY_SIZE(tee_svc_syscall_table) ==
(TEE_SCN_MAX + 1));
thread_user_save_vfp();
/* TA has just entered kernel mode */
tee_ta_update_session_utime_suspend();
/* Restore foreign interrupts which are disabled on exception entry */
thread_restore_foreign_intr();
得到系统调用的id
get_scn_max_args(regs, &scn, &max_args);
trace_syscall(scn);
if (max_args > TEE_SVC_MAX_ARGS) {
DMSG("Too many arguments for SCN %zu (%zu)", scn, max_args);
set_svc_retval(regs, TEE_ERROR_GENERIC);
return;
}
if (scn > TEE_SCN_MAX)
scf = syscall_not_supported;
else
根据id 调用系统调用,所以在optee中所有的系统调用都是定义在tee_svc_syscall_table 这个数组中
scf = tee_svc_syscall_table[scn].fn;
set_svc_retval(regs, tee_svc_do_call(regs, scf));
if (scn != TEE_SCN_RETURN) {
/* We're about to switch back to user mode */
tee_ta_update_session_utime_resume();
}
}
static const struct syscall_entry tee_svc_syscall_table[] = {
SYSCALL_ENTRY(syscall_get_time),
}
以get_time 为例
TEE_Result syscall_get_time(unsigned long cat, TEE_Time *mytime)
{
TEE_Result res, res2;
struct tee_ta_session *s = NULL;
TEE_Time t;
//session是TA和CA 通信的基础,得到当前的session
res = tee_ta_get_current_session(&s);
if (res != TEE_SUCCESS)
return res;
//根据cat来判断要得到哪个时间
switch (cat) {
case UTEE_TIME_CAT_SYSTEM:
res = tee_time_get_sys_time(&t);
break;
case UTEE_TIME_CAT_TA_PERSISTENT:
res = tee_time_get_ta_time((const void *)&s->ctx->uuid, &t);
break;
case UTEE_TIME_CAT_REE:
res = tee_time_get_ree_time(&t);
break;
default:
res = TEE_ERROR_BAD_PARAMETERS;
break;
}
//成功得到时间后,通过tee_svc_copy_to_user 将数据copy到user space的TA
if (res == TEE_SUCCESS || res == TEE_ERROR_OVERFLOW) {
res2 = tee_svc_copy_to_user(mytime, &t, sizeof(t));
if (res2 != TEE_SUCCESS)
res = res2;
}
return res;
}
以UTEE_TIME_CAT_SYSTEM 为例的话,其实现如下:
TEE_Result tee_time_get_sys_time(TEE_Time *time)
{
return _time_source.get_sys_time(time);
}
LOCAL_FUNC el0_svc , :
/* get pointer to current thread context in x0 */
get_thread_ctx sp, 0, 1, 2
/* load saved kernel sp */
ldr x0, [x0, #THREAD_CTX_KERN_SP]
/* Keep pointer to initial recod in x1 */
mov x1, sp
/* Switch to SP_EL0 and restore kernel sp */
msr spsel, #0
mov x2, sp /* Save SP_EL0 */
mov sp, x0
/* Call the handler */
bl tee_svc_handler
这里继续调用tee_svc_handler
void tee_svc_handler(struct thread_svc_regs *regs)
{
size_t scn;
size_t max_args;
syscall_t scf;
COMPILE_TIME_ASSERT(ARRAY_SIZE(tee_svc_syscall_table) ==
(TEE_SCN_MAX + 1));
thread_user_save_vfp();
/* TA has just entered kernel mode */
tee_ta_update_session_utime_suspend();
/* Restore foreign interrupts which are disabled on exception entry */
thread_restore_foreign_intr();
得到系统调用的id
get_scn_max_args(regs, &scn, &max_args);
trace_syscall(scn);
if (max_args > TEE_SVC_MAX_ARGS) {
DMSG("Too many arguments for SCN %zu (%zu)", scn, max_args);
set_svc_retval(regs, TEE_ERROR_GENERIC);
return;
}
if (scn > TEE_SCN_MAX)
scf = syscall_not_supported;
else
根据id 调用系统调用,所以在optee中所有的系统调用都是定义在tee_svc_syscall_table 这个数组中
scf = tee_svc_syscall_table[scn].fn;
set_svc_retval(regs, tee_svc_do_call(regs, scf));
if (scn != TEE_SCN_RETURN) {
/* We're about to switch back to user mode */
tee_ta_update_session_utime_resume();
}
}
static const struct syscall_entry tee_svc_syscall_table[] = {
SYSCALL_ENTRY(syscall_get_time),
}
以get_time 为例
TEE_Result syscall_get_time(unsigned long cat, TEE_Time *mytime)
{
TEE_Result res, res2;
struct tee_ta_session *s = NULL;
TEE_Time t;
//session是TA和CA 通信的基础,得到当前的session
res = tee_ta_get_current_session(&s);
if (res != TEE_SUCCESS)
return res;
//根据cat来判断要得到哪个时间
switch (cat) {
case UTEE_TIME_CAT_SYSTEM:
res = tee_time_get_sys_time(&t);
break;
case UTEE_TIME_CAT_TA_PERSISTENT:
res = tee_time_get_ta_time((const void *)&s->ctx->uuid, &t);
break;
case UTEE_TIME_CAT_REE:
res = tee_time_get_ree_time(&t);
break;
default:
res = TEE_ERROR_BAD_PARAMETERS;
break;
}
//成功得到时间后,通过tee_svc_copy_to_user 将数据copy到user space的TA
if (res == TEE_SUCCESS || res == TEE_ERROR_OVERFLOW) {
res2 = tee_svc_copy_to_user(mytime, &t, sizeof(t));
if (res2 != TEE_SUCCESS)
res = res2;
}
return res;
}
以UTEE_TIME_CAT_SYSTEM 为例的话,其实现如下:
TEE_Result tee_time_get_sys_time(TEE_Time *time)
{
return _time_source.get_sys_time(time);
}