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