diff mbox

[1/2] target-i386: support "invariant tsc" flag

Message ID 20140422191200.328459410@amt.cnet
State New
Headers show

Commit Message

Marcelo Tosatti April 22, 2014, 7:10 p.m. UTC
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>

Comments

Paolo Bonzini April 23, 2014, 12:26 a.m. UTC | #1
Il 22/04/2014 15:10, Marcelo Tosatti ha scritto:
> +    case 0x80000007:
> +        *eax = 0;
> +        *ebx = 0;
> +        *ecx = 0;
> +
> +        if (kvm_enabled()) {
> +            *edx = env->features[FEAT_8000_0007_EDX];
> +        } else {
> +            *edx = 0;
> +        }

I think TCG is able to eliminate unsupported features too before they 
get in env->features[].  Or are those patches not in yet?  Eduardo?

Paolo
Eduardo Habkost April 23, 2014, 1:11 a.m. UTC | #2
On Tue, Apr 22, 2014 at 08:26:36PM -0400, Paolo Bonzini wrote:
> Il 22/04/2014 15:10, Marcelo Tosatti ha scritto:
> >+    case 0x80000007:
> >+        *eax = 0;
> >+        *ebx = 0;
> >+        *ecx = 0;
> >+
> >+        if (kvm_enabled()) {
> >+            *edx = env->features[FEAT_8000_0007_EDX];
> >+        } else {
> >+            *edx = 0;
> >+        }
> 
> I think TCG is able to eliminate unsupported features too before they
> get in env->features[].  Or are those patches not in yet?  Eduardo?

They are not in yet, but while they are not included this filtering
(based on TCG_*_FEATURES macros) should be done in the !kvm_enabled()
block of x86_cpu_realizefn().
diff mbox

Patch

Index: qemu-invariant-tsc/target-i386/cpu.c
===================================================================
--- qemu-invariant-tsc.orig/target-i386/cpu.c
+++ qemu-invariant-tsc/target-i386/cpu.c
@@ -262,6 +262,17 @@  static const char *cpuid_7_0_ebx_feature
     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,
+};
+
 typedef struct FeatureWordInfo {
     const char **feat_names;
     uint32_t cpuid_eax;   /* Input EAX for CPUID */
@@ -305,6 +316,11 @@  static FeatureWordInfo feature_word_info
         .cpuid_needs_ecx = true, .cpuid_ecx = 0,
         .cpuid_reg = R_EBX,
     },
+    [FEAT_8000_0007_EDX] = {
+        .feat_names = cpuid_apm_edx_feature_name,
+        .cpuid_eax = 0x80000007,
+        .cpuid_reg = R_EDX,
+    },
 };
 
 typedef struct X86RegisterInfo32 {
@@ -1740,6 +1756,7 @@  static void x86_cpu_parse_featurestr(CPU
     env->features[FEAT_1_ECX] |= plus_features[FEAT_1_ECX];
     env->features[FEAT_8000_0001_EDX] |= plus_features[FEAT_8000_0001_EDX];
     env->features[FEAT_8000_0001_ECX] |= plus_features[FEAT_8000_0001_ECX];
+    env->features[FEAT_8000_0007_EDX] |= plus_features[FEAT_8000_0007_EDX];
     env->features[FEAT_C000_0001_EDX] |= plus_features[FEAT_C000_0001_EDX];
     env->features[FEAT_KVM] |= plus_features[FEAT_KVM];
     env->features[FEAT_SVM] |= plus_features[FEAT_SVM];
@@ -1748,6 +1765,7 @@  static void x86_cpu_parse_featurestr(CPU
     env->features[FEAT_1_ECX] &= ~minus_features[FEAT_1_ECX];
     env->features[FEAT_8000_0001_EDX] &= ~minus_features[FEAT_8000_0001_EDX];
     env->features[FEAT_8000_0001_ECX] &= ~minus_features[FEAT_8000_0001_ECX];
+    env->features[FEAT_8000_0007_EDX] &= ~minus_features[FEAT_8000_0007_EDX];
     env->features[FEAT_C000_0001_EDX] &= ~minus_features[FEAT_C000_0001_EDX];
     env->features[FEAT_KVM] &= ~minus_features[FEAT_KVM];
     env->features[FEAT_SVM] &= ~minus_features[FEAT_SVM];
@@ -2333,6 +2351,17 @@  void cpu_x86_cpuid(CPUX86State *env, uin
                (AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \
                (L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);
         break;
+    case 0x80000007:
+        *eax = 0;
+        *ebx = 0;
+        *ecx = 0;
+
+        if (kvm_enabled()) {
+            *edx = env->features[FEAT_8000_0007_EDX];
+        } else {
+            *edx = 0;
+        }
+        break;
     case 0x80000008:
         /* virtual & phys address size in low 2 bytes. */
 /* XXX: This value must match the one used in the MMU code. */
Index: qemu-invariant-tsc/target-i386/cpu.h
===================================================================
--- qemu-invariant-tsc.orig/target-i386/cpu.h
+++ qemu-invariant-tsc/target-i386/cpu.h
@@ -398,6 +398,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 */