是否可以在VM内使用VMX CPU指令?

2024-05-15

VM guest 内部的进程是否有可能使用 VMX(AMD-V、VT-x)CPU 指令,然后由外部 VMM 处理而不是直接在 CPU 上处理?

Edit:假设外部VM使用VMX本身来管理其虚拟客户机(即它在Ring -1中运行)。

如果可能的话,是否有支持模拟/拦截 VMX 调用的 VMM 实现(VMware、Parallels、KVM,...)?


也不是英特尔的VT-x也不是 AMD 的AMD-V支持硬件中的完全递归虚拟化 - 其中 CPU 以与虚拟化环境相同的方式保留嵌套虚拟化环境的层次结构call/ret pair.

逻辑处理器仅支持两种操作模式:主机模式(在 Intel 术语中称为 VMX 根模式,AMD 中称为虚拟机管理程序)和来宾模式(在 AMD 手册中称为 VMX 非根模式)。
这意味着一个扁平化的层次结构,其中每个虚拟化环境都被 CPU 同等对待 - CPU 不知道虚拟机的层次结构有多深。

尝试在来宾内部使用虚拟化指令本身会将控制权交给监视器(VMM)。
但最近出现了一些对加速常用虚拟指令的支持,使得嵌套虚拟机成为可能。

我将尝试分析实现嵌套虚拟化所面临的问题。
我没有处理整个事情 - 我正在考虑基本情况,只忽略处理硬件虚拟化的所有部分;这一部分本身就和软件虚拟化一样存在问题。

Note
我不是虚拟化技术方面的专家,也没有任何经验——欢迎指正。
这个答案的目的是让读者从概念上相信嵌套虚拟化是可能的,并概述要面临的问题。

VT-x

逻辑处理器通过执行以下命令进入VMX操作vmxon- 一旦进入该模式,处理器就处于根模式。
Root模式是VMM的模式,它可以启动、恢复和处理VM。

The VMM then set the current VMCS (VM Control Structure) with vmptrld - the VMCS contains all the metadata necessary to virtualise a guest.
The VMCS is read and written not with direct memory accesses but with vmread and vmwrite instructions.

最后,VMM执行vmlaunch开始执行来宾。

接收虚拟机

现在逻辑处理器正在虚拟化环境中执行。
假设来宾本身就是一个 VMM,我们将其称为非根 VMM - 它需要重复上述步骤。

但英特尔在其手册中明确表示(手册 3 - 第 25.1.2 章):

以下指令会导致VM exits当它们在 VMX 非 root 操作中执行时:
[...]
VMX 引入的指令也是如此,其中包括:
[...],VMLAUNCH, VMPTRLD, [...] 和VMXON

vmxon该指令导致 VM 退出,根 VMM 从最后一条指令后的指令恢复vmlaunch,可以检查 VMCS 的退出原因并采取适当的操作。
我不是一个经验丰富的 VMM 编写者,所以我不确定根 VMM 必须做什么来模拟这个指令 - 因为执行vmxon在 VMX root 模式下将会失败并执行vmxoff随后是一个vmxon由非根 VMM 提供的 VM 区域似乎是一个安全漏洞(或导致它的原因),我相信根 VMM 所要做的就是记录来宾现在处于“VMX 根模式”。
这里需要引号:此模式仅存在于软件中,当根 VMM 将控制权交还给非根 VMM 时,CPU 将处于非根 VMX 模式。

之后,非根 VMM 将尝试使用vmptrld设置当前的 VMCS。
vmptrld将导致 VM 退出并且根 VMM 再次获得控制 - 如果 CPU 不支持VMCS 阴影 https://www-ssl.intel.com/content/dam/www/public/us/en/documents/white-papers/intel-vmcs-shadowing-paper.pdf根 VMM 必须记录非根 VMM 给出的指针现在是当前 VMCS - 如果 CPU 确实支持VMCS 阴影VMM 设置VMCS链接指针现场itsVMCS(用于虚拟化非根 VMM 的 VMCS)为非根 VMM 提供的 VMCS。
VMM 通过某种方式知道哪个虚拟化 VMCS 处于活动状态。

