Timer 当我启用“TiedToExecution”时,为什么VirtualBox中的TSC更大?

Timer 当我启用“TiedToExecution”时,为什么VirtualBox中的TSC更大?,timer,virtualbox,Timer,Virtualbox,背景我对rdtsc如何虚拟化的理解:我正在VirtualBox中试验TSC值。我目前对VirtualBox如何模拟rdtsc的理解是,在虚拟模式下,对rdtsc的任何调用都将被预定结果抵消,该结果是另一个寄存器中设置的值。当虚拟机启动时,此值将是主机上的rdtsc 这种策略的一个优点是rdtsc将以预期的方式随着挂钟时间的推移而前进,但缺点是流程可能认为rdtsc花费的时间比预期的要长。例如,在这样的简单代码中: x = rdtsc(); y = rdtsc(); z = y - x; prin

背景我对rdtsc如何虚拟化的理解:我正在VirtualBox中试验TSC值。我目前对VirtualBox如何模拟rdtsc的理解是,在虚拟模式下,对rdtsc的任何调用都将被预定结果抵消,该结果是另一个寄存器中设置的值。当虚拟机启动时,此值将是主机上的rdtsc

这种策略的一个优点是rdtsc将以预期的方式随着挂钟时间的推移而前进,但缺点是流程可能认为rdtsc花费的时间比预期的要长。例如,在这样的简单代码中:

x = rdtsc();
y = rdtsc();
z = y - x;
print z
在guest上执行时,z可能比预期的大,因为与捕获rdtsc相关的挂钟时间成本。如果主机操作系统在这两次调用之间交换VirtualBox进程,情况会更糟

通过阅读VirtualBox手册更改TSC模式,我了解到有一种替代的虚拟化技术,它应该直接模拟TSC。据我所知,偏移量值将只考虑来宾操作系统实际使用CPU的时间。其优点是,就可用循环而言,TSC的行为与主机上的行为完全相同。缺点是,TSC将偏离挂钟时间,因为缺少客户操作系统不知道的周期

我的目标是:我正在尝试将VirtualBox设置为执行第二个选项。我想模仿rdtsc的短期行为,就好像它在硬件中尽可能精确地运行一样,我不在乎它是否与挂钟时间不匹配。我完全知道这在SMP上是不可靠的;这是为了试验,而不是为了企业软件

我所做的:首先,我编写了一个简单的测试程序,反复调用rdtsc,然后打印结果:

__inline__ uint64_t rdtsc()
{
    uint32_t lo, hi;
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
    return (uint64_t)hi << 32 | lo;
}

int main()
{
    int i;
    uint64_t val[8];

    val[0] = rdtsc();    
    val[0] = rdtsc();
    val[0] = rdtsc();
    val[0] = rdtsc();
    val[0] = rdtsc();
    val[0] = rdtsc();
    val[0] = rdtsc();
    val[0] = rdtsc();

    for (i = 0; i < 8; i++) {
        printf("rdtsc (%2d): %llX", i, val[i]);
        if (i > 0) {
            printf("\t\t (+%llX)", (val[i] - val[i - 1]));
        }
        printf("\n");
    }
    return 0;
}
然后,我更改了VirtualBox中的TSCTiedToExecution标志,我认为它应该忽略挂钟时间,以支持更精确的虚拟周期计数。我是从上面提到的手册页面上得到的:

./VBoxManage setextradata "HelloWorld" "VBoxInternal/TM/TSCTiedToExecution" 1
然而,这给了我意想不到的结果。虚拟程序现在返回:

rdtsc ( 0): F2252A1824
rdtsc ( 1): F2252A1836   (+B12)
rdtsc ( 2): F2252A1853   (+B1D)
rdtsc ( 3): F2252A1865   (+AFF)
rdtsc ( 4): F2252A1877   (+B13)
rdtsc ( 5): F2252A1889   (+AF2)
rdtsc ( 6): F2252A18A6   (+B1D)
rdtsc ( 7): F2252A18B8   (+B0C)
使用TSTiedToExecution,rdtsc似乎需要大约1100个周期来执行

问题:首先,我想知道为什么我会有这种行为?这似乎与我所期望的几乎相反,而且肯定与我对如何实现这一点的理解不符

第二,我想知道如何才能实现我最初的目标,即让TSC在每个虚拟周期中都像在硬件上一样前进

我的设置:我在2.67GHz的8x IntelR XeonR CPU X5550上运行。VirtualBox已启用VMX和嵌套分页。我从源代码处编译了它,版本:4.1.2_OSE r38459

提前谢谢


顺便说一句,我开始悬赏,但仍然没有答案…

为了让self哭泣,请尝试禁用VBoxInternal/TM/TSTiedToExecution并再次运行测试程序。下一个代码

ULONGLONG x1 = Cpu::Rdtsc();
ULONGLONG x2 = Cpu::Rdtsc();

DbgPrintUlong('D', x2 - x1, 30, 23);
在禁用VBoxInternal/TM/TSTiedToExecution的VirtualBox上运行时,显示x2-x1占用了大约200000个周期。相比之下,在启用VBoxInternal/TM/TSCTiedToExecution的机器上,只需3000个jf周期。我认为,这种减少是指VirtualBox手册的下一段,在特殊情况下,使来宾中的TSC时间戳计数器反映执行来宾的实际时间可能是有用的

所以,我认为我们在VirtualBox中不会有更好的TSC仿真

我唯一能建议的是使用VmWare Workstation。它有更好的模拟TSC

ULONGLONG x1 = Cpu::Rdtsc();
ULONGLONG x2 = Cpu::Rdtsc();

DbgPrintUlong('D', x2 - x1, 30, 23);