hotspot/src/cpu/x86/vm/vm_version_x86.hpp
changeset 35148 5cfafc99d791
parent 35123 b0b89d83bcf5
child 36555 4f37fd7a5a09
equal deleted inserted replaced
35146:9ebfec283f56 35148:5cfafc99d791
    29 #include "runtime/vm_version.hpp"
    29 #include "runtime/vm_version.hpp"
    30 
    30 
    31 class VM_Version : public Abstract_VM_Version {
    31 class VM_Version : public Abstract_VM_Version {
    32   friend class VMStructs;
    32   friend class VMStructs;
    33   friend class JVMCIVMStructs;
    33   friend class JVMCIVMStructs;
    34 public:
    34 
       
    35  public:
    35   // cpuid result register layouts.  These are all unions of a uint32_t
    36   // cpuid result register layouts.  These are all unions of a uint32_t
    36   // (in case anyone wants access to the register as a whole) and a bitfield.
    37   // (in case anyone wants access to the register as a whole) and a bitfield.
    37 
    38 
    38   union StdCpuid1Eax {
    39   union StdCpuid1Eax {
    39     uint32_t value;
    40     uint32_t value;
   243 
   244 
   244 protected:
   245 protected:
   245   static int _cpu;
   246   static int _cpu;
   246   static int _model;
   247   static int _model;
   247   static int _stepping;
   248   static int _stepping;
   248   static uint64_t _cpuFeatures; // features returned by the "cpuid" instruction
       
   249                                 // 0 if this instruction is not available
       
   250   static const char* _features_str;
       
   251 
   249 
   252   static address   _cpuinfo_segv_addr; // address of instruction which causes SEGV
   250   static address   _cpuinfo_segv_addr; // address of instruction which causes SEGV
   253   static address   _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV
   251   static address   _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV
   254 
   252 
   255   enum {
   253   enum Feature_Flag {
   256     CPU_CX8      = (1 << 0), // next bits are from cpuid 1 (EDX)
   254     CPU_CX8      = (1 << 0), // next bits are from cpuid 1 (EDX)
   257     CPU_CMOV     = (1 << 1),
   255     CPU_CMOV     = (1 << 1),
   258     CPU_FXSR     = (1 << 2),
   256     CPU_FXSR     = (1 << 2),
   259     CPU_HT       = (1 << 3),
   257     CPU_HT       = (1 << 3),
   260     CPU_MMX      = (1 << 4),
   258     CPU_MMX      = (1 << 4),
   284     CPU_AVX512DQ = (1 << 27),
   282     CPU_AVX512DQ = (1 << 27),
   285     CPU_AVX512PF = (1 << 28),
   283     CPU_AVX512PF = (1 << 28),
   286     CPU_AVX512ER = (1 << 29),
   284     CPU_AVX512ER = (1 << 29),
   287     CPU_AVX512CD = (1 << 30),
   285     CPU_AVX512CD = (1 << 30),
   288     CPU_AVX512BW = (1 << 31)
   286     CPU_AVX512BW = (1 << 31)
   289   } cpuFeatureFlags;
   287   };
   290 
   288 
   291 #define CPU_AVX512VL UCONST64(0x100000000) // EVEX instructions with smaller vector length : enums are limited to 32bit
   289 #define CPU_AVX512VL UCONST64(0x100000000) // EVEX instructions with smaller vector length : enums are limited to 32bit
   292 
   290 
   293   enum {
   291   enum Extended_Family {
   294     // AMD
   292     // AMD
   295     CPU_FAMILY_AMD_11H       = 0x11,
   293     CPU_FAMILY_AMD_11H       = 0x11,
   296     // Intel
   294     // Intel
   297     CPU_FAMILY_INTEL_CORE    = 6,
   295     CPU_FAMILY_INTEL_CORE    = 6,
   298     CPU_MODEL_NEHALEM        = 0x1e,
   296     CPU_MODEL_NEHALEM        = 0x1e,
   306     CPU_MODEL_IVYBRIDGE_EP   = 0x3a,
   304     CPU_MODEL_IVYBRIDGE_EP   = 0x3a,
   307     CPU_MODEL_HASWELL_E3     = 0x3c,
   305     CPU_MODEL_HASWELL_E3     = 0x3c,
   308     CPU_MODEL_HASWELL_E7     = 0x3f,
   306     CPU_MODEL_HASWELL_E7     = 0x3f,
   309     CPU_MODEL_BROADWELL      = 0x3d,
   307     CPU_MODEL_BROADWELL      = 0x3d,
   310     CPU_MODEL_SKYLAKE        = CPU_MODEL_HASWELL_E3
   308     CPU_MODEL_SKYLAKE        = CPU_MODEL_HASWELL_E3
   311   } cpuExtendedFamily;
   309   };
   312 
   310 
   313   // cpuid information block.  All info derived from executing cpuid with
   311   // cpuid information block.  All info derived from executing cpuid with
   314   // various function numbers is stored here.  Intel and AMD info is
   312   // various function numbers is stored here.  Intel and AMD info is
   315   // merged in this block: accessor methods disentangle it.
   313   // merged in this block: accessor methods disentangle it.
   316   //
   314   //
   596   static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; }
   594   static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; }
   597   static bool  is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; }
   595   static bool  is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; }
   598   static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; }
   596   static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; }
   599   static address  cpuinfo_cont_addr()           { return _cpuinfo_cont_addr; }
   597   static address  cpuinfo_cont_addr()           { return _cpuinfo_cont_addr; }
   600 
   598 
   601   static void clean_cpuFeatures()   { _cpuFeatures = 0; }
   599   static void clean_cpuFeatures()   { _features = 0; }
   602   static void set_avx_cpuFeatures() { _cpuFeatures = (CPU_SSE | CPU_SSE2 | CPU_AVX); }
   600   static void set_avx_cpuFeatures() { _features = (CPU_SSE | CPU_SSE2 | CPU_AVX); }
   603   static void set_evex_cpuFeatures() { _cpuFeatures = (CPU_AVX512F | CPU_SSE | CPU_SSE2 ); }
   601   static void set_evex_cpuFeatures() { _features = (CPU_AVX512F | CPU_SSE | CPU_SSE2 ); }
   604 
   602 
   605 
   603 
   606   // Initialization
   604   // Initialization
   607   static void initialize();
   605   static void initialize();
   608 
   606 
   686   }
   684   }
   687 
   685 
   688   //
   686   //
   689   // Feature identification
   687   // Feature identification
   690   //
   688   //
   691   static bool supports_cpuid()    { return _cpuFeatures  != 0; }
   689   static bool supports_cpuid()    { return _features  != 0; }
   692   static bool supports_cmpxchg8() { return (_cpuFeatures & CPU_CX8) != 0; }
   690   static bool supports_cmpxchg8() { return (_features & CPU_CX8) != 0; }
   693   static bool supports_cmov()     { return (_cpuFeatures & CPU_CMOV) != 0; }
   691   static bool supports_cmov()     { return (_features & CPU_CMOV) != 0; }
   694   static bool supports_fxsr()     { return (_cpuFeatures & CPU_FXSR) != 0; }
   692   static bool supports_fxsr()     { return (_features & CPU_FXSR) != 0; }
   695   static bool supports_ht()       { return (_cpuFeatures & CPU_HT) != 0; }
   693   static bool supports_ht()       { return (_features & CPU_HT) != 0; }
   696   static bool supports_mmx()      { return (_cpuFeatures & CPU_MMX) != 0; }
   694   static bool supports_mmx()      { return (_features & CPU_MMX) != 0; }
   697   static bool supports_sse()      { return (_cpuFeatures & CPU_SSE) != 0; }
   695   static bool supports_sse()      { return (_features & CPU_SSE) != 0; }
   698   static bool supports_sse2()     { return (_cpuFeatures & CPU_SSE2) != 0; }
   696   static bool supports_sse2()     { return (_features & CPU_SSE2) != 0; }
   699   static bool supports_sse3()     { return (_cpuFeatures & CPU_SSE3) != 0; }
   697   static bool supports_sse3()     { return (_features & CPU_SSE3) != 0; }
   700   static bool supports_ssse3()    { return (_cpuFeatures & CPU_SSSE3)!= 0; }
   698   static bool supports_ssse3()    { return (_features & CPU_SSSE3)!= 0; }
   701   static bool supports_sse4_1()   { return (_cpuFeatures & CPU_SSE4_1) != 0; }
   699   static bool supports_sse4_1()   { return (_features & CPU_SSE4_1) != 0; }
   702   static bool supports_sse4_2()   { return (_cpuFeatures & CPU_SSE4_2) != 0; }
   700   static bool supports_sse4_2()   { return (_features & CPU_SSE4_2) != 0; }
   703   static bool supports_popcnt()   { return (_cpuFeatures & CPU_POPCNT) != 0; }
   701   static bool supports_popcnt()   { return (_features & CPU_POPCNT) != 0; }
   704   static bool supports_avx()      { return (_cpuFeatures & CPU_AVX) != 0; }
   702   static bool supports_avx()      { return (_features & CPU_AVX) != 0; }
   705   static bool supports_avx2()     { return (_cpuFeatures & CPU_AVX2) != 0; }
   703   static bool supports_avx2()     { return (_features & CPU_AVX2) != 0; }
   706   static bool supports_tsc()      { return (_cpuFeatures & CPU_TSC)    != 0; }
   704   static bool supports_tsc()      { return (_features & CPU_TSC)    != 0; }
   707   static bool supports_aes()      { return (_cpuFeatures & CPU_AES) != 0; }
   705   static bool supports_aes()      { return (_features & CPU_AES) != 0; }
   708   static bool supports_erms()     { return (_cpuFeatures & CPU_ERMS) != 0; }
   706   static bool supports_erms()     { return (_features & CPU_ERMS) != 0; }
   709   static bool supports_clmul()    { return (_cpuFeatures & CPU_CLMUL) != 0; }
   707   static bool supports_clmul()    { return (_features & CPU_CLMUL) != 0; }
   710   static bool supports_rtm()      { return (_cpuFeatures & CPU_RTM) != 0; }
   708   static bool supports_rtm()      { return (_features & CPU_RTM) != 0; }
   711   static bool supports_bmi1()     { return (_cpuFeatures & CPU_BMI1) != 0; }
   709   static bool supports_bmi1()     { return (_features & CPU_BMI1) != 0; }
   712   static bool supports_bmi2()     { return (_cpuFeatures & CPU_BMI2) != 0; }
   710   static bool supports_bmi2()     { return (_features & CPU_BMI2) != 0; }
   713   static bool supports_adx()      { return (_cpuFeatures & CPU_ADX) != 0; }
   711   static bool supports_adx()      { return (_features & CPU_ADX) != 0; }
   714   static bool supports_evex()     { return (_cpuFeatures & CPU_AVX512F) != 0; }
   712   static bool supports_evex()     { return (_features & CPU_AVX512F) != 0; }
   715   static bool supports_avx512dq() { return (_cpuFeatures & CPU_AVX512DQ) != 0; }
   713   static bool supports_avx512dq() { return (_features & CPU_AVX512DQ) != 0; }
   716   static bool supports_avx512pf() { return (_cpuFeatures & CPU_AVX512PF) != 0; }
   714   static bool supports_avx512pf() { return (_features & CPU_AVX512PF) != 0; }
   717   static bool supports_avx512er() { return (_cpuFeatures & CPU_AVX512ER) != 0; }
   715   static bool supports_avx512er() { return (_features & CPU_AVX512ER) != 0; }
   718   static bool supports_avx512cd() { return (_cpuFeatures & CPU_AVX512CD) != 0; }
   716   static bool supports_avx512cd() { return (_features & CPU_AVX512CD) != 0; }
   719   static bool supports_avx512bw() { return (_cpuFeatures & CPU_AVX512BW) != 0; }
   717   static bool supports_avx512bw() { return (_features & CPU_AVX512BW) != 0; }
   720   static bool supports_avx512vl() { return (_cpuFeatures & CPU_AVX512VL) != 0; }
   718   static bool supports_avx512vl() { return (_features & CPU_AVX512VL) != 0; }
   721   static bool supports_avx512vlbw() { return (supports_avx512bw() && supports_avx512vl()); }
   719   static bool supports_avx512vlbw() { return (supports_avx512bw() && supports_avx512vl()); }
   722   static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); }
   720   static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); }
   723   static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); }
   721   static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); }
   724   static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); }
   722   static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); }
   725   static bool supports_avxonly()    { return ((supports_avx2() || supports_avx()) && !supports_evex()); }
   723   static bool supports_avxonly()    { return ((supports_avx2() || supports_avx()) && !supports_evex()); }
   744     }
   742     }
   745     return false;
   743     return false;
   746   }
   744   }
   747 
   745 
   748   // AMD features
   746   // AMD features
   749   static bool supports_3dnow_prefetch()    { return (_cpuFeatures & CPU_3DNOW_PREFETCH) != 0; }
   747   static bool supports_3dnow_prefetch()    { return (_features & CPU_3DNOW_PREFETCH) != 0; }
   750   static bool supports_mmx_ext()  { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; }
   748   static bool supports_mmx_ext()  { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; }
   751   static bool supports_lzcnt()    { return (_cpuFeatures & CPU_LZCNT) != 0; }
   749   static bool supports_lzcnt()    { return (_features & CPU_LZCNT) != 0; }
   752   static bool supports_sse4a()    { return (_cpuFeatures & CPU_SSE4A) != 0; }
   750   static bool supports_sse4a()    { return (_features & CPU_SSE4A) != 0; }
   753 
   751 
   754   static bool is_amd_Barcelona()  { return is_amd() &&
   752   static bool is_amd_Barcelona()  { return is_amd() &&
   755                                            extended_cpu_family() == CPU_FAMILY_AMD_11H; }
   753                                            extended_cpu_family() == CPU_FAMILY_AMD_11H; }
   756 
   754 
   757   // Intel and AMD newer cores support fast timestamps well
   755   // Intel and AMD newer cores support fast timestamps well
   758   static bool supports_tscinv_bit() {
   756   static bool supports_tscinv_bit() {
   759     return (_cpuFeatures & CPU_TSCINV) != 0;
   757     return (_features & CPU_TSCINV) != 0;
   760   }
   758   }
   761   static bool supports_tscinv() {
   759   static bool supports_tscinv() {
   762     return supports_tscinv_bit() &&
   760     return supports_tscinv_bit() &&
   763            ( (is_amd() && !is_amd_Barcelona()) ||
   761            ( (is_amd() && !is_amd_Barcelona()) ||
   764              is_intel_tsc_synched_at_init() );
   762              is_intel_tsc_synched_at_init() );
   767   // Intel Core and newer cpus have fast IDIV instruction (excluding Atom).
   765   // Intel Core and newer cpus have fast IDIV instruction (excluding Atom).
   768   static bool has_fast_idiv()     { return is_intel() && cpu_family() == 6 &&
   766   static bool has_fast_idiv()     { return is_intel() && cpu_family() == 6 &&
   769                                            supports_sse3() && _model != 0x1C; }
   767                                            supports_sse3() && _model != 0x1C; }
   770 
   768 
   771   static bool supports_compare_and_exchange() { return true; }
   769   static bool supports_compare_and_exchange() { return true; }
   772 
       
   773   static const char* cpu_features()           { return _features_str; }
       
   774 
   770 
   775   static intx allocate_prefetch_distance() {
   771   static intx allocate_prefetch_distance() {
   776     // This method should be called before allocate_prefetch_style().
   772     // This method should be called before allocate_prefetch_style().
   777     //
   773     //
   778     // Hardware prefetching (distance/size in bytes):
   774     // Hardware prefetching (distance/size in bytes):