1

我正在使用 Linux 内核模块 (VMM) 来测试 Intel VMX,运行自制 VM(VM 以实模式启动,然后切换到启用分页的 32 位保护模式)。
VMM 配置为不使用 rdtsc 退出,并使用 rdtsc 偏移。
然后,VM 运行 rdtsc 来检查性能,如下所示。

static void cpuid(uint32_t code, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
    __asm__ volatile(
            "cpuid"
            :"=a"(*eax),"=b"(*ebx),"=c"(*ecx), "=d"(*edx)
            :"a"(code)
            :"cc");
}

uint64_t rdtsc(void)
{
        uint32_t  lo, hi;
        // RDTSC copies contents of 64-bit TSC into EDX:EAX
        asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
        return (uint64_t)hi << 32 | lo;
}

void i386mode_tests(void)
{
    u32 eax, ebx, ecx, edx;
    u32 i = 0;

    asm ("mov %%cr0, %%eax\n"
         "mov %%eax, %0  \n" : "=m" (eax) : :);

    my_printf("Guest CR0 = 0x%x\n", eax);
    cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
    vm_tsc[0]= rdtsc();
    for (i = 0; i < 100; i ++) {
        rdtsc();
    }
    vm_tsc[1]= rdtsc();
    my_printf("Rdtsc takes %d\n", vm_tsc[1] - vm_tsc[0]);
}

输出是这样的,

Guest CR0 = 0x80050033
Rdtsc takes 2742

另一方面,我制作了一个主机应用程序来做同样的事情,就像上面一样

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

static void cpuid(uint32_t code, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
        __asm__ volatile(
                        "cpuid"
                        :"=a"(*eax),"=b"(*ebx),"=c"(*ecx), "=d"(*edx)
                        :"a"(code)
                        :"cc");
}

uint64_t rdtsc(void)
{
        uint32_t  lo, hi;
        // RDTSC copies contents of 64-bit TSC into EDX:EAX
        asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
        return (uint64_t)hi << 32 | lo;
}

int main(int argc, char **argv)
{
        uint64_t     vm_tsc[2];
        uint32_t eax, ebx, ecx, edx, i;

        cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
        vm_tsc[0]= rdtsc();
        for (i = 0; i < 100; i ++) {
                rdtsc();
        }
        vm_tsc[1]= rdtsc();
        printf("Rdtsc takes %ld\n", vm_tsc[1] - vm_tsc[0]);

        return 0;
}

它输出以下内容,

Rdtsc takes 2325

在 40 次迭代中运行以上两个代码以获得平均值如下,

avag(VM)   = 3188.000000   
avag(host) = 2331.000000

在 VM 和主机中运行代码时,性能差异不容忽视。这不是预期的。
我的理解是,使用 TSC 偏移 + 没有 RDTSC 退出,rdtsc 应该没有什么区别,运行在 VM 和主机上。
这是 VMCS 字段,

 0xA501E97E = control_VMX_cpu_based  
 0xFFFFFFFFFFFFFFF0 = control_CR0_mask  
 0x0000000080050033 = control_CR0_shadow  

在 EPT PTE 的最后一级,bit[5:3] = 6(回写),bit[6] = 1。EPTP[2:0] = 6(回写)
我在裸机和 VMware 中进行了测试,我得到了类似的结果。
我想知道在这种情况下我是否遗漏了什么。

4

0 回答 0