ae23c9
From c78647f69c02d1004dfc1a2f1e2e24960634c795 Mon Sep 17 00:00:00 2001
ae23c9
From: Eduardo Habkost <ehabkost@redhat.com>
ae23c9
Date: Thu, 26 Jul 2018 17:18:57 +0100
ae23c9
Subject: [PATCH 07/14] i386: Add new property to control cache info
ae23c9
ae23c9
RH-Author: Eduardo Habkost <ehabkost@redhat.com>
ae23c9
Message-id: <20180726171904.27418-5-ehabkost@redhat.com>
ae23c9
Patchwork-id: 81526
ae23c9
O-Subject: [qemu-kvm RHEL8/virt212 PATCH v2 04/11] i386: Add new property to control cache info
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
From: Babu Moger <babu.moger@amd.com>
ae23c9
ae23c9
The property legacy-cache will be used to control the cache information.
ae23c9
If user passes "-cpu legacy-cache" then older information will
ae23c9
be displayed even if the hardware supports new information. Otherwise
ae23c9
use the statically loaded cache definitions if available.
ae23c9
ae23c9
Renamed the previous cache structures to legacy_*. If there is any change in
ae23c9
the cache information, then it needs to be initialized in builtin_x86_defs.
ae23c9
ae23c9
Signed-off-by: Babu Moger <babu.moger@amd.com>
ae23c9
Tested-by: Geoffrey McRae <geoff@hostfission.com>
ae23c9
Message-Id: <20180514164156.27034-3-babu.moger@amd.com>
ae23c9
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
ae23c9
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
ae23c9
(cherry picked from commit ab8f992e3e63e91be257e4e343d386dae7be4bcb)
ae23c9
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
ae23c9
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ae23c9
---
ae23c9
 include/hw/i386/pc.h |  4 +++
ae23c9
 target/i386/cpu.c    | 97 ++++++++++++++++++++++++++++++++++++++--------------
ae23c9
 target/i386/cpu.h    |  5 +++
ae23c9
 3 files changed, 80 insertions(+), 26 deletions(-)
ae23c9
ae23c9
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
ae23c9
index ae84db4..5aebf6e 100644
ae23c9
--- a/include/hw/i386/pc.h
ae23c9
+++ b/include/hw/i386/pc.h
ae23c9
@@ -979,6 +979,10 @@ extern void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id);
ae23c9
             .driver   = "Skylake-Server" "-" TYPE_X86_CPU,\
ae23c9
             .property = "clflushopt",\
ae23c9
             .value    = "off",\
ae23c9
+        },{ /* PC_RHEL7_5_COMPAT from PC_COMPAT_2_12 */ \
ae23c9
+            .driver   = TYPE_X86_CPU,\
ae23c9
+            .property = "legacy-cache",\
ae23c9
+            .value    = "on",\
ae23c9
         },
ae23c9
 
ae23c9
 
ae23c9
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
ae23c9
index bd0abc2..7dfc0fc 100644
ae23c9
--- a/target/i386/cpu.c
ae23c9
+++ b/target/i386/cpu.c
ae23c9
@@ -336,10 +336,14 @@ static void encode_cache_cpuid80000006(CPUCacheInfo *l2,
ae23c9
     }
ae23c9
 }
ae23c9
 
ae23c9
-/* Definitions of the hardcoded cache entries we expose: */
ae23c9
+/*
ae23c9
+ * Definitions of the hardcoded cache entries we expose:
ae23c9
+ * These are legacy cache values. If there is a need to change any
ae23c9
+ * of these values please use builtin_x86_defs
ae23c9
+ */
ae23c9
 
ae23c9
 /* L1 data cache: */
