xref: /kvmtool/x86/cpuid.c (revision 1e1b38189cac3fd93bda91bbccb89f2f9274ea02)
1a1fe6bc5SPekka Enberg #include "kvm/kvm.h"
2a1fe6bc5SPekka Enberg #include "kvm/util.h"
3a1fe6bc5SPekka Enberg 
4a1fe6bc5SPekka Enberg #include <sys/ioctl.h>
5a1fe6bc5SPekka Enberg #include <stdlib.h>
6a1fe6bc5SPekka Enberg #include <assert.h>
7a1fe6bc5SPekka Enberg 
8*1e1b3818SPekka Enberg #define CPUID_FUNC_PERFMON		0x0A
9*1e1b3818SPekka Enberg 
10a1fe6bc5SPekka Enberg #define	MAX_KVM_CPUID_ENTRIES		100
11a1fe6bc5SPekka Enberg 
12*1e1b3818SPekka Enberg static void filter_cpuid(struct kvm_cpuid2 *kvm_cpuid)
13*1e1b3818SPekka Enberg {
14*1e1b3818SPekka Enberg 	unsigned int i;
15*1e1b3818SPekka Enberg 
16*1e1b3818SPekka Enberg 	/*
17*1e1b3818SPekka Enberg 	 * Filter CPUID functions that are not supported by the hypervisor.
18*1e1b3818SPekka Enberg 	 */
19*1e1b3818SPekka Enberg 	for (i = 0; i < kvm_cpuid->nent; i++) {
20*1e1b3818SPekka Enberg 		struct kvm_cpuid_entry2 *entry = &kvm_cpuid->entries[i];
21*1e1b3818SPekka Enberg 
22*1e1b3818SPekka Enberg 		switch (entry->function) {
23*1e1b3818SPekka Enberg 		case CPUID_FUNC_PERFMON:
24*1e1b3818SPekka Enberg 			entry->eax	= 0x00;	/* disable it */
25*1e1b3818SPekka Enberg 			break;
26*1e1b3818SPekka Enberg 		default:
27*1e1b3818SPekka Enberg 			/* Keep the CPUID function as -is */
28*1e1b3818SPekka Enberg 			break;
29*1e1b3818SPekka Enberg 		};
30*1e1b3818SPekka Enberg 	}
31*1e1b3818SPekka Enberg }
32*1e1b3818SPekka Enberg 
33a1fe6bc5SPekka Enberg void kvm__setup_cpuid(struct kvm *self)
34a1fe6bc5SPekka Enberg {
35a1fe6bc5SPekka Enberg 	struct kvm_cpuid2 *kvm_cpuid;
36a1fe6bc5SPekka Enberg 
37bb988cf5SAsias He 	kvm_cpuid = calloc(1, sizeof(*kvm_cpuid) + MAX_KVM_CPUID_ENTRIES * sizeof(*kvm_cpuid->entries));
38a1fe6bc5SPekka Enberg 
39bb988cf5SAsias He 	kvm_cpuid->nent = MAX_KVM_CPUID_ENTRIES;
40bb988cf5SAsias He 	if (ioctl(self->sys_fd, KVM_GET_SUPPORTED_CPUID, kvm_cpuid) < 0)
41bb988cf5SAsias He 		die_perror("KVM_GET_SUPPORTED_CPUID failed");
42a1fe6bc5SPekka Enberg 
43*1e1b3818SPekka Enberg 	filter_cpuid(kvm_cpuid);
44*1e1b3818SPekka Enberg 
45a1fe6bc5SPekka Enberg 	if (ioctl(self->vcpu_fd, KVM_SET_CPUID2, kvm_cpuid) < 0)
46a1fe6bc5SPekka Enberg 		die_perror("KVM_SET_CPUID2 failed");
47a1fe6bc5SPekka Enberg 
48bb988cf5SAsias He 	free(kvm_cpuid);
49a1fe6bc5SPekka Enberg }
50