yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
ae23c9
From 980b21f10d74e23a5eb458eaad67c8a2dea65929 Mon Sep 17 00:00:00 2001
ae23c9
From: Eduardo Habkost <ehabkost@redhat.com>
ae23c9
Date: Thu, 26 Jul 2018 17:18:58 +0100
ae23c9
Subject: [PATCH 08/14] i386: Clean up cache CPUID code
ae23c9
ae23c9
RH-Author: Eduardo Habkost <ehabkost@redhat.com>
ae23c9
Message-id: <20180726171904.27418-6-ehabkost@redhat.com>
ae23c9
Patchwork-id: 81528
ae23c9
O-Subject: [qemu-kvm RHEL8/virt212 PATCH v2 05/11] i386: Clean up cache CPUID code
ae23c9
Bugzilla: 1597739
ae23c9
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
ae23c9
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
ae23c9
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
ae23c9
ae23c9
Always initialize CPUCaches structs with cache information, even
ae23c9
if legacy_cache=true.  Use different CPUCaches struct for
ae23c9
CPUID[2], CPUID[4], and the AMD CPUID leaves.
ae23c9
ae23c9
This will simplify a lot the logic inside cpu_x86_cpuid().
ae23c9
ae23c9
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
ae23c9
Signed-off-by: Babu Moger <babu.moger@amd.com>
ae23c9
Message-Id: <1527176614-26271-2-git-send-email-babu.moger@amd.com>
ae23c9
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
ae23c9
(cherry picked from commit a9f27ea9adc8c695197bd08f2e938ef7b4183f07)
ae23c9
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
ae23c9
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ae23c9
---
ae23c9
 target/i386/cpu.c | 117 +++++++++++++++++++++++++++---------------------------
ae23c9
 target/i386/cpu.h |  14 ++++---
ae23c9
 2 files changed, 67 insertions(+), 64 deletions(-)
ae23c9
ae23c9
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
ae23c9
index 7dfc0fc..f98a964 100644
ae23c9
--- a/target/i386/cpu.c
ae23c9
+++ b/target/i386/cpu.c
ae23c9
@@ -1113,7 +1113,7 @@ struct X86CPUDefinition {
ae23c9
 };
ae23c9
 
