首页
社区
课程
招聘
[翻译]虚拟化是如何工作的(第二部分 内存虚拟化)
2018-11-16 18:42 7976

[翻译]虚拟化是如何工作的(第二部分 内存虚拟化)

2018-11-16 18:42
7976

免责声明
我并不是这个领域的专家,是通过大量的研究完成这篇文章。写这篇的目的仅仅是“理解虚拟化是怎样工作的,然后分享给大家”。
如果您在阅读中发现任何问题请告诉我,我会尽快改正。


上一部分,我们已经讨论了处理器虚拟化。那么内存虚拟化呢?如果对内存随意修改,内存很可能会挂,所以在解释VMM怎样控制内存之前,我们先了解一下内存的结构。

内存通常被认为是线性分布的,内存单元用来存储字节,分布在0x00000000-0xFFFFFFFF的32位地址供CPU调用。

但对于现在的大多数计算机来说,以上描述已不适用(小型嵌入式系统有时会以这种方式处理内存以节省资源)。相反,现代计算机使用内存管理单元(MMU),它在CPU中负责将虚拟地址转化为物理地址(虚拟与虚拟化无关,只是名字相似)

地址的转换使用了分页机制,分页的理解重点在计算部分。我们取4KB的物理内存,将其基地址存储到一个表项中。这4KB内存称为一页,这个表称为页表(PT)。因特尔手册中定义一个PT可以保存512个页。按照每个页4KB计算,大概可寻址2MB的内存。但是我们想寻址更多内存,所以我们将512个页表的物理地址存储到一个页目录项(PDE)中。计算一下,每个PDE有1GB的内存。这些内存还不够,我们继续将512个PDE的物理地址存储到一个页目录指针表项(PDPTE)中。然后,将512个PDPTE的物理地址存储到一个PML4E中。

 


物理地址可以理解为“内存中的第0xffec1230个字节”。而虚拟地址则包含不同指针表的所有索引,用于将MMU指引到正确的字节。

64位虚拟地址(9位可表示0-511)的含义如下:

63-48位:16位地址扩展;

47-39位:9位PML4偏移;

38-30位:9位PDPT偏移;

29-21位:9位页目录偏移;

20-12位:9位页表偏移;

11-0位:12位页内偏移;

举个例子,虚拟地址0x00000000007FC031写成二进制形式为:

该虚拟地址的含义为:基于虚拟地址,MMU查找PML4的第一项(索引为0),保存着PDPT的物理地址。继续查找,PDPT的第一项保存着PD的物理地址。在PD中查找第四个PT,在PT中查找第509项的指针。该指针将MMU指引到一个页,该页的第50位表示读或写。

 

要时刻记得,每个表项的实际物理地址由两部分组成。存储在表项中的物理地址的前导位,加上虚拟地址的索引,这两部分共同构成一个有效的物理地址。

也许你已经知道,64位计算机的总线地址大多时候只使用48位。所以在实际的处理器中内存地址只有48位,而不是64位。这意味着指向下一表项的指针并没有64位,但每个表项是64位,所以下一表项的指针不能占用所有位。

实际上,这48位中,存储着最后一个指针的前36位,索引占9位,还余3位。这3位是填充位,如果索引由字节构成,这3位会用来表示索引。


分页机制有利有弊:内存管理单元(MMU)必须将虚拟地址转换为物理地址,这意味着处理器需要花更多时间访问内存。但同时,可以利用它做更多有趣的事。

因为指向下一表项的指针不能占用所有64位(只占用36位),剩下的位就用来做标记位。

例如,这是页表项格式:

   

每个页和它的前表项会分配一个权限级别U/S位(图中为红色)。权限级别为0,表示此页及其存储的数据、代码和表项都只能被内核或操作系统访问。这意味着如果处理器要请求内存数据,就必须处理操作系统或内核的代码,否则内存管理单元会产生页错误异常;权限级别为1,表示可以被用户应用访问。

R/W位(图中为蓝色)自然就是读/写标记位。

最后一位(图中为绿色)是禁止执行标记位,置1表示阻止对页的所有操作。这是一个安全标记位,可以用来防止恶意软件执行在进程数据段中的代码。


所以我们为什么要讨论这些呢?第一,这些是基础的计算机知识。第二,英特尔基于这些内容实现硬件的内存虚拟化。

梳理一下:

内存管理单元只负责将虚拟地址转换为物理地址,将数据传回处理器。配置所有页表并分配给正在运行的进程,仍然是由内核完成。

所以,如果在计算机中新建一个虚拟化用户,自然要配置页表。页表结构配置完成后,为了防止内存发生混乱,要设置用户对内存的访问权限级别。

过去,这些操作必须由VMM完成,通过影子页表将用户页转换为物理页,速度很慢。所以因特尔处理器添加了一个扩展页表(EPT),实现在MMU中转换,速度更快。

如果处理器处于VM-non root状态时用户请求内存,MMU会像往常一样首先计算用户物理地址。此时,MMU会查找一个特殊的指针“扩展页表指针“,它只有36位。接着,MMU会将用户物理地址的47-39位附加在后面,最后再加3位。

看起来很熟悉吧?转化过程还是一样的,只是MMU这次没有用虚拟地址来获取索引,而使用了用户物理地址。

就是通过这些方法,用户机内存映射到宿主机内存的过程中不会覆盖数据。主机可以控制用户机内存,而用户机甚至都不知道用了不同的页结构。


如果你之前不了解页的知识,这篇文章可能会读起来有些困难。我已经试着让文章容易理解,没有包含缓存、使用GDT的内存分段机制等内容。如果有什么问题,欢迎与我交流。

下一部分我准备写点VT-d的东西,但我实在厌倦了读因特尔手册。所以在空闲时候我想介绍一下运用了很多虚拟化技术的Qubes操作系统,或者写一个可以攻击到用户主机的漏洞利用。或者写一点POC Bluepill恶意软件,比如rootkit。


翻译:Green奇

校对:sudozhange

原文链接:https://0x00sec.org/t/a-lot-about-paging-a-little-about-virtualization-part-2/8868






[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2018-12-28 17:54 被Green奇编辑 ,原因:
收藏
点赞5
打赏
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  junkboy   +1.00 2018/11/17
最新回复 (6)
雪    币: 15200
活跃值: (1832)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
会飞的锅 2018-11-16 19:24
2
0
学习了
最后于 2018-11-16 19:25 被会飞的锅编辑 ,原因:
雪    币: 10704
活跃值: (762)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
固件安全 2018-11-16 19:39
3
1
666,思路很清晰,解释的很好很全面,表示我这种小白也看得懂
最后于 2018-11-16 19:40 被固件安全编辑 ,原因:
雪    币: 3402
活跃值: (3447)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
fengyunabc 1 2018-11-17 13:05
4
1
感谢分享!
雪    币: 11716
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
junkboy 2018-11-17 16:22
5
1
辛苦
雪    币: 19586
活跃值: (60148)
能力值: (RANK:125 )
在线值:
发帖
回帖
粉丝
Editor 2018-11-17 16:24
6
0
雪    币: 24
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
nervgu 2018-11-30 16:53
7
0
一个页表到底包含多少个页啊,不是1024吗,这里为啥是512,
游客
登录 | 注册 方可回帖
返回