@@ -1203,6 +1203,23 @@ static char *x86_cpuid_get_hv_vendor(Object *obj, Error **errp)
}
value[CPUID_VENDOR_SZ] = '\0';
+ /* Convert known names */
+ if (!strcmp(value, CPUID_HV_VENDOR_HYPERV) &&
+ env->cpuid_hv_level == CPUID_HV_LEVEL_HYPERV_CPUID_MIN &&
+ env->cpuid_hv_features_set == CPUID_HV_FEATURES_HYPERV) {
+ pstrcpy(value, sizeof(value), "hyperv");
+ } else if (!strcmp(value, CPUID_HV_VENDOR_VMWARE) &&
+ env->cpuid_hv_features_set == CPUID_HV_FEATURES_VMWARE) {
+ if (env->cpuid_hv_level == CPUID_HV_LEVEL_VMWARE_4) {
+ pstrcpy(value, sizeof(value), "vmware4");
+ } else if (env->cpuid_hv_level == CPUID_HV_LEVEL_VMWARE_3) {
+ pstrcpy(value, sizeof(value), "vmware3");
+ }
+ } else if (!strcmp(value, CPUID_HV_VENDOR_KVM) &&
+ (env->cpuid_hv_level == CPUID_HV_LEVEL_KVM_0 ||
+ env->cpuid_hv_level == CPUID_HV_LEVEL_KVM_1)) {
+ pstrcpy(value, sizeof(value), "kvm");
+ }
return value;
}
@@ -1216,7 +1233,46 @@ static void x86_cpuid_set_hv_vendor(Object *obj, const char *value,
memset(adj_value, 0, sizeof(adj_value));
- pstrcpy(adj_value, sizeof(adj_value), value);
+ /* Convert known names */
+ if (!strcmp(value, "hyperv")) {
+ if (!env->cpuid_hv_level_set) {
+ object_property_set_int(obj, CPUID_HV_LEVEL_HYPERV_CPUID_MIN,
+ "hypervisor-level", errp);
+ }
+ if (!env->cpuid_hv_features_set) {
+ object_property_set_int(obj, CPUID_HV_FEATURES_HYPERV,
+ "hypervisor-features", errp);
+ }
+ pstrcpy(adj_value, sizeof(adj_value), CPUID_HV_VENDOR_HYPERV);
+ } else if (!strcmp(value, "vmware") || !strcmp(value, "vmware4")) {
+ if (!env->cpuid_hv_level_set) {
+ object_property_set_int(obj, CPUID_HV_LEVEL_VMWARE_4,
+ "hypervisor-level", errp);
+ }
+ if (!env->cpuid_hv_features_set) {
+ object_property_set_int(obj, CPUID_HV_FEATURES_VMWARE,
+ "hypervisor-features", errp);
+ }
+ pstrcpy(adj_value, sizeof(adj_value), CPUID_HV_VENDOR_VMWARE);
+ } else if (!strcmp(value, "vmware3")) {
+ if (!env->cpuid_hv_level_set) {
+ object_property_set_int(obj, CPUID_HV_LEVEL_VMWARE_3,
+ "hypervisor-level", errp);
+ }
+ if (!env->cpuid_hv_features_set) {
+ object_property_set_int(obj, CPUID_HV_FEATURES_VMWARE,
+ "hypervisor-features", errp);
+ }
+ pstrcpy(adj_value, sizeof(adj_value), CPUID_HV_VENDOR_VMWARE);
+ } else if (!strcmp(value, "kvm")) {
+ if (!env->cpuid_hv_level_set) {
+ object_property_set_int(obj, CPUID_HV_LEVEL_KVM_1,
+ "hypervisor-level", errp);
+ }
+ pstrcpy(adj_value, sizeof(adj_value), CPUID_HV_VENDOR_KVM);
+ } else {
+ pstrcpy(adj_value, sizeof(adj_value), value);
+ }
env->cpuid_hv_vendor1 = 0;
env->cpuid_hv_vendor2 = 0;
@@ -498,6 +498,15 @@
#define CPUID_HV_VENDOR_HYPERV "Microsoft Hv"
#define CPUID_HV_FEATURES_HYPERV 0x31237648 /* "Hv#1" */
+#define CPUID_HV_LEVEL_VMWARE_3 0x40000002
+#define CPUID_HV_LEVEL_VMWARE_4 0x40000010
+#define CPUID_HV_VENDOR_VMWARE "VMwareVMware"
+#define CPUID_HV_FEATURES_VMWARE 0
+
+#define CPUID_HV_LEVEL_KVM_0 0
+#define CPUID_HV_LEVEL_KVM_1 0x40000001
+#define CPUID_HV_VENDOR_KVM "KVMKVMKVM"
+
#define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */
#define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */
Part of "target-i386: Add way to expose VMWare CPUID" Also adds some other known names (kvm, hyperv) to Hypervisor vendor. This allows "hypervisor-vendor=vmware3" instead of "hypervisor-vendor=VMwareVMware,hypervisor-level=2,hypervisor-features=0". And "hypervisor-vendor=vmware" instead of "hypervisor-vendor=VMwareVMware,hypervisor-level=0x10,hypervisor-features=0". This is based on: VMware documention on CPUIDs (Mechanisms to determine if software is running in a VMware virtual machine): http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 Signed-off-by: Don Slutz <Don@CloudSwitch.com> --- target-i386/cpu.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/cpu.h | 9 ++++++++ 2 files changed, 66 insertions(+), 1 deletions(-)