vmread and vmwrite由非根 VMM 执行将或不会导致 VM 退出。
如果 VMCS 阴影处于活动状态,CPU 将不会执行 VM 退出,而是会读取由 VMCS 指向的 VMCSVMCS链接指针在活动 VMCS 中(称为影子VMCS).
这将加快嵌套虚拟机的虚拟化速度。
如果 VMCS 阴影未激活,CPU 将 VM 退出,并且根 VMM 必须模拟读/写。

最后,非根 VMM 将启动其 VM - 这是一个嵌套 VM。
vmlaunch将触发 VM 退出。
根 VMM 必须做一些事情:

  • 将其 VMCS 保存在某处。
  • 合并当前 VMCS 和非根 VMM VMCS - 例如,由于 VMCS 控制哪些事件导致 VM 退出,因此合并后的事件必须是这两者的并集。
  • 将合并后的 VMCS 加载为 CPU 的当前 VMCS
  • Do a vmlaunch/vmresume.

梦里面

现在CPU正在执行嵌套VM(VVM - 虚拟VM?)。
当敏感指令或事件导致 VM 退出时会发生什么?

从处理器的角度来看,虚拟化只有两个级别:根VMX模式和非根VMX模式。
由于客户机处于非根 VMX 模式,因此控制权将转移回根 VMX 模式代码 - 即根 VMM。

根VMM 现在必须了解该事件是来自其VM 还是来自其VM 的VM。
这可以通过跟踪使用情况来完成vmlaunch/vmresume并检查 VMCS 中的位。

如果 VM Exit 定向到非根 VMM,则根 VMM 必须加载其原始 VMCS,最终在其中设置非根 VMM 的链接,更新非根 VMM VMCS 状态位并执行vmresume.
如果 VM 出口定向到它,则根 VMM 将像处理任何其他 VM 出口一样处理它。

梦中梦中梦

如果我们想在嵌套虚拟机中创建虚拟机怎么办? 一种虚拟虚拟机 (VVVM)。

有两点需要注意:

  1. 根 VMM 仍然是每次 VM 退出期间调用的 VMM。
    即使 VVVM 是三层深度,它也不是用于虚拟化它的第一个和/或唯一的管理器。
    从安全角度来看,根VMM是薄弱环节。
  2. 硬件并不真正支持任意深度嵌套。
    VMM 可能不需要太多的努力就可以从支持 1 级嵌套到 n 级嵌套(同样,我在这里经验不足),但仍然需要如上所述的特殊支持。
    这并不像启动虚拟机那么容易,其他一切都将由 CPU 处理。

AMD-v

AMD-v 中没有根模式与非根模式,CPU 开始执行虚拟机vmrun它采用一个指向 VMCB(VM 控制块)的指针,该 VMCB 与 Intel 的 VMCS 具有相同的用途。
Upon a vmrunCPU 处于访客模式。

VMCB 已被缓存,但只能通过通常的内存访问来读取。
The vmload/vmsave指令显式地将受缓存影响的 VMCB 字段加载到缓存中并从缓存中保存。

该接口比英特尔的接口更简单,但同样强大 - 即使涉及嵌套虚拟化。

假设我们在虚拟机内并且代码执行vmrun- 因此我们正在虚拟化一个 VMM。

从技术上讲,VMM 可以随时选择vmrun会或不会触发虚拟机退出。
然而,实际上,AMD-v 目前要求前者始终如此:

以下情况被视为非法状态组合: [...]
* 这VMRUN拦截位清除

因此,根 VMM(我将使用与 Intel 案例中相同的术语)将获得控制权并且必须模拟vmrun(因为硬件仅支持单级虚拟化)。

根VMM可以保存当前VMCB并将其与非根VMM VMCB合并,并继续执行vmrun就像英特尔的案例一样。

退出时,根 VMM 必须确定退出是定向到它还是定向到非根 VMM,这同样可以通过跟踪vmrun以及 VMCB 中的控制位。

又做梦了

我们已经在虚拟机内相对容易地设置了虚拟机 - 现在虚拟机退出时会发生什么?
根 VMM 接收退出,如果定向到非根 VMM,则必须恢复其原始 VMCB 并恢复运行(即使用vmrun及其原始 VMCB)。

