15c3d55faSPekka Enberg #include "kvm/kvm-cpu.h" 25c3d55faSPekka Enberg 3a1fe6bc5SPekka Enberg #include "kvm/kvm.h" 4a1fe6bc5SPekka Enberg #include "kvm/util.h" 5a1fe6bc5SPekka Enberg 6a1fe6bc5SPekka Enberg #include <sys/ioctl.h> 7a1fe6bc5SPekka Enberg #include <stdlib.h> 8a1fe6bc5SPekka Enberg 91e1b3818SPekka Enberg #define CPUID_FUNC_PERFMON 0x0A 101e1b3818SPekka Enberg 11a1fe6bc5SPekka Enberg #define MAX_KVM_CPUID_ENTRIES 100 12a1fe6bc5SPekka Enberg 131e1b3818SPekka Enberg static void filter_cpuid(struct kvm_cpuid2 *kvm_cpuid) 141e1b3818SPekka Enberg { 15*bc0b99a2SCyrill Gorcunov unsigned int signature[3]; 161e1b3818SPekka Enberg unsigned int i; 171e1b3818SPekka Enberg 181e1b3818SPekka Enberg /* 191e1b3818SPekka Enberg * Filter CPUID functions that are not supported by the hypervisor. 201e1b3818SPekka Enberg */ 211e1b3818SPekka Enberg for (i = 0; i < kvm_cpuid->nent; i++) { 221e1b3818SPekka Enberg struct kvm_cpuid_entry2 *entry = &kvm_cpuid->entries[i]; 231e1b3818SPekka Enberg 241e1b3818SPekka Enberg switch (entry->function) { 25*bc0b99a2SCyrill Gorcunov case 0: 26*bc0b99a2SCyrill Gorcunov /* Vendor name */ 27*bc0b99a2SCyrill Gorcunov memcpy(signature, "LKVMLKVMLKVM", 12); 28*bc0b99a2SCyrill Gorcunov entry->ebx = signature[0]; 29*bc0b99a2SCyrill Gorcunov entry->ecx = signature[1]; 30*bc0b99a2SCyrill Gorcunov entry->edx = signature[2]; 31*bc0b99a2SCyrill Gorcunov break; 320d5b41d9SSasha Levin case 1: 330d5b41d9SSasha Levin /* Set X86_FEATURE_HYPERVISOR */ 340d5b41d9SSasha Levin if (entry->index == 0) 350d5b41d9SSasha Levin entry->ecx |= (1 << 31); 360d5b41d9SSasha Levin break; 37abc73d8dSCyrill Gorcunov case 6: 380d5b41d9SSasha Levin /* Clear X86_FEATURE_EPB */ 39abc73d8dSCyrill Gorcunov entry->ecx = entry->ecx & ~(1 << 3); 40abc73d8dSCyrill Gorcunov break; 411e1b3818SPekka Enberg case CPUID_FUNC_PERFMON: 421e1b3818SPekka Enberg entry->eax = 0x00; /* disable it */ 431e1b3818SPekka Enberg break; 441e1b3818SPekka Enberg default: 451e1b3818SPekka Enberg /* Keep the CPUID function as -is */ 461e1b3818SPekka Enberg break; 471e1b3818SPekka Enberg }; 481e1b3818SPekka Enberg } 491e1b3818SPekka Enberg } 501e1b3818SPekka Enberg 5143835ac9SSasha Levin void kvm_cpu__setup_cpuid(struct kvm_cpu *vcpu) 52a1fe6bc5SPekka Enberg { 53a1fe6bc5SPekka Enberg struct kvm_cpuid2 *kvm_cpuid; 54a1fe6bc5SPekka Enberg 553a60be06SSasha Levin kvm_cpuid = calloc(1, sizeof(*kvm_cpuid) + 563a60be06SSasha Levin MAX_KVM_CPUID_ENTRIES * sizeof(*kvm_cpuid->entries)); 57a1fe6bc5SPekka Enberg 58bb988cf5SAsias He kvm_cpuid->nent = MAX_KVM_CPUID_ENTRIES; 5943835ac9SSasha Levin if (ioctl(vcpu->kvm->sys_fd, KVM_GET_SUPPORTED_CPUID, kvm_cpuid) < 0) 60bb988cf5SAsias He die_perror("KVM_GET_SUPPORTED_CPUID failed"); 61a1fe6bc5SPekka Enberg 621e1b3818SPekka Enberg filter_cpuid(kvm_cpuid); 631e1b3818SPekka Enberg 6443835ac9SSasha Levin if (ioctl(vcpu->vcpu_fd, KVM_SET_CPUID2, kvm_cpuid) < 0) 65a1fe6bc5SPekka Enberg die_perror("KVM_SET_CPUID2 failed"); 66a1fe6bc5SPekka Enberg 67bb988cf5SAsias He free(kvm_cpuid); 68a1fe6bc5SPekka Enberg } 69