bzr branch
http://darksoft.org/webbzr/alps/pcitool
330
by Suren A. Chilingaryan
Support for 64-bit registes |
1 |
#define _POSIX_C_SOURCE 200112L
|
2 |
#define _GNU_SOURCE
|
|
3 |
||
4 |
#include <stdio.h> |
|
5 |
#include <string.h> |
|
6 |
#include <stdint.h> |
|
7 |
#include <unistd.h> |
|
8 |
#include <stdint.h> |
|
9 |
#include <assert.h> |
|
10 |
#include <ctype.h> |
|
11 |
#include <time.h> |
|
12 |
#include <sched.h> |
|
13 |
#include <arpa/inet.h> |
|
14 |
#include <sys/time.h> |
|
15 |
||
16 |
#include "pci.h" |
|
17 |
#include "tools.h" |
|
18 |
#include "error.h" |
|
19 |
||
20 |
static void pcilib_run_cpuid(uint32_t eax, uint32_t ecx, uint32_t* abcd) { |
|
21 |
uint32_t ebx = 0, edx; |
|
22 |
# if defined( __i386__ ) && defined ( __PIC__ )
|
|
23 |
/* in case of PIC under 32-bit EBX cannot be clobbered */
|
|
24 |
__asm__ ( "movl %%ebx, %%edi \n\t cpuid \n\t xchgl %%ebx, %%edi" : "=D" (ebx), |
|
25 |
# else
|
|
26 |
__asm__ ( "cpuid" : "+b" (ebx), |
|
27 |
# endif
|
|
28 |
"+a" (eax), "+c" (ecx), "=d" (edx) ); |
|
29 |
abcd[0] = eax; abcd[1] = ebx; abcd[2] = ecx; abcd[3] = edx; |
|
30 |
}
|
|
31 |
||
32 |
static int pcilib_check_xcr0_ymm() { |
|
33 |
uint32_t xcr0; |
|
34 |
__asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" ); |
|
35 |
return ((xcr0 & 6) == 6); /* checking if xmm and ymm state are enabled in XCR0 */ |
|
36 |
}
|
|
37 |
||
38 |
static int pcilib_check_4th_gen_intel_core_features() { |
|
39 |
uint32_t abcd[4]; |
|
40 |
uint32_t fma_movbe_osxsave_mask = ((1 << 12) | (1 << 22) | (1 << 27)); |
|
41 |
uint32_t avx2_bmi12_mask = (1 << 5) | (1 << 3) | (1 << 8); |
|
42 |
||
43 |
/* CPUID.(EAX=01H, ECX=0H):ECX.FMA[bit 12]==1 &&
|
|
44 |
CPUID.(EAX=01H, ECX=0H):ECX.MOVBE[bit 22]==1 &&
|
|
45 |
CPUID.(EAX=01H, ECX=0H):ECX.OSXSAVE[bit 27]==1 */
|
|
46 |
pcilib_run_cpuid( 1, 0, abcd ); |
|
47 |
if ( (abcd[2] & fma_movbe_osxsave_mask) != fma_movbe_osxsave_mask ) |
|
48 |
return 0; |
|
49 |
||
50 |
if ( ! pcilib_check_xcr0_ymm() ) |
|
51 |
return 0; |
|
52 |
||
53 |
/* CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]==1 &&
|
|
54 |
CPUID.(EAX=07H, ECX=0H):EBX.BMI1[bit 3]==1 &&
|
|
55 |
CPUID.(EAX=07H, ECX=0H):EBX.BMI2[bit 8]==1 */
|
|
56 |
pcilib_run_cpuid( 7, 0, abcd ); |
|
57 |
if ( (abcd[1] & avx2_bmi12_mask) != avx2_bmi12_mask ) |
|
58 |
return 0; |
|
59 |
||
60 |
/* CPUID.(EAX=80000001H):ECX.LZCNT[bit 5]==1 */
|
|
61 |
pcilib_run_cpuid( 0x80000001, 0, abcd ); |
|
62 |
if ( (abcd[2] & (1 << 5)) == 0) |
|
63 |
return 0; |
|
64 |
||
65 |
return 1; |
|
66 |
}
|
|
67 |
||
68 |
static int pcilib_detect_cpu_gen() { |
|
69 |
if (pcilib_check_4th_gen_intel_core_features()) |
|
70 |
return 4; |
|
71 |
return 0; |
|
72 |
}
|
|
73 |
||
74 |
int pcilib_get_cpu_gen() { |
|
75 |
int gen = -1; |
|
76 |
||
77 |
if (gen < 0 ) |
|
78 |
gen = pcilib_detect_cpu_gen(); |
|
79 |
||
80 |
return gen; |
|
81 |
}
|
|
82 |
||
83 |
int pcilib_get_page_mask() { |
|
84 |
int pagesize,pagemask,temp; |
|
85 |
||
86 |
pagesize = sysconf(_SC_PAGESIZE); |
|
87 |
||
88 |
for( pagemask=0, temp = pagesize; temp != 1; ) { |
|
89 |
temp = (temp >> 1); |
|
90 |
pagemask = (pagemask << 1)+1; |
|
91 |
}
|
|
92 |
return pagemask; |
|
93 |
}
|
|
94 |
||
95 |
int pcilib_get_cpu_count() { |
|
96 |
int err; |
|
97 |
||
98 |
int cpu_count; |
|
99 |
cpu_set_t mask; |
|
100 |
||
101 |
err = sched_getaffinity(getpid(), sizeof(mask), &mask); |
|
102 |
if (err) return 1; |
|
103 |
||
104 |
#ifdef CPU_COUNT
|
|
105 |
cpu_count = CPU_COUNT(&mask); |
|
106 |
#else
|
|
107 |
for (cpu_count = 0; cpu_count < CPU_SETSIZE; cpu_count++) { |
|
108 |
if (!CPU_ISSET(cpu_count, &mask)) break; |
|
109 |
}
|
|
110 |
#endif
|
|
111 |
||
112 |
if (!cpu_count) cpu_count = PCILIB_DEFAULT_CPU_COUNT; |
|
113 |
return cpu_count; |
|
114 |
}
|
|
115 |