为什么 VMREADs/VMWRITEs 比内存 Read/Write 操作慢

Why are VMREADs/VMWRITEs slower than Memory Read/Write operation

从逻辑上讲,写入任何 CPU 存储变量应该比相应的内存操作更快,因为没有缓存未命中的机会。这些状态缓存在 CPU 中,并且在下一个 VMLAUNCH/VMRESUME 操作之前它们不会更改任何 CPU 状态。因此,它们应该比对内存地址的等效操作更快

在查看 AMD 和 Intel 提供的不同虚拟化解决方案时会出现此问题。 Intel 已强制要求对 VMCS 数据结构的所有更改都应始终通过 VMREAD/VMWRITE 接口,而不是通过常规内存 R/W 操作。但是AMD并没有做这样的限制,它的VMCB区域是通过常规的内存操作来修改的。

英特尔方法的收益应该比 AMD 快 VMExit/VMResume 倍。但是,英特尔会通过添加新指令在灵活性方面有所松动。

然而,实际上,VMREAD/VMWRITE 操作比常规内存操作慢。这对我来说没有任何意义。

常规内存 reads/writes 由专用硬件处理以优化它们,因为真正的程序充满了它们。

大多数工作负载不会花太多时间修改特殊的 CPU 控制寄存器,因此这些指令的内部处理通常没有进行大量优化。在内部,它可能是微码的(即从微码 ROM 解码为许多 uops)。


段寄存器可能不是一个很好的类比,因为写入一个会触发 CPU 从 GDT/LDT 加载描述符。但根据 Agner Fog's testing for Nehalemmov sr, r 每 13 个周期有一个吞吐量,并解码为 6 微指令(来自微码)。 (他停止了稍后 CPUs 的段寄存器测试。)实际上,我不确定那是在 16 位还是 32 位模式下。如果是 16 位实模式,那么写入段寄存器不会读取描述符;它只是更新基数和限制。

读取段寄存器更快:每个时钟读取一个。但这仍然比读取普通寄存器慢(常规 mov 指令在 Nehalem 上的吞吐量为 0.33c)。

Nehalem 每个时钟只能加载 and/or 存储一次,不像 Sandybridge 系列每个时钟可以加载 2 次。但是段寄存器读取可能并不快。

移动 to/from 控制寄存器可能会更慢,因为它比段寄存器更罕见。