src/cpu/x86/vm/vm_version_x86.hpp

changeset 3378
7ab5f6318694
parent 3063
9f12ede5571a
child 3400
22cee0ee8927
     1.1 --- a/src/cpu/x86/vm/vm_version_x86.hpp	Mon Dec 26 20:36:01 2011 -0500
     1.2 +++ b/src/cpu/x86/vm/vm_version_x86.hpp	Sun Jan 01 11:17:59 2012 -0500
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -176,32 +176,54 @@
    1.11      } bits;
    1.12    };
    1.13  
    1.14 +  union ExtCpuid7Edx {
    1.15 +    uint32_t value;
    1.16 +    struct {
    1.17 +      uint32_t               : 8,
    1.18 +              tsc_invariance : 1,
    1.19 +                             : 23;
    1.20 +    } bits;
    1.21 +  };
    1.22 +
    1.23  protected:
    1.24 -   static int _cpu;
    1.25 -   static int _model;
    1.26 -   static int _stepping;
    1.27 -   static int _cpuFeatures;     // features returned by the "cpuid" instruction
    1.28 -                                // 0 if this instruction is not available
    1.29 -   static const char* _features_str;
    1.30 +  static int _cpu;
    1.31 +  static int _model;
    1.32 +  static int _stepping;
    1.33 +  static int _cpuFeatures;     // features returned by the "cpuid" instruction
    1.34 +                               // 0 if this instruction is not available
    1.35 +  static const char* _features_str;
    1.36  
    1.37 -   enum {
    1.38 -     CPU_CX8    = (1 << 0), // next bits are from cpuid 1 (EDX)
    1.39 -     CPU_CMOV   = (1 << 1),
    1.40 -     CPU_FXSR   = (1 << 2),
    1.41 -     CPU_HT     = (1 << 3),
    1.42 -     CPU_MMX    = (1 << 4),
    1.43 -     CPU_3DNOW_PREFETCH  = (1 << 5), // Processor supports 3dnow prefetch and prefetchw instructions
    1.44 -                                     // may not necessarily support other 3dnow instructions
    1.45 -     CPU_SSE    = (1 << 6),
    1.46 -     CPU_SSE2   = (1 << 7),
    1.47 -     CPU_SSE3   = (1 << 8), // SSE3 comes from cpuid 1 (ECX)
    1.48 -     CPU_SSSE3  = (1 << 9),
    1.49 -     CPU_SSE4A  = (1 << 10),
    1.50 -     CPU_SSE4_1 = (1 << 11),
    1.51 -     CPU_SSE4_2 = (1 << 12),
    1.52 -     CPU_POPCNT = (1 << 13),
    1.53 -     CPU_LZCNT  = (1 << 14)
    1.54 -   } cpuFeatureFlags;
    1.55 +  enum {
    1.56 +    CPU_CX8    = (1 << 0), // next bits are from cpuid 1 (EDX)
    1.57 +    CPU_CMOV   = (1 << 1),
    1.58 +    CPU_FXSR   = (1 << 2),
    1.59 +    CPU_HT     = (1 << 3),
    1.60 +    CPU_MMX    = (1 << 4),
    1.61 +    CPU_3DNOW_PREFETCH  = (1 << 5), // Processor supports 3dnow prefetch and prefetchw instructions
    1.62 +                                    // may not necessarily support other 3dnow instructions
    1.63 +    CPU_SSE    = (1 << 6),
    1.64 +    CPU_SSE2   = (1 << 7),
    1.65 +    CPU_SSE3   = (1 << 8), // SSE3 comes from cpuid 1 (ECX)
    1.66 +    CPU_SSSE3  = (1 << 9),
    1.67 +    CPU_SSE4A  = (1 << 10),
    1.68 +    CPU_SSE4_1 = (1 << 11),
    1.69 +    CPU_SSE4_2 = (1 << 12),
    1.70 +    CPU_POPCNT = (1 << 13),
    1.71 +    CPU_LZCNT  = (1 << 14),
    1.72 +    CPU_TSC    = (1 << 15),
    1.73 +    CPU_TSCINV = (1 << 16)
    1.74 +  } cpuFeatureFlags;
    1.75 +
    1.76 +  enum {
    1.77 +    // AMD
    1.78 +    CPU_FAMILY_AMD_11H       = 17,
    1.79 +    // Intel
    1.80 +    CPU_FAMILY_INTEL_CORE    = 6,
    1.81 +    CPU_MODEL_NEHALEM_EP     = 26,
    1.82 +    CPU_MODEL_WESTMERE_EP    = 44,
    1.83 +//  CPU_MODEL_IVYBRIDGE_EP   = ??, TODO - get real value
    1.84 +    CPU_MODEL_SANDYBRIDGE_EP = 45
    1.85 +  } cpuExtendedFamily;
    1.86  
    1.87    // cpuid information block.  All info derived from executing cpuid with
    1.88    // various function numbers is stored here.  Intel and AMD info is
    1.89 @@ -270,6 +292,12 @@
    1.90      ExtCpuid5Ex  ext_cpuid5_ecx; // L1 data cache info (AMD)
    1.91      ExtCpuid5Ex  ext_cpuid5_edx; // L1 instruction cache info (AMD)
    1.92  
    1.93 +    // cpuid function 0x80000007
    1.94 +    uint32_t     ext_cpuid7_eax; // reserved
    1.95 +    uint32_t     ext_cpuid7_ebx; // reserved
    1.96 +    uint32_t     ext_cpuid7_ecx; // reserved
    1.97 +    ExtCpuid7Edx ext_cpuid7_edx; // tscinv
    1.98 +
    1.99      // cpuid function 0x80000008
   1.100      uint32_t     ext_cpuid8_eax; // unused currently
   1.101      uint32_t     ext_cpuid8_ebx; // reserved
   1.102 @@ -286,19 +314,23 @@
   1.103      result += _cpuid_info.std_cpuid1_eax.bits.ext_family;
   1.104      return result;
   1.105    }
   1.106 +
   1.107    static uint32_t extended_cpu_model() {
   1.108      uint32_t result = _cpuid_info.std_cpuid1_eax.bits.model;
   1.109      result |= _cpuid_info.std_cpuid1_eax.bits.ext_model << 4;
   1.110      return result;
   1.111    }
   1.112 +
   1.113    static uint32_t cpu_stepping() {
   1.114      uint32_t result = _cpuid_info.std_cpuid1_eax.bits.stepping;
   1.115      return result;
   1.116    }
   1.117 +
   1.118    static uint logical_processor_count() {
   1.119      uint result = threads_per_core();
   1.120      return result;
   1.121    }
   1.122 +
   1.123    static uint32_t feature_flags() {
   1.124      uint32_t result = 0;
   1.125      if (_cpuid_info.std_cpuid1_edx.bits.cmpxchg8 != 0)
   1.126 @@ -328,6 +360,10 @@
   1.127        result |= CPU_SSE4_2;
   1.128      if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
   1.129        result |= CPU_POPCNT;
   1.130 +    if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0)
   1.131 +      result |= CPU_TSC;
   1.132 +    if (_cpuid_info.ext_cpuid7_edx.bits.tsc_invariance != 0)
   1.133 +      result |= CPU_TSCINV;
   1.134  
   1.135      // AMD features.
   1.136      if (is_amd()) {
   1.137 @@ -352,6 +388,7 @@
   1.138    static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); }
   1.139    static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); }
   1.140    static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); }
   1.141 +  static ByteSize ext_cpuid7_offset() { return byte_offset_of(CpuidInfo, ext_cpuid7_eax); }
   1.142    static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); }
   1.143    static ByteSize tpl_cpuidB0_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB0_eax); }
   1.144    static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); }
   1.145 @@ -382,7 +419,6 @@
   1.146    //
   1.147    static int  cpu_family()        { return _cpu;}
   1.148    static bool is_P6()             { return cpu_family() >= 6; }
   1.149 -
   1.150    static bool is_amd()            { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
   1.151    static bool is_intel()          { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG'
   1.152  
   1.153 @@ -447,14 +483,49 @@
   1.154    static bool supports_sse4_1()   { return (_cpuFeatures & CPU_SSE4_1) != 0; }
   1.155    static bool supports_sse4_2()   { return (_cpuFeatures & CPU_SSE4_2) != 0; }
   1.156    static bool supports_popcnt()   { return (_cpuFeatures & CPU_POPCNT) != 0; }
   1.157 -  //
   1.158 +  static bool supports_tsc()      { return (_cpuFeatures & CPU_TSC)    != 0; }
   1.159 +
   1.160 +  // Intel features
   1.161 +  static bool is_intel_family_core() { return is_intel() &&
   1.162 +                                       extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
   1.163 +
   1.164 +  static bool is_intel_tsc_synched_at_init()  {
   1.165 +    if (is_intel_family_core()) {
   1.166 +      uint32_t ext_model = extended_cpu_model();
   1.167 +      if (ext_model == CPU_MODEL_NEHALEM_EP   ||
   1.168 +          ext_model == CPU_MODEL_WESTMERE_EP  ||
   1.169 +// TODO   ext_model == CPU_MODEL_IVYBRIDGE_EP ||
   1.170 +          ext_model == CPU_MODEL_SANDYBRIDGE_EP) {
   1.171 +        // 2-socket invtsc support. EX versions with 4 sockets are not
   1.172 +        // guaranteed to synchronize tscs at initialization via a double
   1.173 +        // handshake. The tscs can be explicitly set in software.  Code
   1.174 +        // that uses tsc values must be prepared for them to arbitrarily
   1.175 +        // jump backward or forward.
   1.176 +        return true;
   1.177 +      }
   1.178 +    }
   1.179 +    return false;
   1.180 +  }
   1.181 +
   1.182    // AMD features
   1.183 -  //
   1.184    static bool supports_3dnow_prefetch()    { return (_cpuFeatures & CPU_3DNOW_PREFETCH) != 0; }
   1.185    static bool supports_mmx_ext()  { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; }
   1.186    static bool supports_lzcnt()    { return (_cpuFeatures & CPU_LZCNT) != 0; }
   1.187    static bool supports_sse4a()    { return (_cpuFeatures & CPU_SSE4A) != 0; }
   1.188  
   1.189 +  static bool is_amd_Barcelona()  { return is_amd() &&
   1.190 +                                           extended_cpu_family() == CPU_FAMILY_AMD_11H; }
   1.191 +
   1.192 +  // Intel and AMD newer cores support fast timestamps well
   1.193 +  static bool supports_tscinv_bit() {
   1.194 +    return (_cpuFeatures & CPU_TSCINV) != 0;
   1.195 +  }
   1.196 +  static bool supports_tscinv() {
   1.197 +    return supports_tscinv_bit() &&
   1.198 +           ( (is_amd() && !is_amd_Barcelona()) ||
   1.199 +             is_intel_tsc_synched_at_init() );
   1.200 +  }
   1.201 +
   1.202    // Intel Core and newer cpus have fast IDIV instruction (excluding Atom).
   1.203    static bool has_fast_idiv()     { return is_intel() && cpu_family() == 6 &&
   1.204                                             supports_sse3() && _model != 0x1C; }

mercurial