ae23c9
-static CPUCacheInfo l1d_cache = {
ae23c9
+static CPUCacheInfo legacy_l1d_cache = {
ae23c9
     .type = DCACHE,
ae23c9
     .level = 1,
ae23c9
     .size = 32 * KiB,
ae23c9
@@ -352,7 +356,7 @@ static CPUCacheInfo l1d_cache = {
ae23c9
 };
ae23c9
 
ae23c9
 /*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */
ae23c9
-static CPUCacheInfo l1d_cache_amd = {
ae23c9
+static CPUCacheInfo legacy_l1d_cache_amd = {
ae23c9
     .type = DCACHE,
ae23c9
     .level = 1,
ae23c9
     .size = 64 * KiB,
ae23c9
@@ -366,7 +370,7 @@ static CPUCacheInfo l1d_cache_amd = {
ae23c9
 };
ae23c9
 
ae23c9
 /* L1 instruction cache: */
ae23c9
-static CPUCacheInfo l1i_cache = {
ae23c9
+static CPUCacheInfo legacy_l1i_cache = {
ae23c9
     .type = ICACHE,
ae23c9
     .level = 1,
ae23c9
     .size = 32 * KiB,
ae23c9
@@ -379,7 +383,7 @@ static CPUCacheInfo l1i_cache = {
ae23c9
 };
ae23c9
 
ae23c9
 /*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */
ae23c9
-static CPUCacheInfo l1i_cache_amd = {
ae23c9
+static CPUCacheInfo legacy_l1i_cache_amd = {
ae23c9
     .type = ICACHE,
ae23c9
     .level = 1,
ae23c9
     .size = 64 * KiB,
ae23c9
@@ -393,7 +397,7 @@ static CPUCacheInfo l1i_cache_amd = {
ae23c9
 };
ae23c9
 
ae23c9
 /* Level 2 unified cache: */
ae23c9
-static CPUCacheInfo l2_cache = {
ae23c9
+static CPUCacheInfo legacy_l2_cache = {
ae23c9
     .type = UNIFIED_CACHE,
ae23c9
     .level = 2,
ae23c9
     .size = 4 * MiB,
ae23c9
@@ -406,7 +410,7 @@ static CPUCacheInfo l2_cache = {
ae23c9
 };
ae23c9
 
ae23c9
 /*FIXME: CPUID leaf 2 descriptor is inconsistent with CPUID leaf 4 */
ae23c9
-static CPUCacheInfo l2_cache_cpuid2 = {
ae23c9
+static CPUCacheInfo legacy_l2_cache_cpuid2 = {
ae23c9
     .type = UNIFIED_CACHE,
ae23c9
     .level = 2,
ae23c9
     .size = 2 * MiB,
ae23c9
@@ -416,7 +420,7 @@ static CPUCacheInfo l2_cache_cpuid2 = {
ae23c9
 
ae23c9
 
ae23c9
 /*FIXME: CPUID leaf 0x80000006 is inconsistent with leaves 2 & 4 */
ae23c9
-static CPUCacheInfo l2_cache_amd = {
ae23c9
+static CPUCacheInfo legacy_l2_cache_amd = {
ae23c9
     .type = UNIFIED_CACHE,
ae23c9
     .level = 2,
ae23c9
     .size = 512 * KiB,
ae23c9
@@ -428,7 +432,7 @@ static CPUCacheInfo l2_cache_amd = {
ae23c9
 };
ae23c9
 
ae23c9
 /* Level 3 unified cache: */
ae23c9
-static CPUCacheInfo l3_cache = {
ae23c9
+static CPUCacheInfo legacy_l3_cache = {
ae23c9
     .type = UNIFIED_CACHE,
ae23c9
     .level = 3,
ae23c9
     .size = 16 * MiB,
ae23c9
@@ -3321,6 +3325,10 @@ 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
+
ae23c9
     /* Special cases not set in the X86CPUDefinition structs: */
ae23c9
     /* TODO: in-kernel irqchip for hvf */
ae23c9
     if (kvm_enabled()) {
ae23c9
@@ -3670,11 +3678,21 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
ae23c9
         if (!cpu->enable_l3_cache) {
ae23c9
             *ecx = 0;
ae23c9
         } else {
ae23c9
-            *ecx = cpuid2_cache_descriptor(&l3_cache);
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
         }
ae23c9
-        *edx = (cpuid2_cache_descriptor(&l1d_cache) << 16) |
ae23c9
-               (cpuid2_cache_descriptor(&l1i_cache) <<  8) |
ae23c9
-               (cpuid2_cache_descriptor(&l2_cache_cpuid2));
ae23c9
         break;
ae23c9
     case 4:
ae23c9
         /* cache info: needed for Core compatibility */
ae23c9
@@ -3687,27 +3705,35 @@ 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_cache,
ae23c9
-                                    1, cs->nr_cores,
ae23c9
+                encode_cache_cpuid4(l1d, 1, cs->nr_cores,
ae23c9
                                     eax, ebx, ecx, edx);
ae23c9
                 break;
ae23c9
             case 1: /* L1 icache info */
ae23c9
-                encode_cache_cpuid4(&l1i_cache,
ae23c9
-                                    1, cs->nr_cores,
ae23c9
+                encode_cache_cpuid4(l1i, 1, cs->nr_cores,
ae23c9
                                     eax, ebx, ecx, edx);
ae23c9
                 break;
ae23c9
             case 2: /* L2 cache info */
ae23c9
-                encode_cache_cpuid4(&l2_cache,
ae23c9
-                                    cs->nr_threads, cs->nr_cores,
ae23c9
+                encode_cache_cpuid4(l2, 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_cache,
ae23c9
-                                        (1 << pkg_offset), cs->nr_cores,
ae23c9
+                    encode_cache_cpuid4(l3, (1 << pkg_offset), cs->nr_cores,
ae23c9
                                         eax, ebx, ecx, edx);
ae23c9
                     break;
ae23c9
                 }
ae23c9
@@ -3920,8 +3946,13 @@ 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
-        *ecx = encode_cache_cpuid80000005(&l1d_cache_amd);
ae23c9
-        *edx = encode_cache_cpuid80000005(&l1i_cache_amd);
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
         break;
ae23c9
     case 0x80000006:
ae23c9
         /* cache info (L2 cache) */
ae23c9
@@ -3937,9 +3968,17 @@ 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
-        encode_cache_cpuid80000006(&l2_cache_amd,
ae23c9
-                                   cpu->enable_l3_cache ? &l3_cache : NULL,
ae23c9
-                                   ecx, edx);
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
         break;
ae23c9
     case 0x80000007:
ae23c9
         *eax = 0;
ae23c9
@@ -5119,6 +5158,12 @@ static Property x86_cpu_properties[] = {
ae23c9
                      false),
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
+     */
ae23c9
+    DEFINE_PROP_BOOL("legacy-cache", X86CPU, legacy_cache, false),
ae23c9
 
ae23c9
     /*
ae23c9
      * From "Requirements for Implementing the Microsoft
ae23c9
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
ae23c9
index 372f8b7..31715d1 100644
ae23c9
--- a/target/i386/cpu.h
ae23c9
+++ b/target/i386/cpu.h
ae23c9
@@ -1394,6 +1394,11 @@ struct X86CPU {
ae23c9
      */
ae23c9
     bool enable_l3_cache;
ae23c9
 
ae23c9
+    /* Compatibility bits for old machine types.
ae23c9
+     * If true present the old cache topology information
ae23c9
+     */
ae23c9
+    bool legacy_cache;
ae23c9
+
ae23c9
     /* Compatibility bits for old machine types: */
ae23c9
     bool enable_cpuid_0xb;
ae23c9
 
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9