第三章 机器级ISA,版本1.11
本章描述RISC-V系统中最高权限的机器模式(M-mode)下的机器级操作。M模式用于对硬件平台的低级访问,是复位时进入的第一个模式。M模式还可以用于实现在硬件中直接实现过于困难或代价过高的特性。RISC-V机器级ISA包含一个公共核心,该核心根据支持的其他特权级别和硬件实现的其他细节进行扩展。
3.6 物理内存保护
为了支持安全处理和避免错误,需要限制软件在运行硬件上的可访问物理地址。一个可选的物理内存保护(PMP,Physical Memory Protection)单元提供每台机器模式控制寄存器,允许为每个物理内存区域指定物理内存访问特权(读、写、执行)。PMP值与PMA并行检查。
PMP访问控制设置的粒度是特定于平台的,并且在一个平台内可能因物理内存区域而异,但是标准PMP编码支持小至4字节的区域。某些区域的特权可以是硬连接的,例如,某些区域可能只在机器模式下可见,而在低特权层中不可见。
当hart运行在S或U模式时,PMP检查应用于所有访问,当MPRV位在mstatus寄存器中设置并且mstatus寄存器中的MPP字段包含S或U时,PMP检查应用于加载和存储。PMP检查也应用于页表访问以进行虚拟地址转换,其有效特权模式为s。可选地,PMP检查还可以应用于m模式访问,在这种情况下,PMP寄存器本身被锁定,因此即使m模式软件也不能在不重置系统的情况下更改它们。实际上,PMP可以授予S模式和U模式权限(默认情况下没有权限),也可以撤销m模式的权限(默认情况下具有完全权限)。
注:A component is termed a core if it contains an independent instruction fetch unit. A RISC-Vcompatible core might support multiple RISC-V-compatible hardware threads, or harts, through multithreading.
如果一个组件包含一个独立的取指令单元,它就被称为核心。一个兼容RISC-V的内核可以通过多线程支持多个兼容RISC-V的硬件线程(harts)。
3.61 Physical Memory Protection CSRs
RISC-V通过设置两类寄存器来实现PMP: 配置寄存器,8位 地址寄存器;对于RV32是32位,对于RV64是64位,统一记作MXLEN位的 地址寄存器。部分PMP设置还会使用前一个PMP相关联的地址寄存器。
一个配置寄存器和一个地址寄存器组成一个PMP入口(PMP entry)。配置寄存器和地址寄存器均属于CSR(Control and Status Register)。
地址寄存器通常为8-16个,8位的控制寄存器共16个。但显然,无论是对于RV32还是RV64,都不会存在一个只有8位(一个字节大小)的寄存器。故实际的实现上,是把几个控制寄存器组合到一个CSR中,如下图(图片来自官方手册)。RV32有4个csr, pmpcfg0 - pmpcfg3,保存16个PMP表项的配置 pmp0cfg - pmp15cfg;对于RV64,pmpcfg0 和 pmpcfg2 保存了16个PMP表项的配置,pmpcfg1 和 pmpcfg3 是非法的。
RV32有4个csr, pmpcfg0 - pmpcfg3,保存16个PMP表项的配置 pmp0cfg - pmp15cfg;对于RV64,pmpcfg0 和 pmpcfg2 保存了16个PMP表项的配置,pmpcfg1 和 pmpcfg3 是非法的。
值得注意的是,对于RV64来说,pmp8cfg - pmp15cfg是保存在pmpcfg2中,而不是按顺序保存在pmpcfg1中。这样做是为了使得在RV32和RV64两种情况下,pmp8cfg~pmp11cfg均保存在pmpcfg2中,这样可以减少对于64位支持的开销。
PMP地址寄存器是命名为pmpaddr0-pmpaddr15的csr。每个PMP地址寄存器编码RV32的34位物理地址的第33-2位,如图3.26所示。对于RV64,每个PMP地址寄存器编码56位物理地址的第55-2位,如图3.27所示。并非所有的物理地址位都可以实现,因此pmpaddr寄存器是WARL。
在RISC-V设计的Sv32分页虚拟内存模式(详见4.3)下,RV32拥有34位物理地址空间,故对于RV32来说,PMP必须支持34位的物理内存访问管理。故在32位地址寄存器中,保存33 ~ 2位的地址数据。而对于RV64,支持同样功能,其保存第55 ~ 2位
也就是说,对于一个34位地址,若要保存到PMP地址寄存器中,需要将数据右移两位后存储。对于56位地址,将55 ~ 2位保存在PMP地址寄存器的53 ~ 0位。
下面来看配置寄存器:
其中,R、W、X分别对应读、写、执行权限,为1时有该权限,0时无权限。对于R=0 且 W=1的情况不符合实际含义,故作为保留,以便未来某些情况下使用。
- 尝试从不具有执行权限的PMP区域获取指令会引发获取访问异常(fetch access exception)。
- 尝试执行有效地址位于没有读权限的PMP区域内的加载或负载保留指令会引发加载访问异常(load access exception)。
- 尝试执行有效地址位于没有写权限的PMP区域内的存储、存储条件指令(无论成功与否)或AMO指令会引发存储访问异常(store access exception)。
Address Matching
之前说明了,一个PMP entry由一个地址寄存器和一个配置寄存器组成。那么,如何知道该PMP entry控制的物理地址范围呢?这是由配置寄存器中的A字段和地址寄存器共同决定的。
这部分主要解释配置寄存器中的A field的作用。A字段取值如下:
当A=0时,该PMP entry处于未启用状态,不匹配任何地址。
当A不等于零的时候,又分为三种情况,TOR, NA4, NAPOT(如上图中所示),这些模式支持四字节粒度。 其中NA4可以看作时NAPOT的一种特殊情况。所以我们先看一下NAPOT模式下一个PMP entry的地址寄存器所控制的地址范围是多少。
在上图中,当pmpcfg.A为NAPOT时,从pmpaddr的低位开始寻找连续1的个数。 若pmpaddr值为yyyy...yyy0
,即连续1的个数为0,则该PMP entry所控制的地址空间为从yyyy...y000
开始的8个字节。若pmpaddr值为yyyy...yy01
,即连续1的个数为1,则该PMP entry所控制的地址空间为从yyyy...0000
开始的16个字节 。若pmpaddr值为y...yyy01...1
,设连续1的个数为n,则该PMP entry所控制的地址空间为从y…y0000…0开始的2^{n+3}个字节。
这种控制地址范围的方式叫做自然对其2指数地址范围(Naturally Aligned Power-of-2 regions, NAPOT)
考虑一种边界情况,若pmpaddr值为yyyy…yyyy,此时控制的地址范围即是从yyyy…yyyy开始的4个字节,而pmpcfg.A的值为NA4,即Naturally Aligned Four-byte regions.
另一种A字段的取值的TOR。当某个PMP entry 的配置寄存器的A字段设置位TOR时,该PMP entry所控制的地址范围由前一个PMP entry的地址寄存器(值为 pmpaddri−1 )和该PMP entry的地址寄存器(值为 pmpaddri )共同决定。特别的,若第0个PMP entry的A字段为TOR,其所控制的地址空间的下界被认为是0,即匹配所有满足如下条件的地址 0 < y < pmpaddr0。即当前关联的地址寄存器为地址范围的上界,前一个地址寄存器为地址范围的下界。
Locking and Privilege Mode
这部分介绍配置寄存器中L bit的作用。L字段表示PMP entry处于锁定状态,此时对于配置寄存器和对应的地址寄存器的写入会被忽略。被锁定的PMP entries在hart(hardware thread)重置之前都将保持锁定。
我们知道,通常情况下M模式拥有对于所有地址的所有权限。但当L字段为1时,M、S、U模式都必须遵循配置寄存器的权限设置(是否读、写、执行权限)。而当L字段为0时,在M模式下匹配到此PMP entry的任何操作都将成功,而S和U模式下需要遵循配置寄存器中的权限设置。
Priotity and Matching Logic
-
PMP表项的优先级是静态的,与访问的任何字节匹配的编号最低的PMP表项决定该访问是成功还是失败,即pmp0cfg优先级要高于pmp1cfg。
-
匹配的PMP表项必须匹配一次访问的所有字节,否则访问失败,无论L、R、W、X位如何。例如,如果将PMP表项配置为匹配4字节范围 0xC-0xF,并且PMP表项是匹配该地址空间的最高优先级表项,那么对于 0x8-0xF 范围的8字节访问将失败。
-
如果一个PMP表项匹配一次访问的所有字节,那么L、R、W和X位决定这次访问是成功还是失败。如果L位为0,且访问的特权模式为M,则表示访问成功。否则,如果设置了L位或访问的特权模式为S或U,则只有设置了与访问类型对应的R、W或X位,才能访问成功。
-
访问失败会产生加载、存储或指令访问异常。请注意,一条指令可能产生多个访问,这些访问可能不是相互原子的。如果一条指令生成的至少一个访问失败,则会生成一个访问异常,尽管该指令生成的其他访问可能会成功。值得注意的是,引用虚拟内存的指令被分解为多个访问。