第四章 "Smstateen/Ssstateen" 扩展,版本 1.0
可选 RISC-V 扩展的实现有可能在独立的用户线程之间,或在管理程序下运行的独立客户操作系统之间打开隐蔽信道。当某个扩展添加了处理器状态(通常是显式寄存器,也可能是其他形式的状态)时,就会出现此问题,而主操作系统或管理程序不知道这些状态(因此在上下文切换时不会保存/恢复这些状态),但这些状态可以被一个用户线程或客户操作系统修改/写入,并被另一个用户线程或客户操作系统感知/检查/读取。
例如,RISC-V 的高级中断架构(AIA)为一个硬件线程(hart)添加了多达 10 个监督者级 CSR(siselect、sireg、stopi、sseteipnum、sclreipnum、sseteienum、sclreienum、sclaimei、sieh 和 siph),并且硬件也可以选择向后兼容旧的、不支持 AIA 的软件。由于不了解 AIA 的旧管理程序在上下文切换时不知道需要保存/恢复 AIA 的任何新 CSR,这些寄存器就可能在该管理程序上运行的多个客户操作系统之间被用作隐蔽信道。虽然传统做法可能认为这种通信信道无害,但如今对安全的高度关注要求提供方法来堵塞此类信道。
RISC-V 浮点扩展的 f 寄存器和矢量扩展的 v 寄存器同样可能成为用户线程之间的潜在隐蔽信道,但 sstatus 寄存器中的 FS 和 VS 字段避免了这一点。即使操作系统不知道(例如)矢量扩展及其 v 寄存器,当 VS 字段初始化为零时(无论是在机器级由硬件初始化还是由操作系统自己初始化 sstatus 寄存器),对这些寄存器的访问就会被阻止。
显然,防止新的用户级 CSR 被用作隐蔽信道的一种方法是在 mstatus 或 sstatus 中为每个相关扩展添加一个 "XS" 字段,类似于 V 扩展的 VS 字段。然而,考虑到未来可能添加少量状态的扩展数量,这并不被视为一个通用的解决方案。即使使用 64 位的 sstatus(对于 RV32,需要添加 sstatush),也无法确定 sstatus 中是否有足够的剩余位来容纳所有未来的用户级扩展。无论如何,没有必要为此而占用 sstatus(并添加 sstatush)。用于堵塞隐蔽信道的"启用"标志通常不需要在用户线程的上下文切换时进行保存/恢复,这使得它们并不非常适合放在 sstatus 中。因此,为它们提供了新的存放位置。
4.1. 状态启用扩展
Smstateen 和 Ssstateen 扩展共同规定了机器模式和监督者模式的功能。Smstateen 扩展规范包括 mstateen、sstateen和 hstateen* CSR 及其功能。Ssstateen 扩展规范仅包括 sstateen* 和 hstateen* CSR 及其功能。
对于 RV64 硬件线程(hart),此扩展在机器级添加了四个新的 64 位 CSR:mstateen0(机器状态启用 0)、mstateen1、mstateen2 和 mstateen3。
如果实现了监督者模式,则在监督者级定义了另外四个 CSR:sstateen0、sstateen1、sstateen2 和 sstateen3。
如果实现了管理程序扩展,则添加另一组 CSR:hstateen0、hstateen1、hstateen2 和 hstateen3。
对于 RV32,上面列出的寄存器是 32 位的,对于机器级和管理程序的 CSR,每个寄存器对应一组高半 CSR,用于存储其高 32 位:mstateen0h、mstateen1h、mstateen2h、mstateen3h、hstateen0h、hstateen1h、hstateen2h 和 hstateen3h。
RISC-V 指令集手册:第二卷 | © RISC-V International
对于监督者级的 sstateen 寄存器,目前没有添加高半 CSR,因为预计这些寄存器的上 32 位将始终为零,如下文所述。
stateen CSR 的每个位控制对某个扩展状态的较低特权级访问,该扩展未被认为"值得"像 F 和 V 扩展的 FS 和 VS 字段那样在 sstatus 中拥有一个完整的 XS 字段。每个级别提供的寄存器数量为四个,因为预计 4 * 64 = 256 位(机器级和管理程序级)和 4 * 32 = 128 位(监督者级)将在未来很多年(也许只要 RISC-V ISA 还在使用)都足够使用。具体的数字四是在提供位数过少和提供过多可能永远不会用到的 CSR 之间寻求折衷的尝试。未来可能将 stateen CSR 数量加倍的情况将在后面说明。
每个级别的 stateen 寄存器控制对所有较低特权级别状态的访问,但不控制其自身级别的访问。这与现有的 counteren CSR 如何控制对性能计数器寄存器的访问类似。就像 counteren CSR 一样,当 stateen CSR 阻止较低特权级别访问状态时,在这些特权模式之一中尝试执行会读取或写入受保护状态的指令会引发非法指令异常,或者,如果在 VS 或 VU 模式下执行且满足虚拟指令异常的条件,则会引发虚拟指令异常而不是非法指令异常。
当未实现此扩展时,扩展添加的所有状态都可按照该扩展的定义进行访问。
当 stateen CSR 阻止某个特权模式访问状态时,尝试在该特权模式下执行一条会隐式更新状态但不读取状态的指令时,可能会也可能不会引发非法指令或虚拟指令异常。此类情况必须通过明确规定为其中一种方式(引发或不引发异常)来消除歧义。
在某些情况下,stateen CSR 的位将具有双重用途,既作为受控状态启用位,也作为引入该受控状态的 ISA 扩展的启用位。
监督者级 sstateen CSR 的每个位控制用户级(来自 U 模式或 VU 模式)对扩展状态的访问。其意图是从最低有效端(位 0)开始分配 sstateen CSR 的位,一直到位 31,然后继续到下一个编号更高的 sstateen CSR。
对于 sstateen CSR 中每个具有定义用途的位,在匹配的 mstateen CSR 中也定义了相同的位,以控制对同一状态的机器级以下访问。mstateen CSR 的高 32 位(或对于 RV32,对应的高半 CSR)控制对用户级别本来无法访问的状态的访问,因此在监督者级 sstateen CSR 中不需要相应的启用位。其意图是从最高有效端(位 63)开始为此目的分配位,一直到位 32,然后继续到下一个编号更高的 mstateen CSR。如果从最低有效端为 sstateen CSR 分配位的速率足够低,则可能允许在跳到下一个更高编号的 mstateen CSR 之前,从 mstateen CSR 的最高有效端分配位"侵蚀"到低 32 位。在这种情况下,"侵蚀"位的位位置在匹配的 sstateen CSR 中将始终保持为只读零。
对于管理程序扩展,hstateen CSR 的编码与 mstateen CSR 相同,只是控制对虚拟机(来自 VS 和 VU 模式)的访问。
stateen CSR 的每个标准定义位都是 WARL 属性,可以是只读零或只读一,但需满足以下条件。
任何 stateen CSR 中定义为控制某个硬件线程(hart)未实现状态的位,对该 hart 而言是只读零。同样,所有尚未赋予定义含义的保留位也是只读零。对于 mstateen CSR 中每个为零的位(无论是只读零还是被置零),相同的位在匹配的 hstateen 和 sstateen CSR 中也显示为只读零。对于 hstateen CSR 中每个为零的位(无论是只读零还是被置零),在 VS 模式下访问时,相同的位在 sstateen 中也显示为只读零。
监督者级 sstateen CSR 中的位不能是只读一,除非匹配的 mstateen CSR(以及如果存在的话,匹配的 hstateen CSR)中的相同位也是只读一。hstateen CSR 中的位不能是只读一,除非匹配的 mstateen CSR 中的相同位是只读一。
复位时,所有可写的 mstateen 位由硬件初始化为零。如果机器级软件更改了这些值,它负责将 hstateen 和 sstateen CSR 的相应可写位也初始化为零。每个特权级别的软件应设置其各自的 stateen CSR,以指示它准备允许较低特权级软件访问的状态。对于操作系统和管理程序,这通常意味着操作系统或管理程序准备在上下文切换时保存/恢复的状态,或以其他某种方式管理的状态。
对于每个 mstateen CSR,位 63 定义为控制对匹配的 sstateen 和 hstateen CSR 的访问。也就是说,mstateen0 的位 63 控制对 sstateen0 和 hstateen0 的访问;mstateen1 的位 63 控制对 sstateen1 和 hstateen1 的访问;依此类推。同样,每个 hstateen 的位 63 相应地控制对匹配的 sstateen CSR 的访问。
如果管理程序必须为虚拟机模拟一个本应受 sstateen CSR 中某位影响的扩展,则可能需要这种对访问 sstateen CSR 的控制。即使这种模拟不常见,也不应被排除在外。
机器级软件需要相同的控制能力,以便能够模拟管理程序扩展。也就是说,机器级需要控制对监督者级 sstateen CSR 的访问,以便模拟 hstateen CSR(这些 CSR 具有此类控制)。
每个 mstateen CSR 的位 63 仅在未实现管理程序扩展且匹配的监督者级 sstateen CSR 全为只读零时,才能是只读零。在这种情况下,机器级软件应模拟从 S 模式尝试访问受影响的 sstateen CSR,忽略写入操作,并在读取时返回零。每个 hstateen CSR 的位 63 始终是可写的(非只读)。
4.2. 状态启用 0 寄存器
(图 35. 机器状态启用 0 寄存器 (mstateen0))
(图 36. 管理程序状态启用 0 寄存器 (hstateen0))
(图 37. 监督者状态启用 0 寄存器 (sstateen0))
C 位控制对任何和所有自定义状态的访问。这些寄存器中的 C 位本身不是自定义状态;它是标准 CSR(mstateen0、hstateen0 或 sstateen0)的标准字段。
非标准扩展为符合规范而必须满足的要求,不会仅仅因为此位值的改变而放宽。特别是,如果软件设置此位但不执行任何自定义指令或访问任何自定义状态,该软件必须继续按照所有相关 RISC-V 标准的规定执行,否则硬件不符合标准。
FCSR 位控制在浮点指令操作 x 寄存器而非 f 寄存器的情况下(由 Zfinx 及相关扩展(如 Zdinx 等)规定)对 fcsr 的访问。每当 misa.F = 1 时,mstateen0 的 FCSR 位是只读零(因此在 hstateen0 和 sstateen0 中也同样是只读零)。为方便起见,当实现了 stateen CSR 且 misa.F = 0 时,如果一个控制性的 stateen0 CSR 的 FCSR 位为零,则所有浮点指令都会导致非法指令异常(或虚拟指令异常,如果适用),就像它们都访问了 fcsr 一样,无论它们是否真的访问了。
JVT 位控制对由 Zcmt 扩展提供的 jvt CSR 的访问。
mstateen0 中的 SE0 位控制对 hstateen0、hstateen0h 和 sstateen0 CSR 的访问。hstateen0 中的 SE0 位控制对 sstateen0 CSR 的访问。
mstateen0 中的 ENVCFG 位控制对 henvcfg、henvcfgh 和 senvcfg CSR 的访问。hstateen0 中的 ENVCFG 位控制对 senvcfg CSR 的访问。
mstateen0 中的 CSRIND 位控制对由 Sscsrind 扩展提供的 siselect、sireg、vsiselect 和 vsiregCSR 的访问。hstateen0 中的 CSRIND 位控制对由 Sscsrind 扩展提供的 siselect 和 sireg(实际上是 vsiselect 和 vsireg)CSR 的访问。
mstateen0 中的 IMSIC 位控制对 IMSIC 状态的访问,包括由 Ssaia 扩展提供的 CSR stopei 和 vstopei。hstateen0 中的 IMSIC 位控制对客户 IMSIC 状态的访问,包括由 Ssaia 扩展提供的 CSR stopei(实际上是 vstopei)。
将 hstateen0 中的 IMSIC 位设置为零,可以防止虚拟机访问该硬件线程(hart)的 IMSIC,其效果与设置 hstatus.VGEIN = 0 相同。
mstateen0 中的 AIA 位控制对 Ssaia 扩展引入的所有未被 CSRIND 或 IMSIC 位控制的状态的访问。hstateen0 中的 AIA 位控制对 Ssaia 扩展引入的所有未被其自身 CSRIND 或 IMSIC 位控制的状态的访问。
mstateen0 中的 CONTEXT 位控制对由 Sdtrig 扩展提供的 scontext 和 hcontext CSR 的访问。hstateen0 中的 CONTEXT 位控制对由 Sdtrig 扩展提供的 scontext CSR 的访问。
mstateen0 中的 P1P13 位控制对特权规范版本 1.13 引入的 hedelegh 的访问。
mstateen0 中的 SRMCFG 位控制对 Ssqosid 扩展第 18 章引入的 srmcfg CSR 的访问。
4.3. 使用
复位后,当机器级 mstateen CSR 的可写位被初始化为零后,机器级软件可以设置这些寄存器中的位,以启用对受控状态的较低特权级访问。这可能是因为机器级软件知道如何保存/恢复该状态,或者更可能的是,因为机器级软件不进行监督者级环境的切换。(回想一下,mstateen CSR 必须存在的主要原因是使机器级能够模拟管理程序扩展。当机器级不模拟管理程序扩展时,很可能不需要将任何已实现的 mstateen 位保持为零。)
如果机器级将任何可写的 mstateen 位设置为非零值,则它必须通过向其写入零来初始化匹配的 hstateen CSR(如果存在)。并且,如果任何被置为 1 的 mstateen 位在 sstateen CSR 中有匹配的位,机器级软件还必须通过向其写入零来初始化这些 sstateen CSR。通常,机器级软件会希望设置所有 mstateen CSR 的位 63,这需要它向所有 hstateen CSR 写入零。
软件应确保在首次进入监督者级的操作系统时,所有 sstateen CSR 的可写位都初始化为零。然后,操作系统可以设置这些寄存器中的位,以启用用户级对受控状态的访问,这大概是因为它知道如何在上下文切换时保存/恢复该状态。
对于客户操作系统通过相应 hstateen CSR 的位 63 被允许访问的 sstateen CSR,管理程序必须将这些 sstateen CSR 包含在为客户操作系统切换的上下文中。当它启动一个新的客户操作系统时,必须确保这些 sstateen CSR 的可写位被初始化为零,并且必须模拟对任何其他 sstateen CSR 的访问。
如果任何特权级别的软件不支持较低特权级别的多个上下文,则它可以选择通过向其所在级别的 stateen CSR(机器级的 mstateen CSR、操作系统的 sstateen CSR、管理程序的 hstateen CSR)写入全 1 值,来最大化较低特权级对所有状态的访问,而无需知道它授予访问权限的所有状态。这是合理的,因为当较低特权级别只存在一个上下文时,该级别执行上下文之间不存在隐蔽信道的风险。预计这种情况在机器级很常见,例如,对于仅托管单个客户虚拟机的类型 1 管理程序也可能出现这种情况。
如果预计有需要,未来可以通过添加以下 CSR 来将 stateen CSR 的数量加倍:
0x38C mstateen4, 0x39C mstateen4h
0x38D mstateen5, 0x39D mstateen5h
0x38E mstateen6, 0x39E mstateen6h
0x38F mstateen7, 0x39F mstateen7h
0x18C sstateen4
0x18D sstateen5
0x18E sstateen6
0x18F sstateen7
0x68C hstateen4, 0x69C hstateen4h
0x68D hstateen5, 0x69D hstateen5h
0x68E hstateen6, 0x69E hstateen6h
0x68F hstateen7, 0x69F hstateen7h
这些额外的 CSR 并非原始提案的确定部分,因为尚不清楚它们是否会被需要,并且相信第一组(编号 0-3 的寄存器)中位的消耗速率将足够慢,以至于任何即将到来的短缺都会提前很多年可预见。目前,甚至不知道需要多少年才会耗尽仅仅是 mstateen0、sstateen0 和 hstateen0。