Sat, 07 Nov 2020 10:30:02 +0800
Added tag mips-jdk8u275-b01 for changeset d3b4d62f391f
apetushkov@9858 | 1 | /* |
apetushkov@9858 | 2 | * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. |
apetushkov@9858 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
apetushkov@9858 | 4 | * |
apetushkov@9858 | 5 | * This code is free software; you can redistribute it and/or modify it |
apetushkov@9858 | 6 | * under the terms of the GNU General Public License version 2 only, as |
apetushkov@9858 | 7 | * published by the Free Software Foundation. |
apetushkov@9858 | 8 | * |
apetushkov@9858 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
apetushkov@9858 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
apetushkov@9858 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
apetushkov@9858 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
apetushkov@9858 | 13 | * accompanied this code). |
apetushkov@9858 | 14 | * |
apetushkov@9858 | 15 | * You should have received a copy of the GNU General Public License version |
apetushkov@9858 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
apetushkov@9858 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
apetushkov@9858 | 18 | * |
apetushkov@9858 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
apetushkov@9858 | 20 | * or visit www.oracle.com if you need additional information or have any |
apetushkov@9858 | 21 | * questions. |
apetushkov@9858 | 22 | * |
apetushkov@9858 | 23 | */ |
apetushkov@9858 | 24 | |
apetushkov@9858 | 25 | #include "precompiled.hpp" |
apetushkov@9858 | 26 | #include "jvm.h" |
apetushkov@9858 | 27 | #include "utilities/macros.hpp" |
apetushkov@9858 | 28 | #include "asm/macroAssembler.hpp" |
apetushkov@9858 | 29 | #include "asm/macroAssembler.inline.hpp" |
apetushkov@9858 | 30 | #include "memory/allocation.inline.hpp" |
apetushkov@9858 | 31 | #include "memory/resourceArea.hpp" |
apetushkov@9858 | 32 | #include "runtime/java.hpp" |
apetushkov@9858 | 33 | #include "runtime/stubCodeGenerator.hpp" |
apetushkov@9858 | 34 | #include "vm_version_ext_x86.hpp" |
apetushkov@9858 | 35 | |
apetushkov@9858 | 36 | typedef enum { |
apetushkov@9858 | 37 | CPU_FAMILY_8086_8088 = 0, |
apetushkov@9858 | 38 | CPU_FAMILY_INTEL_286 = 2, |
apetushkov@9858 | 39 | CPU_FAMILY_INTEL_386 = 3, |
apetushkov@9858 | 40 | CPU_FAMILY_INTEL_486 = 4, |
apetushkov@9858 | 41 | CPU_FAMILY_PENTIUM = 5, |
apetushkov@9858 | 42 | CPU_FAMILY_PENTIUMPRO = 6, // Same family several models |
apetushkov@9858 | 43 | CPU_FAMILY_PENTIUM_4 = 0xF |
apetushkov@9858 | 44 | } FamilyFlag; |
apetushkov@9858 | 45 | |
apetushkov@9858 | 46 | typedef enum { |
apetushkov@9858 | 47 | RDTSCP_FLAG = 0x08000000, // bit 27 |
apetushkov@9858 | 48 | INTEL64_FLAG = 0x20000000 // bit 29 |
apetushkov@9858 | 49 | } _featureExtendedEdxFlag; |
apetushkov@9858 | 50 | |
apetushkov@9858 | 51 | #define CPUID_STANDARD_FN 0x0 |
apetushkov@9858 | 52 | #define CPUID_STANDARD_FN_1 0x1 |
apetushkov@9858 | 53 | #define CPUID_STANDARD_FN_4 0x4 |
apetushkov@9858 | 54 | #define CPUID_STANDARD_FN_B 0xb |
apetushkov@9858 | 55 | |
apetushkov@9858 | 56 | #define CPUID_EXTENDED_FN 0x80000000 |
apetushkov@9858 | 57 | #define CPUID_EXTENDED_FN_1 0x80000001 |
apetushkov@9858 | 58 | #define CPUID_EXTENDED_FN_2 0x80000002 |
apetushkov@9858 | 59 | #define CPUID_EXTENDED_FN_3 0x80000003 |
apetushkov@9858 | 60 | #define CPUID_EXTENDED_FN_4 0x80000004 |
apetushkov@9858 | 61 | #define CPUID_EXTENDED_FN_7 0x80000007 |
apetushkov@9858 | 62 | #define CPUID_EXTENDED_FN_8 0x80000008 |
apetushkov@9858 | 63 | |
apetushkov@9858 | 64 | typedef enum { |
apetushkov@9858 | 65 | FPU_FLAG = 0x00000001, |
apetushkov@9858 | 66 | VME_FLAG = 0x00000002, |
apetushkov@9858 | 67 | DE_FLAG = 0x00000004, |
apetushkov@9858 | 68 | PSE_FLAG = 0x00000008, |
apetushkov@9858 | 69 | TSC_FLAG = 0x00000010, |
apetushkov@9858 | 70 | MSR_FLAG = 0x00000020, |
apetushkov@9858 | 71 | PAE_FLAG = 0x00000040, |
apetushkov@9858 | 72 | MCE_FLAG = 0x00000080, |
apetushkov@9858 | 73 | CX8_FLAG = 0x00000100, |
apetushkov@9858 | 74 | APIC_FLAG = 0x00000200, |
apetushkov@9858 | 75 | SEP_FLAG = 0x00000800, |
apetushkov@9858 | 76 | MTRR_FLAG = 0x00001000, |
apetushkov@9858 | 77 | PGE_FLAG = 0x00002000, |
apetushkov@9858 | 78 | MCA_FLAG = 0x00004000, |
apetushkov@9858 | 79 | CMOV_FLAG = 0x00008000, |
apetushkov@9858 | 80 | PAT_FLAG = 0x00010000, |
apetushkov@9858 | 81 | PSE36_FLAG = 0x00020000, |
apetushkov@9858 | 82 | PSNUM_FLAG = 0x00040000, |
apetushkov@9858 | 83 | CLFLUSH_FLAG = 0x00080000, |
apetushkov@9858 | 84 | DTS_FLAG = 0x00200000, |
apetushkov@9858 | 85 | ACPI_FLAG = 0x00400000, |
apetushkov@9858 | 86 | MMX_FLAG = 0x00800000, |
apetushkov@9858 | 87 | FXSR_FLAG = 0x01000000, |
apetushkov@9858 | 88 | SSE_FLAG = 0x02000000, |
apetushkov@9858 | 89 | SSE2_FLAG = 0x04000000, |
apetushkov@9858 | 90 | SS_FLAG = 0x08000000, |
apetushkov@9858 | 91 | HTT_FLAG = 0x10000000, |
apetushkov@9858 | 92 | TM_FLAG = 0x20000000 |
apetushkov@9858 | 93 | } FeatureEdxFlag; |
apetushkov@9858 | 94 | |
apetushkov@9858 | 95 | static BufferBlob* cpuid_brand_string_stub_blob; |
apetushkov@9858 | 96 | static const int cpuid_brand_string_stub_size = 550; |
apetushkov@9858 | 97 | |
apetushkov@9858 | 98 | extern "C" { |
apetushkov@9858 | 99 | typedef void (*getCPUIDBrandString_stub_t)(void*); |
apetushkov@9858 | 100 | } |
apetushkov@9858 | 101 | |
apetushkov@9858 | 102 | static getCPUIDBrandString_stub_t getCPUIDBrandString_stub = NULL; |
apetushkov@9858 | 103 | |
apetushkov@9858 | 104 | class VM_Version_Ext_StubGenerator: public StubCodeGenerator { |
apetushkov@9858 | 105 | public: |
apetushkov@9858 | 106 | |
apetushkov@9858 | 107 | VM_Version_Ext_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {} |
apetushkov@9858 | 108 | |
apetushkov@9858 | 109 | address generate_getCPUIDBrandString(void) { |
apetushkov@9858 | 110 | // Flags to test CPU type. |
apetushkov@9858 | 111 | const uint32_t HS_EFL_AC = 0x40000; |
apetushkov@9858 | 112 | const uint32_t HS_EFL_ID = 0x200000; |
apetushkov@9858 | 113 | // Values for when we don't have a CPUID instruction. |
apetushkov@9858 | 114 | const int CPU_FAMILY_SHIFT = 8; |
apetushkov@9858 | 115 | const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT); |
apetushkov@9858 | 116 | const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT); |
apetushkov@9858 | 117 | |
apetushkov@9858 | 118 | Label detect_486, cpu486, detect_586, done, ext_cpuid; |
apetushkov@9858 | 119 | |
apetushkov@9858 | 120 | StubCodeMark mark(this, "VM_Version_Ext", "getCPUIDNameInfo_stub"); |
apetushkov@9858 | 121 | # define __ _masm-> |
apetushkov@9858 | 122 | |
apetushkov@9858 | 123 | address start = __ pc(); |
apetushkov@9858 | 124 | |
apetushkov@9858 | 125 | // |
apetushkov@9858 | 126 | // void getCPUIDBrandString(VM_Version::CpuidInfo* cpuid_info); |
apetushkov@9858 | 127 | // |
apetushkov@9858 | 128 | // LP64: rcx and rdx are first and second argument registers on windows |
apetushkov@9858 | 129 | |
apetushkov@9858 | 130 | __ push(rbp); |
apetushkov@9858 | 131 | #ifdef _LP64 |
apetushkov@9858 | 132 | __ mov(rbp, c_rarg0); // cpuid_info address |
apetushkov@9858 | 133 | #else |
apetushkov@9858 | 134 | __ movptr(rbp, Address(rsp, 8)); // cpuid_info address |
apetushkov@9858 | 135 | #endif |
apetushkov@9858 | 136 | __ push(rbx); |
apetushkov@9858 | 137 | __ push(rsi); |
apetushkov@9858 | 138 | __ pushf(); // preserve rbx, and flags |
apetushkov@9858 | 139 | __ pop(rax); |
apetushkov@9858 | 140 | __ push(rax); |
apetushkov@9858 | 141 | __ mov(rcx, rax); |
apetushkov@9858 | 142 | // |
apetushkov@9858 | 143 | // if we are unable to change the AC flag, we have a 386 |
apetushkov@9858 | 144 | // |
apetushkov@9858 | 145 | __ xorl(rax, HS_EFL_AC); |
apetushkov@9858 | 146 | __ push(rax); |
apetushkov@9858 | 147 | __ popf(); |
apetushkov@9858 | 148 | __ pushf(); |
apetushkov@9858 | 149 | __ pop(rax); |
apetushkov@9858 | 150 | __ cmpptr(rax, rcx); |
apetushkov@9858 | 151 | __ jccb(Assembler::notEqual, detect_486); |
apetushkov@9858 | 152 | |
apetushkov@9858 | 153 | __ movl(rax, CPU_FAMILY_386); |
apetushkov@9858 | 154 | __ jmp(done); |
apetushkov@9858 | 155 | |
apetushkov@9858 | 156 | // |
apetushkov@9858 | 157 | // If we are unable to change the ID flag, we have a 486 which does |
apetushkov@9858 | 158 | // not support the "cpuid" instruction. |
apetushkov@9858 | 159 | // |
apetushkov@9858 | 160 | __ bind(detect_486); |
apetushkov@9858 | 161 | __ mov(rax, rcx); |
apetushkov@9858 | 162 | __ xorl(rax, HS_EFL_ID); |
apetushkov@9858 | 163 | __ push(rax); |
apetushkov@9858 | 164 | __ popf(); |
apetushkov@9858 | 165 | __ pushf(); |
apetushkov@9858 | 166 | __ pop(rax); |
apetushkov@9858 | 167 | __ cmpptr(rcx, rax); |
apetushkov@9858 | 168 | __ jccb(Assembler::notEqual, detect_586); |
apetushkov@9858 | 169 | |
apetushkov@9858 | 170 | __ bind(cpu486); |
apetushkov@9858 | 171 | __ movl(rax, CPU_FAMILY_486); |
apetushkov@9858 | 172 | __ jmp(done); |
apetushkov@9858 | 173 | |
apetushkov@9858 | 174 | // |
apetushkov@9858 | 175 | // At this point, we have a chip which supports the "cpuid" instruction |
apetushkov@9858 | 176 | // |
apetushkov@9858 | 177 | __ bind(detect_586); |
apetushkov@9858 | 178 | __ xorl(rax, rax); |
apetushkov@9858 | 179 | __ cpuid(); |
apetushkov@9858 | 180 | __ orl(rax, rax); |
apetushkov@9858 | 181 | __ jcc(Assembler::equal, cpu486); // if cpuid doesn't support an input |
apetushkov@9858 | 182 | // value of at least 1, we give up and |
apetushkov@9858 | 183 | // assume a 486 |
apetushkov@9858 | 184 | |
apetushkov@9858 | 185 | // |
apetushkov@9858 | 186 | // Extended cpuid(0x80000000) for processor brand string detection |
apetushkov@9858 | 187 | // |
apetushkov@9858 | 188 | __ bind(ext_cpuid); |
apetushkov@9858 | 189 | __ movl(rax, CPUID_EXTENDED_FN); |
apetushkov@9858 | 190 | __ cpuid(); |
apetushkov@9858 | 191 | __ cmpl(rax, CPUID_EXTENDED_FN_4); |
apetushkov@9858 | 192 | __ jcc(Assembler::below, done); |
apetushkov@9858 | 193 | |
apetushkov@9858 | 194 | // |
apetushkov@9858 | 195 | // Extended cpuid(0x80000002) // first 16 bytes in brand string |
apetushkov@9858 | 196 | // |
apetushkov@9858 | 197 | __ movl(rax, CPUID_EXTENDED_FN_2); |
apetushkov@9858 | 198 | __ cpuid(); |
apetushkov@9858 | 199 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_0_offset()))); |
apetushkov@9858 | 200 | __ movl(Address(rsi, 0), rax); |
apetushkov@9858 | 201 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_1_offset()))); |
apetushkov@9858 | 202 | __ movl(Address(rsi, 0), rbx); |
apetushkov@9858 | 203 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_2_offset()))); |
apetushkov@9858 | 204 | __ movl(Address(rsi, 0), rcx); |
apetushkov@9858 | 205 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_3_offset()))); |
apetushkov@9858 | 206 | __ movl(Address(rsi,0), rdx); |
apetushkov@9858 | 207 | |
apetushkov@9858 | 208 | // |
apetushkov@9858 | 209 | // Extended cpuid(0x80000003) // next 16 bytes in brand string |
apetushkov@9858 | 210 | // |
apetushkov@9858 | 211 | __ movl(rax, CPUID_EXTENDED_FN_3); |
apetushkov@9858 | 212 | __ cpuid(); |
apetushkov@9858 | 213 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_4_offset()))); |
apetushkov@9858 | 214 | __ movl(Address(rsi, 0), rax); |
apetushkov@9858 | 215 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_5_offset()))); |
apetushkov@9858 | 216 | __ movl(Address(rsi, 0), rbx); |
apetushkov@9858 | 217 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_6_offset()))); |
apetushkov@9858 | 218 | __ movl(Address(rsi, 0), rcx); |
apetushkov@9858 | 219 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_7_offset()))); |
apetushkov@9858 | 220 | __ movl(Address(rsi,0), rdx); |
apetushkov@9858 | 221 | |
apetushkov@9858 | 222 | // |
apetushkov@9858 | 223 | // Extended cpuid(0x80000004) // last 16 bytes in brand string |
apetushkov@9858 | 224 | // |
apetushkov@9858 | 225 | __ movl(rax, CPUID_EXTENDED_FN_4); |
apetushkov@9858 | 226 | __ cpuid(); |
apetushkov@9858 | 227 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_8_offset()))); |
apetushkov@9858 | 228 | __ movl(Address(rsi, 0), rax); |
apetushkov@9858 | 229 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_9_offset()))); |
apetushkov@9858 | 230 | __ movl(Address(rsi, 0), rbx); |
apetushkov@9858 | 231 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_10_offset()))); |
apetushkov@9858 | 232 | __ movl(Address(rsi, 0), rcx); |
apetushkov@9858 | 233 | __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_11_offset()))); |
apetushkov@9858 | 234 | __ movl(Address(rsi,0), rdx); |
apetushkov@9858 | 235 | |
apetushkov@9858 | 236 | // |
apetushkov@9858 | 237 | // return |
apetushkov@9858 | 238 | // |
apetushkov@9858 | 239 | __ bind(done); |
apetushkov@9858 | 240 | __ popf(); |
apetushkov@9858 | 241 | __ pop(rsi); |
apetushkov@9858 | 242 | __ pop(rbx); |
apetushkov@9858 | 243 | __ pop(rbp); |
apetushkov@9858 | 244 | __ ret(0); |
apetushkov@9858 | 245 | |
apetushkov@9858 | 246 | # undef __ |
apetushkov@9858 | 247 | |
apetushkov@9858 | 248 | return start; |
apetushkov@9858 | 249 | }; |
apetushkov@9858 | 250 | }; |
apetushkov@9858 | 251 | |
apetushkov@9858 | 252 | |
apetushkov@9858 | 253 | // VM_Version_Ext statics |
apetushkov@9858 | 254 | const size_t VM_Version_Ext::VENDOR_LENGTH = 13; |
apetushkov@9858 | 255 | const size_t VM_Version_Ext::CPU_EBS_MAX_LENGTH = (3 * 4 * 4 + 1); |
apetushkov@9858 | 256 | const size_t VM_Version_Ext::CPU_TYPE_DESC_BUF_SIZE = 256; |
apetushkov@9858 | 257 | const size_t VM_Version_Ext::CPU_DETAILED_DESC_BUF_SIZE = 4096; |
apetushkov@9858 | 258 | char* VM_Version_Ext::_cpu_brand_string = NULL; |
apetushkov@9858 | 259 | jlong VM_Version_Ext::_max_qualified_cpu_frequency = 0; |
apetushkov@9858 | 260 | |
apetushkov@9858 | 261 | int VM_Version_Ext::_no_of_threads = 0; |
apetushkov@9858 | 262 | int VM_Version_Ext::_no_of_cores = 0; |
apetushkov@9858 | 263 | int VM_Version_Ext::_no_of_packages = 0; |
apetushkov@9858 | 264 | |
apetushkov@9858 | 265 | void VM_Version_Ext::initialize(void) { |
apetushkov@9858 | 266 | ResourceMark rm; |
apetushkov@9858 | 267 | |
apetushkov@9858 | 268 | cpuid_brand_string_stub_blob = BufferBlob::create("getCPUIDBrandString_stub", cpuid_brand_string_stub_size); |
apetushkov@9858 | 269 | if (cpuid_brand_string_stub_blob == NULL) { |
apetushkov@9858 | 270 | vm_exit_during_initialization("Unable to allocate getCPUIDBrandString_stub"); |
apetushkov@9858 | 271 | } |
apetushkov@9858 | 272 | CodeBuffer c(cpuid_brand_string_stub_blob); |
apetushkov@9858 | 273 | VM_Version_Ext_StubGenerator g(&c); |
apetushkov@9858 | 274 | getCPUIDBrandString_stub = CAST_TO_FN_PTR(getCPUIDBrandString_stub_t, |
apetushkov@9858 | 275 | g.generate_getCPUIDBrandString()); |
apetushkov@9858 | 276 | } |
apetushkov@9858 | 277 | |
apetushkov@9858 | 278 | const char* VM_Version_Ext::cpu_model_description(void) { |
apetushkov@9858 | 279 | uint32_t cpu_family = extended_cpu_family(); |
apetushkov@9858 | 280 | uint32_t cpu_model = extended_cpu_model(); |
apetushkov@9858 | 281 | const char* model = NULL; |
apetushkov@9858 | 282 | |
apetushkov@9858 | 283 | if (cpu_family == CPU_FAMILY_PENTIUMPRO) { |
apetushkov@9858 | 284 | for (uint32_t i = 0; i <= cpu_model; i++) { |
apetushkov@9858 | 285 | model = _model_id_pentium_pro[i]; |
apetushkov@9858 | 286 | if (model == NULL) { |
apetushkov@9858 | 287 | break; |
apetushkov@9858 | 288 | } |
apetushkov@9858 | 289 | } |
apetushkov@9858 | 290 | } |
apetushkov@9858 | 291 | return model; |
apetushkov@9858 | 292 | } |
apetushkov@9858 | 293 | |
apetushkov@9858 | 294 | const char* VM_Version_Ext::cpu_brand_string(void) { |
apetushkov@9858 | 295 | if (_cpu_brand_string == NULL) { |
apetushkov@9858 | 296 | _cpu_brand_string = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_EBS_MAX_LENGTH, mtInternal); |
apetushkov@9858 | 297 | if (NULL == _cpu_brand_string) { |
apetushkov@9858 | 298 | return NULL; |
apetushkov@9858 | 299 | } |
apetushkov@9858 | 300 | int ret_val = cpu_extended_brand_string(_cpu_brand_string, CPU_EBS_MAX_LENGTH); |
apetushkov@9858 | 301 | if (ret_val != OS_OK) { |
apetushkov@9858 | 302 | FREE_C_HEAP_ARRAY(char, _cpu_brand_string, mtInternal); |
apetushkov@9858 | 303 | _cpu_brand_string = NULL; |
apetushkov@9858 | 304 | } |
apetushkov@9858 | 305 | } |
apetushkov@9858 | 306 | return _cpu_brand_string; |
apetushkov@9858 | 307 | } |
apetushkov@9858 | 308 | |
apetushkov@9858 | 309 | const char* VM_Version_Ext::cpu_brand(void) { |
apetushkov@9858 | 310 | const char* brand = NULL; |
apetushkov@9858 | 311 | |
apetushkov@9858 | 312 | if ((_cpuid_info.std_cpuid1_ebx.value & 0xFF) > 0) { |
apetushkov@9858 | 313 | int brand_num = _cpuid_info.std_cpuid1_ebx.value & 0xFF; |
apetushkov@9858 | 314 | brand = _brand_id[0]; |
apetushkov@9858 | 315 | for (int i = 0; brand != NULL && i <= brand_num; i += 1) { |
apetushkov@9858 | 316 | brand = _brand_id[i]; |
apetushkov@9858 | 317 | } |
apetushkov@9858 | 318 | } |
apetushkov@9858 | 319 | return brand; |
apetushkov@9858 | 320 | } |
apetushkov@9858 | 321 | |
apetushkov@9858 | 322 | bool VM_Version_Ext::cpu_is_em64t(void) { |
apetushkov@9858 | 323 | return ((_cpuid_info.ext_cpuid1_edx.value & INTEL64_FLAG) == INTEL64_FLAG); |
apetushkov@9858 | 324 | } |
apetushkov@9858 | 325 | |
apetushkov@9858 | 326 | bool VM_Version_Ext::is_netburst(void) { |
apetushkov@9858 | 327 | return (is_intel() && (extended_cpu_family() == CPU_FAMILY_PENTIUM_4)); |
apetushkov@9858 | 328 | } |
apetushkov@9858 | 329 | |
apetushkov@9858 | 330 | bool VM_Version_Ext::supports_tscinv_ext(void) { |
apetushkov@9858 | 331 | if (!supports_tscinv_bit()) { |
apetushkov@9858 | 332 | return false; |
apetushkov@9858 | 333 | } |
apetushkov@9858 | 334 | |
apetushkov@9858 | 335 | if (is_intel()) { |
apetushkov@9858 | 336 | return true; |
apetushkov@9858 | 337 | } |
apetushkov@9858 | 338 | |
apetushkov@9858 | 339 | if (is_amd()) { |
apetushkov@9858 | 340 | return !is_amd_Barcelona(); |
apetushkov@9858 | 341 | } |
apetushkov@9858 | 342 | |
apetushkov@9858 | 343 | return false; |
apetushkov@9858 | 344 | } |
apetushkov@9858 | 345 | |
apetushkov@9858 | 346 | void VM_Version_Ext::resolve_cpu_information_details(void) { |
apetushkov@9858 | 347 | |
apetushkov@9858 | 348 | // in future we want to base this information on proper cpu |
apetushkov@9858 | 349 | // and cache topology enumeration such as: |
apetushkov@9858 | 350 | // Intel 64 Architecture Processor Topology Enumeration |
apetushkov@9858 | 351 | // which supports system cpu and cache topology enumeration |
apetushkov@9858 | 352 | // either using 2xAPICIDs or initial APICIDs |
apetushkov@9858 | 353 | |
apetushkov@9858 | 354 | // currently only rough cpu information estimates |
apetushkov@9858 | 355 | // which will not necessarily reflect the exact configuration of the system |
apetushkov@9858 | 356 | |
apetushkov@9858 | 357 | // this is the number of logical hardware threads |
apetushkov@9858 | 358 | // visible to the operating system |
apetushkov@9858 | 359 | _no_of_threads = os::processor_count(); |
apetushkov@9858 | 360 | |
apetushkov@9858 | 361 | // find out number of threads per cpu package |
apetushkov@9858 | 362 | int threads_per_package = threads_per_core() * cores_per_cpu(); |
apetushkov@9858 | 363 | |
apetushkov@9858 | 364 | // use amount of threads visible to the process in order to guess number of sockets |
apetushkov@9858 | 365 | _no_of_packages = _no_of_threads / threads_per_package; |
apetushkov@9858 | 366 | |
apetushkov@9858 | 367 | // process might only see a subset of the total number of threads |
apetushkov@9858 | 368 | // from a single processor package. Virtualization/resource management for example. |
apetushkov@9858 | 369 | // If so then just write a hard 1 as num of pkgs. |
apetushkov@9858 | 370 | if (0 == _no_of_packages) { |
apetushkov@9858 | 371 | _no_of_packages = 1; |
apetushkov@9858 | 372 | } |
apetushkov@9858 | 373 | |
apetushkov@9858 | 374 | // estimate the number of cores |
apetushkov@9858 | 375 | _no_of_cores = cores_per_cpu() * _no_of_packages; |
apetushkov@9858 | 376 | } |
apetushkov@9858 | 377 | |
apetushkov@9858 | 378 | int VM_Version_Ext::number_of_threads(void) { |
apetushkov@9858 | 379 | if (_no_of_threads == 0) { |
apetushkov@9858 | 380 | resolve_cpu_information_details(); |
apetushkov@9858 | 381 | } |
apetushkov@9858 | 382 | return _no_of_threads; |
apetushkov@9858 | 383 | } |
apetushkov@9858 | 384 | |
apetushkov@9858 | 385 | int VM_Version_Ext::number_of_cores(void) { |
apetushkov@9858 | 386 | if (_no_of_cores == 0) { |
apetushkov@9858 | 387 | resolve_cpu_information_details(); |
apetushkov@9858 | 388 | } |
apetushkov@9858 | 389 | return _no_of_cores; |
apetushkov@9858 | 390 | } |
apetushkov@9858 | 391 | |
apetushkov@9858 | 392 | int VM_Version_Ext::number_of_sockets(void) { |
apetushkov@9858 | 393 | if (_no_of_packages == 0) { |
apetushkov@9858 | 394 | resolve_cpu_information_details(); |
apetushkov@9858 | 395 | } |
apetushkov@9858 | 396 | return _no_of_packages; |
apetushkov@9858 | 397 | } |
apetushkov@9858 | 398 | |
apetushkov@9858 | 399 | const char* VM_Version_Ext::cpu_family_description(void) { |
apetushkov@9858 | 400 | int cpu_family_id = extended_cpu_family(); |
apetushkov@9858 | 401 | if (is_amd()) { |
apetushkov@9858 | 402 | return _family_id_amd[cpu_family_id]; |
apetushkov@9858 | 403 | } |
apetushkov@9858 | 404 | if (is_intel()) { |
apetushkov@9858 | 405 | if (cpu_family_id == CPU_FAMILY_PENTIUMPRO) { |
apetushkov@9858 | 406 | return cpu_model_description(); |
apetushkov@9858 | 407 | } |
apetushkov@9858 | 408 | return _family_id_intel[cpu_family_id]; |
apetushkov@9858 | 409 | } |
apetushkov@9858 | 410 | return "Unknown x86"; |
apetushkov@9858 | 411 | } |
apetushkov@9858 | 412 | |
apetushkov@9858 | 413 | int VM_Version_Ext::cpu_type_description(char* const buf, size_t buf_len) { |
apetushkov@9858 | 414 | assert(buf != NULL, "buffer is NULL!"); |
apetushkov@9858 | 415 | assert(buf_len >= CPU_TYPE_DESC_BUF_SIZE, "buffer len should at least be == CPU_TYPE_DESC_BUF_SIZE!"); |
apetushkov@9858 | 416 | |
apetushkov@9858 | 417 | const char* cpu_type = NULL; |
apetushkov@9858 | 418 | const char* x64 = NULL; |
apetushkov@9858 | 419 | |
apetushkov@9858 | 420 | if (is_intel()) { |
apetushkov@9858 | 421 | cpu_type = "Intel"; |
apetushkov@9858 | 422 | x64 = cpu_is_em64t() ? " Intel64" : ""; |
apetushkov@9858 | 423 | } else if (is_amd()) { |
apetushkov@9858 | 424 | cpu_type = "AMD"; |
apetushkov@9858 | 425 | x64 = cpu_is_em64t() ? " AMD64" : ""; |
apetushkov@9858 | 426 | } else { |
apetushkov@9858 | 427 | cpu_type = "Unknown x86"; |
apetushkov@9858 | 428 | x64 = cpu_is_em64t() ? " x86_64" : ""; |
apetushkov@9858 | 429 | } |
apetushkov@9858 | 430 | |
apetushkov@9858 | 431 | jio_snprintf(buf, buf_len, "%s %s%s SSE SSE2%s%s%s%s%s%s%s%s", |
apetushkov@9858 | 432 | cpu_type, |
apetushkov@9858 | 433 | cpu_family_description(), |
apetushkov@9858 | 434 | supports_ht() ? " (HT)" : "", |
apetushkov@9858 | 435 | supports_sse3() ? " SSE3" : "", |
apetushkov@9858 | 436 | supports_ssse3() ? " SSSE3" : "", |
apetushkov@9858 | 437 | supports_sse4_1() ? " SSE4.1" : "", |
apetushkov@9858 | 438 | supports_sse4_2() ? " SSE4.2" : "", |
apetushkov@9858 | 439 | supports_sse4a() ? " SSE4A" : "", |
apetushkov@9858 | 440 | is_netburst() ? " Netburst" : "", |
apetushkov@9858 | 441 | is_intel_family_core() ? " Core" : "", |
apetushkov@9858 | 442 | x64); |
apetushkov@9858 | 443 | |
apetushkov@9858 | 444 | return OS_OK; |
apetushkov@9858 | 445 | } |
apetushkov@9858 | 446 | |
apetushkov@9858 | 447 | int VM_Version_Ext::cpu_extended_brand_string(char* const buf, size_t buf_len) { |
apetushkov@9858 | 448 | assert(buf != NULL, "buffer is NULL!"); |
apetushkov@9858 | 449 | assert(buf_len >= CPU_EBS_MAX_LENGTH, "buffer len should at least be == CPU_EBS_MAX_LENGTH!"); |
apetushkov@9858 | 450 | assert(getCPUIDBrandString_stub != NULL, "not initialized"); |
apetushkov@9858 | 451 | |
apetushkov@9858 | 452 | // invoke newly generated asm code to fetch CPU Brand String |
apetushkov@9858 | 453 | getCPUIDBrandString_stub(&_cpuid_info); |
apetushkov@9858 | 454 | |
apetushkov@9858 | 455 | // fetch results into buffer |
apetushkov@9858 | 456 | *((uint32_t*) &buf[0]) = _cpuid_info.proc_name_0; |
apetushkov@9858 | 457 | *((uint32_t*) &buf[4]) = _cpuid_info.proc_name_1; |
apetushkov@9858 | 458 | *((uint32_t*) &buf[8]) = _cpuid_info.proc_name_2; |
apetushkov@9858 | 459 | *((uint32_t*) &buf[12]) = _cpuid_info.proc_name_3; |
apetushkov@9858 | 460 | *((uint32_t*) &buf[16]) = _cpuid_info.proc_name_4; |
apetushkov@9858 | 461 | *((uint32_t*) &buf[20]) = _cpuid_info.proc_name_5; |
apetushkov@9858 | 462 | *((uint32_t*) &buf[24]) = _cpuid_info.proc_name_6; |
apetushkov@9858 | 463 | *((uint32_t*) &buf[28]) = _cpuid_info.proc_name_7; |
apetushkov@9858 | 464 | *((uint32_t*) &buf[32]) = _cpuid_info.proc_name_8; |
apetushkov@9858 | 465 | *((uint32_t*) &buf[36]) = _cpuid_info.proc_name_9; |
apetushkov@9858 | 466 | *((uint32_t*) &buf[40]) = _cpuid_info.proc_name_10; |
apetushkov@9858 | 467 | *((uint32_t*) &buf[44]) = _cpuid_info.proc_name_11; |
apetushkov@9858 | 468 | |
apetushkov@9858 | 469 | return OS_OK; |
apetushkov@9858 | 470 | } |
apetushkov@9858 | 471 | |
apetushkov@9858 | 472 | size_t VM_Version_Ext::cpu_write_support_string(char* const buf, size_t buf_len) { |
apetushkov@9858 | 473 | guarantee(buf != NULL, "buffer is NULL!"); |
apetushkov@9858 | 474 | guarantee(buf_len > 0, "buffer len not enough!"); |
apetushkov@9858 | 475 | |
apetushkov@9858 | 476 | unsigned int flag = 0; |
apetushkov@9858 | 477 | unsigned int fi = 0; |
apetushkov@9858 | 478 | size_t written = 0; |
apetushkov@9858 | 479 | const char* prefix = ""; |
apetushkov@9858 | 480 | |
apetushkov@9858 | 481 | #define WRITE_TO_BUF(string) \ |
apetushkov@9858 | 482 | { \ |
apetushkov@9858 | 483 | int res = jio_snprintf(&buf[written], buf_len - written, "%s%s", prefix, string); \ |
apetushkov@9858 | 484 | if (res < 0) { \ |
apetushkov@9858 | 485 | return buf_len - 1; \ |
apetushkov@9858 | 486 | } \ |
apetushkov@9858 | 487 | written += res; \ |
apetushkov@9858 | 488 | if (prefix[0] == '\0') { \ |
apetushkov@9858 | 489 | prefix = ", "; \ |
apetushkov@9858 | 490 | } \ |
apetushkov@9858 | 491 | } |
apetushkov@9858 | 492 | |
apetushkov@9858 | 493 | for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) { |
apetushkov@9858 | 494 | if (flag == HTT_FLAG && (((_cpuid_info.std_cpuid1_ebx.value >> 16) & 0xff) <= 1)) { |
apetushkov@9858 | 495 | continue; /* no hyperthreading */ |
apetushkov@9858 | 496 | } else if (flag == SEP_FLAG && (cpu_family() == CPU_FAMILY_PENTIUMPRO && ((_cpuid_info.std_cpuid1_eax.value & 0xff) < 0x33))) { |
apetushkov@9858 | 497 | continue; /* no fast system call */ |
apetushkov@9858 | 498 | } |
apetushkov@9858 | 499 | if ((_cpuid_info.std_cpuid1_edx.value & flag) && strlen(_feature_edx_id[fi]) > 0) { |
apetushkov@9858 | 500 | WRITE_TO_BUF(_feature_edx_id[fi]); |
apetushkov@9858 | 501 | } |
apetushkov@9858 | 502 | } |
apetushkov@9858 | 503 | |
apetushkov@9858 | 504 | for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) { |
apetushkov@9858 | 505 | if ((_cpuid_info.std_cpuid1_ecx.value & flag) && strlen(_feature_ecx_id[fi]) > 0) { |
apetushkov@9858 | 506 | WRITE_TO_BUF(_feature_ecx_id[fi]); |
apetushkov@9858 | 507 | } |
apetushkov@9858 | 508 | } |
apetushkov@9858 | 509 | |
apetushkov@9858 | 510 | for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) { |
apetushkov@9858 | 511 | if ((_cpuid_info.ext_cpuid1_ecx.value & flag) && strlen(_feature_extended_ecx_id[fi]) > 0) { |
apetushkov@9858 | 512 | WRITE_TO_BUF(_feature_extended_ecx_id[fi]); |
apetushkov@9858 | 513 | } |
apetushkov@9858 | 514 | } |
apetushkov@9858 | 515 | |
apetushkov@9858 | 516 | for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) { |
apetushkov@9858 | 517 | if ((_cpuid_info.ext_cpuid1_edx.value & flag) && strlen(_feature_extended_edx_id[fi]) > 0) { |
apetushkov@9858 | 518 | WRITE_TO_BUF(_feature_extended_edx_id[fi]); |
apetushkov@9858 | 519 | } |
apetushkov@9858 | 520 | } |
apetushkov@9858 | 521 | |
apetushkov@9858 | 522 | if (supports_tscinv_bit()) { |
apetushkov@9858 | 523 | WRITE_TO_BUF("Invariant TSC"); |
apetushkov@9858 | 524 | } |
apetushkov@9858 | 525 | |
apetushkov@9858 | 526 | return written; |
apetushkov@9858 | 527 | } |
apetushkov@9858 | 528 | |
apetushkov@9858 | 529 | /** |
apetushkov@9858 | 530 | * Write a detailed description of the cpu to a given buffer, including |
apetushkov@9858 | 531 | * feature set. |
apetushkov@9858 | 532 | */ |
apetushkov@9858 | 533 | int VM_Version_Ext::cpu_detailed_description(char* const buf, size_t buf_len) { |
apetushkov@9858 | 534 | assert(buf != NULL, "buffer is NULL!"); |
apetushkov@9858 | 535 | assert(buf_len >= CPU_DETAILED_DESC_BUF_SIZE, "buffer len should at least be == CPU_DETAILED_DESC_BUF_SIZE!"); |
apetushkov@9858 | 536 | |
apetushkov@9858 | 537 | static const char* unknown = "<unknown>"; |
apetushkov@9858 | 538 | char vendor_id[VENDOR_LENGTH]; |
apetushkov@9858 | 539 | const char* family = NULL; |
apetushkov@9858 | 540 | const char* model = NULL; |
apetushkov@9858 | 541 | const char* brand = NULL; |
apetushkov@9858 | 542 | int outputLen = 0; |
apetushkov@9858 | 543 | |
apetushkov@9858 | 544 | family = cpu_family_description(); |
apetushkov@9858 | 545 | if (family == NULL) { |
apetushkov@9858 | 546 | family = unknown; |
apetushkov@9858 | 547 | } |
apetushkov@9858 | 548 | |
apetushkov@9858 | 549 | model = cpu_model_description(); |
apetushkov@9858 | 550 | if (model == NULL) { |
apetushkov@9858 | 551 | model = unknown; |
apetushkov@9858 | 552 | } |
apetushkov@9858 | 553 | |
apetushkov@9858 | 554 | brand = cpu_brand_string(); |
apetushkov@9858 | 555 | |
apetushkov@9858 | 556 | if (brand == NULL) { |
apetushkov@9858 | 557 | brand = cpu_brand(); |
apetushkov@9858 | 558 | if (brand == NULL) { |
apetushkov@9858 | 559 | brand = unknown; |
apetushkov@9858 | 560 | } |
apetushkov@9858 | 561 | } |
apetushkov@9858 | 562 | |
apetushkov@9858 | 563 | *((uint32_t*) &vendor_id[0]) = _cpuid_info.std_vendor_name_0; |
apetushkov@9858 | 564 | *((uint32_t*) &vendor_id[4]) = _cpuid_info.std_vendor_name_2; |
apetushkov@9858 | 565 | *((uint32_t*) &vendor_id[8]) = _cpuid_info.std_vendor_name_1; |
apetushkov@9858 | 566 | vendor_id[VENDOR_LENGTH-1] = '\0'; |
apetushkov@9858 | 567 | |
apetushkov@9858 | 568 | outputLen = jio_snprintf(buf, buf_len, "Brand: %s, Vendor: %s\n" |
apetushkov@9858 | 569 | "Family: %s (0x%x), Model: %s (0x%x), Stepping: 0x%x\n" |
apetushkov@9858 | 570 | "Ext. family: 0x%x, Ext. model: 0x%x, Type: 0x%x, Signature: 0x%8.8x\n" |
apetushkov@9858 | 571 | "Features: ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n" |
apetushkov@9858 | 572 | "Ext. features: eax: 0x%8.8x, ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n" |
apetushkov@9858 | 573 | "Supports: ", |
apetushkov@9858 | 574 | brand, |
apetushkov@9858 | 575 | vendor_id, |
apetushkov@9858 | 576 | family, |
apetushkov@9858 | 577 | extended_cpu_family(), |
apetushkov@9858 | 578 | model, |
apetushkov@9858 | 579 | extended_cpu_model(), |
apetushkov@9858 | 580 | cpu_stepping(), |
apetushkov@9858 | 581 | _cpuid_info.std_cpuid1_eax.bits.ext_family, |
apetushkov@9858 | 582 | _cpuid_info.std_cpuid1_eax.bits.ext_model, |
apetushkov@9858 | 583 | _cpuid_info.std_cpuid1_eax.bits.proc_type, |
apetushkov@9858 | 584 | _cpuid_info.std_cpuid1_eax.value, |
apetushkov@9858 | 585 | _cpuid_info.std_cpuid1_ebx.value, |
apetushkov@9858 | 586 | _cpuid_info.std_cpuid1_ecx.value, |
apetushkov@9858 | 587 | _cpuid_info.std_cpuid1_edx.value, |
apetushkov@9858 | 588 | _cpuid_info.ext_cpuid1_eax, |
apetushkov@9858 | 589 | _cpuid_info.ext_cpuid1_ebx, |
apetushkov@9858 | 590 | _cpuid_info.ext_cpuid1_ecx, |
apetushkov@9858 | 591 | _cpuid_info.ext_cpuid1_edx); |
apetushkov@9858 | 592 | |
apetushkov@9858 | 593 | if (outputLen < 0 || (size_t) outputLen >= buf_len - 1) { |
apetushkov@9858 | 594 | if (buf_len > 0) { buf[buf_len-1] = '\0'; } |
apetushkov@9858 | 595 | return OS_ERR; |
apetushkov@9858 | 596 | } |
apetushkov@9858 | 597 | |
apetushkov@9858 | 598 | cpu_write_support_string(&buf[outputLen], buf_len - outputLen); |
apetushkov@9858 | 599 | |
apetushkov@9858 | 600 | return OS_OK; |
apetushkov@9858 | 601 | } |
apetushkov@9858 | 602 | |
apetushkov@9858 | 603 | const char* VM_Version_Ext::cpu_name(void) { |
apetushkov@9858 | 604 | char cpu_type_desc[CPU_TYPE_DESC_BUF_SIZE]; |
apetushkov@9858 | 605 | size_t cpu_desc_len = sizeof(cpu_type_desc); |
apetushkov@9858 | 606 | |
apetushkov@9858 | 607 | cpu_type_description(cpu_type_desc, cpu_desc_len); |
apetushkov@9858 | 608 | char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_desc_len, mtTracing); |
apetushkov@9858 | 609 | if (NULL == tmp) { |
apetushkov@9858 | 610 | return NULL; |
apetushkov@9858 | 611 | } |
apetushkov@9858 | 612 | strncpy(tmp, cpu_type_desc, cpu_desc_len); |
apetushkov@9858 | 613 | return tmp; |
apetushkov@9858 | 614 | } |
apetushkov@9858 | 615 | |
apetushkov@9858 | 616 | const char* VM_Version_Ext::cpu_description(void) { |
apetushkov@9858 | 617 | char cpu_detailed_desc_buffer[CPU_DETAILED_DESC_BUF_SIZE]; |
apetushkov@9858 | 618 | size_t cpu_detailed_desc_len = sizeof(cpu_detailed_desc_buffer); |
apetushkov@9858 | 619 | |
apetushkov@9858 | 620 | cpu_detailed_description(cpu_detailed_desc_buffer, cpu_detailed_desc_len); |
apetushkov@9858 | 621 | |
apetushkov@9858 | 622 | char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_detailed_desc_len, mtTracing); |
apetushkov@9858 | 623 | |
apetushkov@9858 | 624 | if (NULL == tmp) { |
apetushkov@9858 | 625 | return NULL; |
apetushkov@9858 | 626 | } |
apetushkov@9858 | 627 | |
apetushkov@9858 | 628 | strncpy(tmp, cpu_detailed_desc_buffer, cpu_detailed_desc_len); |
apetushkov@9858 | 629 | return tmp; |
apetushkov@9858 | 630 | } |
apetushkov@9858 | 631 | |
apetushkov@9858 | 632 | /** |
apetushkov@9858 | 633 | * See Intel Application note 485 (chapter 10) for details |
apetushkov@9858 | 634 | * on frequency extraction from cpu brand string. |
apetushkov@9858 | 635 | * http://www.intel.com/content/dam/www/public/us/en/documents/application-notes/processor-identification-cpuid-instruction-note.pdf |
apetushkov@9858 | 636 | * |
apetushkov@9858 | 637 | */ |
apetushkov@9858 | 638 | jlong VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) { |
apetushkov@9858 | 639 | // get brand string |
apetushkov@9858 | 640 | const char* const brand_string = cpu_brand_string(); |
apetushkov@9858 | 641 | if (brand_string == NULL) { |
apetushkov@9858 | 642 | return 0; |
apetushkov@9858 | 643 | } |
apetushkov@9858 | 644 | |
apetushkov@9858 | 645 | const u8 MEGA = 1000000; |
apetushkov@9858 | 646 | u8 multiplier = 0; |
apetushkov@9858 | 647 | jlong frequency = 0; |
apetushkov@9858 | 648 | |
apetushkov@9858 | 649 | // the frequency information in the cpu brand string |
apetushkov@9858 | 650 | // is given in either of two formats "x.xxyHz" or "xxxxyHz", |
apetushkov@9858 | 651 | // where y=M,G,T and x is digits |
apetushkov@9858 | 652 | const char* Hz_location = strchr(brand_string, 'H'); |
apetushkov@9858 | 653 | |
apetushkov@9858 | 654 | if (Hz_location != NULL) { |
apetushkov@9858 | 655 | if (*(Hz_location + 1) == 'z') { |
apetushkov@9858 | 656 | // switch on y in "yHz" |
apetushkov@9858 | 657 | switch(*(Hz_location - 1)) { |
apetushkov@9858 | 658 | case 'M' : |
apetushkov@9858 | 659 | // Set multiplier to frequency is in Hz |
apetushkov@9858 | 660 | multiplier = MEGA; |
apetushkov@9858 | 661 | break; |
apetushkov@9858 | 662 | case 'G' : |
apetushkov@9858 | 663 | multiplier = MEGA * 1000; |
apetushkov@9858 | 664 | break; |
apetushkov@9858 | 665 | case 'T' : |
apetushkov@9858 | 666 | multiplier = MEGA * 1000 * 1000; |
apetushkov@9858 | 667 | break; |
apetushkov@9858 | 668 | } |
apetushkov@9858 | 669 | } |
apetushkov@9858 | 670 | } |
apetushkov@9858 | 671 | |
apetushkov@9858 | 672 | if (multiplier > 0) { |
apetushkov@9858 | 673 | // compute frequency (in Hz) from brand string |
apetushkov@9858 | 674 | if (*(Hz_location - 4) == '.') { // if format is "x.xx" |
apetushkov@9858 | 675 | frequency = (jlong)(*(Hz_location - 5) - '0') * (multiplier); |
apetushkov@9858 | 676 | frequency += (jlong)(*(Hz_location - 3) - '0') * (multiplier / 10); |
apetushkov@9858 | 677 | frequency += (jlong)(*(Hz_location - 2) - '0') * (multiplier / 100); |
apetushkov@9858 | 678 | } else { // format is "xxxx" |
apetushkov@9858 | 679 | frequency = (jlong)(*(Hz_location - 5) - '0') * 1000; |
apetushkov@9858 | 680 | frequency += (jlong)(*(Hz_location - 4) - '0') * 100; |
apetushkov@9858 | 681 | frequency += (jlong)(*(Hz_location - 3) - '0') * 10; |
apetushkov@9858 | 682 | frequency += (jlong)(*(Hz_location - 2) - '0'); |
apetushkov@9858 | 683 | frequency *= multiplier; |
apetushkov@9858 | 684 | } |
apetushkov@9858 | 685 | } |
apetushkov@9858 | 686 | return frequency; |
apetushkov@9858 | 687 | } |
apetushkov@9858 | 688 | |
apetushkov@9858 | 689 | |
apetushkov@9858 | 690 | jlong VM_Version_Ext::maximum_qualified_cpu_frequency(void) { |
apetushkov@9858 | 691 | if (_max_qualified_cpu_frequency == 0) { |
apetushkov@9858 | 692 | _max_qualified_cpu_frequency = max_qualified_cpu_freq_from_brand_string(); |
apetushkov@9858 | 693 | } |
apetushkov@9858 | 694 | return _max_qualified_cpu_frequency; |
apetushkov@9858 | 695 | } |
apetushkov@9858 | 696 | |
apetushkov@9858 | 697 | const char* const VM_Version_Ext::_family_id_intel[] = { |
apetushkov@9858 | 698 | "8086/8088", |
apetushkov@9858 | 699 | "", |
apetushkov@9858 | 700 | "286", |
apetushkov@9858 | 701 | "386", |
apetushkov@9858 | 702 | "486", |
apetushkov@9858 | 703 | "Pentium", |
apetushkov@9858 | 704 | "Pentium Pro", //or Pentium-M/Woodcrest depeding on model |
apetushkov@9858 | 705 | "", |
apetushkov@9858 | 706 | "", |
apetushkov@9858 | 707 | "", |
apetushkov@9858 | 708 | "", |
apetushkov@9858 | 709 | "", |
apetushkov@9858 | 710 | "", |
apetushkov@9858 | 711 | "", |
apetushkov@9858 | 712 | "", |
apetushkov@9858 | 713 | "Pentium 4" |
apetushkov@9858 | 714 | }; |
apetushkov@9858 | 715 | |
apetushkov@9858 | 716 | const char* const VM_Version_Ext::_family_id_amd[] = { |
apetushkov@9858 | 717 | "", |
apetushkov@9858 | 718 | "", |
apetushkov@9858 | 719 | "", |
apetushkov@9858 | 720 | "", |
apetushkov@9858 | 721 | "5x86", |
apetushkov@9858 | 722 | "K5/K6", |
apetushkov@9858 | 723 | "Athlon/AthlonXP", |
apetushkov@9858 | 724 | "", |
apetushkov@9858 | 725 | "", |
apetushkov@9858 | 726 | "", |
apetushkov@9858 | 727 | "", |
apetushkov@9858 | 728 | "", |
apetushkov@9858 | 729 | "", |
apetushkov@9858 | 730 | "", |
apetushkov@9858 | 731 | "", |
apetushkov@9858 | 732 | "Opteron/Athlon64", |
apetushkov@9858 | 733 | "Opteron QC/Phenom" // Barcelona et.al. |
apetushkov@9858 | 734 | }; |
apetushkov@9858 | 735 | // Partially from Intel 64 and IA-32 Architecture Software Developer's Manual, |
apetushkov@9858 | 736 | // September 2013, Vol 3C Table 35-1 |
apetushkov@9858 | 737 | const char* const VM_Version_Ext::_model_id_pentium_pro[] = { |
apetushkov@9858 | 738 | "", |
apetushkov@9858 | 739 | "Pentium Pro", |
apetushkov@9858 | 740 | "", |
apetushkov@9858 | 741 | "Pentium II model 3", |
apetushkov@9858 | 742 | "", |
apetushkov@9858 | 743 | "Pentium II model 5/Xeon/Celeron", |
apetushkov@9858 | 744 | "Celeron", |
apetushkov@9858 | 745 | "Pentium III/Pentium III Xeon", |
apetushkov@9858 | 746 | "Pentium III/Pentium III Xeon", |
apetushkov@9858 | 747 | "Pentium M model 9", // Yonah |
apetushkov@9858 | 748 | "Pentium III, model A", |
apetushkov@9858 | 749 | "Pentium III, model B", |
apetushkov@9858 | 750 | "", |
apetushkov@9858 | 751 | "Pentium M model D", // Dothan |
apetushkov@9858 | 752 | "", |
apetushkov@9858 | 753 | "Core 2", // 0xf Woodcrest/Conroe/Merom/Kentsfield/Clovertown |
apetushkov@9858 | 754 | "", |
apetushkov@9858 | 755 | "", |
apetushkov@9858 | 756 | "", |
apetushkov@9858 | 757 | "", |
apetushkov@9858 | 758 | "", |
apetushkov@9858 | 759 | "", |
apetushkov@9858 | 760 | "Celeron", // 0x16 Celeron 65nm |
apetushkov@9858 | 761 | "Core 2", // 0x17 Penryn / Harpertown |
apetushkov@9858 | 762 | "", |
apetushkov@9858 | 763 | "", |
apetushkov@9858 | 764 | "Core i7", // 0x1A CPU_MODEL_NEHALEM_EP |
apetushkov@9858 | 765 | "Atom", // 0x1B Z5xx series Silverthorn |
apetushkov@9858 | 766 | "", |
apetushkov@9858 | 767 | "Core 2", // 0x1D Dunnington (6-core) |
apetushkov@9858 | 768 | "Nehalem", // 0x1E CPU_MODEL_NEHALEM |
apetushkov@9858 | 769 | "", |
apetushkov@9858 | 770 | "", |
apetushkov@9858 | 771 | "", |
apetushkov@9858 | 772 | "", |
apetushkov@9858 | 773 | "", |
apetushkov@9858 | 774 | "", |
apetushkov@9858 | 775 | "Westmere", // 0x25 CPU_MODEL_WESTMERE |
apetushkov@9858 | 776 | "", |
apetushkov@9858 | 777 | "", |
apetushkov@9858 | 778 | "", // 0x28 |
apetushkov@9858 | 779 | "", |
apetushkov@9858 | 780 | "Sandy Bridge", // 0x2a "2nd Generation Intel Core i7, i5, i3" |
apetushkov@9858 | 781 | "", |
apetushkov@9858 | 782 | "Westmere-EP", // 0x2c CPU_MODEL_WESTMERE_EP |
apetushkov@9858 | 783 | "Sandy Bridge-EP", // 0x2d CPU_MODEL_SANDYBRIDGE_EP |
apetushkov@9858 | 784 | "Nehalem-EX", // 0x2e CPU_MODEL_NEHALEM_EX |
apetushkov@9858 | 785 | "Westmere-EX", // 0x2f CPU_MODEL_WESTMERE_EX |
apetushkov@9858 | 786 | "", |
apetushkov@9858 | 787 | "", |
apetushkov@9858 | 788 | "", |
apetushkov@9858 | 789 | "", |
apetushkov@9858 | 790 | "", |
apetushkov@9858 | 791 | "", |
apetushkov@9858 | 792 | "", |
apetushkov@9858 | 793 | "", |
apetushkov@9858 | 794 | "", |
apetushkov@9858 | 795 | "", |
apetushkov@9858 | 796 | "Ivy Bridge", // 0x3a |
apetushkov@9858 | 797 | "", |
apetushkov@9858 | 798 | "Haswell", // 0x3c "4th Generation Intel Core Processor" |
apetushkov@9858 | 799 | "", // 0x3d "Next Generation Intel Core Processor" |
apetushkov@9858 | 800 | "Ivy Bridge-EP", // 0x3e "Next Generation Intel Xeon Processor E7 Family" |
apetushkov@9858 | 801 | "", // 0x3f "Future Generation Intel Xeon Processor" |
apetushkov@9858 | 802 | "", |
apetushkov@9858 | 803 | "", |
apetushkov@9858 | 804 | "", |
apetushkov@9858 | 805 | "", |
apetushkov@9858 | 806 | "", |
apetushkov@9858 | 807 | "Haswell", // 0x45 "4th Generation Intel Core Processor" |
apetushkov@9858 | 808 | "Haswell", // 0x46 "4th Generation Intel Core Processor" |
apetushkov@9858 | 809 | NULL |
apetushkov@9858 | 810 | }; |
apetushkov@9858 | 811 | |
apetushkov@9858 | 812 | /* Brand ID is for back compability |
apetushkov@9858 | 813 | * Newer CPUs uses the extended brand string */ |
apetushkov@9858 | 814 | const char* const VM_Version_Ext::_brand_id[] = { |
apetushkov@9858 | 815 | "", |
apetushkov@9858 | 816 | "Celeron processor", |
apetushkov@9858 | 817 | "Pentium III processor", |
apetushkov@9858 | 818 | "Intel Pentium III Xeon processor", |
apetushkov@9858 | 819 | "", |
apetushkov@9858 | 820 | "", |
apetushkov@9858 | 821 | "", |
apetushkov@9858 | 822 | "", |
apetushkov@9858 | 823 | "Intel Pentium 4 processor", |
apetushkov@9858 | 824 | NULL |
apetushkov@9858 | 825 | }; |
apetushkov@9858 | 826 | |
apetushkov@9858 | 827 | |
apetushkov@9858 | 828 | const char* const VM_Version_Ext::_feature_edx_id[] = { |
apetushkov@9858 | 829 | "On-Chip FPU", |
apetushkov@9858 | 830 | "Virtual Mode Extensions", |
apetushkov@9858 | 831 | "Debugging Extensions", |
apetushkov@9858 | 832 | "Page Size Extensions", |
apetushkov@9858 | 833 | "Time Stamp Counter", |
apetushkov@9858 | 834 | "Model Specific Registers", |
apetushkov@9858 | 835 | "Physical Address Extension", |
apetushkov@9858 | 836 | "Machine Check Exceptions", |
apetushkov@9858 | 837 | "CMPXCHG8B Instruction", |
apetushkov@9858 | 838 | "On-Chip APIC", |
apetushkov@9858 | 839 | "", |
apetushkov@9858 | 840 | "Fast System Call", |
apetushkov@9858 | 841 | "Memory Type Range Registers", |
apetushkov@9858 | 842 | "Page Global Enable", |
apetushkov@9858 | 843 | "Machine Check Architecture", |
apetushkov@9858 | 844 | "Conditional Mov Instruction", |
apetushkov@9858 | 845 | "Page Attribute Table", |
apetushkov@9858 | 846 | "36-bit Page Size Extension", |
apetushkov@9858 | 847 | "Processor Serial Number", |
apetushkov@9858 | 848 | "CLFLUSH Instruction", |
apetushkov@9858 | 849 | "", |
apetushkov@9858 | 850 | "Debug Trace Store feature", |
apetushkov@9858 | 851 | "ACPI registers in MSR space", |
apetushkov@9858 | 852 | "Intel Architecture MMX Technology", |
apetushkov@9858 | 853 | "Fast Float Point Save and Restore", |
apetushkov@9858 | 854 | "Streaming SIMD extensions", |
apetushkov@9858 | 855 | "Streaming SIMD extensions 2", |
apetushkov@9858 | 856 | "Self-Snoop", |
apetushkov@9858 | 857 | "Hyper Threading", |
apetushkov@9858 | 858 | "Thermal Monitor", |
apetushkov@9858 | 859 | "", |
apetushkov@9858 | 860 | "Pending Break Enable" |
apetushkov@9858 | 861 | }; |
apetushkov@9858 | 862 | |
apetushkov@9858 | 863 | const char* const VM_Version_Ext::_feature_extended_edx_id[] = { |
apetushkov@9858 | 864 | "", |
apetushkov@9858 | 865 | "", |
apetushkov@9858 | 866 | "", |
apetushkov@9858 | 867 | "", |
apetushkov@9858 | 868 | "", |
apetushkov@9858 | 869 | "", |
apetushkov@9858 | 870 | "", |
apetushkov@9858 | 871 | "", |
apetushkov@9858 | 872 | "", |
apetushkov@9858 | 873 | "", |
apetushkov@9858 | 874 | "", |
apetushkov@9858 | 875 | "SYSCALL/SYSRET", |
apetushkov@9858 | 876 | "", |
apetushkov@9858 | 877 | "", |
apetushkov@9858 | 878 | "", |
apetushkov@9858 | 879 | "", |
apetushkov@9858 | 880 | "", |
apetushkov@9858 | 881 | "", |
apetushkov@9858 | 882 | "", |
apetushkov@9858 | 883 | "", |
apetushkov@9858 | 884 | "Execute Disable Bit", |
apetushkov@9858 | 885 | "", |
apetushkov@9858 | 886 | "", |
apetushkov@9858 | 887 | "", |
apetushkov@9858 | 888 | "", |
apetushkov@9858 | 889 | "", |
apetushkov@9858 | 890 | "", |
apetushkov@9858 | 891 | "RDTSCP", |
apetushkov@9858 | 892 | "", |
apetushkov@9858 | 893 | "Intel 64 Architecture", |
apetushkov@9858 | 894 | "", |
apetushkov@9858 | 895 | "" |
apetushkov@9858 | 896 | }; |
apetushkov@9858 | 897 | |
apetushkov@9858 | 898 | const char* const VM_Version_Ext::_feature_ecx_id[] = { |
apetushkov@9858 | 899 | "Streaming SIMD Extensions 3", |
apetushkov@9858 | 900 | "PCLMULQDQ", |
apetushkov@9858 | 901 | "64-bit DS Area", |
apetushkov@9858 | 902 | "MONITOR/MWAIT instructions", |
apetushkov@9858 | 903 | "CPL Qualified Debug Store", |
apetushkov@9858 | 904 | "Virtual Machine Extensions", |
apetushkov@9858 | 905 | "Safer Mode Extensions", |
apetushkov@9858 | 906 | "Enhanced Intel SpeedStep technology", |
apetushkov@9858 | 907 | "Thermal Monitor 2", |
apetushkov@9858 | 908 | "Supplemental Streaming SIMD Extensions 3", |
apetushkov@9858 | 909 | "L1 Context ID", |
apetushkov@9858 | 910 | "", |
apetushkov@9858 | 911 | "Fused Multiply-Add", |
apetushkov@9858 | 912 | "CMPXCHG16B", |
apetushkov@9858 | 913 | "xTPR Update Control", |
apetushkov@9858 | 914 | "Perfmon and Debug Capability", |
apetushkov@9858 | 915 | "", |
apetushkov@9858 | 916 | "Process-context identifiers", |
apetushkov@9858 | 917 | "Direct Cache Access", |
apetushkov@9858 | 918 | "Streaming SIMD extensions 4.1", |
apetushkov@9858 | 919 | "Streaming SIMD extensions 4.2", |
apetushkov@9858 | 920 | "x2APIC", |
apetushkov@9858 | 921 | "MOVBE", |
apetushkov@9858 | 922 | "Popcount instruction", |
apetushkov@9858 | 923 | "TSC-Deadline", |
apetushkov@9858 | 924 | "AESNI", |
apetushkov@9858 | 925 | "XSAVE", |
apetushkov@9858 | 926 | "OSXSAVE", |
apetushkov@9858 | 927 | "AVX", |
apetushkov@9858 | 928 | "F16C", |
apetushkov@9858 | 929 | "RDRAND", |
apetushkov@9858 | 930 | "" |
apetushkov@9858 | 931 | }; |
apetushkov@9858 | 932 | |
apetushkov@9858 | 933 | const char* const VM_Version_Ext::_feature_extended_ecx_id[] = { |
apetushkov@9858 | 934 | "LAHF/SAHF instruction support", |
apetushkov@9858 | 935 | "Core multi-processor leagacy mode", |
apetushkov@9858 | 936 | "", |
apetushkov@9858 | 937 | "", |
apetushkov@9858 | 938 | "", |
apetushkov@9858 | 939 | "Advanced Bit Manipulations: LZCNT", |
apetushkov@9858 | 940 | "SSE4A: MOVNTSS, MOVNTSD, EXTRQ, INSERTQ", |
apetushkov@9858 | 941 | "Misaligned SSE mode", |
apetushkov@9858 | 942 | "", |
apetushkov@9858 | 943 | "", |
apetushkov@9858 | 944 | "", |
apetushkov@9858 | 945 | "", |
apetushkov@9858 | 946 | "", |
apetushkov@9858 | 947 | "", |
apetushkov@9858 | 948 | "", |
apetushkov@9858 | 949 | "", |
apetushkov@9858 | 950 | "", |
apetushkov@9858 | 951 | "", |
apetushkov@9858 | 952 | "", |
apetushkov@9858 | 953 | "", |
apetushkov@9858 | 954 | "", |
apetushkov@9858 | 955 | "", |
apetushkov@9858 | 956 | "", |
apetushkov@9858 | 957 | "", |
apetushkov@9858 | 958 | "", |
apetushkov@9858 | 959 | "", |
apetushkov@9858 | 960 | "", |
apetushkov@9858 | 961 | "", |
apetushkov@9858 | 962 | "", |
apetushkov@9858 | 963 | "", |
apetushkov@9858 | 964 | "", |
apetushkov@9858 | 965 | "" |
apetushkov@9858 | 966 | }; |