c461a1
From 4e903b8594bb59a953e66ca0fb422079f6f6b573 Mon Sep 17 00:00:00 2001
c461a1
From: Eduardo Habkost <ehabkost@redhat.com>
c461a1
Date: Wed, 21 Aug 2019 14:30:05 +0200
c461a1
Subject: [PATCH 1/3] target-i386: Support "invariant tsc" flag
c461a1
MIME-Version: 1.0
c461a1
Content-Type: text/plain; charset=UTF-8
c461a1
Content-Transfer-Encoding: 8bit
c461a1
c461a1
RH-Author: Eduardo Habkost <ehabkost@redhat.com>
c461a1
Message-id: <20190821143006.23516-2-ehabkost@redhat.com>
c461a1
Patchwork-id: 90101
c461a1
O-Subject: [RHEL-7.8 qemu-kvm PATCH 1/2] target-i386: Support "invariant tsc" flag
c461a1
Bugzilla: 1626871
c461a1
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
c461a1
RH-Acked-by: Bandan Das <bsd@redhat.com>
c461a1
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
c461a1
c461a1
From: Marcelo Tosatti <mtosatti@redhat.com>
c461a1
c461a1
Expose "Invariant TSC" flag, if KVM is enabled. From Intel documentation:
c461a1
c461a1
17.13.1 Invariant TSC The time stamp counter in newer processors may
c461a1
support an enhancement, referred to as invariant TSC. Processor’s
c461a1
support for invariant TSC is indicated by CPUID.80000007H:EDX[8].
c461a1
The invariant TSC will run at a constant rate in all ACPI P-, C-.
c461a1
and T-states. This is the architectural behavior moving forward. On
c461a1
processors with invariant TSC support, the OS may use the TSC for wall
c461a1
clock timer services (instead of ACPI or HPET timers). TSC reads are
c461a1
much more efficient and do not incur the overhead associated with a ring
c461a1
transition or access to a platform resource.
c461a1
c461a1
Backport notes:
c461a1
  One extra line to remove invtsc was added to
c461a1
  kvm_cpu_fill_host(), to replace the unmigratable_flags field,
c461a1
  and fix the same issue fixed by upstream commit 120eee7d1fdb
c461a1
  ("target-i386: Set migratable=yes by default on "host" CPU
c461a1
  mooel").
c461a1
c461a1
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
c461a1
[ehabkost: redo feature filtering to use .tcg_features]
c461a1
[ehabkost: add CPUID_APM_INVTSC macro, add it to .unmigratable_flags]
c461a1
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
c461a1
Signed-off-by: Andreas Färber <afaerber@suse.de>
c461a1
(cherry picked from commit 303752a9068bfe84b9b05f1cd5ad5ff65b7f3ea6)
c461a1
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
c461a1
c461a1
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
c461a1
---
c461a1
 target-i386/cpu.c | 26 ++++++++++++++++++++++++++
c461a1
 target-i386/cpu.h |  4 ++++
c461a1
 2 files changed, 30 insertions(+)
c461a1
c461a1
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
c461a1
index c2fcd1e..c74f597 100644
c461a1
--- a/target-i386/cpu.c
c461a1
+++ b/target-i386/cpu.c
c461a1
@@ -199,6 +199,17 @@ static const char *cpuid_xsave_feature_name[] = {
c461a1
     NULL, NULL, NULL, NULL,
c461a1
 };
c461a1
 
c461a1
+static const char *cpuid_apm_edx_feature_name[] = {
c461a1
+    NULL, NULL, NULL, NULL,
c461a1
+    NULL, NULL, NULL, NULL,
c461a1
+    "invtsc", NULL, NULL, NULL,
c461a1
+    NULL, NULL, NULL, NULL,
c461a1
+    NULL, NULL, NULL, NULL,
c461a1
+    NULL, NULL, NULL, NULL,
c461a1
+    NULL, NULL, NULL, NULL,
c461a1
+    NULL, NULL, NULL, NULL,
c461a1
+};
c461a1
+
c461a1
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
c461a1
 #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
c461a1
           CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
c461a1
@@ -258,6 +269,7 @@ static const char *cpuid_xsave_feature_name[] = {
c461a1
           CPUID_7_0_EBX_RDSEED */
c461a1
 #define TCG_7_0_ECX_FEATURES 0
c461a1
 #define TCG_7_0_EDX_FEATURES 0
c461a1
+#define TCG_APM_FEATURES 0
c461a1
 
c461a1
 
c461a1
 typedef struct FeatureWordInfo {
c461a1
@@ -326,6 +338,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
c461a1
         .cpuid_reg = R_EDX,
c461a1
         .tcg_features = TCG_7_0_EDX_FEATURES,
c461a1
     },
c461a1
+    [FEAT_8000_0007_EDX] = {
c461a1
+        .feat_names = cpuid_apm_edx_feature_name,
c461a1
+        .cpuid_eax = 0x80000007,
c461a1
+        .cpuid_reg = R_EDX,
c461a1
+        .tcg_features = TCG_APM_FEATURES,
c461a1
+    },
c461a1
     [FEAT_8000_0008_EBX] = {
c461a1
         .feat_names = cpuid_80000008_ebx_feature_name,
c461a1
         .cpuid_eax = 0x80000008,
c461a1
@@ -1750,6 +1768,8 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
c461a1
 
c461a1
     /* arch-facilities: deprecated (see comment on x86_cpu_realizefn()) */
c461a1
     x86_cpu_def->features[FEAT_7_0_EDX] &= ~CPUID_7_0_EDX_ARCH_CAPABILITIES;
c461a1
+    /* invtsc: not migratable, so not enabled by default */
c461a1
+    x86_cpu_def->features[FEAT_8000_0007_EDX] &= ~CPUID_APM_INVTSC;
c461a1
 
c461a1
 #endif /* CONFIG_KVM */
c461a1
 }
c461a1
@@ -2805,6 +2825,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
c461a1
         *ecx = 0x02008140;
c461a1
         *edx = 0;
c461a1
         break;
c461a1
+    case 0x80000007:
c461a1
+        *eax = 0;
c461a1
+        *ebx = 0;
c461a1
+        *ecx = 0;
c461a1
+        *edx = env->features[FEAT_8000_0007_EDX];
c461a1
+        break;
c461a1
     case 0x80000008:
c461a1
         /* virtual & phys address size in low 2 bytes. */
c461a1
 /* XXX: This value must match the one used in the MMU code. */
c461a1
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
c461a1
index 5d47ab8..cbbc34f 100644
c461a1
--- a/target-i386/cpu.h
c461a1
+++ b/target-i386/cpu.h
c461a1
@@ -408,6 +408,7 @@ typedef enum FeatureWord {
c461a1
     FEAT_7_0_EDX,       /* CPUID[EAX=7,ECX=0].EDX */
c461a1
     FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
c461a1
     FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
c461a1
+    FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */
c461a1
     FEAT_8000_0008_EBX, /* CPUID[8000_0008].EBX */
c461a1
     FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
c461a1
     FEAT_KVM,           /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
c461a1
@@ -613,6 +614,9 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
c461a1
 #define CPUID_XSAVE_XGETBV1    (1U << 2)
c461a1
 #define CPUID_XSAVE_XSAVES     (1U << 3)
c461a1
 
c461a1
+/* CPUID[0x80000007].EDX flags: */
c461a1
+#define CPUID_APM_INVTSC       (1U << 8)
c461a1
+
c461a1
 #define CPUID_VENDOR_SZ      12
c461a1
 
c461a1
 #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
c461a1
-- 
c461a1
1.8.3.1
c461a1