内存管理技术一:页表

寄存器satp

操作系统分为用户模式和内核模式,riscv架构也分为特权架构和非特权架构。特权架构指的是因为定时器中断,异常和系统调用等情况,进程从用户模式切换到内核模式时,对一些特权架构的寄存器进行一系列的操作,也是用户态和内核态可以进行分离的实现原理。

Satp(Supervisor Address Translation and Protection Register)寄存器是虚拟地址转换的一个非常重要的寄存器,下图展示了stap寄存器的内容。

32位操作系统时satp寄存器

64位操作系统时satp寄存器

当MODE位为0时,虚拟地址不会进行转化,此刻的虚拟地址就是物理地址。软件会将satp寄存器的其他字段清0。MODE为不同值时,会根据MODE位选择不同结构的页表,如下图所示。在32位的操作系统下,页表只有sv32一种结构。在64位操作系统下,有sv39,sv48等多种页表结构。

PPN存放的是最高级页表的起始页号(页目录),根据相应的page大小进行可以得到最高级页表(页目录)的物理地址。这样cpu就可以告诉虚拟内存地址从哪里翻译成物理内存地址。(页表的地址必须为物理地址,因为内容本身只能存放在真正的物理地址中,页表是虚拟地址指向物理地址的媒介)每一个应用程序都有属于自己的页表,当cpu从一个应用程序切换到另一个应用程序的时候,也需要切换satp寄存器中的内容。每个进程都有自己的进程描述符,在进程描述符中会定义页目录的地址并将该地址写入到stap寄存器中。

页表和多级页表

如果直接将虚拟地址一一对应映射到物理地址,那么对于页表机制的空间需求太大了。
比如全中国14亿人,如果每个人的信息都是中国浙江嘉兴海宁奕斯伟xxx,那么14亿人占据的信息大小就会非常大。而如果对信息进行分类,比如同属中国,保留34个省,再保留下面的县,那么需要保存的数据量将会变得非常小(类似于填写快递收货地址)。页表的分页机制就是类似这种原理。


一级页表的思路是:定位数据所在的页和页内的偏移,就可以转化成为物理地址。如下图:

3212位共计20位元素,可以表示2^20=1M个页,一个页的大小为4k,可以正好覆盖虚拟内存的1M*4K=4GB。011位共计12位可以覆盖页的大小:2^12=4k,可以表示为页内偏移。该方法需要为页表分配1M(页表数量)*4k(单个页表的大小)=4MB的内存空间。占用空间还是太大,于是多级页表出现了。
image.png

虚拟地址和物理地址的组成

先来看虚拟地址的组成:


Sv32虚拟地址

再来看转换后的物理地址:


Sv32物理地址

页表要做的事情就是将虚拟地址中的20位的VPN[0]和VPN[1]经过页表的转换,变成22位的PPN[0]和PPN[1],最后的12位page offset称作页内偏移,物理地址和虚拟地址的page offset是一样的。转换的形式如下图所示:

页表项PTE

页表项(page table entry)是页表中存储的内容,是寻址的媒介与核心。sv32中,页表包含了2^10个PTEs,每个页表项为4个字节。下图展示了PTE的组成。



V位表示PTE是否有效,如果V=0,则PTE中的其他位是无效的。R,W,X分别表示页的可读,可写,可执行权限。当这三位都为0时,PTE中的PPN表示的是指向下一级页表的物理页号。下图表示的是,XWR在不同的权限位时,PTE的含义。



U位表示的是当前页在用户模式下是否可用。只有当U=1时,用户模式下才可以使用当前页。当sstatus寄存器的SUM位为1时,表明supervisor模式下可以访问user模式下的页面。当SUM位为1,且U=1时,supervisor模式下的softwatre可以访问页面。但是通常情况下,SUM为为0,supervisor访问user模式下的页会产生错误,而且SUM位是否位1,,supervisor模式尽量不要访问U=1的页面。
G位表示是否是全局映射。未能将全局映射设置为全局的,会降低性能。而将非全局映射标记会全局的,可能会导致bug。

RSW保留供supervisor模式下使用,此处可以暂时忽略。
每个lead PTE(即表示虚拟地址对应物理页号的PTE)都包含A(access)和D(dirty)位。其中A位表示虚拟页在上次A被清零之后是否被读/写/执行过。D位表示虚拟页在D位上次被清零之后是否被写过。正常情况下将A和D位置1来提高效率。对于non-leaf PTE,D,A,U位被保留用作未来的标准使用,并且必须被软件清零。

多级页表寻址过程

