RISC-V Linux 向量扩展支持

本文档简要概述了 Linux 提供给用户空间的接口,以便支持 RISC-V 向量扩展的使用。

1. prctl() 接口

添加了两个新的 prctl() 调用,以允许程序管理用户空间中向量使用的启用状态。 这些接口的预期使用指南是为 init 系统提供一种修改在其域下运行的进程的 V 可用性的方法。 不建议在库例程中调用这些接口,因为库不应覆盖从父进程配置的策略。 此外,用户必须注意这些接口不可移植到非 Linux 或非 RISC-V 环境,因此不鼓励在可移植代码中使用。 要获取 ELF 程序中 V 的可用性,请读取辅助向量中 COMPAT_HWCAP_ISA_VELF_HWCAP 位。

  • prctl(PR_RISCV_V_SET_CONTROL, unsigned long arg)

    设置调用线程的向量启用状态,其中 control 参数由两个 2 位启用状态和一个用于继承模式的位组成。 调用进程的其他线程不受影响。

    启用状态是一个三态值,每个值在 control 参数中占据 2 位空间

    • PR_RISCV_V_VSTATE_CTRL_DEFAULT: 在 execve() 上使用系统范围的默认启用状态。 系统范围的默认设置可以通过 sysctl 接口进行控制(请参阅下面的 sysctl 部分)。

    • PR_RISCV_V_VSTATE_CTRL_ON: 允许线程运行向量。

    • PR_RISCV_V_VSTATE_CTRL_OFF: 禁止向量。 在这种情况下执行向量指令将陷入并导致线程终止。

    arg:control 参数是一个 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]:表示调用线程的向量启用状态。 一旦启用向量,调用线程就无法关闭向量。 如果此掩码中的值为 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:不支持向量,当前或下一个掩码的启用状态无效;

    • EPERM:如果为调用线程启用了向量,则在 PR_RISCV_V_VSTATE_CTRL_CUR_MASK 中关闭向量。

    成功时
    • 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 程序可以通过读取辅助向量中 COMPAT_HWCAP_ISA_VELF_HWCAP 位来获取 V 对自身的可用性。

    返回值
    • 成功时返回一个非负值;

    • EINVAL:不支持向量。

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] 所指示的那样,向量寄存器会被系统调用破坏。

1: https://github.com/riscv/riscv-v-spec/blob/master/calling-convention.adoc