Linux系统调用源码分析(四)

前文讲了Linux系统调用是基于ARMv8的异常模式来实现的,说是异常模式,其实就是4种程序运行的等级,分别是:

EL0-User,一般的应用程序运行在此级别。

EL1-Suervisor,操作系统运行在此级别,Linux内核,设备驱动等都运行在此级别。

EL2-Hypervisor,虚拟机系统运行在此级别,在此级别Guest客户机的虚拟内存需要做多一层Stage2的地址转换。

EL3-Secure monitor,安全级别。

 

除了EL0没有异常向量表外,其他级别都有一个VBAR_ELx寄存器保存异常向量表的基地址,也就是说ARMv8一共支持3个异常向量表,但在Linux内核平常只用到了VBAR_EL1,如果运行了虚拟机则会额外用到VBAR_EL2。

图片

由上图可知,每个异常向量表分为4组情形,每组情形又有4个向量入口地址,分别处理4种不同类型的异常。每个向量入口空间128字节,也就是说,在这个空间里可以放入32条指令(每条指令4字节)。举个例子,如果一个设备发出了一个异步IRQ中断,这时CPU自动把VBAR_EL1的地址,和第二组向量的IRQ类型的偏移量相加(VBAR_EL1+0x280),得出向量入口地址,然后跳转到那里,执行里面的第一条指令。

这时候可能有朋友会问,VBAR_EL1保存的地址是物理地址还是虚拟地址?答案是,都可以。像在uboot中不会开启MMU,这时配置的是物理地址,在Linux中会开启MMU,使用就是虚拟地址。也就是说CPU发作访问指令是在寻址之前的,寻址之后MMU要如何处理,那是MMU的事,和向量表寄存器没有关系了,而且向量表寄存器指向的地址是常驻内存的,不会发生缺页的情况,所以也不用更担心在执行的过程中会引发缺页异常。

下面我们再看一下kernel_ventry向量入口定义的代码:

图片

75行,.align 7汇编伪代码,表式这一向量入口指令编译是以2的7次方,即128位对齐的,也就是说每一个向量入口都以128字节对齐,只要此宏的代码限制在128字节以内就可对应ARM的向量偏移机制,正常的工作。

76行,定义了ARM64_UNMAP_KERNEL_AT_EL0使能从EL1返回EL0的时候,把kernel unmap掉的功能,这样让user不可见内核。

80行,读取tpidrro_el0寄存器,取得当前线程ID

81行,把tpidrro_el0寄存器清0

89行,当前堆栈指针sp的内容减去S_FRAME_SIZE(值为sizeof(struct pt_regs)),由于Linux堆栈是向低地址方向发展的,所以此行代码的功能相当于在堆栈中拉出S_FRAME_SIZE大小的空间,用于保存当前的执行现场(保存通用寄存器的值)

90行,\el,\label的意思是引用传入宏的参数,\()的意思与C语言的#一样表示连接字符串,所以,把参数代入后此行代码等同与b el0_sync

 

el0_sync就是el0的同步异常处理程序(代码归代码,当前异常级别为EL1),此代码前文已经分析过了,在此不再赘述。

 

下面我们看一下整个系统调用的流程,如图所示:

 

1、当程序调用C库打开一个文件的时候,把系统调用的参数放入x1-x6寄存器(系统调用最多用到6个参数),把系统调用号放在x8寄存器里,然后执行SVC指令,CPU进入EL1。

2、CPU把当前程序指针寄存器PC放入ELR_EL1里,把PSTATE放入SPSR_EL1里,把系统调用的原因放在ESR_EL1里,然后通过VBAR_EL1加上偏移量取得异常向量的入口地址,接着开始执行入口的第一行代码。这一过程是CPU自动完成的,不需要程序干预。

3、内核保存异常发生时程序的执行现场,然后通过异常的原因及系统调用号找到系统调用的具体函数,接着执行函数,把返回值放入x0寄存器里。这一过程是内核实现的,每种操作系统可以有不同的实现。

4、系统调用完成后,程序需要主动设置ELR_EL1和SPSR_EL1的值,原因是异常会发生嵌套,一旦发生异常嵌套ELR_EL1和SPSR_EL1的值就会随之发生改变,所以当系统调用返回时,需要恢复之前保存的ELR_EL1和SPSR_EL1的值。最后内核调用ERET命令,CPU自动把ELR_EL1写回PC,把SPSR_EL1写回PSTATE,并返回到EL0里。这时程序就返回到用户态继续运行了。

 

以上就是系统调用的整体流程,系统调用是理解Linux内核的一个窗口,理解了系统调用就相当于打开了这扇窗口,以后追踪文件系统,网络收发,都有线索可循了。

 

原文:https://mp.weixin.qq.com/s/Bgpn3Pvih63UWF0tLrHxOQ

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值