]> git.proxmox.com Git - qemu.git/blobdiff - target-i386/cpuid.c
iothread: replace fair_mutex with a condition variable
[qemu.git] / target-i386 / cpuid.c
index 165045ec4268fdda3f6b680669a37dea471faaed..e1ae3af1e3c5b2fc7f64d544525546bec6f6a1fa 100644 (file)
@@ -73,7 +73,7 @@ static const char *ext3_feature_name[] = {
 };
 
 static const char *kvm_feature_name[] = {
-    "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, "kvm_asyncpf", NULL, NULL, NULL,
+    "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", "kvm_asyncpf", NULL, NULL, NULL,
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -103,9 +103,8 @@ typedef struct model_features_t {
 int check_cpuid = 0;
 int enforce_cpuid = 0;
 
-static void host_cpuid(uint32_t function, uint32_t count,
-                       uint32_t *eax, uint32_t *ebx,
-                       uint32_t *ecx, uint32_t *edx)
+void host_cpuid(uint32_t function, uint32_t count,
+                uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
 {
 #if defined(CONFIG_KVM)
     uint32_t vec[4];
@@ -183,20 +182,22 @@ static int altcmp(const char *s, const char *e, const char *altstr)
 }
 
 /* search featureset for flag *[s..e), if found set corresponding bit in
- * *pval and return success, otherwise return zero
+ * *pval and return true, otherwise return false
  */
-static int lookup_feature(uint32_t *pval, const char *s, const char *e,
-    const char **featureset)
+static bool lookup_feature(uint32_t *pval, const char *s, const char *e,
+                           const char **featureset)
 {
     uint32_t mask;
     const char **ppc;
+    bool found = false;
 
-    for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc)
+    for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc) {
         if (*ppc && !altcmp(s, e, *ppc)) {
             *pval |= mask;
-            break;
+            found = true;
         }
-    return (mask ? 1 : 0);
+    }
+    return found;
 }
 
 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
@@ -229,6 +230,9 @@ typedef struct x86_def_t {
     char model_id[48];
     int vendor_override;
     uint32_t flags;
+    /* Store the results of Centaur's CPUID instructions */
+    uint32_t ext4_features;
+    uint32_t xlevel2;
 } x86_def_t;
 
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -521,6 +525,18 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
     cpu_x86_fill_model_id(x86_cpu_def->model_id);
     x86_cpu_def->vendor_override = 0;
 
+    /* Call Centaur's CPUID instruction. */
+    if (x86_cpu_def->vendor1 == CPUID_VENDOR_VIA_1 &&
+        x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 &&
+        x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) {
+        host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx);
+        if (eax >= 0xC0000001) {
+            /* Support VIA max extended level */
+            x86_cpu_def->xlevel2 = eax;
+            host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx);
+            x86_cpu_def->ext4_features = edx;
+        }
+    }
 
     /*
      * Every SVM feature requires emulation support in KVM - so we can't just
@@ -848,13 +864,14 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
     env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16);
     env->cpuid_version |= def->stepping;
     env->cpuid_features = def->features;
-    env->pat = 0x0007040600070406ULL;
     env->cpuid_ext_features = def->ext_features;
     env->cpuid_ext2_features = def->ext2_features;
     env->cpuid_ext3_features = def->ext3_features;
     env->cpuid_xlevel = def->xlevel;
     env->cpuid_kvm_features = def->kvm_features;
     env->cpuid_svm_features = def->svm_features;
+    env->cpuid_ext4_features = def->ext4_features;
+    env->cpuid_xlevel2 = def->xlevel2;
     if (!kvm_enabled()) {
         env->cpuid_features &= TCG_FEATURES;
         env->cpuid_ext_features &= TCG_EXT_FEATURES;
@@ -1035,8 +1052,18 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
 {
     /* test if maximum index reached */
     if (index & 0x80000000) {
-        if (index > env->cpuid_xlevel)
-            index = env->cpuid_level;
+        if (index > env->cpuid_xlevel) {
+            if (env->cpuid_xlevel2 > 0) {
+                /* Handle the Centaur's CPUID instruction. */
+                if (index > env->cpuid_xlevel2) {
+                    index = env->cpuid_xlevel2;
+                } else if (index < 0xC0000000) {
+                    index = env->cpuid_xlevel;
+                }
+            } else {
+                index =  env->cpuid_xlevel;
+            }
+        }
     } else {
         if (index > env->cpuid_level)
             index = env->cpuid_level;
@@ -1115,6 +1142,21 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         *ecx = 0;
         *edx = 0;
         break;
+    case 7:
+        if (kvm_enabled()) {
+            KVMState *s = env->kvm_state;
+
+            *eax = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EAX);
+            *ebx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EBX);
+            *ecx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_ECX);
+            *edx = kvm_arch_get_supported_cpuid(s, 0x7, count, R_EDX);
+        } else {
+            *eax = 0;
+            *ebx = 0;
+            *ecx = 0;
+            *edx = 0;
+        }
+        break;
     case 9:
         /* Direct Cache Access Information Leaf */
         *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
@@ -1139,10 +1181,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
             break;
         }
         if (kvm_enabled()) {
-            *eax = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EAX);
-            *ebx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EBX);
-            *ecx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_ECX);
-            *edx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EDX);
+            KVMState *s = env->kvm_state;
+
+            *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX);
+            *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX);
+            *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX);
+            *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX);
         } else {
             *eax = 0;
             *ebx = 0;
@@ -1231,6 +1275,28 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
                *edx = 0;
        }
         break;
+    case 0xC0000000:
+        *eax = env->cpuid_xlevel2;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
+    case 0xC0000001:
+        /* Support for VIA CPU's CPUID instruction */
+        *eax = env->cpuid_version;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = env->cpuid_ext4_features;
+        break;
+    case 0xC0000002:
+    case 0xC0000003:
+    case 0xC0000004:
+        /* Reserved for the future, and now filled with zero */
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = 0;
+        break;
     default:
         /* reserved values: zero */
         *eax = 0;