【问题标题】:Which networking syscalls cause VM Exits to Hypervisor in Intel VMX?哪些网络系统调用会导致 VM 退出到 Intel VMX 中的 Hypervisor?
【发布时间】:2021-12-27 22:56:58
【问题描述】:

我无法理解哪个(如果有)系统调用会导致虚拟机退出到英特尔 VMX 下的 VMX 根模式。我对与网络相关的系统调用(即 socket、accept、send、recv)特别感兴趣,因为它们需要一个“虚拟”设备。我知道必须调用管理程序才能实际打开套接字,但这可以并行完成(假设在多核处理器上)?

任何澄清将不胜感激。

【问题讨论】:

  • VMX 本身没有定义任何应该捕获或导致 VM 退出到主机的“系统调用”。 CPU 甚至不需要知道 VMX 工作的系统调用是什么。这完全由操作系统决定。你的意思是用 [linux-kernel] 和可能的 [linux] 来标记它吗?否则这个问题有点不正确。
  • 感谢您的回复。我想我的意思是用 linux-kernel 和/或 linux 来标记它(我会这样做)。但是,如果发生与网络相关的系统调用,我可以使用哪些文档来确定来宾操作系统是否会导致 VM 退出?
  • 例如,我有兴趣找出哪些(如果有的话)系统调用应该为支持 VMX 的机器上的来宾 Ubuntu 操作系统捕获或导致 VM 退出到主机。
  • mmap 可能在没有硬件支持嵌套页表的旧 CPU 上。或者是的,可能任何涉及虚拟硬件或半虚拟化驱动程序的东西。但请注意open()socket() 系统调用不会发送任何数据包;甚至write 也不会必然在 TCP 连接上发送数据包,具体取决于写入的大小与 MTU 的关系。但是send 可能会,除非你使用MSG_MORE
  • @ballsmahoney 好的,现在我明白你所说的“并行”是什么意思了,我已经编辑了我的答案来解决这个问题。

标签: linux-kernel x86 virtual-machine virtualization hypervisor


【解决方案1】:

根据Intel 64 and IA-32 Architectures Software Developer's Manual(第3卷第22章)int 0x80sysentersyscall,Linux下用于执行系统调用的三个主要指令都不会导致VM退出 本身。所以一般来说,没有一个明确的方法来判断哪些系统调用会导致 VM 退出,哪些不会。

VM 退出可以在很多情况下发生,例如主机可以配置一个异常位图来决定哪些异常会导致 VM 退出,包括页面错误,因此理论上几乎任何执行内存操作的代码(内核或用户) 可能会导致 VM 退出。

排除这种极端情况并专门讨论网络,正如Peter Cordesabove comment 中所建议的那样,您应该关注的是[可能] 发送和接收数据的操作,因为这些操作最终需要与硬件(网卡):

  • socketsocketpair{get,set}sockoptbindshutdown(等等)这样的系统调用不应导致虚拟机退出,因为它们不需要与底层硬件通信,它们只是操纵逻辑内核数据结构。

  • readrecvwrite 可能会导致 VM 退出,除非内核在发送之前已经有数据可供读取或正在等待积累足够的数据以进行写入(例如,按照 Nagle's algorithm)。内核是否真正停止从硬件读取或直接发送到硬件取决于套接字选项、系统调用标志和底层套接字/连接的当前状态。

  • sendto, recvfrom, sendmsg, recvmsg (etc.), select, poll, epoll (etc.) on network sockets都可能导致VM退出,再次取决于具体情况,和上一点的推理差不多。

  • connect 对于数据报套接字 (SOCK_DGRAM) 不需要 VM 退出,因为它只是设置默认地址,但对于基于连接的协议(例如 SOCK_STREAM)绝对可以,因为内核需要发送和接收建立连接的数据包。

  • accept 还需要发送/接收数据,因此会导致 VM 退出。

我知道必须调用管理程序才能真正打开套接字,但这可以并行完成吗(假设在多核处理器上)?

“并行”不是我会使用的术语,但网络 I/O 操作可以由操作系统异步处理,例如数据包不一定在通过系统调用请求时准确地接收或发送,而是在需要时。例如,在来宾用户空间程序发出相关系统调用之前,可能已经执行了接收数据所需的一个或多个 VM 出口。

如果在多核系统上并且有可以允许 VMM 和来宾同时运行的可用内核,是否总是需要发生 VM 退出(如果需要)以在 NIC 上发送数据包?我想我想问的是,增加并行性是否可以通过允许虚拟机管理程序与来宾并行运行来防止 VM 退出。

当 VM 退出时,客户 CPU 将停止并且无法恢复执行,直到 VMM 为其发出 VMRESUME(请参阅 Intel SDE Vol 3 第 23.1 章“虚拟机控制结构概述”)。不可能“阻止”VM 退出的发生,但是在多处理器系统上,VMM 理论上可以在多个内核上运行,并将 VM 退出的处理委托给另一个 VMM 线程,同时提前恢复停止的 VM。

因此,虽然提高并行度不能阻止 VM 退出,但理论上可以减少它们的开销。但是请注意,这只会发生在可以在恢复来宾时“延迟”处理的 VM 退出上。例如,如果来宾页面错误和 VM 退出,VMM 不能真正“委托”处理 VM 退出并更早恢复来宾,因为来宾需要在恢复执行之前解决页面故障。


总而言之,当客户内核需要与硬件通信时,这可能会导致 VM 退出。访问模拟硬件以进行 I/O 操作需要管理程序介入并因此导致 VM 退出。然而,有一些可能的优化需要考虑:

  • 硬件直通可用于支持IOMMU 的系统,以使设备直接可用于来宾操作系统,并在硬件通信中实现非常低的开销,无需退出虚拟机。参见Intel VT-dIntel VT-cSR-IOV,以及"PCI passthrough via OVMF" on ArchWiki

  • Virtio 是网络 (NIC) 和块设备(磁盘)的半虚拟化标准,旨在减少 I/O 开销(即所需的 VM 出口的总数),但需要支持来自客人和主人。在这种情况下,客人“意识到”自己是客人。另见:Virtio for Linux/KVM


进一步阅读:

【讨论】:

  • 感谢 Marco 的出色回答。但是,如果您不介意扩展它们,我还有其他澄清问题; “除非内核已经有数据可供读取,否则读取、接收或写入会导致 VM 退出”是什么意思?由于这是异步处理的,VMM 是否有可能在不导致 VM 退出的情况下继续修改 VCPU 状态,现在数据可用,不必执行 VM 退出?
  • 此外,当您说“在来宾用户空间程序发出相关系统调用之前,可能已经执行了接收数据所需的一个或多个 VM 退出”,数据(例如来自 read/recv ) 在显式系统调用之前已经被读取/接收?据我了解,VT-X 甚至 AMD-V 等技术消除了对二进制转换的需求,因此我不确定 VMM(或其他任何人)如何过早地知道提前为客人获取此信息。
  • @ballsmahoney 在这两种情况下,我只是表示内核可能已经从设备接收到数据,例如通过中断或通过硬件 I/O(两者都可能导致 VM 退出),并且在进行实际系统调用时,无需再次退出,因为数据已经在来宾内核缓冲区中准备好,因此来宾用户空间程序发出系统调用不会导致 VM 退出,而只会获取已接收数据的副本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-08
  • 2016-01-04
  • 2012-07-25
相关资源
最近更新 更多