Blame SOURCES/kvm-i386-Clean-up-cache-CPUID-code.patch

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