首页 > 解决方案 > 像 KVM 这样的管理程序是否需要在 CPUID 上退出 VM?

问题描述

想象一下用于 VM 检测的简单 CPU 时序检查。

static inline unsigned long long rdtsc_diff_vmexit() {
    unsigned long long ret, ret2;
    unsigned eax, edx;
    __asm__ volatile("rdtsc" : "=a" (eax), "=d" (edx));
    ret  = ((unsigned long long)eax) | (((unsigned long long)edx) << 32);
    /* vm exit forced here. it uses: eax = 0; cpuid; */
    __asm__ volatile("cpuid" : /* no output */ : "a"(0x00));
    /**/
    __asm__ volatile("rdtsc" : "=a" (eax), "=d" (edx));
    ret2  = ((unsigned long long)eax) | (((unsigned long long)edx) << 32);
    return ret2 - ret;
}

在真正的硬件上,cpuid 比在 KVM 中运行时花费的时间要少得多。

我在玩 rdtsc 偏移,我在想是否可以不退出 CPUID?我试过禁用退出,不出所料,VM 没有启动(UEFI 固件根本没有出现,没有串行输出)。

我试图弄清楚为什么会这样。我能想到的唯一可能导致问题的事情是报告 CPU 内核/线程。

所以问题是:这甚至可能吗?如果不是,为什么?如果是,有什么资源可以用来让它工作吗?

标签: linuxlinux-kernelkvmhypervisor

解决方案


查看英特尔手册:

英特尔® 64 和 IA-32 架构软件开发人员手册第 3C 卷:系统编程指南,第 3 部分 订单号:326019-072US 2020 年 5 月

Section 25.1.2: Instructions That Cause VM Exits Unconditionally

CPUID 中列出的第一条指令。很清楚,不,您不能禁用 CPUID 上的退出。您可以调整 TSC_OFFSET 字段以解决此问题,但您将希望在系统运行时不断纠正其初始偏移量。这1可能会为您提供一些见解。

此外,没有规定您只能在退出时解释一个操作码。您承担了退出的费用,因此可能值得单步执行一些操作码以避免快速退出。如果您浏览 usenix 论文,您可能会找到一些关于此的建议。这是经典:2


推荐阅读