ae23c9
 static CPUCaches epyc_cache_info = {
ae23c9
-    .l1d_cache = {
ae23c9
+    .l1d_cache = &(CPUCacheInfo) {
ae23c9
         .type = DCACHE,
ae23c9
         .level = 1,
ae23c9
         .size = 32 * KiB,
ae23c9
@@ -1125,7 +1125,7 @@ static CPUCaches epyc_cache_info = {
ae23c9
         .self_init = 1,
ae23c9
         .no_invd_sharing = true,
ae23c9
     },
ae23c9
-    .l1i_cache = {
ae23c9
+    .l1i_cache = &(CPUCacheInfo) {
ae23c9
         .type = ICACHE,
ae23c9
         .level = 1,
ae23c9
         .size = 64 * KiB,
ae23c9
@@ -1137,7 +1137,7 @@ static CPUCaches epyc_cache_info = {
ae23c9
         .self_init = 1,
ae23c9
         .no_invd_sharing = true,
ae23c9
     },
ae23c9
-    .l2_cache = {
ae23c9
+    .l2_cache = &(CPUCacheInfo) {
ae23c9
         .type = UNIFIED_CACHE,
ae23c9
         .level = 2,
ae23c9
         .size = 512 * KiB,
ae23c9
@@ -1147,7 +1147,7 @@ static CPUCaches epyc_cache_info = {
ae23c9
         .sets = 1024,
ae23c9
         .lines_per_tag = 1,
ae23c9
     },
ae23c9
-    .l3_cache = {
ae23c9
+    .l3_cache = &(CPUCacheInfo) {
ae23c9
         .type = UNIFIED_CACHE,
ae23c9
         .level = 3,
ae23c9
         .size = 8 * MiB,
ae23c9
@@ -3325,9 +3325,8 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
ae23c9
         env->features[w] = def->features[w];
ae23c9
     }
ae23c9
 
ae23c9
-    /* Store Cache information from the X86CPUDefinition if available */
ae23c9
-    env->cache_info = def->cache_info;
ae23c9
-    cpu->legacy_cache = def->cache_info ? 0 : 1;
ae23c9
+    /* legacy-cache defaults to 'off' if CPU model provides cache info */
ae23c9
+    cpu->legacy_cache = !def->cache_info;
ae23c9
 
ae23c9
     /* Special cases not set in the X86CPUDefinition structs: */
ae23c9
     /* TODO: in-kernel irqchip for hvf */
ae23c9
@@ -3678,21 +3677,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
ae23c9
         if (!cpu->enable_l3_cache) {
ae23c9
             *ecx = 0;
ae23c9
         } else {
ae23c9
-            if (env->cache_info && !cpu->legacy_cache) {
ae23c9
-                *ecx = cpuid2_cache_descriptor(&env->cache_info->l3_cache);
ae23c9
-            } else {
ae23c9
-                *ecx = cpuid2_cache_descriptor(&legacy_l3_cache);
ae23c9
-            }
ae23c9
-        }
ae23c9
-        if (env->cache_info && !cpu->legacy_cache) {
ae23c9
-            *edx = (cpuid2_cache_descriptor(&env->cache_info->l1d_cache) << 16) |
ae23c9
-                   (cpuid2_cache_descriptor(&env->cache_info->l1i_cache) <<  8) |
ae23c9
-                   (cpuid2_cache_descriptor(&env->cache_info->l2_cache));
ae23c9
-        } else {
ae23c9
-            *edx = (cpuid2_cache_descriptor(&legacy_l1d_cache) << 16) |
ae23c9
-                   (cpuid2_cache_descriptor(&legacy_l1i_cache) <<  8) |
ae23c9
-                   (cpuid2_cache_descriptor(&legacy_l2_cache_cpuid2));
ae23c9
+            *ecx = cpuid2_cache_descriptor(env->cache_info_cpuid2.l3_cache);
ae23c9
         }
ae23c9
+        *edx = (cpuid2_cache_descriptor(env->cache_info_cpuid2.l1d_cache) << 16) |
ae23c9
+               (cpuid2_cache_descriptor(env->cache_info_cpuid2.l1i_cache) <<  8) |
ae23c9
+               (cpuid2_cache_descriptor(env->cache_info_cpuid2.l2_cache));
ae23c9
         break;
ae23c9
     case 4:
ae23c9
         /* cache info: needed for Core compatibility */
ae23c9
@@ -3705,35 +3694,27 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
ae23c9
             }
ae23c9
         } else {
ae23c9
             *eax = 0;
ae23c9
-            CPUCacheInfo *l1d, *l1i, *l2, *l3;
ae23c9
-            if (env->cache_info && !cpu->legacy_cache) {
ae23c9
-                l1d = &env->cache_info->l1d_cache;
ae23c9
-                l1i = &env->cache_info->l1i_cache;
ae23c9
-                l2 = &env->cache_info->l2_cache;
ae23c9
-                l3 = &env->cache_info->l3_cache;
ae23c9
-            } else {
ae23c9
-                l1d = &legacy_l1d_cache;
ae23c9
-                l1i = &legacy_l1i_cache;
ae23c9
-                l2 = &legacy_l2_cache;
ae23c9
-                l3 = &legacy_l3_cache;
ae23c9
-            }
ae23c9
             switch (count) {
ae23c9
             case 0: /* L1 dcache info */
ae23c9
-                encode_cache_cpuid4(l1d, 1, cs->nr_cores,
ae23c9
+                encode_cache_cpuid4(env->cache_info_cpuid4.l1d_cache,
ae23c9
+                                    1, cs->nr_cores,
ae23c9
                                     eax, ebx, ecx, edx);
ae23c9
                 break;
ae23c9
             case 1: /* L1 icache info */
ae23c9
-                encode_cache_cpuid4(l1i, 1, cs->nr_cores,
ae23c9
+                encode_cache_cpuid4(env->cache_info_cpuid4.l1i_cache,
ae23c9
+                                    1, cs->nr_cores,
ae23c9
                                     eax, ebx, ecx, edx);
ae23c9
                 break;
ae23c9
             case 2: /* L2 cache info */
ae23c9
-                encode_cache_cpuid4(l2, cs->nr_threads, cs->nr_cores,
ae23c9
+                encode_cache_cpuid4(env->cache_info_cpuid4.l2_cache,
ae23c9
+                                    cs->nr_threads, cs->nr_cores,
ae23c9
                                     eax, ebx, ecx, edx);
ae23c9
                 break;
ae23c9
             case 3: /* L3 cache info */
ae23c9
                 pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);
ae23c9
                 if (cpu->enable_l3_cache) {
ae23c9
-                    encode_cache_cpuid4(l3, (1 << pkg_offset), cs->nr_cores,
ae23c9
+                    encode_cache_cpuid4(env->cache_info_cpuid4.l3_cache,
ae23c9
+                                        (1 << pkg_offset), cs->nr_cores,
ae23c9
                                         eax, ebx, ecx, edx);
ae23c9
                     break;
ae23c9
                 }
ae23c9
@@ -3946,13 +3927,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
ae23c9
                (L1_ITLB_2M_ASSOC <<  8) | (L1_ITLB_2M_ENTRIES);
ae23c9
         *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \
ae23c9
                (L1_ITLB_4K_ASSOC <<  8) | (L1_ITLB_4K_ENTRIES);
ae23c9
-        if (env->cache_info && !cpu->legacy_cache) {
ae23c9
-            *ecx = encode_cache_cpuid80000005(&env->cache_info->l1d_cache);
ae23c9
-            *edx = encode_cache_cpuid80000005(&env->cache_info->l1i_cache);
ae23c9
-        } else {
ae23c9
-            *ecx = encode_cache_cpuid80000005(&legacy_l1d_cache_amd);
ae23c9
-            *edx = encode_cache_cpuid80000005(&legacy_l1i_cache_amd);
ae23c9
-        }
ae23c9
+        *ecx = encode_cache_cpuid80000005(env->cache_info_amd.l1d_cache);
ae23c9
+        *edx = encode_cache_cpuid80000005(env->cache_info_amd.l1i_cache);
ae23c9
         break;
ae23c9
     case 0x80000006:
ae23c9
         /* cache info (L2 cache) */
ae23c9
@@ -3968,17 +3944,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
ae23c9
                (L2_DTLB_4K_ENTRIES << 16) | \
ae23c9
                (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \
ae23c9
                (L2_ITLB_4K_ENTRIES);
ae23c9
-        if (env->cache_info && !cpu->legacy_cache) {
ae23c9
-            encode_cache_cpuid80000006(&env->cache_info->l2_cache,
ae23c9
-                                       cpu->enable_l3_cache ?
ae23c9
-                                       &env->cache_info->l3_cache : NULL,
ae23c9
-                                       ecx, edx);
ae23c9
-        } else {
ae23c9
-            encode_cache_cpuid80000006(&legacy_l2_cache_amd,
ae23c9
-                                       cpu->enable_l3_cache ?
ae23c9
-                                       &legacy_l3_cache : NULL,
ae23c9
-                                       ecx, edx);
ae23c9
-        }
ae23c9
+        encode_cache_cpuid80000006(env->cache_info_amd.l2_cache,
ae23c9
+                                   cpu->enable_l3_cache ?
ae23c9
+                                   env->cache_info_amd.l3_cache : NULL,
ae23c9
+                                   ecx, edx);
ae23c9
         break;
ae23c9
     case 0x80000007:
ae23c9
         *eax = 0;
ae23c9
@@ -4675,6 +4644,37 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
ae23c9
             cpu->phys_bits = 32;
ae23c9
         }
ae23c9
     }
ae23c9
+
ae23c9
+    /* Cache information initialization */
ae23c9
+    if (!cpu->legacy_cache) {
ae23c9
+        if (!xcc->cpu_def || !xcc->cpu_def->cache_info) {
ae23c9
+            char *name = x86_cpu_class_get_model_name(xcc);
ae23c9
+            error_setg(errp,
ae23c9
+                       "CPU model '%s' doesn't support legacy-cache=off", name);
ae23c9
+            g_free(name);
ae23c9
+            return;
ae23c9
+        }
ae23c9
+        env->cache_info_cpuid2 = env->cache_info_cpuid4 = env->cache_info_amd =
ae23c9
+            *xcc->cpu_def->cache_info;
ae23c9
+    } else {
ae23c9
+        /* Build legacy cache information */
ae23c9
+        env->cache_info_cpuid2.l1d_cache = &legacy_l1d_cache;
ae23c9
+        env->cache_info_cpuid2.l1i_cache = &legacy_l1i_cache;
ae23c9
+        env->cache_info_cpuid2.l2_cache = &legacy_l2_cache_cpuid2;
ae23c9
+        env->cache_info_cpuid2.l3_cache = &legacy_l3_cache;
ae23c9
+
ae23c9
+        env->cache_info_cpuid4.l1d_cache = &legacy_l1d_cache;
ae23c9
+        env->cache_info_cpuid4.l1i_cache = &legacy_l1i_cache;
ae23c9
+        env->cache_info_cpuid4.l2_cache = &legacy_l2_cache;
ae23c9
+        env->cache_info_cpuid4.l3_cache = &legacy_l3_cache;
ae23c9
+
ae23c9
+        env->cache_info_amd.l1d_cache = &legacy_l1d_cache_amd;
ae23c9
+        env->cache_info_amd.l1i_cache = &legacy_l1i_cache_amd;
ae23c9
+        env->cache_info_amd.l2_cache = &legacy_l2_cache_amd;
ae23c9
+        env->cache_info_amd.l3_cache = &legacy_l3_cache;
ae23c9
+    }
ae23c9
+
ae23c9
+
ae23c9
     cpu_exec_realizefn(cs, &local_err);
ae23c9
     if (local_err != NULL) {
ae23c9
         error_propagate(errp, local_err);
ae23c9
@@ -5159,11 +5159,10 @@ static Property x86_cpu_properties[] = {
ae23c9
     DEFINE_PROP_BOOL("vmware-cpuid-freq", X86CPU, vmware_cpuid_freq, true),
ae23c9
     DEFINE_PROP_BOOL("tcg-cpuid", X86CPU, expose_tcg, true),
ae23c9
     /*
ae23c9
-     * lecacy_cache defaults to CPU model being chosen. This is set in
ae23c9
-     * x86_cpu_load_def based on cache_info which is initialized in
ae23c9
-     * builtin_x86_defs
ae23c9
+     * lecacy_cache defaults to true unless the CPU model provides its
ae23c9
+     * own cache information (see x86_cpu_load_def()).
ae23c9
      */
ae23c9
-    DEFINE_PROP_BOOL("legacy-cache", X86CPU, legacy_cache, false),
ae23c9
+    DEFINE_PROP_BOOL("legacy-cache", X86CPU, legacy_cache, true),
ae23c9
 
ae23c9
     /*
ae23c9
      * From "Requirements for Implementing the Microsoft
ae23c9
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
ae23c9
index 31715d1..88fdf80 100644
ae23c9
--- a/target/i386/cpu.h
ae23c9
+++ b/target/i386/cpu.h
ae23c9
@@ -1097,10 +1097,10 @@ typedef struct CPUCacheInfo {
ae23c9
 
ae23c9
 
ae23c9
 typedef struct CPUCaches {
ae23c9
-        CPUCacheInfo l1d_cache;
ae23c9
-        CPUCacheInfo l1i_cache;
ae23c9
-        CPUCacheInfo l2_cache;
ae23c9
-        CPUCacheInfo l3_cache;
ae23c9
+        CPUCacheInfo *l1d_cache;
ae23c9
+        CPUCacheInfo *l1i_cache;
ae23c9
+        CPUCacheInfo *l2_cache;
ae23c9
+        CPUCacheInfo *l3_cache;
ae23c9
 } CPUCaches;
ae23c9
 
ae23c9
 typedef struct CPUX86State {
ae23c9
@@ -1288,7 +1288,11 @@ typedef struct CPUX86State {
ae23c9
     /* Features that were explicitly enabled/disabled */
ae23c9
     FeatureWordArray user_features;
ae23c9
     uint32_t cpuid_model[12];
ae23c9
-    CPUCaches *cache_info;
ae23c9
+    /* Cache information for CPUID.  When legacy-cache=on, the cache data
ae23c9
+     * on each CPUID leaf will be different, because we keep compatibility
ae23c9
+     * with old QEMU versions.
ae23c9
+     */
ae23c9
+    CPUCaches cache_info_cpuid2, cache_info_cpuid4, cache_info_amd;
ae23c9
 
ae23c9
     /* MTRRs */
ae23c9
     uint64_t mtrr_fixed[11];
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9