summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--target-i386/cpu.c22
-rw-r--r--target-i386/cpu.h2
2 files changed, 17 insertions, 7 deletions
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 89b4ac7ec5..388bc5c527 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -238,6 +238,8 @@ typedef struct x86_def_t {
     /* Store the results of Centaur's CPUID instructions */
     uint32_t ext4_features;
     uint32_t xlevel2;
+    /* The feature bits on CPUID[EAX=7,ECX=0].EBX */
+    uint32_t cpuid_7_0_ebx_features;
 } x86_def_t;
 
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -521,6 +523,12 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
     x86_cpu_def->ext_features = ecx;
     x86_cpu_def->features = edx;
 
+    if (kvm_enabled() && x86_cpu_def->level >= 7) {
+        x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX);
+    } else {
+        x86_cpu_def->cpuid_7_0_ebx_features = 0;
+    }
+
     host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
     x86_cpu_def->xlevel = eax;
 
@@ -1185,6 +1193,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
     env->cpuid_kvm_features = def->kvm_features;
     env->cpuid_svm_features = def->svm_features;
     env->cpuid_ext4_features = def->ext4_features;
+    env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features;
     env->cpuid_xlevel2 = def->xlevel2;
     object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000,
                             "tsc-frequency", &error);
@@ -1451,13 +1460,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         *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);
+        /* Structured Extended Feature Flags Enumeration Leaf */
+        if (count == 0) {
+            *eax = 0; /* Maximum ECX value for sub-leaves */
+            *ebx = env->cpuid_7_0_ebx; /* Feature flags */
+            *ecx = 0; /* Reserved */
+            *edx = 0; /* Reserved */
         } else {
             *eax = 0;
             *ebx = 0;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index b5b9a50695..2460f6348b 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -741,6 +741,8 @@ typedef struct CPUX86State {
     /* Store the results of Centaur's CPUID instructions */
     uint32_t cpuid_xlevel2;
     uint32_t cpuid_ext4_features;
+    /* Flags from CPUID[EAX=7,ECX=0].EBX */
+    uint32_t cpuid_7_0_ebx;
 
     /* MTRRs */
     uint64_t mtrr_fixed[11];