RISC-V Linux 的向量扩展支持¶
本文档简要概述了 Linux 为支持用户空间使用 RISC-V 向量扩展而提供的接口。
1. prctl() 接口¶
添加了两个新的 prctl() 调用,允许程序管理在用户空间使用向量(Vector)的启用状态。这些接口的预期使用准则是为 init 系统提供一种修改其域下运行进程的 V 可用性的方法。不建议在库例程(library routines)中调用这些接口,因为库不应覆盖从父进程配置的策略。此外,用户必须注意这些接口不可移植到非 Linux 或非 RISC-V 环境,因此不建议在可移植代码中使用。要在 ELF 程序中获取 V 的可用性,请读取辅助向量(auxiliary vector)中 ELF_HWCAP 的 COMPAT_HWCAP_ISA_V 位。
prctl(PR_RISCV_V_SET_CONTROL, unsigned long arg)
设置调用线程的向量启用状态,其中控制参数由两个 2 位启用状态和一个用于继承模式的位组成。调用进程的其他线程不受影响。
启用状态是一个三态值,每个值在控制参数中占用 2 位空间
PR_RISCV_V_VSTATE_CTRL_DEFAULT:在 execve() 时使用系统范围的默认启用状态。系统范围的默认设置可以通过 sysctl 接口进行控制(参见下文的 sysctl 部分)。PR_RISCV_V_VSTATE_CTRL_ON:允许在该线程中运行 Vector。PR_RISCV_V_VSTATE_CTRL_OFF:不允许使用 Vector。在此类条件下执行向量指令将产生陷阱(trap)并导致线程终止。
arg:控制参数是一个 5 位值,由 3 部分组成,分别由 3 个掩码进行访问。
3 个掩码
PR_RISCV_V_VSTATE_CTRL_CUR_MASK、PR_RISCV_V_VSTATE_CTRL_NEXT_MASK和PR_RISCV_V_VSTATE_CTRL_INHERIT分别代表 bit[1:0]、bit[3:2] 和 bit[4]。bit[1:0] 对应当前线程的启用状态,bit[3:2] 处的设置在下一次 execve() 时生效。bit[4] 定义了 bit[3:2] 中设置的继承模式。PR_RISCV_V_VSTATE_CTRL_CUR_MASK:bit[1:0]:决定调用线程的向量启用状态。一旦启用 Vector,调用线程将无法将其关闭。如果此掩码中的值为PR_RISCV_V_VSTATE_CTRL_OFF但当前启用状态并非关闭,则prctl()调用将失败并返回EPERM。在此处设置PR_RISCV_V_VSTATE_CTRL_DEFAULT不会产生任何效果,只是恢复原来的启用状态。PR_RISCV_V_VSTATE_CTRL_NEXT_MASK:bit[3:2]:决定调用线程在下一次 execve() 系统调用时的向量启用设置。如果在此掩码中使用PR_RISCV_V_VSTATE_CTRL_DEFAULT,则启用状态将由 execve() 发生时的系统范围启用状态决定。PR_RISCV_V_VSTATE_CTRL_INHERIT:bit[4]:PR_RISCV_V_VSTATE_CTRL_NEXT_MASK设置的继承模式。如果设置了此位,则后续的 execve() 不会清除PR_RISCV_V_VSTATE_CTRL_NEXT_MASK和PR_RISCV_V_VSTATE_CTRL_INHERIT中的设置。即使系统范围的默认值发生更改,此设置依然保持不变。
- 返回值
成功时返回 0;
EINVAL:不支持 Vector,当前或下一个掩码的启用状态无效;
EPERM:如果已为调用线程启用了 Vector,却试图在 PR_RISCV_V_VSTATE_CTRL_CUR_MASK 中关闭 Vector。
- 成功时:
对 PR_RISCV_V_VSTATE_CTRL_CUR_MASK 的有效设置将立即生效。PR_RISCV_V_VSTATE_CTRL_NEXT_MASK 中指定的启用状态在下一次 execve() 调用时生效;如果设置了 PR_RISCV_V_VSTATE_CTRL_INHERIT 位,则在所有随后的 execve() 调用中生效。
每次成功的调用都会覆盖调用线程先前的设置。
prctl(PR_RISCV_V_GET_CONTROL)
获取调用线程的相同向量启用状态。下一次 execve() 调用的设置以及继承位会通过按位或(OR)组合在一起。
请注意,ELF 程序可以通过读取辅助向量中
ELF_HWCAP的COMPAT_HWCAP_ISA_V位来获取自身 V 的可用性。- 返回值
成功时返回非负值;
EINVAL:不支持 Vector。
2. 系统运行时配置(sysctl)¶
为了减轻信号栈扩展带来的 ABI 影响,向管理员、发行版维护人员和开发人员提供了一种策略机制,以 sysctl 旋钮(knob)的形式控制用户空间进程的默认向量启用状态
/proc/sys/abi/riscv_v_default_allow
向该文件写入文本形式的 0 或 1 可以为新启动的用户空间程序设置系统默认的启用状态。有效值为
0:默认不允许新进程执行向量代码。
1:默认允许新进程执行向量代码。
读取该文件会返回当前的系统默认启用状态。
在每次 execve() 调用时,新进程的新启用状态都会被设为系统默认值,除非
为调用进程设置了 PR_RISCV_V_VSTATE_CTRL_INHERIT,且 PR_RISCV_V_VSTATE_CTRL_NEXT_MASK 中的设置不是 PR_RISCV_V_VSTATE_CTRL_DEFAULT。或者,
PR_RISCV_V_VSTATE_CTRL_NEXT_MASK 中的设置不是 PR_RISCV_V_VSTATE_CTRL_DEFAULT。
修改系统默认启用状态不会影响任何未进行 execve() 调用的现有进程或线程的启用状态。
3. 跨系统调用的向量寄存器状态¶
正如 V 扩展 1.0 版本 [1] 所指出的,向量寄存器会被系统调用破坏(clobbered)。
1: https://github.com/riscv/riscv-v-spec/blob/master/calling-convention.adoc