trusty系统调用

trusty中,可以通过系统调用陷入kernel,获取kernel服务。

这里记录一下trusty的系统调用框架结构,代码基于google trusty源码

1、应用程序接口
在文件lib/include/trusty_syscalls.h中,申明了上层调用的syscall接口。如:

1 // send_msg()系统调用的号码是0x23
2 #define __NR_send_msg 0x23
3 // send_msg()系统调用原型申明
4 long send_msg (uint32_t handle, ipc_msg_t *msg);

这样,应用层程序可以调用这些接口获取系统服务了。

 

2、陷入内核
在lib/lib/libc-trusty/arch/arm/trusty_syscall.S文件中,
// 各个系统调用函数对应的汇编代码

.section .text.send_msg
FUNCTION(send_msg)
    ldr r12, =__NR_send_msg // 系统调用号置入r12寄存器
    swi #0    // 通过swi陷入内核,执行内核代码
    bx lr    // 返回lr寄存器位置

用户空间的这些代码是通过脚本解析生成的,看注释。具体生成方式方法需要在明确要再明确一下。

 

3、内核中系统调用服务函数申明
lk/trusty/lib/syscall目录定好了trusty内核处理系统调用的框架。
在lk/trusty/lib/trusty/include/syscall_table.h定义了一系列宏,其余用户空间的syscall号码一一对应。

形如:DEF_SYSCALL(0x23, send_msg, long, 2, uint32_t handle, ipc_msg_t *msg)

在lk/trusty/lib/syscall/syscall.c文件中其进行展开,得到系统调用函数数组:
#define DEF_SYSCALL(nr, fn, rtype, nr_args, ...) rtype sys_##fn (void);
=》long sys_send_msg(void);
#define DEF_SYSCALL(nr, fn, rtype, nr_args, ...) [(nr)] = (unsigned long) (sys_##fn),
=》[0x23] = (unsigned long) sys_send_msg,
前一个做函数原型申明,后一个定义了函数指针数组,

1 long sys_send_msg(void);
2 
3 const unsigned long syscall_table [] = {
4 ……
5 [0x23] = (unsigned long) sys_send_msg,
6 ……
7 };

这些sys_***类似的函数要在kernel中实现功能。

 

4、系统调用过程
用户调用到swi指令,这是arm软中断指令,此时CPU会强制从系统异常向量表的软中断异常处开始执行(可能为0x00000008),
trusty中这里安排了一条跳转指令,直接跳到arm_syscall符号处。
external/lk/arch/arm/arm/start.S

 1 .section ".text.boot"
 2 .globl _start
 3 _start:
 4     b platform_reset
 5     b arm_undefined
 6     b arm_syscall
 7     b arm_prefetch_abort
 8     b arm_data_abort
 9     b arm_reserved
10     b arm_irq
11     b arm_fiq
12 #if WITH_SMP
13     b arm_reset
14 #endif

该标号在

lk/trusty/lib/syscall/arch/arm/syscall.S中有定义:

 1 /* ARM syscall ABI
 2  * ===============
 3  * Only syscalls with 4 args (max) are currently supported
 4  * r0-r3 = args
 5  * r0-r1 = return value (r0 only if 32-bit retval)
 6  * r12   = syscall number, expected to be trashed.
 7  * syscalls run with interrupts enabled
 8  */
 9 FUNCTION (arm_syscall)
10         srsdb   sp!, #MODE_SVC
11         sub     sp, sp, #8
12         stmia   sp, { r13-r14 }^
13         // 保存r13、r14、spsr相关寄存器
14 
15         cpsie   iaf
16         // 开中断,cpsr中相关位
17 
18         ldr     r14, =nr_syscalls
19         ldr     r14, [r14]
20         // 将nr_syscalls的值放入r14,nr_syscalls是当前系统支持的系统调用个数
21         cmp     r12, r14
22         // 比较r12与r14,如r12保存的是中断请求号
23 
24         ldrlo   r14, =syscall_table
25         // ldrlo是条件加载,如果r12<r14,将syscall_table地址置入r14,
26         // syscall_table就是syscall服务函数数组的地址
27         ldrlo   r14, [r14, r12, lsl#2]
28         // 将r14 + r12 * 4的值放入r14寄存器,该值即为对应系统调用号的服务函数地址
29         rsblos  r12, r14, #1    /* This will set the same flags as the cmp above */
30         // rsb逆向减法指令,r12 = 1 - r14,结果影响cpsr
31         ldrhs   r14,=sys_undefined
32         // r14置入sys_undefined函数的地址(如果1 >= r14?)
33         blx     r14
34         // 跳转执行r14指示的syscall程序
35 
36         cpsid   iaf
37         // 关中断
38 
39         ldmia   sp, { r13-r14 }^
40         add     sp, sp, #8
41         rfeia   sp!
42         // 恢复之前的r13、r14等寄存器

 

这样上层请求的系统调用最终会进入内核中对应的服务函数中执行

 

posted @ 2020-09-05 23:48  hunterDing  阅读(652)  评论(0编辑  收藏  举报