网站开发 平台建设,杭州企业建站,wordpress p=,企业管理咨询公司招聘说明
在深入一点了解了系统调用以及非安全world#xff08;REE#xff09;/安全world#xff08;TEE#xff09;切换时参数传递和结果返回的实现原理#xff08;通过通用寄存器实现#xff09;#xff0c;对通用寄存器的使用有了一个全新的认识#xff0c;对知识做个总…说明
在深入一点了解了系统调用以及非安全worldREE/安全worldTEE切换时参数传递和结果返回的实现原理通过通用寄存器实现对通用寄存器的使用有了一个全新的认识对知识做个总结。
简介
Arm AArch64状态下提供了31个64位通用寄存器X0 ~ X30。
通用体现
不同于特殊寄存器每一bit可能都有特殊作用通用寄存器本身没有任何作用就是一个64位存储器其作用是由使用体现。任意时间任意环境任意特权等级任意安全等级用户态/内核态都可以使用这些通用寄存器没有任何访问限制。 应用层调用系统调用应用态和内核态切换参数传递和结果返回等都是使用通用寄存器实现。应用层程序执行函数调用时参数传递也是使用通用寄存器实现。REE与TEE通信需要做非安全world和安全world切换异常等级切换等也是使用通用寄存器传递参数和运行结果。任何异常等级中函数执行也是使用这些通用寄存器切换异常等级也不会丢失。
重点通用寄存器是参数传递返回结果等一些通用行为使用的寄存器在任何场景环境下用户态/内核态切换安全world/非安全world切换都是一样没有其它寄存器。
32位形态
X0 ~ X30是64位寄存器也可以作为32位寄存器使用其32位形态(W0 ~ W30)取自相应64位寄存器(X0 ~ X30)的低32位例如W0映射到X0的低32位,W1映射到X1的低32位。读写其32位形态行为如下
读取从32位寄存器(W0-W30)读取时,忽略相应64位寄存器(X0-X30)高32位,并保持其它不变。写入将数据写入32位寄存器(W0-W30)时,会将其对应的64位寄存器(X0-X30)的高32位设置为零,例如将0xFFFFFFFF写入W0会将X0设置为0x00000000FFFFFFFF。
用途
通用寄存器的用途更多的是一种使用规范并没有什么强制限制。不同使用场景会有些细微区别。
规范
根据用途通用寄存器可以分为四组。
x0 ~ x7
传递参数
应用层函数调用传递子函数的参数超出的参数用堆栈传递。应用层调用系统调用传递系统调用的参数系统调用只支持6个参数因此只用到了x0 ~ x5。REE与TEE通信SMC请求使用x0 ~ x7 传递参数。
传递返回值
应用层调用系统调用函数调用64位的返回结果保存在x0中。REE与TEE通信ERET使用x0 ~ x3 传递TEE运行结果。
临时存储器
在函数中也可以用作临时寄存器可以保存中间值或调用者的寄存器变量。
X9-X15调用者寄存器
网上描述如果调用者需要在调用另一个函数时保留一些寄存器中的任何值则调用者必须将受影响的寄存器保存在自己的堆栈帧中。 也可以修改子例程而不需要在返回调用函数时保存值到堆栈和从堆栈中恢复它们。后续体会较深时再修正。
X19-X29被调用寄存器
网上描述这些寄存器保存在被调用者内部。 只要在返回前保存并恢复就可以在被调用的子程序中修改。后续体会较深时再修正。
X8, X16-X18, X29, X30特殊目的寄存器
X8 是间接结果寄存器。用于传递间接结果的地址位置例如函数返回大型结构的位置。x8 在系统调用syscall中用于传递系统调用编号。网上描述X16 和 X17 分别是 IP0 和 IP1临时寄存器intra-procedure-call 可以通过veneers或者类似代码使用或者作为子程序调用之间的中间值的临时寄存器。它们可以被函数破坏。veneers代码是链接器自动插入的一小段代码例如当分支跳转目标超出分支指令支持的范围时。X18 是平台寄存器保留供平台 ABI 使用。这是平台上的一个附加临时寄存器没有为其分配特殊含义。X29 是 Frame Pointer 寄存器指向当前方法栈的底部。用于连接栈帧使用时必须保存。X30 是链接寄存器这个寄存器会记录着当前方法的调用方地址 即当前方法调用完成时应该返回的位置。我们进行函数调用的时候会用X30记录当前调用地址等调用函数执行完毕会从X30取出地址进行返回。我们遇到 Crash 要获取方法堆栈其本质就是不断的向上递归每一个 x30 寄存器的记录状态也就是栈上 X30 寄存器的内容 来找到上层调用方。后续体会较深时再修正。
实际使用
系统调用实现
// 标准C库muslsyscall 实现
#define __asm_syscall(...) do { \__asm__ __volatile__ ( svc 0 \: r(x0) : __VA_ARGS__ : memory, cc); \return x0; \ //使用 x0传递返回值} while (0)static inline long __syscall0(long n)
{ register long x8 __asm__(x8) n; //使用 x8传递系统编译编号register long x0 __asm__(x0);__asm_syscall(r(x8));
}
...
static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
{register long x8 __asm__(x8) n; register long x0 __asm__(x0) a; //使用x0 ~ x5传递参数register long x1 __asm__(x1) b;register long x2 __asm__(x2) c;register long x3 __asm__(x3) d;register long x4 __asm__(x4) e;register long x5 __asm__(x5) f;__asm_syscall(r(x8), 0(x0), r(x1), r(x2), r(x3), r(x4), r(x5));
}