Riscv虚拟内存Sv48

原文地址:https://joessem.com/archives/riscv-mmu.html

MMU:内存管理单元(memory managemeny unit ,缩写为 MMU)
负责虚拟地址到物理地址的转换。

RISCV 通过修改 SATP 寄存器来决定是否开启 MMU 功能。

Satp 寄存器

寄存器位域划分:

mmu1

该寄存器保存根页表的物理页号(PPN),即其主管物理地址除以 4 KiB;地址空间标识符 (ASID),它有助于在每个地址空间的基础上进行地址转换围栏;和 MODE 字段,表示当前的地址转换方案。

对于 RV64,共有以下几种地址转换方案可供选择:

mmu2

但是,当 MODE == Bare 时,监管者的虚拟地址和监管者的物理地址是相等的,同时 satp 寄存器其他位域不起作用。
到目前为止 RV64 仅有 Sv39 和 Sv48 被定义。 Sv57 和 Sv64 暂时保留未被实现。

当 satp 被写入并执行指令 [sfence.vma]( satp.MODE != Bare),之后的 S-Mode/U-Mode 指令地址和访问的数据地址都必须通过虚拟地址来进行访问,且访问时会被转换成物理地址,由 page table entry (PTE) 中的控制位来决定当前访问的实际物理地址是否被允许。

地址转换算法

以 Sv48 方案为例。
(兼容性:支持 Sv48 的系统也应该支持 Sv39,在此不介绍 Sv39)

Sv48 实现支持 48 位虚拟地址空间,划分为 4 个 KiB 页面。
Sv48 地址划分如图所示。

mmu3

加载和存储有效地址 (64 位) 的 63-48 位必须全部等于 47 位,否则将发生页面错误异常。
36 位 VPN 通过 4 级页表转换为 44 位的 PPN, 12 位的页偏移不进行转换。

Sv48 的 PTE 格式如图所示:

mmu4

PTE [9:0] 表示控制位。

Valid 位指示该 PTE 是否有效;Readable,Writeable,eXecutable 指示了该页是否可读、可写、可运行,当这三位都是 0 时,表明该 PTE 指向了下一层页表,其为非叶 PTE ,否则就是叶 PTE;User 位指示了该页是否可以被用户模式访问;Global 指示了全局映射,存在于所有的地址空间中;Access 位指示了该页最近是否被读、写、取;Dirty 位指示了虚拟页最近是否被写过。对于非叶 PTE,D,A,U 位被保留,并被清零。RSW 是保留的,用于操作系统软件。

任何级别的 PTE 都可能是叶子 PTE,因此除了 4 个 KiB 页面之外,Sv48 还支持 2 个 MiB 兆页、1 个 GiB 兆页和 512 个 GiB 兆页,每一个都必须在虚拟和物理上与与其大小相等的边界对齐。
如果物理地址没有充分对齐,将引发页面错误异常。

虚拟地址 (va) 转换为物理地址 ( pa ) 的计算方式如下:

  1. 使 a= satp.ppn * PAGESIZE , i=LEVELS -1 (PAGESIZE=2^12 , LEVELS = 4)。

  2. 设置 PTE 为地址 a + va.vpn [i] * PTESIZE 的 pte 值(PTESIZE=8)。如果访问 pte 违反了 PMA 或 PMP 检查,则引发访问异常。

  3. 如果 PTE.V ==0 | (PTE.R=0 && PTE.W=1),停止并抛出 page-fault 异常。

  4. 否则,PTE 有效。如果 PTE.R=1 & PTE.X=1 , 跳到第 5 步。否则,这个 PTE 是指向下一个层级的页表的指针。

    1. 使 i=i-1,如果 i<0,停止并抛出 page-fault 异常。
    2. 否则,让 a = PTE.ppn * PAGESIZE , 并跳到第 2 步。
  5. 叶 PTE 被找到。根据 PTE.R、PTE.W、PTE.X、PTE.U 位域的值,以及当前特权模式和 MSTATUS 寄存器 SUM 与 MXR 位域的值,判断请求的内存访问是否被允许。如果不被允许,停止并抛出 page-fault 异常。

  6. 如果 i>0 & pa.ppn [i-1:0]!=0 ,这是一个非对齐的超级页,停止并抛出 page-fault 异常。

  7. 如果 PTE.A=0,或者内存访问为 STORE 且 PTE.D=0,要么引发一个页面错误异常,要么:

    1. 设置 PTE.A=0,且如果内存访问方式为 store,PTE.D=0;
    2. 如果这个访问违反了 PMA 或 PMP 检查,引发访问异常;
    3. 步骤 2 中的更新和 pte 的加载必须是原子的;特别是,PTE 的中间存储不会被察觉到。
  8. 地址转换成功。转换后的物理地址为:

    1. Pa.pgoff=va.pgoff;
    2. 如果 i>0,则这是一个超级页的地址转换,使 pa.ppn [i-1:0] = va.vpn [i-1:0];
    3. Pa.ppn[LEVELS -1:i] = PTE.ppn[LEVELS-1:i]]

需要注意的是,每个 level 0 PTE 都表示 4KB 的内存访问属性。
比如有个 level 0 PTE 内的值为 [0x200000DF]。PPN [] 的值为 0x80000,表示地址范围为 0x80000000~0x80000FFF 的 4KB 物理地址。控制位 ( PTE [9:0] ) 的值为 0B0011011111,代表的含义可参考以上控制位信息解释。
所以该 level 0 PTE [0x200000DF] 表示映射到物理地址 0x80000000~0x80000FFF 的 4KB 范围内,可以被 U-Mode 访问,可读 / 可写 / 可执行

posted @ 2023-03-04 11:57  我星伤悲  阅读(890)  评论(0)    收藏  举报