From: Asias He Date: Mon, 12 Jul 2010 12:52:23 +0000 (+0800) Subject: kvm__setup_cpuid: use KVM_GET_SUPPORTED_CPUID to simplify cpuid setup X-Git-Tag: next-20110824~3^2~528^2~98 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=324ede8e59b4625c57287a96336767b52c4d3a67;p=karo-tx-linux.git kvm__setup_cpuid: use KVM_GET_SUPPORTED_CPUID to simplify cpuid setup Let kernel setup "struct kvm_cpuid2" for us! https://kerneltrap.org/mailarchive/linux-kernel/2010/4/27/4563640 Avi Kivity: ''' No. KVM_GET_CPUID2 reads what was set by KVM_SET_CPUID, as modified by the guest executing the cpuid instruction. KVM_GET_SUPPORTED_CPUID tells userspace which bits are supported by the host cpu and kvm. The API for KVM_GET_SUPPORTED_CPUID returns all cpuid leaves supported in one go, IIRC. ''' Signed-off-by: Asias He Signed-off-by: Pekka Enberg --- diff --git a/tools/kvm/cpuid.c b/tools/kvm/cpuid.c index 7fdfb83a84b2..9119855b3646 100644 --- a/tools/kvm/cpuid.c +++ b/tools/kvm/cpuid.c @@ -1,254 +1,24 @@ #include "kvm/kvm.h" - -#include "kvm/cpufeature.h" #include "kvm/util.h" #include #include #include -static struct kvm_cpuid2 *kvm_cpuid__new(unsigned long nent) -{ - struct kvm_cpuid2 *self; - - self = calloc(1, sizeof(*self) + (sizeof(struct kvm_cpuid_entry2) * nent)); - if (!self) - die("out of memory"); - - return self; -} - -static void kvm_cpuid__delete(struct kvm_cpuid2 *self) -{ - free(self); -} - #define MAX_KVM_CPUID_ENTRIES 100 -enum { - CPUID_GET_VENDOR_ID = 0x00, - CPUID_GET_HIGHEST_EXT_FUNCTION = 0x80000000, -}; - -static uint32_t cpuid_highest_ext_func(void) -{ - struct cpuid_regs regs; - - regs = (struct cpuid_regs) { - .eax = CPUID_GET_HIGHEST_EXT_FUNCTION, - }; - host_cpuid(®s); - - return regs.eax; -} - -static uint32_t cpuid_highest_func(void) -{ - struct cpuid_regs regs; - - regs = (struct cpuid_regs) { - .eax = CPUID_GET_VENDOR_ID, - }; - host_cpuid(®s); - - return regs.eax; -} - void kvm__setup_cpuid(struct kvm *self) { struct kvm_cpuid2 *kvm_cpuid; - uint32_t highest_ext; - uint32_t function; - uint32_t highest; - uint32_t ndx = 0; - - kvm_cpuid = kvm_cpuid__new(MAX_KVM_CPUID_ENTRIES); - highest = cpuid_highest_func(); - - for (function = 0; function <= highest; function++) { - /* - * NOTE NOTE NOTE! Functions 0x0b and 0x0d seem to need special - * treatment as per qemu sources but we treat them as regular - * CPUID functions here because they are fairly exotic and the - * Linux kernel is not interested in them during boot up. - */ - switch (function) { - case 0x00: { /* Vendor-ID and Largest Standard Function */ - kvm_cpuid->entries[ndx++] = (struct kvm_cpuid_entry2) { - .function = 0, - .index = 0, - .flags = 0, - .eax = 4, - .ebx = CPUID_VENDOR_INTEL_1, - .ecx = CPUID_VENDOR_INTEL_3, - .edx = CPUID_VENDOR_INTEL_2, - }; - break; - } - case 0x01: { /* Feature Information */ - struct cpuid_regs regs; - - regs = (struct cpuid_regs) { - .eax = function, - }; - host_cpuid(®s); - - kvm_cpuid->entries[ndx++] = (struct kvm_cpuid_entry2) { - .function = function, - .index = 0, - .flags = 0, - .eax = regs.eax, - .ebx = regs.ebx, - .ecx = - cpu_feature_disable(regs.ecx, KVM__X86_FEATURE_XSAVE) & - cpu_feature_disable(regs.ecx, KVM__X86_FEATURE_VMX), - .edx = regs.edx, - }; - break; - } - case 0x02: { /* Processor configuration descriptor */ - struct cpuid_regs regs; - uint32_t times; - - regs = (struct cpuid_regs) { - .eax = function, - }; - host_cpuid(®s); - - kvm_cpuid->entries[ndx++] = (struct kvm_cpuid_entry2) { - .function = function, - .index = 0, - .flags = KVM_CPUID_FLAG_STATEFUL_FUNC | KVM_CPUID_FLAG_STATE_READ_NEXT, - .eax = regs.eax, - .ebx = regs.ebx, - .ecx = regs.ecx, - .edx = regs.edx, - }; - - times = regs.eax & 0xff; /* AL */ - - while (times-- > 0) { - regs = (struct cpuid_regs) { - .eax = function, - }; - host_cpuid(®s); - - kvm_cpuid->entries[ndx++] = (struct kvm_cpuid_entry2) { - .function = function, - .index = 0, - .flags = KVM_CPUID_FLAG_STATEFUL_FUNC, - .eax = regs.eax, - .ebx = regs.ebx, - .ecx = regs.ecx, - .edx = regs.edx, - }; - } - break; - } - case 0x04: { /* Deterministic Cache Parameters */ - uint32_t eax; - /* - * eax for n cores - * eax = (n - 1) << 26 - * eax for k threads - * eax = (k - 1) << 14 - * they could be OR'ified - */ - eax = 0; - - /* L1 dcache info */ - kvm_cpuid->entries[ndx++] = (struct kvm_cpuid_entry2) { - .function = function, - .index = 0, - .flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX | KVM_CPUID_FLAG_STATE_READ_NEXT, - .eax = eax | 0x0000121, - .ebx = 0x1c0003f, - .ecx = 0x000003f, - .edx = 0x0000001, - }; - - /* L1 icache info */ - kvm_cpuid->entries[ndx++] = (struct kvm_cpuid_entry2) { - .function = function, - .index = 1, - .flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX | KVM_CPUID_FLAG_STATE_READ_NEXT, - .eax = eax | 0x0000122, - .ebx = 0x1c0003f, - .ecx = 0x000003f, - .edx = 0x0000001, - }; - - /* L2 cache info */ - kvm_cpuid->entries[ndx++] = (struct kvm_cpuid_entry2) { - .function = function, - .index = 2, - .flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX | KVM_CPUID_FLAG_STATE_READ_NEXT, - .eax = eax | 0x0000143, - .ebx = 0x3c0003f, - .ecx = 0x0000fff, - .edx = 0x0000001, - }; - - /* End of list */ - kvm_cpuid->entries[ndx++] = (struct kvm_cpuid_entry2) { - .function = function, - .index = 3, - .flags = 0, - .eax = 0, - .ebx = 0, - .ecx = 0, - .edx = 0, - }; - break; - } - default: { - struct cpuid_regs regs; - - regs = (struct cpuid_regs) { - .eax = function, - }; - host_cpuid(®s); - - kvm_cpuid->entries[ndx++] = (struct kvm_cpuid_entry2) { - .function = function, - .index = 0, - .flags = 0, - .eax = regs.eax, - .ebx = regs.ebx, - .ecx = regs.ecx, - .edx = regs.edx, - }; - break; - }}; - } - - highest_ext = cpuid_highest_ext_func(); - - for (function = CPUID_GET_HIGHEST_EXT_FUNCTION; function <= highest_ext; function++) { - struct cpuid_regs regs; - - regs = (struct cpuid_regs) { - .eax = function, - }; - host_cpuid(®s); - - kvm_cpuid->entries[ndx++] = (struct kvm_cpuid_entry2) { - .function = function, - .index = 0, - .flags = 0, - .eax = regs.eax, - .ebx = regs.ebx, - .ecx = regs.ecx, - .edx = regs.edx, - }; - } - assert(ndx < MAX_KVM_CPUID_ENTRIES); + kvm_cpuid = calloc(1, sizeof(*kvm_cpuid) + MAX_KVM_CPUID_ENTRIES * sizeof(*kvm_cpuid->entries)); - kvm_cpuid->nent = ndx; + kvm_cpuid->nent = MAX_KVM_CPUID_ENTRIES; + if (ioctl(self->sys_fd, KVM_GET_SUPPORTED_CPUID, kvm_cpuid) < 0) + die_perror("KVM_GET_SUPPORTED_CPUID failed"); if (ioctl(self->vcpu_fd, KVM_SET_CPUID2, kvm_cpuid) < 0) die_perror("KVM_SET_CPUID2 failed"); - kvm_cpuid__delete(kvm_cpuid); + free(kvm_cpuid); }