5.2.1 IPIPE区分双核系统调用(复用x8寄存器)

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客

原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

5.2 ARM64 Xenomai系统调用

5.2.1 IPIPE区分双核系统调用(复用x8寄存器)

回顾一下《5.1. ARM64 Linux系统调用》,当程序在用户层(EL0)执行 SVC 指令时,它会触发一个同步异常(即软件中断),导致处理器进入更高的特权级别(通常是 EL1,即操作系统运行的级别)。

以write 系统调用为例,其中的关键代码片段如下:

0x0000fffff7f08c7c <+44>:    mov     x8, #0x40  // #64
0x0000fffff7f08c80 <+48>:    svc     #0x0

在发起 SVC 指令之前,应用程序需要将系统调用号以及任何必要的参数放置在特定的寄存器中。对于 AArch64 来说:系统调用号通常放在 x8 寄存器。在当前的例子中,x8 被设置为 0x40。

IPIPE是不可能改变上述指令和规则的,只能在兼容的基础上创新。

具体的方法是:x8是64位的通用寄存器,其中传递的系统调用号,以__COBALT_SYSCALL_BIT(0x10000000)为界限划分,0x10000000以下的范围给Linux使用,0x10000000及以上的范围给Xenomai使用。

实际上,ARM64 Linux根本用不了这么大的范围。宏定义__NR_syscalls它表示系统调用表的大小,即支持的最大系统调用编号加一,定义在include/uapi/asm-generic/unistd.h,当前的值是294(#define __NR_syscalls 294)。所以只要发现x8中的系统调用号超过__NR_syscalls,就必然是Xenomai系统调用。

接下来看一下Xenomai系统调用号和系统调用表的定义。

Xenomai系统调用号定义在include/xenomai/cobalt/uapi/syscall.h,起始系统调用号sc_cobalt_bind竟然是0,说好的从0x10000000开始的呢?

别着急,来看以下Xenomai是怎么通过x8传递系统调用号的。

应用程序自身一般是不会直接使用汇编指令svc来触发系统调用的,而是通过调用库函数来间接触发系统调用。这里就有操作空间了。

在用户层,Xenomai3的实时核是cobalt,它在用户层的库是libcobalt。参考lib/cobalt/arch/arm64/include/asm/xenomai/syscall.h,使用svc触发系统调用之前,总是使用宏__xn_syscode(__nr),把Xenomai原始的系统调用号,与0x10000000进行逻辑或运算,赋值到w8即x8寄存器的低32位。

在内核层,通过宏__xn_syscall(__regs),对x8寄存器的值执行与用户层相反的操作,即与~0x10000000进行逻辑与运算,得到原始的系统调用号。下图的例子是以sc_cobalt_read(#define sc_cobalt_read 81)为例子,进行说明。

第1186行,两个判断条件都成立,会依次调用ipipe_fastcall_hook->handle_head_syscall。

在handle_head_syscall中,第498行,通过宏__xn_syscall(__regs)得到原始系统调用号0x51。

接下来的章节,会用实例从用户层和内核层来演示Xenomai系统调用。

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客

原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值