1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
#include "common.h"
/***
*
* @param leaf
* @param reg union regs_t
* @return contents of eax register
*/
unsigned int CPUID(unsigned int leaf, union regs_t *reg) {
memset(reg, 0, sizeof(*reg));
__get_cpuid(leaf, ®->gpr.eax, ®->gpr.ebx, ®->gpr.ecx, ®->gpr.edx);
return reg->gpr.eax;
}
int is_cpu_hyperthreaded() {
union regs_t reg;
CPUID(1, ®);
// Hyperthreading feature flag is located in bit 28 of EDX (regs[3])
if (reg.gpr.edx & bit_HTT) {
// hyperthreaded
return 1;
}
return 0;
}
int is_cpu_virtual() {
union regs_t reg;
CPUID(1, ®);
// Virtualization flag is located in bit 31 of ECX
if (reg.gpr.ecx & bit_VRT) {
return 1;
}
return 0;
}
char *get_sys_product() {
union regs_t reg;
static char vendor[255] = {0};
if (is_cpu_virtual()) {
CPUID(0x40000000, ®);
strncat(vendor, (char *) ®.bytes[1], sizeof(reg.bytes));
rstrip(vendor);
}
#if defined(__linux__)
if (!strlen(vendor)) {
strcpy(vendor, get_sys_dmi_product());
rstrip(vendor);
}
#elif defined(__APPLE__)
if (!strlen(vendor)) {
strcpy(vendor, get_sys_product_darwin());
rstrip(vendor);
}
#endif
return vendor;
}
unsigned int get_cpu_count() {
union regs_t reg;
unsigned int result;
if (is_cpu_hyperthreaded()) {
CPUID(1, ®);
// cpu count is located in bits 16:23 of EBX
result = reg.gpr.ebx >> 16 & 0xff;
} else { // Legacy check
// Core Count is located in 0:7 of ECX
CPUID(0x80000008, ®);
result = 1 + (reg.gpr.ecx & 0xff);
}
#if defined(__linux__) || (defined(__APPLE__) || defined(TARGET_OS_MAC))
if (result == 1) {
// One CPU might indicate we were unable to poll the information
// See what the kernel thinks
result = sysconf(_SC_NPROCESSORS_ONLN);
}
#endif
return result;
}
char *get_cpu_manufacturer() {
union regs_t reg;
static char manufacturer[255] = {0};
CPUID(0, ®);
strncat(manufacturer, (char *) ®.bytes[1], 4);
strncat(manufacturer, (char *) ®.bytes[3], 4);
strncat(manufacturer, (char *) ®.bytes[2], 4);
return manufacturer;
}
char *get_cpu_vendor() {
union regs_t reg;
static char vendor[255] = {0};
for (unsigned int leaf = 2; leaf < 5; leaf++) {
CPUID(0x80000000 + leaf, ®);
strncat(vendor, (char *) reg.bytes, sizeof(reg.bytes));
}
rstrip(vendor);
return vendor;
}
|