RISCV Linux 虚拟内存精讲系列一 Sv39

        笔者认为,Linux 操作系统(Operating System)最核心的机制是虚拟内存(Virtual Memory)。因为,操作系统主要作用是将硬件环境抽象起来,给在其中运行的应用(Applications)提供一个统一的、抽象的运行环境(Execution Environment),使得应用(Applications)专注于为用户提供各种各样的业务逻辑(Business Logics)。其中,虚拟内存提供了核心的支撑作用。

        从下(底层,baremetal)往上看,运行的程序与外界交互,主要是与主存(Main Memory)、外围设备(Peripheral Devices)交互(Access,Read/Write,IO)都是通过对其对应的地址(Addresses)进行读写操作(Read/Write Operations)来实现的。

        而操作系统为了统一管理与外界的交互,使得,在操作系统上运行的应用(Applications)需要间接地(Indrectly)实现地址的访问,也就是通过操作系统来实现交互。那么,虚拟内存就提供了这么一个机制,通过不同的页表(Page Table)为每个应用提供一个独立的地址空间(Address Space),然后,该地址空间的地址,通过对应的页表,转换成实际的物理地址(Physical Address),从而,对外界进行访问。

        这里所说的虚拟地址(Virtual Address, VA),主要指的 CPU load/store/branch 等指令所使用的地址。而物理地址(Physical Address, PA),主要指的是SoC上的总线地址,即经过总线的路由(Routing)后,指派到对应的设备上。

        也就是说,在没有虚拟地址转换时,虚拟地址等于物理地址。

        基于上述概念,以 RISCV Linux 以及 RISCV Sv39 为例,通过一系列的文章,详细地梳理清楚 在 RISCV Sv39 上,Linux 是如何实现其虚拟内存机制的。

        (顺便提一句,vmlinux 中的 vm,就是 virtual memory 的缩写)

        这是该系列的第一篇文章,主要讲述 RISCV Sv39。

        RISCV Sv39 指 64 位的 RISCV CPU 中,其有效虚拟地址位数为 39 位,也就是有效位(Effective bits)为 0 - 38,另,39 - 64 的值与 bit 38 一样。也就是 Two's Complement 的计数方式,方便地址的计算与划分。

The RISC-V Instruction Set Manual: Volume II Privileged Architecture. P 11.4.

        Instruction fetch addresses and load and store effective addresses,which are 64 bits, must have bits 63–39 all equal to bit 38, or else a page-fault exception will occur.

        The 27-bit VPN is translated into a 44-bit PPN via a three-level page table, while the 12-bit page offset is untranslated.

        即,根据RISCV Sv39 规定,39位有效虚拟地址被划分为4段,高位三段为虚拟页表索引号(Virtual Page Number),低12位为 页表偏移量(Page Offset)。

        另外,Sv39 规定,物理地址有效位数为 56 位,即 0 - 55。如下:

        另外,页表项 PTE (Page Table Entry) 的设计,如下:

        这里需要注意的是,在RISCV 64 位的CPU角度上看,其访问的地址(Virtual Address)是64位的。当 CPU 中的虚拟地址转换模式(Virtual Address Translation Mode)被选定后,如 Sv39,那么,64位的CPU访问地址(CPU Access Virtual Address),将装换成虚拟地址转换模式指定的虚拟地址,如 Sv39 虚拟地址 (Sv39 Virtual address)。其转换规则由其转换模式规定,如Sv39 规定,低39位CPU访问地址有效,高位值必须等于 bit 38,类似符号扩展(sign extension)。基于,转换模式,可以找到其对应的虚拟地址转换模式指定的物理地址,如 Sv39 物理地址(Sv39 Physical Address),56位有效位的物理地址。然后,通过 0 扩展模式(zero extension)将其装换成机器级(machine level)物理地址(physical address),也就是上面所说的SoC总线地址(Bus Address)。

        也就是,从CPU角度出发,地址的转换如下:

虚拟地址(Virtual Address, VA)/ CPU访问地址(CPU Access Virtual Address)/ 逻辑地址(Logical Address )

-- 符号扩展(sign extension)--

        ==> Sv39 虚拟地址 (Sv39 Virtual address)(VPN + Page Offset)

-- 虚拟地址转换模式 --

        ==> Sv39 物理地址(Sv39 Physical Address)(PPN + Page Offset)

