forked from HexHive/SMoTherSpectre
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpmc.c
112 lines (89 loc) · 3.34 KB
/
pmc.c
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
108
109
110
111
112
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include "pmc.h"
#include "util.h"
/************ Utils to read/write msr files **********************/
void write_to_IA32_PERF_GLOBAL_CTRL(int msr_fd, uint64_t val)
{
VERIFY(pwrite(msr_fd, &val, sizeof(val), 0x38F) == sizeof(val),
"write_to_IA32_PERF_GLOBAL_CTRL");
}
void write_to_IA32_PMCi(int msr_fd, int i, uint64_t val)
{
VERIFY(pwrite(msr_fd, &val, sizeof(val), 0xC1 + i) == sizeof(val),
"write_to_IA32_PMCi");
}
uint64_t read_IA32_PMCi(int msr_fd, int i)
{
uint64_t toret = -1;
VERIFY(pread(msr_fd, &toret, sizeof(toret), 0xC1 + i) == sizeof(toret),
"read_IA32_PMCi");
return toret;
}
void write_to_IA32_PERFEVTSELi(int msr_fd, int i, uint64_t val)
{
VERIFY(pwrite(msr_fd, &val, sizeof(val), 0x186 + i) == sizeof(val),
"write_to_IA32_PERFEVTSELi");
}
/***********************************************************/
volatile int msr_fd;
void setup_pmc(int core, counter *programmables, size_t n_programmables)
{
char msr_path[] = "/dev/cpu/*/msr";
msr_path[9] = '0' + core;
msr_fd = open(msr_path, O_RDWR);
VERIFY(msr_fd >= 0, "open");
/* DISABLE ALL COUNTERS */
write_to_IA32_PERF_GLOBAL_CTRL(msr_fd, 0ull);
/* PROGRAM ALL PMCs */
unsigned i;
for (i = 0; i < n_programmables; i++)
write_to_IA32_PERFEVTSELi(msr_fd, i, programmables[i].hexcode);
int rv = lseek(msr_fd, 0x38F, SEEK_SET);
VERIFY(rv == 0x38F, "lseek");
}
__attribute__((always_inline))
inline void zero_pmc(size_t n_programmables){
unsigned i;
for(i = 0; i < n_programmables; i++)
write_to_IA32_PMCi(msr_fd, i, 0ull);
}
__attribute__((always_inline))
inline void start_pmc() {
uint64_t val = 15ull | (7ull << 32);
asm("mov %[write], %%eax;"
"mov %[fd], %%edi;"
"mov %[val], %%rsi;"
"mov $8, %%edx;"
"syscall;"
:
: [write] "i" (SYS_write),
[val] "r" (&val),
[fd] "m" (msr_fd)
: "eax", "edi", "rsi", "edx");
}
__attribute__((always_inline))
inline void stop_pmc() {
uint64_t val = 0;
asm("mov %[write], %%eax;"
"mov %[fd], %%edi;"
"mov %[val], %%rsi;"
"mov $8, %%edx;"
"syscall;"
:
: [write] "i" (SYS_write),
[val] "r" (&val),
[fd] "m" (msr_fd)
: "eax", "edi", "rsi", "edx");
}
void dump_stats(counter *programmables, size_t n_programmables) {
unsigned i;
for (i = 0; i < n_programmables; i++)
printf(",%s=%9ld", programmables[i].name, read_IA32_PMCi(msr_fd, i));
}
void get_stats(uint64_t *ctrs, size_t n_programmables){
unsigned i;
for(i = 0; i < n_programmables; i++)
ctrs[i] = read_IA32_PMCi(msr_fd, i);
}