我想知道使用英特尔VMX / VT技术的虚拟机管理程序如何模拟内存映射I / O(以便客户可以认为它正在对设备执行内存映射I / O)。
我认为基本原则是设置EPT页面表,使得有问题的内存地址会因为无法读取或写入而导致EPT违规(即VM退出)?但是,下一个问题是如何处理VM退出。这样的VM退出将填写所有退出资格原因等,包括客户线性和客户物理地址等。但是我在这些退出资格字段中缺少的是一些字段指示 - 在写入指令的情况下 - 尝试写入的值和写入的大小。同样,对于读取指令,一些位字段指示读取的目的地,比如寄存器或存储器位置(在存储器到存储器串操作的情况下)将是很好的。这将使管理程序很容易弄清楚客户尝试做什么,然后模拟设备对客户的行为。
但麻烦的是,我无法在退出资格中找到这样的字段。我可以看到一个指向错误指令所在位置的指令,因此我可以遍历页表读取指令,然后对其进行解码以理解指令,然后模拟I / O行为。但是,这要求管理程序对所有x86指令进行相当完整的描述,并能够解码它们。这对于管理程序来说似乎是一个沉重的负担,并且还要求它在以后的指令添加中保持最新状态。并且CPU应该已经拥有此信息。
我有可能错过这些相关领域,因为文档非常广泛,但我试图仔细搜索但却找不到它。也许有人可以指出我正确的方向或确认管理程序需要包含指令解码器。
答案 0 :(得分:1)
我相信大多数虚拟机会对指令进行解码。它实际上并不那么难,并且大多数虚拟机都有软件模拟器可以在CPU VM扩展不可用或完成任务时回退。您不需要处理每条指令,只需处理那些可以占用内存操作数的指令,并且您可以忽略所有不是1,2或4字节内存操作数的指令,因为您不可能模拟除了那些尺寸。 (对于内存映射设备缓冲区,如视频内存,您不希望捕获每次内存访问,因为这太慢了,因此您必须采取不同的方法。)
但是,有一种方法可以让CPU为您完成工作,但它比解码指令本身慢得多,而且并不完全完美。您可以在临时映射到RAM的有效页面时单步执行该指令。 VM出口将告诉您访客物理地址访问以及它是读还是写。不幸的是,它不能可靠地告诉你它是否是读 - 修改 - 写指令,那些可能只是设置写标志,以及一些可以产生差异的设备寄存器。复制指令可能更容易(它只能是最多15个字节,但要注意页面边界)并在主机中执行它,但这要求您可以将页面映射到主机中的相同虚拟地址,如同客人。
您可以组合这些技术,解码实际用于访问内存映射设备寄存器的常用指令,同时使用单步执行无法识别的指令。
请注意,选择编写自己的虚拟机管理程序会给自己带来沉重的负担。与模拟整个IBM PC兼容计算机的任务相比,必须在软件中解码指令是一个相当小的负担。英特尔虚拟化扩展并非旨在简化这一过程,而是旨在提高效率。编写一个解释指令的纯软件模拟器会更容易。处理内存映射I / O只是将读取和写入调度到正确的函数。
答案 1 :(得分:1)
我不清楚VT-X是如何工作的,但我认为我看到你的愿望清单中存在一个缺陷:
请记住,x86不是加载/存储计算机。 add [rdi], 2
的加载部分没有体系结构可见的目标,因此您建议的告诉管理程序在何处查找或放置数据的解决方案并不真正有效,除非有一些临时位置,不属于guest虚拟机的架构状态,仅用于虚拟机管理程序和VMX硬件之间的通信。
要有效地处理具有内存目标的读 - 修改 - 写指令,VM应该在一个VM退出时执行整个操作。所以你不能只提供单独的加载和存储接口。
更重要的是,处理原子读 - 修改 - 写是一种特殊情况。 lock add [rdi], 2
不能仅作为单独的加载和存储来完成。