-- 0 扩展模式(zero extension)--

        ==> 机器级(machine level)物理地址(physical address, PA)/ SoC总线地址(Bus Address)

        通过 S mode 下的 satp 控制状态寄存器(Control Status Register, CSR),设定虚拟地址转换模式,如 Sv39,即物理根页表号(Root PPN),如下:

        其转换过程如下:

        其中,虚拟地址到物理地址的转换过程,大致如下:(在不考虑PTE属性的情况下)

#define XLEN (64) // 64 bits RISCV CPU
#define BITS_IN_BYTE (8) // 1 Byte = 8 bits
#define SATP_PPN_MASK (0x0fff'ffff'ffff)
#define PAGE_SIZE_BITS (12) // 4KB per page
#define PAGE_SIZE (1 << PAGE_SIZE_BITS)
#define PTE_SIZE (XLEN / BITS_IN_BYTE) // 8 Bytes per PTE
#define PTE_ENTRIES_PER_PAGE (PAGE_SIZE / PTE_SIZE) // 512 entries per page
#define Level_0_VA_OFFSET_BITS (PAGE_SIZE_BITS + 9 + 9)
#define Level_1_VA_OFFSET_BITS (PAGE_SIZE_BITS + 9)
#define Level_2_VA_OFFSET_BITS (PAGE_SIZE_BITS)PTE* level_0_page_table = (satp & SATP_PPN_MASK) << PAGE_SIZE_BITS
PTE* level_1_page_table = level_0_page_table[(va >> (Level_0_VA_OFFSET_BITS)) & (512 - 1)]
PTE* level_2_page_table = level_1_page_table[(va >> (Level_1_VA_OFFSET_BITS)) & (512 - 1)]
PTE* leaf_PTE = level_2_page_table[(va >> (Level_2_VA_OFFSET_BITS)) & (512 - 1)]
void * pa = leaf_PTE.ppn << Level_2_VA_OFFSET_BITS + (va & (1 << Level_2_VA_OFFSET_BITS - 1))

        具体的转换过程,请参考官方手册。

        其中,当 PTE 在 level_0_page_table 时,就是 叶表项(leaf_pte),那么该 PTE 描述的 1GB的空间(30 Bits),即

#define XLEN (64) // 64 bits RISCV CPU
#define BITS_IN_BYTE (8) // 1 Byte = 8 bits
#define SATP_PPN_MASK (0x0fff'ffff'ffff)
#define PAGE_SIZE_BITS (12) // 4KB per page
#define PAGE_SIZE (1 << PAGE_SIZE_BITS)
#define PTE_SIZE (XLEN / BITS_IN_BYTE) // 8 Bytes per PTE
#define PTE_ENTRIES_PER_PAGE (PAGE_SIZE / PTE_SIZE) // 512 entries per page
#define Level_0_VA_OFFSET_BITS (PAGE_SIZE_BITS + 9 + 9)
#define Level_1_VA_OFFSET_BITS (PAGE_SIZE_BITS + 9)
#define Level_2_VA_OFFSET_BITS (PAGE_SIZE_BITS)PTE* level_0_page_table = (satp & SATP_PPN_MASK) << PAGE_SIZE_BITS
PTE* leaf_PTE = level_0_page_table[(va >> (Level_0_VA_OFFSET_BITS)) & (512 - 1)]
void * pa = leaf_PTE.ppn << Level_0_VA_OFFSET_BITS + (va & (1 << Level_0_VA_OFFSET_BITS - 1))

        同理,当 PTE 在 level_1_page_table 时,就是 叶表项(leaf_pte),那么该 PTE 描述的 2MB的空间(21 Bits),即

#define XLEN (64) // 64 bits RISCV CPU
#define BITS_IN_BYTE (8) // 1 Byte = 8 bits
#define SATP_PPN_MASK (0x0fff'ffff'ffff)
#define PAGE_SIZE_BITS (12) // 4KB per page
#define PAGE_SIZE (1 << PAGE_SIZE_BITS)
#define PTE_SIZE (XLEN / BITS_IN_BYTE) // 8 Bytes per PTE
#define PTE_ENTRIES_PER_PAGE (PAGE_SIZE / PTE_SIZE) // 512 entries per page
#define Level_0_VA_OFFSET_BITS (PAGE_SIZE_BITS + 9 + 9)
#define Level_1_VA_OFFSET_BITS (PAGE_SIZE_BITS + 9)
#define Level_2_VA_OFFSET_BITS (PAGE_SIZE_BITS)PTE* level_0_page_table = (satp & SATP_PPN_MASK) << PAGE_SIZE_BITS
PTE* level_1_page_table = level_0_page_table[(va >> (Level_0_VA_OFFSET_BITS)) & (512 - 1)]
PTE* leaf_PTE = level_1_page_table[(va >> (Level_1_VA_OFFSET_BITS)) & (512 - 1)]
void * pa = leaf_PTE.ppn << Level_1_VA_OFFSET_BITS + (va & (1 << Level_1_VA_OFFSET_BITS - 1))

        那么,基于 RISCV Sv39 的虚拟地址转换模式大致上如上所示。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/87914.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/87914.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【apply from: “$flutterRoot/packages/flutter_tools/gradle/flutter.gradle“作用】

