Power Architecture 64 位 Linux 系统调用 ABI

系统调用

调用

系统调用通过 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 跟踪系统调用(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 可能会也可能不会导致事务被硬件判定为失败。