1 /*
2 * Copyright (c) 1997, 2012, 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 *
44 ext_model : 4,
45 ext_family : 8,
46 : 4;
47 } bits;
48 };
49
50 union StdCpuid1Ebx { // example, unused
51 uint32_t value;
52 struct {
53 uint32_t brand_id : 8,
54 clflush_size : 8,
55 threads_per_cpu : 8,
56 apic_id : 8;
57 } bits;
58 };
59
60 union StdCpuid1Ecx {
61 uint32_t value;
62 struct {
63 uint32_t sse3 : 1,
64 : 2,
65 monitor : 1,
66 : 1,
67 vmx : 1,
68 : 1,
69 est : 1,
70 : 1,
71 ssse3 : 1,
72 cid : 1,
73 : 2,
74 cmpxchg16: 1,
75 : 4,
76 dca : 1,
77 sse4_1 : 1,
78 sse4_2 : 1,
79 : 2,
80 popcnt : 1,
81 : 1,
82 aes : 1,
83 : 1,
84 osxsave : 1,
232 CPU_CMOV = (1 << 1),
233 CPU_FXSR = (1 << 2),
234 CPU_HT = (1 << 3),
235 CPU_MMX = (1 << 4),
236 CPU_3DNOW_PREFETCH = (1 << 5), // Processor supports 3dnow prefetch and prefetchw instructions
237 // may not necessarily support other 3dnow instructions
238 CPU_SSE = (1 << 6),
239 CPU_SSE2 = (1 << 7),
240 CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX)
241 CPU_SSSE3 = (1 << 9),
242 CPU_SSE4A = (1 << 10),
243 CPU_SSE4_1 = (1 << 11),
244 CPU_SSE4_2 = (1 << 12),
245 CPU_POPCNT = (1 << 13),
246 CPU_LZCNT = (1 << 14),
247 CPU_TSC = (1 << 15),
248 CPU_TSCINV = (1 << 16),
249 CPU_AVX = (1 << 17),
250 CPU_AVX2 = (1 << 18),
251 CPU_AES = (1 << 19),
252 CPU_ERMS = (1 << 20) // enhanced 'rep movsb/stosb' instructions
253 } cpuFeatureFlags;
254
255 enum {
256 // AMD
257 CPU_FAMILY_AMD_11H = 0x11,
258 // Intel
259 CPU_FAMILY_INTEL_CORE = 6,
260 CPU_MODEL_NEHALEM = 0x1e,
261 CPU_MODEL_NEHALEM_EP = 0x1a,
262 CPU_MODEL_NEHALEM_EX = 0x2e,
263 CPU_MODEL_WESTMERE = 0x25,
264 CPU_MODEL_WESTMERE_EP = 0x2c,
265 CPU_MODEL_WESTMERE_EX = 0x2f,
266 CPU_MODEL_SANDYBRIDGE = 0x2a,
267 CPU_MODEL_SANDYBRIDGE_EP = 0x2d,
268 CPU_MODEL_IVYBRIDGE_EP = 0x3a
269 } cpuExtendedFamily;
270
271 // cpuid information block. All info derived from executing cpuid with
272 // various function numbers is stored here. Intel and AMD info is
412 if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0)
413 result |= CPU_SSE4_2;
414 if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
415 result |= CPU_POPCNT;
416 if (_cpuid_info.std_cpuid1_ecx.bits.avx != 0 &&
417 _cpuid_info.std_cpuid1_ecx.bits.osxsave != 0 &&
418 _cpuid_info.xem_xcr0_eax.bits.sse != 0 &&
419 _cpuid_info.xem_xcr0_eax.bits.ymm != 0) {
420 result |= CPU_AVX;
421 if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0)
422 result |= CPU_AVX2;
423 }
424 if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0)
425 result |= CPU_TSC;
426 if (_cpuid_info.ext_cpuid7_edx.bits.tsc_invariance != 0)
427 result |= CPU_TSCINV;
428 if (_cpuid_info.std_cpuid1_ecx.bits.aes != 0)
429 result |= CPU_AES;
430 if (_cpuid_info.sef_cpuid7_ebx.bits.erms != 0)
431 result |= CPU_ERMS;
432
433 // AMD features.
434 if (is_amd()) {
435 if ((_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) ||
436 (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0))
437 result |= CPU_3DNOW_PREFETCH;
438 if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0)
439 result |= CPU_LZCNT;
440 if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0)
441 result |= CPU_SSE4A;
442 }
443
444 return result;
445 }
446
447 static void get_processor_features();
448
449 public:
450 // Offsets for cpuid asm stub
451 static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); }
538 // Feature identification
539 //
540 static bool supports_cpuid() { return _cpuFeatures != 0; }
541 static bool supports_cmpxchg8() { return (_cpuFeatures & CPU_CX8) != 0; }
542 static bool supports_cmov() { return (_cpuFeatures & CPU_CMOV) != 0; }
543 static bool supports_fxsr() { return (_cpuFeatures & CPU_FXSR) != 0; }
544 static bool supports_ht() { return (_cpuFeatures & CPU_HT) != 0; }
545 static bool supports_mmx() { return (_cpuFeatures & CPU_MMX) != 0; }
546 static bool supports_sse() { return (_cpuFeatures & CPU_SSE) != 0; }
547 static bool supports_sse2() { return (_cpuFeatures & CPU_SSE2) != 0; }
548 static bool supports_sse3() { return (_cpuFeatures & CPU_SSE3) != 0; }
549 static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; }
550 static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 0; }
551 static bool supports_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; }
552 static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; }
553 static bool supports_avx() { return (_cpuFeatures & CPU_AVX) != 0; }
554 static bool supports_avx2() { return (_cpuFeatures & CPU_AVX2) != 0; }
555 static bool supports_tsc() { return (_cpuFeatures & CPU_TSC) != 0; }
556 static bool supports_aes() { return (_cpuFeatures & CPU_AES) != 0; }
557 static bool supports_erms() { return (_cpuFeatures & CPU_ERMS) != 0; }
558
559 // Intel features
560 static bool is_intel_family_core() { return is_intel() &&
561 extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
562
563 static bool is_intel_tsc_synched_at_init() {
564 if (is_intel_family_core()) {
565 uint32_t ext_model = extended_cpu_model();
566 if (ext_model == CPU_MODEL_NEHALEM_EP ||
567 ext_model == CPU_MODEL_WESTMERE_EP ||
568 ext_model == CPU_MODEL_SANDYBRIDGE_EP ||
569 ext_model == CPU_MODEL_IVYBRIDGE_EP) {
570 // <= 2-socket invariant tsc support. EX versions are usually used
571 // in > 2-socket systems and likely don't synchronize tscs at
572 // initialization.
573 // Code that uses tsc values must be prepared for them to arbitrarily
574 // jump forward or backward.
575 return true;
576 }
577 }
|
1 /*
2 * Copyright (c) 1997, 2013, 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 *
44 ext_model : 4,
45 ext_family : 8,
46 : 4;
47 } bits;
48 };
49
50 union StdCpuid1Ebx { // example, unused
51 uint32_t value;
52 struct {
53 uint32_t brand_id : 8,
54 clflush_size : 8,
55 threads_per_cpu : 8,
56 apic_id : 8;
57 } bits;
58 };
59
60 union StdCpuid1Ecx {
61 uint32_t value;
62 struct {
63 uint32_t sse3 : 1,
64 clmul : 1,
65 : 1,
66 monitor : 1,
67 : 1,
68 vmx : 1,
69 : 1,
70 est : 1,
71 : 1,
72 ssse3 : 1,
73 cid : 1,
74 : 2,
75 cmpxchg16: 1,
76 : 4,
77 dca : 1,
78 sse4_1 : 1,
79 sse4_2 : 1,
80 : 2,
81 popcnt : 1,
82 : 1,
83 aes : 1,
84 : 1,
85 osxsave : 1,
233 CPU_CMOV = (1 << 1),
234 CPU_FXSR = (1 << 2),
235 CPU_HT = (1 << 3),
236 CPU_MMX = (1 << 4),
237 CPU_3DNOW_PREFETCH = (1 << 5), // Processor supports 3dnow prefetch and prefetchw instructions
238 // may not necessarily support other 3dnow instructions
239 CPU_SSE = (1 << 6),
240 CPU_SSE2 = (1 << 7),
241 CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX)
242 CPU_SSSE3 = (1 << 9),
243 CPU_SSE4A = (1 << 10),
244 CPU_SSE4_1 = (1 << 11),
245 CPU_SSE4_2 = (1 << 12),
246 CPU_POPCNT = (1 << 13),
247 CPU_LZCNT = (1 << 14),
248 CPU_TSC = (1 << 15),
249 CPU_TSCINV = (1 << 16),
250 CPU_AVX = (1 << 17),
251 CPU_AVX2 = (1 << 18),
252 CPU_AES = (1 << 19),
253 CPU_ERMS = (1 << 20), // enhanced 'rep movsb/stosb' instructions
254 CPU_CLMUL = (1 << 21) // carryless multiply for CRC
255 } cpuFeatureFlags;
256
257 enum {
258 // AMD
259 CPU_FAMILY_AMD_11H = 0x11,
260 // Intel
261 CPU_FAMILY_INTEL_CORE = 6,
262 CPU_MODEL_NEHALEM = 0x1e,
263 CPU_MODEL_NEHALEM_EP = 0x1a,
264 CPU_MODEL_NEHALEM_EX = 0x2e,
265 CPU_MODEL_WESTMERE = 0x25,
266 CPU_MODEL_WESTMERE_EP = 0x2c,
267 CPU_MODEL_WESTMERE_EX = 0x2f,
268 CPU_MODEL_SANDYBRIDGE = 0x2a,
269 CPU_MODEL_SANDYBRIDGE_EP = 0x2d,
270 CPU_MODEL_IVYBRIDGE_EP = 0x3a
271 } cpuExtendedFamily;
272
273 // cpuid information block. All info derived from executing cpuid with
274 // various function numbers is stored here. Intel and AMD info is
414 if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0)
415 result |= CPU_SSE4_2;
416 if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
417 result |= CPU_POPCNT;
418 if (_cpuid_info.std_cpuid1_ecx.bits.avx != 0 &&
419 _cpuid_info.std_cpuid1_ecx.bits.osxsave != 0 &&
420 _cpuid_info.xem_xcr0_eax.bits.sse != 0 &&
421 _cpuid_info.xem_xcr0_eax.bits.ymm != 0) {
422 result |= CPU_AVX;
423 if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0)
424 result |= CPU_AVX2;
425 }
426 if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0)
427 result |= CPU_TSC;
428 if (_cpuid_info.ext_cpuid7_edx.bits.tsc_invariance != 0)
429 result |= CPU_TSCINV;
430 if (_cpuid_info.std_cpuid1_ecx.bits.aes != 0)
431 result |= CPU_AES;
432 if (_cpuid_info.sef_cpuid7_ebx.bits.erms != 0)
433 result |= CPU_ERMS;
434 if (_cpuid_info.std_cpuid1_ecx.bits.clmul != 0)
435 result |= CPU_CLMUL;
436
437 // AMD features.
438 if (is_amd()) {
439 if ((_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) ||
440 (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0))
441 result |= CPU_3DNOW_PREFETCH;
442 if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0)
443 result |= CPU_LZCNT;
444 if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0)
445 result |= CPU_SSE4A;
446 }
447
448 return result;
449 }
450
451 static void get_processor_features();
452
453 public:
454 // Offsets for cpuid asm stub
455 static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); }
542 // Feature identification
543 //
544 static bool supports_cpuid() { return _cpuFeatures != 0; }
545 static bool supports_cmpxchg8() { return (_cpuFeatures & CPU_CX8) != 0; }
546 static bool supports_cmov() { return (_cpuFeatures & CPU_CMOV) != 0; }
547 static bool supports_fxsr() { return (_cpuFeatures & CPU_FXSR) != 0; }
548 static bool supports_ht() { return (_cpuFeatures & CPU_HT) != 0; }
549 static bool supports_mmx() { return (_cpuFeatures & CPU_MMX) != 0; }
550 static bool supports_sse() { return (_cpuFeatures & CPU_SSE) != 0; }
551 static bool supports_sse2() { return (_cpuFeatures & CPU_SSE2) != 0; }
552 static bool supports_sse3() { return (_cpuFeatures & CPU_SSE3) != 0; }
553 static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; }
554 static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 0; }
555 static bool supports_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; }
556 static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; }
557 static bool supports_avx() { return (_cpuFeatures & CPU_AVX) != 0; }
558 static bool supports_avx2() { return (_cpuFeatures & CPU_AVX2) != 0; }
559 static bool supports_tsc() { return (_cpuFeatures & CPU_TSC) != 0; }
560 static bool supports_aes() { return (_cpuFeatures & CPU_AES) != 0; }
561 static bool supports_erms() { return (_cpuFeatures & CPU_ERMS) != 0; }
562 static bool supports_clmul() { return (_cpuFeatures & CPU_CLMUL) != 0; }
563
564 // Intel features
565 static bool is_intel_family_core() { return is_intel() &&
566 extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
567
568 static bool is_intel_tsc_synched_at_init() {
569 if (is_intel_family_core()) {
570 uint32_t ext_model = extended_cpu_model();
571 if (ext_model == CPU_MODEL_NEHALEM_EP ||
572 ext_model == CPU_MODEL_WESTMERE_EP ||
573 ext_model == CPU_MODEL_SANDYBRIDGE_EP ||
574 ext_model == CPU_MODEL_IVYBRIDGE_EP) {
575 // <= 2-socket invariant tsc support. EX versions are usually used
576 // in > 2-socket systems and likely don't synchronize tscs at
577 // initialization.
578 // Code that uses tsc values must be prepared for them to arbitrarily
579 // jump forward or backward.
580 return true;
581 }
582 }
|