Power Architecture 64 位 Linux 系统调用 ABI¶
syscall¶
调用¶
系统调用通过 `sc` 指令进行,并在 `sc` 指令之后的指令处继续执行返回。
如果 AT_HWCAP2 ELF 辅助向量中出现 PPC_FEATURE2_SCV,则 `scv 0` 指令是一种替代方法,它可能提供更好的性能,但调用序列有一些差异。
系统调用调用序列[1]与 Power Architecture 64 位 ELF ABI 规范 C 函数调用序列相匹配,包括寄存器保存规则,但有以下差异。
参数¶
系统调用号在 r0 中指定。
一个系统调用最多有 6 个整数参数,通过 r3-r8 传递。
返回值¶
对于 `sc` 指令,返回值和错误条件都会返回。cr0.SO 是错误条件,r3 是返回值。当 cr0.SO 清除时,系统调用成功,r3 是返回值。当 cr0.SO 设置时,系统调用失败,r3 是错误值(通常对应于 errno)。
对于 `scv 0` 指令,如果返回值是 -4095..-1(即,它作为无符号比较 >= -MAX_ERRNO (-4095)),则表示失败,在这种情况下,错误值是返回值的相反数。
堆栈¶
系统调用不会修改调用者的堆栈帧。例如,不会使用调用者的堆栈帧 LR 和 CR 保存字段。
寄存器保存规则¶
寄存器保存规则与 ELF ABI 调用序列匹配,但有一些差异。
对于 `sc` 指令,与 ELF ABI 的差异如下:
寄存器 |
保存规则 |
目的 |
---|---|---|
r0 |
易失 |
(系统调用号。) |
r3 |
易失 |
(参数 1 和返回值。) |
r4-r8 |
易失 |
(参数 2-6。) |
cr0 |
易失 |
(cr0.SO 是返回错误条件。) |
cr1, cr5-7 |
非易失 |
|
lr |
非易失 |
对于 `scv 0` 指令,与 ELF ABI 的差异如下:
寄存器 |
保存规则 |
目的 |
---|---|---|
r0 |
易失 |
(系统调用号。) |
r3 |
易失 |
(参数 1 和返回值。) |
r4-r8 |
易失 |
(参数 2-6。) |
所有浮点和向量数据寄存器以及控制和状态寄存器都是非易失的。
事务内存¶
如果处理器处于事务或挂起事务状态,则系统调用行为可能会发生变化,并且系统调用可能会影响事务的行为。
如果在进行系统调用时处理器处于挂起状态,则系统调用将正常执行,并将正常返回。系统调用将在挂起状态下执行,因此其副作用将根据通常的事务内存语义持久化。系统调用可能会或可能不会导致硬件注销该事务。
如果在进行系统调用时处理器处于事务状态,则行为取决于 AT_HWCAP2 ELF 辅助向量中是否存在 PPC_FEATURE2_HTM_NOSC。
如果存在(对于较新的内核是这种情况),则将不会执行系统调用,并且内核将在 TEXASR SPR 中使用失败代码 TM_CAUSE_SYSCALL | TM_CAUSE_PERSISTENT 注销该事务。
如果不存在(较旧的内核),则内核将挂起事务状态,并且系统调用将像挂起状态系统调用一样继续进行,并且在返回调用者之前恢复事务状态。这种情况未明确定义或支持,因此不应依赖此行为。
`scv 0` 系统调用将始终表现为 PPC_FEATURE2_HTM_NOSC。
ptrace¶
当跟踪系统调用 (PTRACE_SYSCALL) 时,pt_regs.trap 值包含系统调用类型,可用于区分 `sc` 和 `scv 0` 系统调用,并且可以解释不同的寄存器约定。
如果 (pt_regs.trap & 0xfff0) 的值为 0xc00,则表示系统调用是使用 `sc` 指令执行的;如果值为 0x3000,则表示系统调用是使用 `scv 0` 指令执行的。
vsyscall¶
vsyscall 调用序列与系统调用调用序列匹配,但有以下差异。一些 vsyscall 可能具有不同的调用序列。
参数和返回值¶
r0 不用作输入。vsyscall 由其地址选择。
堆栈¶
vsyscall 可能使用或不使用调用者的堆栈帧保存区域。
寄存器保存规则¶
r0 |
易失 |
cr1, cr5-7 |
易失 |
lr |
易失 |
调用¶
vsyscall 通过分支带链接指令到 vsyscall 函数地址执行。
事务内存¶
vsyscall 将在与调用者相同的事务状态下运行。vsyscall 可能会或可能不会导致硬件注销该事务。