其他分享
首页 > 其他分享> > RISCV MMU 概述

RISCV MMU 概述

作者:互联网

1. 背景简介

Linux 内存管理包含很多内容,主要知识点可以参考 Linux Mem。本文只描述其中的一个知识点 Paging and MMU

本文以全志 D1 为例,包含了平头哥出品的一颗 Riscv64 的 CPU IP-Core,代号 C906。具体手册可以参考 C906 用户手册

2. X86_64

同样是 64bit cpu,x86_64 支持 48bit 和 57bit 两种线性地址模式,分别对应 4level 和 5level mmu 映射:

线性地址mmu 层级Linux user address spaceLinux kernel address space
Sv48 (48bit)4level: pgd→pud→pmd→pte→page(4k)0x00000000 00000000 - 0x00007FFF FFFFFFFF0xFFFF8000 00000000 - 0xFFFFFFFF FFFFFFFF
Sv57 (57bit)5level: pgd→p4d→pud→pmd→pte→page(4k)0x00000000 00000000 - 0x00FFFFFF FFFFFFFF0xFF000000 00000000 - 0xFFFFFFFF FFFFFFFF

X86_64 使用 CR3 寄存器来保存 MMU 映射表的根地址。

更详细信息可以参考 分页寻址(Paging)机制详解内核地址空间布局详解

3. C906

Sv39/Sv48/Sv57/Sv64 这几种模式 riscv64 都支持。因为 C906 设计的应用场景不需要那么多的内存资源,目前 C906 只支持 Sv39 模式,对应 3level mmu 映射。

线性地址mmu 层级Linux user address spaceLinux kernel address space
Sv39 (39bit)3level: pgd→pmd→pte→page(4k)0x00000000 00000000 - 0x0000003F FFFFFFFF0xFFFFFFC0 00000000 - 0xFFFFFFFF FFFFFFFF

和 x86 CR3 类似,riscv 使用 SATP 寄存器来保存 MMU 映射表的根地址。具体的映射关系如下:
在这里插入图片描述

3.1 SATP 寄存器

SATP 寄存器的具体格式如下图所示:
在这里插入图片描述

具体字段的解析如下:

ValueNameDescription
0BareNo translation or protection
1-7-Reserved
8Sv39Page-based 39-bit virtual addressing
9Sv48Page-based 48-bit virtual addressing
10Sv57Reserved for page-based 57-bit virtual addressing
11Sv64Reserved for page-based 64-bit virtual addressing
12-15-Reserved

当 Mode 为 0 时,MMU 关闭。C906 只支持 MMU 关闭和 Sv39 两种模式。

3.2 页表表项

pgd/p4d/pud/pmd/pte 每级页表中包含的表项大小都是 8 bytes,每个 4k page 内存只能容纳 512 个页表项,所以每级页表的寻址范围为 9bit。

c906 具体的页表表项格式如下所示:
在这里插入图片描述
具体字段的解析如下:

XRW 权限说明

XWRMeaning
000Pointer to next level of page table
001Read-only page
010Reserved for future use
011Read-write page
100Execute-only page
101Read-execute page
110Reserved for future page
111Read-write-execute page

违反 XWR 权限时将会触发 Page Fault 异常。

C906 扩展页面属性如下

3.3 Huge Page

x86 的页表表项中使用了一个 PS 位来标识当前是不是 huge page,如果设置了这个 bit,那么 pud 能直接寻址 1G 的大页,pmd 能直接寻址 2M 的大页。
在这里插入图片描述
c906 的表项中并没有 PS 这个 bit,它是用 XRW 3 个 bit 的组合来标识当前是不是最后一级页表的。

3.4 ASID

ASID (Adress Space ID) 的主要目的是给 mmu 缓存到 tlb 时打标签用的,如果页表表项中设置了 G – Global 则是全局的不受 ASID 的约束。

在 Linux 中每个用户进程拥有自己的地址空间,拥有一套独立的 mmu 映射关系。所以在进程切换时 mmu 映射也需要切换。

ASID 作用主要有两个:

ASID 的详细原理可以参考:内核页表隔离 (KPTI) 详解

4. Linux 对 mmu 的常用操作

linux 在以下场景下会对mmu 进行操作,这里就不详细展开:

scenedescription
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) 详解

标签:映射,RISCV,ASID,mmu,MMU,C906,概述,页表,page
来源: https://blog.csdn.net/pwl999/article/details/123613069