AMD-v 支持快速虚拟化vmsave and vmload指令通过考虑它们的地址来宾地址,从而受到通常的页面嵌套虚拟化的影响。

再次提起 Inception

与 Intel 的情况一样,只要 VMM 支持该功能,虚拟化就可以再次嵌套。

针对英特尔案例的关键安全警告也适用于 AMD 案例。


Due to its implementation-defined format and the fact the memory area can be used just as a spill area that is not updated in real time

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以在VM内使用VMX CPU指令? 的相关文章

  • 为什么在展开的 ADD 循环内重新初始化寄存器会使其运行速度更快,即使循环内有更多指令?

    我有以下代码 include
  • 32 位到 64 位内联汇编移植

    我有一段 C 代码 在 GNU Linux 环境下用 g 编译 它加载一个函数指针 它如何执行并不重要 使用一些内联汇编将一些参数推送到堆栈上 然后调用该函数 代码如下 unsigned long stack 1 23 33 43 save
  • 整数溢出问题

    我不断遇到整数溢出问题 我不知道如何解决它 有人可以帮忙吗 edx 包含 181 eax 包含 174 xor eax edx mov edx 2 div edx 假设你谈论的是x86 div edx这实际上没有意义 32位div将edx
  • Intel:序列化指令和分支预测

    英特尔架构开发人员手册 http www intel com content www us en architecture and technology 64 ia 32 architectures software developer v
  • CISC 机器 - 它们不只是将复杂指令转换为 RISC 吗?

    也许我在架构上存在误解 但如果机器有 比如说 乘法指令 该指令是否未转换为更小的指令 或者过于复杂以至于最终与等效的 RISC 指令具有相同的速度 乘法是一个不好的例子 它在两种体系结构中都是一条指令 将上面的 乘法 替换为 CISC 中更
  • 如何在 GCC C++ 中编写多行内联汇编代码?

    这看起来不太友好 asm command 1 command 2 command 3 我真的必须在每一行加上双引号吗 另外 由于多行字符串文字在 GCC 中不起作用 我也无法欺骗它 我总是在互联网上找到一些例子 该人手动插入制表符和换行符而
  • IDA pro asm 指令更改

    我只是想知道我怎样才能 更改IDA视图A中的asm指令 如何编辑指令 对于 实例 jnz 到 jmp 如何插入新指令 call func1 调用 func2 插入到现有的 代码 我知道如何制作 diff 文件 我知道如何在我的 DLL 上应
  • 如何在WinMobile6上启用ARMv6非对齐访问?

    ARMv6 引入了一个很棒的功能 未对齐的内存访问 这使得代码中的某些事情变得更加简单和更快 但微软只在winCE6中提供了API 现在大多数 PDA 都基于 WinMobile6 基于 CE 5 x 默认情况下禁用未对齐访问 我尝试在 C
  • 将 Docker 容器连接到本地主机的最简单方法

    我想知道是否可以从 Docker 容器连接到本地主机上的应用程序 我运行两个 Docker 容器 它们通过以下方式相互连接link选项 但是如何将其中一个容器连接到本地主机呢 是的 使用docker run network containe
  • 在 Intel x86 架构上使用非 AVX 指令移动 xmm 整数寄存器值

    我有以下问题 需要使用 AVX2 以外的任何工具来解决 我有 3 个值存储在 m128i 变量中 不需要第四个值 需要将这些值移动 4 3 5 我需要两个功能 一个用于按这些值进行右逻辑移位 另一个用于左逻辑移位 有谁知道使用 SSE AV
  • Android NDK 代码中的 SIGILL

    我在市场上有一个 NDK 应用程序 并获得了有关以下内容的本机崩溃报告 SIGILL信号 我使用 Google Breakpad 生成本机崩溃报告 以下是详细信息 我的应用程序是为armeabi v7a with霓虹灯支持 它在 NVIDI
  • 一个地址有多少字节? [复制]

    这个问题在这里已经有答案了 在64位机器上 我们知道一个地址是8个字节 然而 我并不完全清楚一个地址中有多少字节的信息 虚拟内存中的每个字节都有一个地址吗 或者内存中的每 64 位都有一个地址 还是取决于架构 如果这取决于架构 那么我应该如
  • long double(GCC 特定)和 __float128

    我正在寻找有关的详细信息long double and float128在 GCC x86 中 更多是出于好奇而不是因为实际问题 可能很少有人需要这些 我只是有史以来第一次 truly需要一个double 但我想知道你的工具箱里有什么以及它
  • 学习 (N)ASM 的最佳资源是什么? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想学习汇编已经有一段时间了 尽管我之前尝试过几次 但我还没有真正能够超越 Hello world 有
  • 在 x86 程序集中打印寄存器值的简单方法

    我需要在 8086 Assembly 中编写一个程序 接收来自用户的数据 进行一些数学计算并在屏幕上打印答案 我已经编写了程序的所有部分并且一切正常 但我不知道如何打印号码显示到屏幕上 在我所有计算结束时 答案是 AX 它被视为无符号 16
  • ICC 中的 -O3 会扰乱内在函数,使用 -O1 或 -O2 或相应的手动汇编即可

    这是后续这个问题 http stackoverflow com questions 49791664 o2 in icc messes up assembler fine with o1 in icc and all optimizatio
  • 如何在 MacOS 上使用 nasm 进行编译

    我正在尝试在汇编器上编译并链接我的第一个程序 我尝试编译以下代码 include stud io inc global main section text main xor eax eax again PRINT Hello PUTCHAR
  • 比“add esp, 4”更小的指令

    又是我 我的程序中有很多 add esp 4 我正在尝试减小它的大小 是否有任何更小的指令可以替代 add esp 4 pop edx 或者您不介意破坏的任何其他整数寄存器 这就是现代编译器实际上所做的 https stackoverflo
  • 如何从程序内部获取指向程序的特定可执行文件部分的指针? (也许是诽谤)

    我在 Linux 环境中 需要编写一个程序来检索放置在其可执行文件的某个部分中的一些数据 那么 如何从程序内部获取指向程序某个部分 通过其名称 的指针呢 我知道可以使用elf getdata 将节的索引作为参数传递给 get 和Elf Da
  • INT 13h 无法读取超出特定扇区的数据

    我正在为我的操作系统编写内核 在将磁盘扇区加载到内存时遇到问题 以下是从磁盘加载扇区的函数代码部分 mov ax 0x3000 mov es ax mov ax 0x0201 mov bx word ptr bp 6 bx 0x000 0x

