|
1 /* |
|
2 * Copyright 1997-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 class VM_Version: public Abstract_VM_Version { |
|
26 public: |
|
27 // cpuid result register layouts. These are all unions of a uint32_t |
|
28 // (in case anyone wants access to the register as a whole) and a bitfield. |
|
29 |
|
30 union StdCpuid1Eax { |
|
31 uint32_t value; |
|
32 struct { |
|
33 uint32_t stepping : 4, |
|
34 model : 4, |
|
35 family : 4, |
|
36 proc_type : 2, |
|
37 : 2, |
|
38 ext_model : 4, |
|
39 ext_family : 8, |
|
40 : 4; |
|
41 } bits; |
|
42 }; |
|
43 |
|
44 union StdCpuid1Ebx { // example, unused |
|
45 uint32_t value; |
|
46 struct { |
|
47 uint32_t brand_id : 8, |
|
48 clflush_size : 8, |
|
49 threads_per_cpu : 8, |
|
50 apic_id : 8; |
|
51 } bits; |
|
52 }; |
|
53 |
|
54 union StdCpuid1Ecx { |
|
55 uint32_t value; |
|
56 struct { |
|
57 uint32_t sse3 : 1, |
|
58 : 2, |
|
59 monitor : 1, |
|
60 : 1, |
|
61 vmx : 1, |
|
62 : 1, |
|
63 est : 1, |
|
64 : 1, |
|
65 ssse3 : 1, |
|
66 cid : 1, |
|
67 : 2, |
|
68 cmpxchg16: 1, |
|
69 : 4, |
|
70 dca : 1, |
|
71 : 4, |
|
72 popcnt : 1, |
|
73 : 8; |
|
74 } bits; |
|
75 }; |
|
76 |
|
77 union StdCpuid1Edx { |
|
78 uint32_t value; |
|
79 struct { |
|
80 uint32_t : 4, |
|
81 tsc : 1, |
|
82 : 3, |
|
83 cmpxchg8 : 1, |
|
84 : 6, |
|
85 cmov : 1, |
|
86 : 7, |
|
87 mmx : 1, |
|
88 fxsr : 1, |
|
89 sse : 1, |
|
90 sse2 : 1, |
|
91 : 1, |
|
92 ht : 1, |
|
93 : 3; |
|
94 } bits; |
|
95 }; |
|
96 |
|
97 union DcpCpuid4Eax { |
|
98 uint32_t value; |
|
99 struct { |
|
100 uint32_t cache_type : 5, |
|
101 : 21, |
|
102 cores_per_cpu : 6; |
|
103 } bits; |
|
104 }; |
|
105 |
|
106 union DcpCpuid4Ebx { |
|
107 uint32_t value; |
|
108 struct { |
|
109 uint32_t L1_line_size : 12, |
|
110 partitions : 10, |
|
111 associativity : 10; |
|
112 } bits; |
|
113 }; |
|
114 |
|
115 union ExtCpuid1Ecx { |
|
116 uint32_t value; |
|
117 struct { |
|
118 uint32_t LahfSahf : 1, |
|
119 CmpLegacy : 1, |
|
120 : 4, |
|
121 abm : 1, |
|
122 sse4a : 1, |
|
123 misalignsse : 1, |
|
124 prefetchw : 1, |
|
125 : 22; |
|
126 } bits; |
|
127 }; |
|
128 |
|
129 union ExtCpuid1Edx { |
|
130 uint32_t value; |
|
131 struct { |
|
132 uint32_t : 22, |
|
133 mmx_amd : 1, |
|
134 mmx : 1, |
|
135 fxsr : 1, |
|
136 : 4, |
|
137 long_mode : 1, |
|
138 tdnow2 : 1, |
|
139 tdnow : 1; |
|
140 } bits; |
|
141 }; |
|
142 |
|
143 union ExtCpuid5Ex { |
|
144 uint32_t value; |
|
145 struct { |
|
146 uint32_t L1_line_size : 8, |
|
147 L1_tag_lines : 8, |
|
148 L1_assoc : 8, |
|
149 L1_size : 8; |
|
150 } bits; |
|
151 }; |
|
152 |
|
153 union ExtCpuid8Ecx { |
|
154 uint32_t value; |
|
155 struct { |
|
156 uint32_t cores_per_cpu : 8, |
|
157 : 24; |
|
158 } bits; |
|
159 }; |
|
160 |
|
161 protected: |
|
162 static int _cpu; |
|
163 static int _model; |
|
164 static int _stepping; |
|
165 static int _cpuFeatures; // features returned by the "cpuid" instruction |
|
166 // 0 if this instruction is not available |
|
167 static const char* _features_str; |
|
168 |
|
169 enum { |
|
170 CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX) |
|
171 CPU_CMOV = (1 << 1), |
|
172 CPU_FXSR = (1 << 2), |
|
173 CPU_HT = (1 << 3), |
|
174 CPU_MMX = (1 << 4), |
|
175 CPU_3DNOW= (1 << 5), // 3DNow comes from cpuid 0x80000001 (EDX) |
|
176 CPU_SSE = (1 << 6), |
|
177 CPU_SSE2 = (1 << 7), |
|
178 CPU_SSE3 = (1 << 8), // sse3 comes from cpuid 1 (ECX) |
|
179 CPU_SSSE3= (1 << 9), |
|
180 CPU_SSE4 = (1 <<10), |
|
181 CPU_SSE4A= (1 <<11) |
|
182 } cpuFeatureFlags; |
|
183 |
|
184 // cpuid information block. All info derived from executing cpuid with |
|
185 // various function numbers is stored here. Intel and AMD info is |
|
186 // merged in this block: accessor methods disentangle it. |
|
187 // |
|
188 // The info block is laid out in subblocks of 4 dwords corresponding to |
|
189 // rax, rbx, rcx and rdx, whether or not they contain anything useful. |
|
190 struct CpuidInfo { |
|
191 // cpuid function 0 |
|
192 uint32_t std_max_function; |
|
193 uint32_t std_vendor_name_0; |
|
194 uint32_t std_vendor_name_1; |
|
195 uint32_t std_vendor_name_2; |
|
196 |
|
197 // cpuid function 1 |
|
198 StdCpuid1Eax std_cpuid1_rax; |
|
199 StdCpuid1Ebx std_cpuid1_rbx; |
|
200 StdCpuid1Ecx std_cpuid1_rcx; |
|
201 StdCpuid1Edx std_cpuid1_rdx; |
|
202 |
|
203 // cpuid function 4 (deterministic cache parameters) |
|
204 DcpCpuid4Eax dcp_cpuid4_rax; |
|
205 DcpCpuid4Ebx dcp_cpuid4_rbx; |
|
206 uint32_t dcp_cpuid4_rcx; // unused currently |
|
207 uint32_t dcp_cpuid4_rdx; // unused currently |
|
208 |
|
209 // cpuid function 0x80000000 // example, unused |
|
210 uint32_t ext_max_function; |
|
211 uint32_t ext_vendor_name_0; |
|
212 uint32_t ext_vendor_name_1; |
|
213 uint32_t ext_vendor_name_2; |
|
214 |
|
215 // cpuid function 0x80000001 |
|
216 uint32_t ext_cpuid1_rax; // reserved |
|
217 uint32_t ext_cpuid1_rbx; // reserved |
|
218 ExtCpuid1Ecx ext_cpuid1_rcx; |
|
219 ExtCpuid1Edx ext_cpuid1_rdx; |
|
220 |
|
221 // cpuid functions 0x80000002 thru 0x80000004: example, unused |
|
222 uint32_t proc_name_0, proc_name_1, proc_name_2, proc_name_3; |
|
223 uint32_t proc_name_4, proc_name_5, proc_name_6, proc_name_7; |
|
224 uint32_t proc_name_8, proc_name_9, proc_name_10,proc_name_11; |
|
225 |
|
226 // cpuid function 0x80000005 //AMD L1, Intel reserved |
|
227 uint32_t ext_cpuid5_rax; // unused currently |
|
228 uint32_t ext_cpuid5_rbx; // reserved |
|
229 ExtCpuid5Ex ext_cpuid5_rcx; // L1 data cache info (AMD) |
|
230 ExtCpuid5Ex ext_cpuid5_rdx; // L1 instruction cache info (AMD) |
|
231 |
|
232 // cpuid function 0x80000008 |
|
233 uint32_t ext_cpuid8_rax; // unused currently |
|
234 uint32_t ext_cpuid8_rbx; // reserved |
|
235 ExtCpuid8Ecx ext_cpuid8_rcx; |
|
236 uint32_t ext_cpuid8_rdx; // reserved |
|
237 }; |
|
238 |
|
239 // The actual cpuid info block |
|
240 static CpuidInfo _cpuid_info; |
|
241 |
|
242 // Extractors and predicates |
|
243 static bool is_extended_cpu_family() { |
|
244 const uint32_t Extended_Cpu_Family = 0xf; |
|
245 return _cpuid_info.std_cpuid1_rax.bits.family == Extended_Cpu_Family; |
|
246 } |
|
247 static uint32_t extended_cpu_family() { |
|
248 uint32_t result = _cpuid_info.std_cpuid1_rax.bits.family; |
|
249 if (is_extended_cpu_family()) { |
|
250 result += _cpuid_info.std_cpuid1_rax.bits.ext_family; |
|
251 } |
|
252 return result; |
|
253 } |
|
254 static uint32_t extended_cpu_model() { |
|
255 uint32_t result = _cpuid_info.std_cpuid1_rax.bits.model; |
|
256 if (is_extended_cpu_family()) { |
|
257 result |= _cpuid_info.std_cpuid1_rax.bits.ext_model << 4; |
|
258 } |
|
259 return result; |
|
260 } |
|
261 static uint32_t cpu_stepping() { |
|
262 uint32_t result = _cpuid_info.std_cpuid1_rax.bits.stepping; |
|
263 return result; |
|
264 } |
|
265 static uint logical_processor_count() { |
|
266 uint result = threads_per_core(); |
|
267 return result; |
|
268 } |
|
269 static uint32_t feature_flags() { |
|
270 uint32_t result = 0; |
|
271 if (_cpuid_info.std_cpuid1_rdx.bits.cmpxchg8 != 0) |
|
272 result |= CPU_CX8; |
|
273 if (_cpuid_info.std_cpuid1_rdx.bits.cmov != 0) |
|
274 result |= CPU_CMOV; |
|
275 if (_cpuid_info.std_cpuid1_rdx.bits.fxsr != 0 || is_amd() && |
|
276 _cpuid_info.ext_cpuid1_rdx.bits.fxsr != 0) |
|
277 result |= CPU_FXSR; |
|
278 // HT flag is set for multi-core processors also. |
|
279 if (threads_per_core() > 1) |
|
280 result |= CPU_HT; |
|
281 if (_cpuid_info.std_cpuid1_rdx.bits.mmx != 0 || is_amd() && |
|
282 _cpuid_info.ext_cpuid1_rdx.bits.mmx != 0) |
|
283 result |= CPU_MMX; |
|
284 if (is_amd() && _cpuid_info.ext_cpuid1_rdx.bits.tdnow != 0) |
|
285 result |= CPU_3DNOW; |
|
286 if (_cpuid_info.std_cpuid1_rdx.bits.sse != 0) |
|
287 result |= CPU_SSE; |
|
288 if (_cpuid_info.std_cpuid1_rdx.bits.sse2 != 0) |
|
289 result |= CPU_SSE2; |
|
290 if (_cpuid_info.std_cpuid1_rcx.bits.sse3 != 0) |
|
291 result |= CPU_SSE3; |
|
292 if (_cpuid_info.std_cpuid1_rcx.bits.ssse3 != 0) |
|
293 result |= CPU_SSSE3; |
|
294 if (is_amd() && _cpuid_info.ext_cpuid1_rcx.bits.sse4a != 0) |
|
295 result |= CPU_SSE4A; |
|
296 return result; |
|
297 } |
|
298 |
|
299 static void get_processor_features(); |
|
300 |
|
301 public: |
|
302 // Offsets for cpuid asm stub |
|
303 static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); } |
|
304 static ByteSize std_cpuid1_offset() { return byte_offset_of(CpuidInfo, std_cpuid1_rax); } |
|
305 static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_rax); } |
|
306 static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_rax); } |
|
307 static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_rax); } |
|
308 static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_rax); } |
|
309 |
|
310 // Initialization |
|
311 static void initialize(); |
|
312 |
|
313 // Asserts |
|
314 static void assert_is_initialized() { |
|
315 assert(_cpuid_info.std_cpuid1_rax.bits.family != 0, "VM_Version not initialized"); |
|
316 } |
|
317 |
|
318 // |
|
319 // Processor family: |
|
320 // 3 - 386 |
|
321 // 4 - 486 |
|
322 // 5 - Pentium |
|
323 // 6 - PentiumPro, Pentium II, Celeron, Xeon, Pentium III, Athlon, |
|
324 // Pentium M, Core Solo, Core Duo, Core2 Duo |
|
325 // family 6 model: 9, 13, 14, 15 |
|
326 // 0x0f - Pentium 4, Opteron |
|
327 // |
|
328 // Note: The cpu family should be used to select between |
|
329 // instruction sequences which are valid on all Intel |
|
330 // processors. Use the feature test functions below to |
|
331 // determine whether a particular instruction is supported. |
|
332 // |
|
333 static int cpu_family() { return _cpu;} |
|
334 static bool is_P6() { return cpu_family() >= 6; } |
|
335 |
|
336 static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA' |
|
337 static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG' |
|
338 |
|
339 static uint cores_per_cpu() { |
|
340 uint result = 1; |
|
341 if (is_intel()) { |
|
342 result = (_cpuid_info.dcp_cpuid4_rax.bits.cores_per_cpu + 1); |
|
343 } else if (is_amd()) { |
|
344 result = (_cpuid_info.ext_cpuid8_rcx.bits.cores_per_cpu + 1); |
|
345 } |
|
346 return result; |
|
347 } |
|
348 |
|
349 static uint threads_per_core() { |
|
350 uint result = 1; |
|
351 if (_cpuid_info.std_cpuid1_rdx.bits.ht != 0) { |
|
352 result = _cpuid_info.std_cpuid1_rbx.bits.threads_per_cpu / |
|
353 cores_per_cpu(); |
|
354 } |
|
355 return result; |
|
356 } |
|
357 |
|
358 static intx L1_data_cache_line_size() { |
|
359 intx result = 0; |
|
360 if (is_intel()) { |
|
361 result = (_cpuid_info.dcp_cpuid4_rbx.bits.L1_line_size + 1); |
|
362 } else if (is_amd()) { |
|
363 result = _cpuid_info.ext_cpuid5_rcx.bits.L1_line_size; |
|
364 } |
|
365 if (result < 32) // not defined ? |
|
366 result = 32; // 32 bytes by default on x86 |
|
367 return result; |
|
368 } |
|
369 |
|
370 // |
|
371 // Feature identification |
|
372 // |
|
373 static bool supports_cpuid() { return _cpuFeatures != 0; } |
|
374 static bool supports_cmpxchg8() { return (_cpuFeatures & CPU_CX8) != 0; } |
|
375 static bool supports_cmov() { return (_cpuFeatures & CPU_CMOV) != 0; } |
|
376 static bool supports_fxsr() { return (_cpuFeatures & CPU_FXSR) != 0; } |
|
377 static bool supports_ht() { return (_cpuFeatures & CPU_HT) != 0; } |
|
378 static bool supports_mmx() { return (_cpuFeatures & CPU_MMX) != 0; } |
|
379 static bool supports_sse() { return (_cpuFeatures & CPU_SSE) != 0; } |
|
380 static bool supports_sse2() { return (_cpuFeatures & CPU_SSE2) != 0; } |
|
381 static bool supports_sse3() { return (_cpuFeatures & CPU_SSE3) != 0; } |
|
382 static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; } |
|
383 static bool supports_sse4() { return (_cpuFeatures & CPU_SSE4) != 0; } |
|
384 // |
|
385 // AMD features |
|
386 // |
|
387 static bool supports_3dnow() { return (_cpuFeatures & CPU_3DNOW) != 0; } |
|
388 static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_rdx.bits.mmx_amd != 0; } |
|
389 static bool supports_3dnow2() { return is_amd() && _cpuid_info.ext_cpuid1_rdx.bits.tdnow2 != 0; } |
|
390 static bool supports_sse4a() { return (_cpuFeatures & CPU_SSE4A) != 0; } |
|
391 |
|
392 static bool supports_compare_and_exchange() { return true; } |
|
393 |
|
394 static const char* cpu_features() { return _features_str; } |
|
395 |
|
396 static intx allocate_prefetch_distance() { |
|
397 // This method should be called before allocate_prefetch_style(). |
|
398 // |
|
399 // Hardware prefetching (distance/size in bytes): |
|
400 // Pentium 3 - 64 / 32 |
|
401 // Pentium 4 - 256 / 128 |
|
402 // Athlon - 64 / 32 ???? |
|
403 // Opteron - 128 / 64 only when 2 sequential cache lines accessed |
|
404 // Core - 128 / 64 |
|
405 // |
|
406 // Software prefetching (distance in bytes / instruction with best score): |
|
407 // Pentium 3 - 128 / prefetchnta |
|
408 // Pentium 4 - 512 / prefetchnta |
|
409 // Athlon - 128 / prefetchnta |
|
410 // Opteron - 256 / prefetchnta |
|
411 // Core - 256 / prefetchnta |
|
412 // It will be used only when AllocatePrefetchStyle > 0 |
|
413 |
|
414 intx count = AllocatePrefetchDistance; |
|
415 if (count < 0) { // default ? |
|
416 if (is_amd()) { // AMD |
|
417 if (supports_sse2()) |
|
418 count = 256; // Opteron |
|
419 else |
|
420 count = 128; // Athlon |
|
421 } else { // Intel |
|
422 if (supports_sse2()) |
|
423 if (cpu_family() == 6) { |
|
424 count = 256; // Pentium M, Core, Core2 |
|
425 } else { |
|
426 count = 512; // Pentium 4 |
|
427 } |
|
428 else |
|
429 count = 128; // Pentium 3 (and all other old CPUs) |
|
430 } |
|
431 } |
|
432 return count; |
|
433 } |
|
434 static intx allocate_prefetch_style() { |
|
435 assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); |
|
436 // Return 0 if AllocatePrefetchDistance was not defined or |
|
437 // prefetch instruction is not supported. |
|
438 return (AllocatePrefetchDistance > 0 && |
|
439 (supports_3dnow() || supports_sse())) ? AllocatePrefetchStyle : 0; |
|
440 } |
|
441 }; |