diff mbox

[PULL,17/19] target-i386: Support "invariant tsc" flag

Message ID 1403734339-14405-18-git-send-email-afaerber@suse.de
State New
Headers show

Commit Message

Andreas Färber June 25, 2014, 10:12 p.m. UTC
From: Marcelo Tosatti <mtosatti@redhat.com>

Expose "Invariant TSC" flag, if KVM is enabled. From Intel documentation:

17.13.1 Invariant TSC The time stamp counter in newer processors may
support an enhancement, referred to as invariant TSC. Processor’s
support for invariant TSC is indicated by CPUID.80000007H:EDX[8].
The invariant TSC will run at a constant rate in all ACPI P-, C-.
and T-states. This is the architectural behavior moving forward. On
processors with invariant TSC support, the OS may use the TSC for wall
clock timer services (instead of ACPI or HPET timers). TSC reads are
much more efficient and do not incur the overhead associated with a ring
transition or access to a platform resource.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
[ehabkost: redo feature filtering to use .tcg_features]
[ehabkost: add CPUID_APM_INVTSC macro, add it to .unmigratable_flags]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 target-i386/cpu.c | 25 +++++++++++++++++++++++++
 target-i386/cpu.h |  4 ++++
 2 files changed, 29 insertions(+)

Comments

ChenLiang Aug. 8, 2014, 7:07 a.m. UTC | #1
Hi,
We found that value of host cpus tsc are same to echo other when host has invariant tsc flag.
But it is not in vm. The problem is that offset of vcpus tsc are not equal. The offset is set when
vcpu is created. Is it ok to set same offset? And is it reasonable?

Best regards
Chen Liang


From: Marcelo Tosatti <mtosatti@redhat.com>


Expose "Invariant TSC" flag, if KVM is enabled. From Intel documentation:

17.13.1 Invariant TSC The time stamp counter in newer processors may support an enhancement, referred to as invariant TSC. Processor’s support for invariant TSC is indicated by CPUID.80000007H:EDX[8].
The invariant TSC will run at a constant rate in all ACPI P-, C-.
and T-states. This is the architectural behavior moving forward. On processors with invariant TSC support, the OS may use the TSC for wall clock timer services (instead of ACPI or HPET timers). TSC reads are much more efficient and do not incur the overhead associated with a ring transition or access to a platform resource.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

[ehabkost: redo feature filtering to use .tcg_features]
[ehabkost: add CPUID_APM_INVTSC macro, add it to .unmigratable_flags]
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>

Signed-off-by: Andreas Färber <afaerber@suse.de>
Marcelo Tosatti Aug. 8, 2014, 9:42 p.m. UTC | #2
Chen Liang,

On Fri, Aug 08, 2014 at 07:07:59AM +0000, chenliang (T) wrote:
> Hi,
> We found that value of host cpus tsc are same to echo other when host has invariant tsc flag.

What you mean exactly?

Do you have a test program?

> But it is not in vm. The problem is that offset of vcpus tsc are not equal. The offset is set when
> vcpu is created. Is it ok to set same offset? And is it reasonable?
> 
> Best regards
> Chen Liang


The code at kvm_write_tsc(), in the kernel (arch/x86/kvm/x86.c), should 
adjust the vcpu tsc offsets properly resulting in cross SMP TSCs being
equal in the VM.
diff mbox

Patch

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index b651a94..4cfb9a3 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -263,6 +263,17 @@  static const char *cpuid_7_0_ebx_feature_name[] = {
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 };
 
+static const char *cpuid_apm_edx_feature_name[] = {
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    "invtsc", NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL,
+};
+
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
 #define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
           CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
@@ -317,6 +328,7 @@  static const char *cpuid_7_0_ebx_feature_name[] = {
           CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
           CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
           CPUID_7_0_EBX_RDSEED */
+#define TCG_APM_FEATURES 0
 
 
 typedef struct FeatureWordInfo {
@@ -372,6 +384,13 @@  static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
         .cpuid_reg = R_EBX,
         .tcg_features = TCG_7_0_EBX_FEATURES,
     },
+    [FEAT_8000_0007_EDX] = {
+        .feat_names = cpuid_apm_edx_feature_name,
+        .cpuid_eax = 0x80000007,
+        .cpuid_reg = R_EDX,
+        .tcg_features = TCG_APM_FEATURES,
+        .unmigratable_flags = CPUID_APM_INVTSC,
+    },
 };
 
 typedef struct X86RegisterInfo32 {
@@ -2385,6 +2404,12 @@  void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
                (AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \
                (L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);
         break;
+    case 0x80000007:
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+        *edx = env->features[FEAT_8000_0007_EDX];
+        break;
     case 0x80000008:
         /* virtual & phys address size in low 2 bytes. */
 /* XXX: This value must match the one used in the MMU code. */
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index b5e1b41..e634d83 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -402,6 +402,7 @@  typedef enum FeatureWord {
     FEAT_7_0_EBX,       /* CPUID[EAX=7,ECX=0].EBX */
     FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
     FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
+    FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */
     FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
     FEAT_KVM,           /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
     FEAT_SVM,           /* CPUID[8000_000A].EDX */
@@ -561,6 +562,9 @@  typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_EBX_ADX      (1U << 19)
 #define CPUID_7_0_EBX_SMAP     (1U << 20)
 
+/* CPUID[0x80000007].EDX flags: */
+#define CPUID_APM_INVTSC       (1U << 8)
+
 #define CPUID_VENDOR_SZ      12
 
 #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */