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