Sv32虚拟地址va被转化成物理地址pa的过程如下:

  1. a = stap.ppn * PAGESIZE, i = LEVELS - 1(stap中的ppn字段表示的页目录的物理页号,乘PAGESIZE得到的是页目录的物理地址。对于sv32,PAGESIZE = 2^12(4Kb), LEVELS = 2,表示的是二级页表映射,i表示VPN[1], VPN[0],所以要减1)
  2. pte的地址:a + va.vpn[i]*PTESIZE(a是页目录的物理地址,vpn[i]中存放的是index,乘PTESIZE得到了对应PTE的偏移地址,加上页目录的基地址之后就得到了页目录对应的PTE,可以通过PTE得到下一级页表的)
    此时需要对pte的进行安全性的检查,如果违反PMA和PMP的检查,则出发一个access-fault
  3. 如果pte的V位为0,或者r为0且w位为1,则停止并原始的access type触发一个page fault
  4. 如果经过了上述的检查,则表明PTE是有效的。如果pte页表项的r为1,或者x为1,则直接跳转到步骤5。(表明此时PTE为leaf PTE,已经寻找到了对应虚拟地址对应的物理页号)。否则PTE中的PPN指向的是下一级页表的物理页号。将i = i-1,如果i=0,则停止并根据原始的access type触发一个page fault。如果i大于等于0,a = pte.ppn * PAGESIZE(得到了下一级页表的物理页号*size得到了下一级页表的物理地址),并跳转到步骤2。
  5. 到第五步说明已经寻找到了leaf PTE。根据当前特权模式以及mstatus寄存器中的SUM和MXR(如果MXR = 0,只有load被标记位可读的页才可以成功,如果为1,则load可读可执行的页都会成功)字段的值,判断pte中的r,w,x和u位是否符合内存访问的请求。如果不符合,则停止并根据原始的access type触发一个page fault。
  6. 如果i>0,且pte.ppn[i-1 : 0] 不等于0,则说明这是一个未对齐的super page,停止并根据原始的access type触发一个page fault
  7. 如果pte的a位为0,或者memory access为store且pte的d位为0时,根据原始access type触发一个page fault,或者:
  • 将pte的a位置1,且如果memory access是store时,将pte的d位设为1
  • 如果access违反了PMA或者PMP的检查,触发一个page fault
  • 此更新和步骤2中load pte的过程必须是原子的,尤其地,不能在此过程中插入store操作
  1. 到该步骤则说明虚拟地址到物理地址的转换是成功的。leaf PTE中的PPN就是最终转换成功的物理页号,加上虚拟地址的offset就变成了物理地址。转换后的物理地址要满足一下特性:
  • pa.pgoff = va.pgof(物理地址的页内偏移与虚拟地址的页内偏移是一样的)
  • 如果i>0,则说明这是一个superpage的转换,pa.ppn[i-1 : 0] = va.vpn[i-1 : 0]。
  • pa.ppn[LEVELS-1 :i] = pte.ppn[LEVELS-1 : i](最终的物理地址的物理页号是leaf PTE的物理页号)

64位操作系统的多级页表转换

32位操作系统的页表转换只有sv32一种,已经在2.3.4中详细讲述。64位操作系统根据satp寄存器的MODE位可以分为sv39和sv48等多种页表转换方式,但原理其实和sv32差不多。sv39采用的是三级页表,sv48为四级页表,下图分别展示了在sv39和sv48时的虚拟地址,物理地址和页表项pte。




下图来自MIT的xv6操作系统课程对sv39三级页表映射方案从虚拟地址到物理地址地址转换的总结。


image.png

Page fault

产生page fault的情况有很多种,比如因为懒加载机制,并没有给当前虚拟地址分配物理地址;根据地址转换的安全性检查,也会产生page fault;或者pte因为物理存储机制被存放至磁盘空间,也需要page fault进行swap等等。本章节将会讲述产生page fault的原因,后续章节中会讲述xvisor是如何具体处理page fault的。下图展示了在地址转换的过程中出现page fault的情形:


image.png

内核空间的处理比较简单,也不容易出现page fault的情况,只要处理vmalloc即可。对于用户空间来说,page fault的处理要考虑的情况比较多。首先要对虚拟地址的合法性进行检查。如果一个地址不在合法的VMA区间内,就判定为bad area,并处罚segmentation fault。如果在地址合法的情况下,首先考虑是否是因为用户控件的malloc懒加载机制。
因为malloc是动态分配内存机制,并且为了节省内存,内核并不会立刻为其分配物理内存,而是只是对vma进行信息记录。当地址真正被使用到的时候,处罚page fault,通过mmap建立对应的heap和stack内存区域的映射。在x86的实现机制中,还有一种情况(riscv的linux需要考证),就是在pte页表项的P位为0时,表明该页表项是存在的。只是从内存空间拷贝至了外部磁盘空间,需要调用swap_page将页面的内容拷贝回内存。

参考资料:

MIT操作系统课程
兰新宇:linux内核和虚拟化博客
riscv特权架构文档
微信读书:qemu/kvm源码解析与应用
《系统虚拟化》

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容