[置顶] 泰晓 RISC-V 实验箱,配套 30+ 讲嵌入式 Linux 系统开发公开课
RISCV MMU 概述
Author: pwl999 Date: 2022/03/17 Project: RISC-V Linux 内核剖析 Video: RISC-V Paging&MMU - 直播回放
背景简介
Linux 内存管理包含很多内容,主要知识点可以参考 Linux Mem。本文只描述其中的一个知识点 Paging and MMU
。
本文以全志 D1
为例,包含了平头哥出品的一颗 Riscv64 的 CPU IP-Core,代号 C906
。具体手册可以参考 C906 用户手册。
X86_64
同样是 64bit cpu,x86_64 支持 48bit 和 57bit 两种线性地址模式,分别对应 4level 和 5level mmu 映射:
线性地址 | mmu 层级 | Linux user address space | Linux kernel address space |
---|---|---|---|
Sv48 (48bit) | 4level: pgd→pud→pmd→pte→page(4k) | 0x00000000 00000000 - 0x00007FFF FFFFFFFF | 0xFFFF8000 00000000 - 0xFFFFFFFF FFFFFFFF |
Sv57 (57bit) | 5level: pgd→p4d→pud→pmd→pte→page(4k) | 0x00000000 00000000 - 0x00FFFFFF FFFFFFFF | 0xFF000000 00000000 - 0xFFFFFFFF FFFFFFFF |
X86_64 使用 CR3
寄存器来保存 MMU 映射表的根地址。
更详细信息可以参考 分页寻址(Paging)机制详解 和 内核地址空间布局详解。
C906
Sv39/Sv48/Sv57/Sv64 这几种模式 riscv64 都支持。因为 C906 设计的应用场景不需要那么多的内存资源,目前 C906 只支持 Sv39 模式,对应 3level mmu 映射。
线性地址 | mmu 层级 | Linux user address space | Linux kernel address space |
---|---|---|---|
Sv39 (39bit) | 3level: pgd→pmd→pte→page(4k) | 0x00000000 00000000 - 0x0000003F FFFFFFFF | 0xFFFFFFC0 00000000 - 0xFFFFFFFF FFFFFFFF |
和 x86 CR3
类似,riscv 使用 SATP
寄存器来保存 MMU 映射表的根地址。具体的映射关系如下:
SATP 寄存器
SATP
寄存器的具体格式如下图所示:
具体字段的解析如下:
- Mode - MMU 地址翻译模式
Value | Name | Description |
---|---|---|
0 | Bare | No translation or protection |
1-7 | - | Reserved |
8 | Sv39 | Page-based 39-bit virtual addressing |
9 | Sv48 | Page-based 48-bit virtual addressing |
10 | Sv57 | Reserved for page-based 57-bit virtual addressing |
11 | Sv64 | Reserved for page-based 64-bit virtual addressing |
12-15 | - | Reserved |
当 Mode 为 0 时,MMU 关闭。C906 只支持 MMU 关闭和 Sv39 两种模式。
- ASID – 当前 ASID。表示当前程序的 ASID 号。
- PPN – 硬件回填根 PPN。第一级硬件回填使用的 PPN (Phsical Page Number)。
页表表项
pgd
/p4d
/pud
/pmd
/pte
每级页表中包含的表项大小都是 8 bytes,每个 4k page 内存只能容纳 512 个页表项,所以每级页表的寻址范围为 9bit。
c906 具体的页表表项格式如下所示:
具体字段的解析如下:
- PPN – 页表物理地址。PPN[i] 分别代表三级页表转换时所对应的 PPN 值。
RSW – Reserved for Software。用于预留给软件做自定义页表功能的位。default 为 2’b0。
D – Dirty D 位为 1 时,表明该页是否被改写。 1’b0: 当前页未被写/不可写; 1’b1: 当前页已经被写/可写。 此位在 C906 的硬件实现与 W 属性类似。当 D 位为 0 时,对此页面进行写操作会触发 Page Fault (store) 异常,通过在异常服务程序中配置 D 位来维护该页面是否已经被改写/可写的定义。该位复位为 0。
A – Accessed A 位为 1 时,表明该页被访问过。为 0 时表示没被访问过,对该页表的访问会触发 Page Fault (对应访问 类型) 异常且将该域置为 1。该位复位为 0。
G – Global 全局页面标识,当前页可供多个进程共享,该位复位为 0。 1’b0: 非共享页面,进程号 ASID 私有; 1’b1: 共享页面。
U – User 用户模式可访问,该位复位为 0。 1’b0: 用户模式不可访问,当用户模式访问,出 page fault 异常; 1’b1: 用户模式可访问。
- X :可执行;W :可写;R :可读。
XRW 权限说明 |X |W |R |Meaning| |-|-|-|-| |0 |0 |0 |Pointer to next level of page table| |0 |0 |1 |Read-only page| |0 |1 |0 |Reserved for future use| |0 |1 |1 |Read-write page| |1 |0 |0 |Execute-only page| |1 |0 |1 |Read-execute page| |1 |1 |0 |Reserved for future page| |1 |1 |1 |Read-write-execute page| 违反 XWR 权限时将会触发 Page Fault 异常。
- V – Valid 表明物理页在内存中是否分配好,访问一个 V 为 0 的页面,将触发 Page Fault 异常。该位复位为 0。 1’b0: 当前页没有分配好; 1’b1: 当前页已分配好。
C906 扩展页面属性如下
SO– Strong order 用于表示内存对访问顺序的要求: 1’b0: no strong order(Normal-memory); 1’b1: strong order(Device)。 默认是 no strong order。
C – Cacheable 1’b0: Non-cacheable; 1’b1: Cacheable。 默认是 Non-cacheable。
B – Buff er 1’b0: Non-bufferable ; 1’b1: Bufferable 。 默认是 Non-bufferable 。
Sec (T – Trustable) 用于表征页面属于可信世界或者非可信世界,该位仅在配有 TEE 扩展时有意义,C906 中该位未定义。 1’b0: Non-trustable; 1’b1: Trustable; 默认是 Trustable。
Huge Page
x86 的页表表项中使用了一个 PS
位来标识当前是不是 huge page,如果设置了这个 bit,那么 pud
能直接寻址 1G 的大页,pmd
能直接寻址 2M 的大页。
c906 的表项中并没有 PS
这个 bit,它是用 XRW
3 个 bit 的组合来标识当前是不是最后一级页表的。
- 如果
XRW
=000
,则是中间一级页表 - 如果
XRW
!=000
,则是最后一级页表。pgd
为 1G 大页,pmd
为 2M 大页。
ASID
ASID
(Adress Space ID) 的主要目的是给 mmu 缓存到 tlb 时打标签用的,如果页表表项中设置了 G – Global
则是全局的不受 ASID
的约束。
在 Linux 中每个用户进程拥有自己的地址空间,拥有一套独立的 mmu 映射关系。所以在进程切换时 mmu 映射也需要切换。
ASID
作用主要有两个:
- 减少 tlb 的全局刷新。
- 在不刷新的情况下做权限隔离。
ASID
的详细原理可以参考:内核页表隔离 (KPTI) 详解 。
Linux 对 mmu 的常用操作
Linux 在以下场景下会对mmu 进行操作,这里就不详细展开:
scene | description |
---|---|
fork() | 简单复制 mmu 映射关系 |
execv() | 重新创建用户态 vma 映射 |
mmap() | 创建一段新的 vma 映射 |
task_switch | 切换不同地址空间的 mmu 映射 |
page_fault() | 根据 vma 映射创建实际的 mmu 映射 |
mprotect() | 更改 vma 和 mmu 的内存属性 |
system call | 在开启 KPTI 的情况下,会发生 mmu 切换 |
mem reclaim | 在回收文件内存以后,销毁对应 mmu 映射 |
参考文档
1.C906 用户手册
2.分页寻址(Paging)机制详解
3.内核地址空间布局详解
4.commit:RISC-V: Paging and MMU
5.内核页表隔离 (KPTI) 详解
猜你喜欢:
- 我要投稿:发表原创技术文章,收获福利、挚友与行业影响力
- 知识星球:独家 Linux 实战经验与技巧,订阅「Linux知识星球」
- 视频频道:泰晓学院,B 站,发布各类 Linux 视频课
- 开源小店:欢迎光临泰晓科技自营店,购物支持泰晓原创
- 技术交流:Linux 用户技术交流微信群,联系微信号:tinylab
支付宝打赏 | 微信打赏 | |
请作者喝杯咖啡吧 |
Read Album:
- TinyBPT 和面向 buildroot 的二进制包管理服务(3):服务端说明
- TinyBPT 和面向 buildroot 的二进制包管理服务(2):客户端说明
- TinyBPT 和面向 buildroot 的二进制包管理服务(1):设计简介与框架
- RISC-V Linux 内核及周边技术动态第 118 期
- RISC-V Linux 内核及周边技术动态第 117 期