В KVM CPUID отсутствуют функции «Расширенная информация о процессоре и биты функций»

#linux-kernel #kvm

#linux-ядро #kvm

Вопрос:

Я пытаюсь использовать KVM с QEMU. Мне не хватает многих функций в QEMU (те функции, которые присутствуют в хосте). Я проверил код в QEMU, и он проверяет функции, предоставляемые KVM. Я написал простой код на языке .c, который проверяет, предоставляет ли KVM доступные функции :

 #include <stdio.h>
#include <fcntl.h>
#include <linux/kvm.h>
#include <stdint.h>

static struct kvm_cpuid_entry2 *cpuid_find_entry(struct kvm_cpuid2 *cpuid,
                                             uint32_t function,
                                             uint32_t index);
void main(){
    int status, fd, max=64;
    uint32_t ret = 0;
    fd = open("/dev/kvm", O_RDWR | O_CLOEXEC);
    if (fd == -1)
        errx("cannot open /dev/kvm");

    status = ioctl(fd, KVM_GET_API_VERSION,0);
    printf("kvm api=%dn", status);

    struct kvm_cpuid2 *cpuid;
    int r, size;

    size = sizeof(*cpuid)   max * sizeof(*cpuid->entries);
    cpuid = malloc(size);
    cpuid->nent = max;
    r = ioctl(fd , KVM_GET_SUPPORTED_CPUID, cpuid);
    if (r == 0 amp;amp; cpuid->nent >= max) {
        errx("2 bign");
    }
    if (r < 0){
        errx("problemn");
    }

    struct kvm_cpuid_entry2 *entry = cpuid_find_entry(cpuid, 0x80000001, 0);
    if (entry) {
        ret = entry->edx;
    }
    printf("edx = %xn", ret);
    if (ret amp; (1U << 0)) printf(" fpu");
    if (ret amp; (1U << 1)) printf(" vme");
    if (ret amp; (1U << 2)) printf(" de");
    if (ret amp; (1U << 3)) printf(" pse");
    if (ret amp; (1U << 4)) printf(" tsc");
    if (ret amp; (1U << 5)) printf(" msr");
    if (ret amp; (1U << 6)) printf(" pae");
    if (ret amp; (1U << 7)) printf(" mce");
    if (ret amp; (1U << 8)) printf(" cx8");
    if (ret amp; (1U << 9)) printf(" apic");
    if (ret amp; (1U << 11)) printf(" syscall");
    if (ret amp; (1U << 12)) printf(" mtrr");
    if (ret amp; (1U << 13)) printf(" pge");
    if (ret amp; (1U << 14)) printf(" mca");
    if (ret amp; (1U << 15)) printf(" cmov");
    if (ret amp; (1U << 16)) printf(" pat");
    if (ret amp; (1U << 17)) printf(" pse36");
    if (ret amp; (1U << 18)) printf(" mp");
    if (ret amp; (1U << 20)) printf(" nx");
    if (ret amp; (1U << 22)) printf(" mmxext");
    if (ret amp; (1U << 23)) printf(" mmx");
    if (ret amp; (1U << 24)) printf(" fxsr");
    if (ret amp; (1U << 25)) printf(" fxsr_opt");
    if (ret amp; (1U << 26)) printf(" pdpe1gb");
    if (ret amp; (1U << 27)) printf(" rdtscp");
    if (ret amp; (1U << 29)) printf(" lm");
    if (ret amp; (1U << 30)) printf(" 3dnowext");
    if (ret amp; (1U << 31)) printf(" 3dnow");
    printf("n");
}

static struct kvm_cpuid_entry2 *cpuid_find_entry(struct kvm_cpuid2 *cpuid,
                                                 uint32_t function,
                                                 uint32_t index)
{
    int i;
    for (i = 0; i < cpuid->nent;   i) {
        if (cpuid->entries[i].function == function amp;amp;
            cpuid->entries[i].index == index) {
            return amp;cpuid->entries[i];
        }
    }
    /* not found: */
    return NULL;
}
 

приведенный выше код выводит :

 kvm api=12
edx = 28100800
 syscall nx rdtscp lm
 

Если я проверю в командной строке, я получу:

 > cat /proc/cpuinfo | grep flags | uniq
flags           : fpu vme de pse tsc msr pae mce 
cx8 apic sep mtrr pge mca cmov pat pse36 clflush 
mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp 
lm constant_tsc arch_perfmon nopl xtopology 
tsc_reliable nonstop_tsc cpuid pni pclmulqdq 
vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe 
popcnt tsc_deadline_timer aes xsave avx f16c 
rdrand hypervisor lahf_lm abm 3dnowprefetch 
cpuid_fault invpcid_single pti ssbd ibrs ibpb 
stibp tpr_shadow vnmi ept vpid ept_ad fsgsbase 
tsc_adjust bmi1 hle avx2 smep bmi2 invpcid rtm mpx 
avx512f avx512dq rdseed adx smap clflushopt clwb 
avx512cd avx512bw avx512vl xsaveopt xsavec xsaves 
arat pku ospke flush_l1d arch_capabilities
 

Очевидно, что многие функции «EAX = 8000000001h: расширенная информация о процессоре и биты функций» отсутствуют (в частности, я ищу pdpe1gb).Я прочитал kvm api, и в нем ничего не упоминается об этом.

использование:

vendor_id: GenuineIntel Семейство процессоров : 6 модель : 85 название модели : Intel (R) Xeon (R) Gold 6130 CPU @ 2.10GHz

использование kvm api 12.

использование ubutnu 18 с ядром 5.4.0-70-generic

Я настроил nested=Y (мой хост также является виртуальной машиной).

  1. Где я могу найти документ, в котором описывается, что поддерживается KVM, а что нет? может быть, он не поддерживает?
  2. 26 бит, который я проверяю, был путем изучения кода QEMU. Где я могу найти документы о битах Intel?
  3. Почему я не получаю бит pdpe1gb, отображаемый в моем примере?

Комментарии:

1. Пожалуйста, добавьте свою версию ядра.

2. На сайте Intel есть большие PDF-файлы для каждого процессора, которые описывают CPUID и другие общедоступные функции.

3. @stark — я не нашел PDF-файл от intel, но я нахожу wiki по адресу en.wikipedia.org/wiki/CPUID