随机推荐

  • 将两个反斜杠替换为一个反斜杠

    我想用单个反斜杠替换带有两个反斜杠的字符串 但是 替换似乎不接受 作为替换字符串 这是解释器的输出 gt gt gt import tempfile gt gt gt temp folder tempfile gettempdir gt g
  • 通过php将mp3转换为ogg

    我有一个网站 用户可以上传音乐并将其转换为 mp3 但我需要 mp3 和 ogg 文件支持才能以 html5 播放音乐 那么 有没有可以将mp3转换为ogg的php脚本呢 使用 ffmpeg 您可以直接从 php 脚本执行命令
  • mysql 数据库正在复制,但在主服务器上创建的用户未在从服务器上复制

    在主从复制中 我们使用 mysql DB 在从服务器上复制少量数据库 我在主服务器上创建了一个用户 不幸的是它没有在从服务器上复制 Replicate Do DB app1 app2 mysql 用户创建命令 GRANT SELECT on
  • MVC4 捆绑:由于 css3 功能而缩小失败?

    我想使用 MVC4 捆绑和缩小 但我总是在未缩小的 css 文件中收到此错误消息作为注释 Minification failed Returning unminified contents 534 29 run time error CSS
  • JS 库请求的常见 HTTP 标头是什么?

    使用JavaScript 框架原型 http www prototypejs org 我注意到 Ajax 请求通过一个名为X Requested With 其他 JavaScript 库 如 jQuery dojo 和 YUI 是否会向其
  • Activity 暂停时调用 FragmentManager.popBackStack 是否安全

    的文档FragmentManager popBackStack https developer android com reference android app FragmentManager html popBackStack java
  • 使用 PHP 将 SVG 图像转换为 PNG

    我正在开发一个网络项目 该项目涉及动态生成的美国地图 根据一组数据为不同的州着色 这个 SVG 文件为我提供了一张很好的美国空白地图 并且很容易更改每个州的颜色 困难在于 IE 浏览器不支持 SVG 因此为了让我使用 svg 提供的便捷语法
  • div 之间的额外空间从何而来?

    http www lethalmonk6 byethost24 com index html http www lethalmonk6 byethost24 com index html 如果您使用 firebug 检查 项目链接 div
  • 如何在Tensorflow中保存估计器以供以后使用?

    我按照教程 TF Layers 指南 构建卷积神经网络 以下是代码 https github com tensorflow tensorflow blob r1 1 tensorflow examples tutorials layers
  • 将“列表”转换为“集合”?

    OCaml 真的没有从列表转换为集合的函数吗 如果是这样的话 是否可以制作一个通用函数list to set 我尝试制作一个多态集 但没有成功 基本问题 列表可以包含任何类型的元素 集合 假设你的意思是Set http caml inria
  • 您是否将信息添加到每个 .hpp/.cpp 文件的顶部? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 创建新的 C 头文件 源文件时 您会在顶部添加哪些信息 例如 您是否添加日期 您的姓名 文件描述等 您是否使用结构化格式来存储此信息 e g F
  • 在多个数组中搜索字符串,然后设置 var - jQuery

    我正在寻找基于字符串存在于哪个数组中设置一个变量 例如 var primary red blue yellow var secondary orange purple green 然后检查 purple 并返回它在 secondary 数组
  • 简单的颜色变化

    我正在创建一个用户界面 用户可以在其中更改页面的颜色值 我想要的是获取分配给其背景颜色的值并将其变亮一定程度 我只是想获得一条亮点线 而不必每次都制作新图像 示例 用户将背景颜色设置为 ECECEC 现在我希望某个元素边框变成 F4F4F4
  • 如何在android中安装和使用couch db

    我应该如何在 android 中安装和使用 couch Db 我的意思是本地沙发数据库 我可以在平板电脑和模拟器中使用它 为此我必须遵循哪些步骤 我目前正在开发一个使用它的项目 有两种选择 1 couchbase android 是的 co
  • 选择 UITableViewCell 时 UIView 背景颜色消失

    我在界面生成器中构建了一个简单的 tableViewCell 它包含一个包含图像的 UIView 现在 当我选择单元格时 会显示默认的蓝色选择背景 但 UIView 的背景颜色消失了 我的 UITableViewCell 的实现文件没有做任
  • Streamlabs API 405 响应代码

    我正在尝试使用Streamlabs API https dev streamlabs com Streamlabs API 使用 Oauth2 来创建应用程序 因此 首先我将使用我的应用程序的用户发送到一个授权链接 其中包含我的应用程序的客
  • CSS calc() 是否可以得到负值?

    假设我们有一个位于视口中心的容器 centered margin 0 auto width 960px 在该容器内 我有另一个容器 其宽度需要为视口宽度的 100 我可以将边距设置为 widest margin 0 480px 例如 问题是
  • 当选项卡重新加载(chrome 扩展)时,如何运行此脚本?

    所以我想在指定 URL 中重新加载选项卡时运行脚本 它几乎可以工作 但实际上 id 不能 这是我的清单文件 manifest version 2 name Sample Extension description Sample Chrome
  • 在 jQuery DataTables 中的 Ajax 请求后在 td 中添加 html 元素

    我想在获得 ajax 响应后在 td 中添加 html 元素 结果将是这样的 tr td class mycus class span class mycus class2 XYZ span td td class mycus class
  • 是否可以在VM内使用VMX CPU指令?

    VM guest 内部的进程是否有可能使用 VMX AMD V VT x CPU 指令 然后由外部 VMM 处理而不是直接在 CPU 上处理 Edit 假设外部VM使用VMX本身来管理其虚拟客户机 即它在Ring 1中运行 如果可能的话 是