RISC-V 的分页机制¶
RISC-V 目前有 Sv32, Sv39, Sv48 和 Sv57 四种分页机制,Sv64 目前被保留使用。几种分页机制均采用了多级页表的映射方式。
Sv32¶
Sv32 下的地址布局如下:
+----------+----------+------------+
Virtual Address | VPN[1] | VPN[0] | offset | -----> 32 bits
+----------+----------+------------+
(10 bits) (10 bits) (12 bits)
Physical Address +------------+----------+------------+
| PPN[1] | PPN[0] | offset | -----> 34 bits
+------------+----------+------------+
(12 bits) (10 bits) (12 bits)
+------------+----------+--+-+-+-+-+-+-+-+-+
Page Table Entry | PPN[1] | PPN[0] | |D|A|G|U|X|W|R|V| -----> 32 bits
+------------+----------+--+-+-+-+-+-+-+-+-+
(12 bits) (10 bits) |
`- RSW (2 bits)
Sv32 下每一个页表项大小为四字节,每一个页表共有 \(2^{10}\) 个页表项,于是每个页表的大小为 \(2^{15}\) 个比特,即 \(2^{12}\) 字节,也就是 4 KiB。而每个页号对应的页内偏移共有 12 位,也是 4 KiB 的空间,一个页表可以刚好放入一个页内。
在使用虚拟地址时(将 satp
寄存器的 MODE
域设置为对应虚拟内存的选项)时,内存管理单元会首先从 satp
中读取页表根节点的基址,之后根据页表项后的标志位判断是否需要进行二级页表的查找。若不再向下查找,则将虚拟地址中的偏移量作为物理地址偏移量,将尚未访问的级别的页号直接从虚拟地址中获取到物理地址,已经访问的级别则从页表项中获取。整个地址翻译过程的细节可以见 RISC-V Privileged Spec 中的 4.3.2 节。
Sv39, Sv47, Sv57¶
Sv39 使用 39 位的虚拟地址,每一级页号为 9 位,页表项大小为 64 位,从而保证一个页表可以被保存在一个页内。Sv39 下的物理地址为 56 位,期中 PPN[2]
为 26 位。
Sv48 与 Sv39 类似,但是使用了四级页表,虚拟地址中每一级页号仍然是 9 位,物理地址为 56 位,最高一级 PPN[3]
为 17 位。
Sv57 使用五级页表并且将 PPN[4]
都设置为了 8 位,物理地址仍然为 56 位。
Sv39, Sv48, Sv57 中所有 PPN 位数总和均为 44 位,与 satp
寄存器中的 PPN 保持一致。