@@ -1254,6 +1254,18 @@ static void kvm_trim_features(uint32_t *features, uint32_t supported)
}
}
+static inline void set_bit(int bit, uint32_t *field)
+{
+ field[bit >> 5] |= 1 << (bit & 0x1F);
+}
+
+static inline int is_vendor_intel(struct kvm_cpuid_entry2 *ent)
+{
+ return ent->ebx == 0x756e6547 && /* "Genu" */
+ ent->ecx == 0x6c65746e && /* "ineI" */
+ ent->edx == 0x49656e69; /* "ntel" */
+}
+
int kvm_arch_qemu_init_env(CPUState *cenv)
{
struct kvm_cpuid_entry2 cpuid_ent[100];
@@ -1299,6 +1311,9 @@ int kvm_arch_qemu_init_env(CPUState *cenv)
kvm_trim_features(&cenv->cpuid_ext3_features,
kvm_arch_get_supported_cpuid(cenv, 0x80000001, R_ECX));
+ struct kvm_cpuid_entry2 *vmx_ent = NULL;
+ int is_intel = 0;
+
copy = *cenv;
copy.regs[R_EAX] = 0;
@@ -1322,8 +1337,26 @@ int kvm_arch_qemu_init_env(CPUState *cenv)
if (i == 0xd && copy.regs[R_EAX] == 0)
break;
}
- } else
- do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, ©);
+ } else {
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, ©);
+ /* check if this is intel */
+ if (cpuid_ent[cpuid_nent - 1].function == 0x00000000)
+ is_intel = is_vendor_intel(&cpuid_ent[cpuid_nent - 1]);
+ else if (cpuid_ent[cpuid_nent - 1].function == 0x00000001)
+ vmx_ent = &cpuid_ent[cpuid_nent - 1];
+ }
+ }
+
+ /* simulate vmx support for Intel only */
+ if (is_intel) {
+ /* No entry for 0x00000001 function was found ,creating a new one */
+ if (!vmx_ent && cpuid_nent < 100) {
+ vmx_ent = &cpuid_ent[cpuid_nent++];
+ memset(vmx_ent, 0, sizeof(*vmx_ent));
+ vmx_ent->function = 0x00000001;
+ }
+ if (vmx_ent)
+ set_bit(5, &vmx_ent->ecx);
}
copy.regs[R_EAX] = 0x80000000;