这行代码的作用是将 Flutter 的 Gradle 构建脚本集成到 Android 项目中&#xff0c;具体细节如下&#xff1a;作用解析&#xff1a;引入 Flutter 构建逻辑 flutter.gradle 是 Flutter SDK 的核心构建脚本&#xff0c;它负责&#xff1a; 编译 Dart 代码为原生二进制文件&#x…

深入理解JavaScript设计模式之命令模式

深入理解JavaScript设计模式之命令模式 文章目录深入理解JavaScript设计模式之命令模式定义简单命令模式组合命令模式使用命令模式实现文本编辑器目标关键类说明实现的效果交互逻辑流程所有代码&#xff1a;总结定义 命令模式也是设计模式种相对于变焦简单容易理解的一种设计模…

CSS 网页布局:从基础到进阶

CSS 网页布局&#xff1a;从基础到进阶 引言 随着互联网的飞速发展&#xff0c;网页设计已经成为了一个不可或缺的领域。CSS&#xff08;层叠样式表&#xff09;作为网页设计中的关键工具&#xff0c;用于控制网页元素的样式和布局。本文将为您全面解析CSS网页布局&#xff0c;…

【人工智能】大语言模型(LLM) NLP

大语言模型&#xff08;LLM&#xff09;& NLP1.大语言模型&#xff08;LLM&#xff09;1.1 一句话解释1.2 更形象的比喻1.3 为什么叫 “大” 模型1.4 它能做什么1.5 现实中的例子2.对比 NLP2.1 用 “汽车进化” 比喻 NLP → LLM2.2 为什么说 LLM 属于 NLP2.3 LLM 的 “革命…

Unity HDRP + Azure IoT 的 Python 后端实现与集成方案

Unity HDRP Azure IoT 的 Python 后端实现与集成方案 虽然Unity HDRP本身使用C#开发&#xff0c;但我们可以构建Python后端服务支持物联网系统&#xff0c;并与Unity引擎深度集成。以下是完整的实现方案&#xff1a; 系统架构 #mermaid-svg-qCDb0g9Ik287Cg8X {font-family:&qu…

小黑黑日常积累大模型prompt句式2:【以段落的形式输出,不分点列举】【如果没有相关内容则不输出】【可读性强】【输出格式规范】

以段落的形式输出&#xff0c;不分点列举 每个标题下直接接续段落内容&#xff0c;不编号、不分点。......标题下直接接续段落内容&#xff0c;不继续进行分点列举。如果没有相关内容则不输出 若某一部分无法从原文中提取有效信息&#xff0c;则跳过该部分内容&#xff0c;不做…

React Native 基础组件详解<一>

一、Text组件 1&#xff09;numberOfLines&#xff1a;显示行数 2&#xff09;ellipsizeMode&#xff1a;超出隐藏的位置 clip->裁掉 head/middle/ tail->点的位置 3&#xff09;selectable: 是否可以选中 4&#xff09;selectionColor&#xff1a;选中后的颜色 5&#…

异步编程(Promise/Generator/async)

1、Promise 2、Generator 3、async/await

【Note】《Kafka: The Definitive Guide》 第8章: Cross-Cluster Data Mirroring

《Kafka: The Definitive Guide》 第8章&#xff1a; Cross-Cluster Data Mirroring 一、跨集群镜像的场景与价值 多区域低延迟访问 将业务数据从主集群实时复制到多个地理区域的集群&#xff0c;缩短消费者跨区读取延迟。 灾备切换 当主集群出现故障时&#xff0c;可快速将消…

「Windows/Mac OS」AIGC图片生成视频 ,webui + stable-diffusion环境部署教程

stable-diffusion webui 环境搭建目录 一、Windows 环境部署 stable-diffusion-webui1、准备条件2、安装Python 3.10.X&#xff08;**较新版本的 Python 不支持 torch**&#xff09;3、安装Git 教程4、使用Git 下载 stable-diffusion-webui 存储库&#xff0c;4.1、显示报错 5…

