Я работаю с модулем ядра Linux (VMM) для тестирования Intel VMX, чтобы запустить самодельную виртуальную машину (виртуальная машина запускается в реальном режиме, а затем переключается в 32-битный защищенный режим с включенной функцией пейджинга).
VMMнастроено на НЕ использование выхода rdtsc и использование смещения rdtsc.
Затем виртуальная машина запускает 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
Разница в производительности НЕ может быть проигнорирована при выполнении кодов в ВМ и в хосте.Это НЕ ожидается.
Насколько я понимаю, при использовании смещения TSC + отсутствие выхода RDTSC, должно быть небольшое различие в rdtsc, работающем на ВМ и хосте.
Вот поля VMCS,
0xA501E97E = control_VMX_cpu_based
0xFFFFFFFFFFFFFFF0 = control_CR0_mask
0x0000000080050033 = control_CR0_shadow
На последнем уровне EPT PTE, бит [5: 3] = 6 (обратная запись), бит [6] = 1. EPTP [2: 0] = 6 (обратная запись)
Я тестировал на голом металлеи в VMware я получил аналогичные результаты.
Мне интересно, есть ли что-то, что я пропустил в этом случае.