MENU

Riscv虚拟内存Sv48

October 1, 2022 • 阅读: 1567 • 笔记&折腾

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 访问,可读/可写/可执行

Leave a Comment

已有 1 条评论
  1. 您好~我是腾讯云开发者社区运营,关注了您分享的技术文章,觉得内容很棒,我们诚挚邀请您加入腾讯云自媒体分享计划。完整福利和申请地址请见:https://cloud.tencent.com/developer/support-plan
    作者申请此计划后将作者的文章进行搬迁同步到社区的专栏下,你只需要简单填写一下表单申请即可,我们会给作者提供包括流量、云服务器等,另外还有些周边礼物。