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; }