nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* ws_cpuid.h |
2 | * Get the CPU info on x86 processors that support it |
||
3 | * |
||
4 | * Wireshark - Network traffic analyzer |
||
5 | * By Gerald Combs <gerald@wireshark.org> |
||
6 | * Copyright 1998 Gerald Combs |
||
7 | * |
||
8 | * This program is free software; you can redistribute it and/or |
||
9 | * modify it under the terms of the GNU General Public License |
||
10 | * as published by the Free Software Foundation; either version 2 |
||
11 | * of the License, or (at your option) any later version. |
||
12 | * |
||
13 | * This program is distributed in the hope that it will be useful, |
||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 | * GNU General Public License for more details. |
||
17 | * |
||
18 | * You should have received a copy of the GNU General Public License |
||
19 | * along with this program; if not, write to the Free Software |
||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
||
21 | */ |
||
22 | |||
23 | /* |
||
24 | * Get CPU info on platforms where the cpuid instruction can be used skip 32 bit versions for GCC |
||
25 | * Intel has documented the CPUID instruction in the "Intel(r) 64 and IA-32 |
||
26 | * Architectures Developer's Manual" at http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html |
||
27 | * the ws_cpuid() routine will return 0 if cpuinfo isn't available. |
||
28 | */ |
||
29 | |||
30 | #if defined(_MSC_VER) /* MSVC */ |
||
31 | static gboolean |
||
32 | ws_cpuid(guint32 *CPUInfo, guint32 selector) |
||
33 | { |
||
34 | CPUInfo[0] = CPUInfo[1] = CPUInfo[2] = CPUInfo[3] = 0; |
||
35 | __cpuid((int *) CPUInfo, selector); |
||
36 | /* XXX, how to check if it's supported on MSVC? just in case clear all flags above */ |
||
37 | return TRUE; |
||
38 | } |
||
39 | |||
40 | #elif defined(__GNUC__) /* GCC/clang */ |
||
41 | |||
42 | #if defined(__x86_64__) |
||
43 | static inline gboolean |
||
44 | ws_cpuid(guint32 *CPUInfo, int selector) |
||
45 | { |
||
46 | __asm__ __volatile__("cpuid" |
||
47 | : "=a" (CPUInfo[0]), |
||
48 | "=b" (CPUInfo[1]), |
||
49 | "=c" (CPUInfo[2]), |
||
50 | "=d" (CPUInfo[3]) |
||
51 | : "a"(selector)); |
||
52 | return TRUE; |
||
53 | } |
||
54 | #elif defined(__i386__) |
||
55 | static gboolean |
||
56 | ws_cpuid(guint32 *CPUInfo _U_, int selector _U_) |
||
57 | { |
||
58 | /* |
||
59 | * TODO: need a test if older proccesors have the cpuid instruction. |
||
60 | * |
||
61 | * The correct way to test for this, according to the Intel64/IA-32 |
||
62 | * documentation from Intel, in section 17.1 "USING THE CPUID |
||
63 | * INSTRUCTION", is to try to change the ID bit (bit 21) in |
||
64 | * EFLAGS. If it can be changed, the machine supports CPUID, |
||
65 | * otherwise it doesn't. |
||
66 | * |
||
67 | * Some 486's, and all subsequent processors, support CPUID. |
||
68 | * |
||
69 | * For those who are curious, the way you distinguish between |
||
70 | * an 80386 and an 80486 is to try to set the flag in EFLAGS |
||
71 | * that causes unaligned accesses to fault - that's bit 18. |
||
72 | * However, if the SMAP bit is set in CR4, that bit controls |
||
73 | * whether explicit supervisor-mode access to user-mode pages |
||
74 | * are allowed, so that should presumably only be done in a |
||
75 | * very controlled environment, such as the system boot process. |
||
76 | * |
||
77 | * So, if you want to find out what type of CPU the system has, |
||
78 | * it's probably best to ask the OS, if it supplies the result |
||
79 | * of any CPU type testing it's done. |
||
80 | */ |
||
81 | return FALSE; |
||
82 | } |
||
83 | #else /* not x86 */ |
||
84 | static gboolean |
||
85 | ws_cpuid(guint32 *CPUInfo _U_, int selector _U_) |
||
86 | { |
||
87 | /* Not x86, so no cpuid instruction */ |
||
88 | return FALSE; |
||
89 | } |
||
90 | #endif |
||
91 | |||
92 | #else /* Other compilers */ |
||
93 | |||
94 | static gboolean |
||
95 | ws_cpuid(guint32 *CPUInfo _U_, int selector _U_) |
||
96 | { |
||
97 | return FALSE; |
||
98 | } |
||
99 | #endif |
||
100 | |||
101 | static int |
||
102 | ws_cpuid_sse42(void) |
||
103 | { |
||
104 | guint32 CPUInfo[4]; |
||
105 | |||
106 | if (!ws_cpuid(CPUInfo, 1)) |
||
107 | return 0; |
||
108 | |||
109 | /* in ECX bit 20 toggled on */ |
||
110 | return (CPUInfo[2] & (1 << 20)); |
||
111 | } |