For most workloads it will be necessary to determine characteristics of CPU on which they are run. Most processors have some way of querying capabilities. x86 CPU uses instruction. CPUID Unfortunately you cannot just start a VM and then execute the CPUID instruction. The program will not crash but you will not get useful information either. The reason for this is that sometimes we'd like to tell guests what is available and what is not available for use. At this point we will go with a simple approach - we will let our guest OS do whatever KVM features are available. KVM has an ioctl to do that - . It also has that defines vCPU response to CPUID instruction. KVM_GET_SUPPORTED_CPUID KVM_SET_CPUID2 Before we can make a call to we need to create structure and allocate enough space for it. KVM_GET_SUPPORTED_CPUID kvm_cpuid2 The structure is defined as follows: kvm_cpuid2 __u32 nent; __u32 padding; }; __u32 function; __u32 index; __u32 flags; __u32 eax; __u32 ebx; __u32 ecx; __u32 edx; __u32 padding[ ]; }; { struct kvm_cpuid2 [0]; struct kvm_cpuid_entry2 entries { struct kvm_cpuid_entry2 3 You can see that it has two elements but it also has a trailing array. The way we allocate memory for this type of structure is ← pseudo-code ⚠️ sizeof(kvm_cpuid2) + number_of_entries * sizeof(kvm_cpuid_entry2) Following is piece of code that allocates memory for structure and uses to populate it. kvm_cpuid2 KVM_GET_SUPPORTED_CPUID nent = ; size = (*cpuid) + nent * (*cpuid->entries); cpuid = (struct kvm_cpuid2*) (size); bzero(cpuid, size); cpuid->nent = nent; (ioctl(kvm, KVM_GET_SUPPORTED_CPUID, cpuid) == ) { ( , ret); ; } * ; struct kvm_cpuid2 cpuid int 40 unsigned long sizeof sizeof malloc if -1 printf "KVM_GET_SUPPORTED_CPUID could not read CPUID info. Error code: %d\n" return -1 Now it can be useful to print out all the available options that KVM has reported. It could be useful to know this once the vCPU starts. ( i = ; i < cpuid->nent; i++) { ( , cpuid->entries[i].function, cpuid->entries[i].index, cpuid->entries[i].flags, cpuid->entries[i].eax, cpuid->entries[i].ebx, cpuid->entries[i].ecx, cpuid->entries[i].edx); } for int 0 printf "F: 0x%08x, idx: 0x%08x, flags: 0x%08x, eax: 0x%08x, ebx: 0x%08x, ecx: 0x%08x, edx: 0x%08x\n" Now we can use our pointer to structure to configure vCPU. cpuid (ioctl(vcpufd, KVM_SET_CPUID2, cpuid) == ) { ( , ret); ; } if -1 printf "KVM_SET_CPUID2 could not set CPUID info. Error code: %d\n" return -1 And that is it! Now you can execute CPUID instruction on your vCPU and get correct results. Check out `program.asm` in my kvm-playground repo ( ) for an example of an assembly program that reads information about CPU using CPUID and outputs that information via serial port. https://gitlab.com/mvuksano/kvm-playground/-/tree/master/03-cpuid See you next time when we will start working on enabling paging on our x86 CPU 👋 📖 Resources: https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt