Нужен ли гипервизор, такой как KVM, для выхода из ВМ по CPUID? - PullRequest
3 голосов
/ 02 августа 2020

Представьте себе простую проверку синхронизации ЦП, которая используется для обнаружения ВМ.

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.

Я был играл со смещением rdts c, и я думал, можно ли просто не выйти по CPUID? Я попытался отключить выход, и неудивительно, что виртуальная машина не загружалась (прошивка UEFI вообще не отображалась, нет последовательного вывода).

Я пытался понять, почему это происходит. Единственное, о чем я могу думать, что потенциально может вызвать проблемы, - это сообщение о количестве ядер / потоков ЦП.

Итак, вопрос: возможно ли это вообще? Если нет, то почему? Если да, то есть ли какие-нибудь ресурсы, которые я могу использовать, чтобы заставить его работать?

1 Ответ

2 голосов
/ 08 августа 2020

Глядя на руководство Intel:

Руководство разработчика программного обеспечения для архитектур Intel® 64 и IA-32, том 3 C: Руководство по системному программированию, часть 3 Номер для заказа: 326019-072US Май 2020

Section 25.1.2: Instructions That Cause VM Exits Unconditionally

Первая инструкция, указанная в CPUID. Совершенно очевидно, что вы не можете отключить выходы на CPUID. Вы можете настроить поле TSC_OFFSET, чтобы учесть это, но вам нужно будет постоянно корректировать его начальное смещение по мере работы системы. Этот 1 может дать вам некоторую информацию.

Кроме того, нет правила, согласно которому вы интерпретируете только один код операции при выходе. Вы взяли на себя расходы по выходу, поэтому, возможно, стоит пройти через несколько кодов операций, чтобы избежать быстрого набора выходов. Если вы просмотрите статьи по usenix, вы, вероятно, найдете несколько предложений по этому поводу. Это класс c: 2

...