fence

fence

RISC-V 汇编 参考

lyszt.net 更详细地介绍了 fence 和其他 RISC-V 指令。

描述

FENCE 指令用于按照其他 RISC-V hart 和外部设备或协处理器所观察到的顺序,对设备 I/O 和内存访问进行排序。设备输入(I)、设备输出(O)、内存读(R)和内存写(W)的任意组合都可以相对于这些相同类型的任意组合进行排序。通俗地说,其他任何 RISC-V hart 或外部设备都不能在 FENCE 之前观察到 successor 集合中的任何操作先于 FENCE 之前的 predecessor 集合中的任何操作。memorymodel 提供了 RISC-V 内存一致性模型的精确描述。

FENCE 指令还对 hart 所进行的、被外部设备所进行的存储器读和写所观察到的存储器读和写进行排序。然而,FENCE 指令不对使用任何其他信号机制的外部设备所进行的事件观察进行排序。

ℹ
设备可能通过某种外部通信机制观察到对存储器位置的访问,例如,驱动中断信号到中断控制器的存储器映射控制寄存器。这种通信超出了 FENCE 排序机制的范围,因此 FENCE 指令无法保证中断信号的变化何时对中断控制器可见。特定设备可能提供额外的排序保证以减少软件开销,但这些都超出了 RISC-V 内存模型的范围。

EEI 将定义哪些 I/O 操作是可能的,特别是哪些存储器地址在被加载和存储指令访问时将被分别视为并按设备输入和设备输出操作排序,而不是存储器读和写。例如,存储器映射 I/O 设备通常使用非缓存加载和存储进行访问,这些访问使用 I 和 O 位而不是 R 和 W 位进行排序。指令集扩展还可能描述新的 I/O 指令,这些指令也将使用 FENCE 指令中的 I 和 O 位进行排序。

Fence 模式编码

FENCE 模式字段 fm 定义了 FENCE 指令的语义。一个 FENCE(fm=0000)将其 predecessor 集合中的所有存储器操作排序在其 successor 集合中的所有存储器操作之前。

FENCE.TSO 指令编码为 fm=1000、predecessor=RW、successor=RW 的 FENCE 指令。FENCE.TSO 将其 predecessor 集合中的所有加载操作排序在其 successor 集合中的所有存储器操作之前,并将其 predecessor 集合中的所有存储操作排序在其 successor 集合中的所有存储操作之前。这使得 FENCE.TSO 的 predecessor 集合中的 non-AMO 存储操作与其 successor 集合中的 non-AMO 加载操作之间无序。

ℹ
因为 FENCE RW,RW 施加的排序是 FENCE.TSO 所施加排序的超集,所以忽略 fm 字段并将 FENCE.TSO 实现为 FENCE RW,RW 是正确的。

FENCE 指令中未使用的字段——rs1 and rd——保留用于未来扩展中的更细粒度 fence。为了向前兼容,基础实现应忽略这些字段#,标准软件应将这些字段置零。同样,许多 fm 和 predecessor/successor 集合设置也保留供未来使用。基础实现应将所有此类保留配置视为 FENCE 指令(fm=0000),标准软件应仅使用非保留配置。

ℹ
我们选择宽松内存模型以允许简单机器实现以及可能的未来协处理器或加速器扩展获得高性能。我们将 I/O 排序与存储器 R/W 排序分开,以避免设备驱动 hart 内不必要的串行化,同时也支持控制附加协处理器或 I/O 设备的替代非存储器路径。简单实现还可以额外忽略 predecessor and successor 字段,并始终对所有操作执行保守的 FENCE。