【深度学习】 深度学习训练配置参数详解

深度学习训练配置参数详解 1. 启动初始化参数说明CUDA_VISIBLE_DEVICES指定使用的GPU设备编号&#xff08;"0"表示单卡&#xff09;seed随机种子&#xff08;1777777&#xff09;&#xff0c;保证实验可复现性cuda是否启用GPU加速&#xff08;True&#xff09;benchm…

期望,积分,均值,求和的关系

1. 回顾期望的定义 对于连续性随机变量 X X X&#xff0c;期望为&#xff1a; E X ∼ f ( x ) [ X ] ∫ Ω x f ( x ) d x E_{X\sim f(x)}[X] \int_{\Omega}xf(x)dx EX∼f(x)​[X]∫Ω​xf(x)dx 其中 f ( x ) f(x) f(x)为概率密度函数&#xff0c; Ω \Omega Ω为概率密度函…

1.如何对多个控件进行高效的绑定 C#例子 WPF例子

使用ObservableCollection高效为多个控件绑定数据在WPF开发中&#xff0c;数据绑定是一个非常重要的功能&#xff0c;它允许我们将UI控件与数据源进行绑定&#xff0c;从而实现数据的自动更新。当需要为多个控件绑定数据时&#xff0c;使用ObservableCollection可以大大提高开发…

JSONLines和JSON数据格式使用教程

文章目录 一、核心区别二、JSONLines 的优势三、Python 中使用 JSONLines1. 写入 JSONLines 文件2. 读取 JSONLines 文件3. 处理大文件示例四、常见工具支持1. 命令行工具2. 编程语言库五、适用场景选择六、注意事项总结JSONLines(简称 jsonl 或 jl)和传统 JSON 都是用于存储…

链表算法之【反转链表】

目录 LeetCode-206题 LeetCode-206题 给定一个单链表的头节点&#xff0c;请反转链表&#xff0c;并返回反转后的链表 class Solution {public ListNode reverseList(ListNode head) {// checkif (head null || head.next null)return head;// 双指针ListNode p1 head;Li…

回溯题解——子集【LeetCode】输入的视角(选或不选)

78. 子集 ✅ 一、算法逻辑讲解&#xff08;逐步思路&#xff09; 逻辑讲解&#xff1a; dfs(i)&#xff1a;表示从下标 i 开始&#xff0c;做“选 or 不选”的子集构造。 终止条件 if i n&#xff1a; 到达数组末尾&#xff0c;表示一种完整子集构造完成。 把当前构造路径…

使用Electron开发跨平台本地文件管理器:从入门到实践

在当今数字化时代&#xff0c;文件管理是每个计算机用户日常工作中不可或缺的一部分。虽然操作系统都提供了自己的文件管理器&#xff0c;但开发一个自定义的文件管理器可以带来更好的用户体验、特定功能的集成以及跨平台的一致性。本文将详细介绍如何使用Electron框架构建一个…

JBHI 2025 | 潜在扩散模型赋能胸部X射线骨抑制

Abstract: 肺部疾病是全球健康面临的一项重大挑战&#xff0c;胸部 X 光检查&#xff08;CXR&#xff09;因其方便性和经济性而成为一种重要的诊断工具。 然而&#xff0c;CXR 图像中重叠的骨结构往往会阻碍肺部病变的检测&#xff0c;从而导致潜在的误诊。 为解决这一问题&am…

408第三季part2 - 计算机网络 - 计算机网络基本概念

理解然后区分一下这2个区别特点是建立连接存储转发的意思是A先发给B&#xff0c;B再发给C&#xff0c;就这样这里缺点比如A很大&#xff0c;你给B缓存开销大还需要排序然后形象的图题目分组头部要放一些源地址和目的地址这些东西以后发数据只会往近的发&#xff0c;不可能往下面…

互补功率放大器Multisim电路仿真——硬件工程师笔记

目录 1 互补功率放大器基础知识 1.1 工作原理 1.2 电路结构 1.3 优点 1.4 缺点 1.5 应用 1.6 总结 2 OCL乙类互补功率放大电路 2.1 电路结构 2.2 工作原理 2.3 优点 2.4 缺点 2.5 总结 3 OCL甲乙类互补功率放大电路 3.1 电路结构 3.2 工作原理 3.3 优点 3.4 …