-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcacheutils.h
More file actions
183 lines (150 loc) · 4.34 KB
/
cacheutils.h
File metadata and controls
183 lines (150 loc) · 4.34 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#ifndef _CACHEUTILS_H_
#define _CACHEUTILS_H_
#include <setjmp.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/utsname.h>
#include <unistd.h>
/* ============================================================
* User configuration
* ============================================================ */
size_t CACHE_MISS = 150;
#define USE_RDTSC_BEGIN_END 0
#define USE_RDTSCP 1
/* ============================================================
* User configuration End
* ============================================================ */
// ---------------------------------------------------------------------------
uint64_t rdtsc() {
uint64_t a, d;
asm volatile("mfence");
#if USE_RDTSCP
asm volatile("rdtscp" : "=a"(a), "=d"(d)::"rcx");
#else
asm volatile("rdtsc" : "=a"(a), "=d"(d));
#endif
a = (d << 32) | a;
asm volatile("mfence");
return a;
}
// ---------------------------------------------------------------------------
void flush(void *p) { asm volatile("clflush 0(%0)\n" : : "c"(p) : "rax"); }
// ---------------------------------------------------------------------------
void maccess(void *p) { asm volatile("movq (%0), %%rax\n" : : "c"(p) : "rax"); }
// ---------------------------------------------------------------------------
void mfence() { asm volatile("mfence"); }
// ---------------------------------------------------------------------------
int flush_reload(void *ptr) {
uint64_t start = 0, end = 0;
#if USE_RDTSC_BEGIN_END
start = rdtsc_begin();
#else
start = rdtsc();
#endif
maccess(ptr);
#if USE_RDTSC_BEGIN_END
end = rdtsc_end();
#else
end = rdtsc();
#endif
mfence();
flush(ptr);
if (end - start < CACHE_MISS) {
return 1;
}
return 0;
}
// ---------------------------------------------------------------------------
int flush_reload_t(void *ptr) {
uint64_t start = 0, end = 0;
#if USE_RDTSC_BEGIN_END
start = rdtsc_begin();
#else
start = rdtsc();
#endif
maccess(ptr);
#if USE_RDTSC_BEGIN_END
end = rdtsc_end();
#else
end = rdtsc();
#endif
mfence();
flush(ptr);
return (int)(end - start);
}
// ---------------------------------------------------------------------------
int reload_t(void *ptr) {
uint64_t start = 0, end = 0;
#if USE_RDTSC_BEGIN_END
start = rdtsc_begin();
#else
start = rdtsc();
#endif
maccess(ptr);
#if USE_RDTSC_BEGIN_END
end = rdtsc_end();
#else
end = rdtsc();
#endif
mfence();
return (int)(end - start);
}
// ---------------------------------------------------------------------------
size_t detect_flush_reload_threshold() {
size_t reload_time = 0, flush_reload_time = 0, i, count = 1000000;
size_t dummy[16];
size_t *ptr = dummy + 8;
maccess(ptr);
for (i = 0; i < count; i++) {
reload_time += reload_t(ptr);
}
for (i = 0; i < count; i++) {
flush_reload_time += flush_reload_t(ptr);
}
reload_time /= count;
flush_reload_time /= count;
return (flush_reload_time + reload_time * 2) / 3;
}
// ---------------------------------------------------------------------------
size_t get_physical_address(size_t vaddr) {
int fd = open("/proc/self/pagemap", O_RDONLY);
uint64_t virtual_addr = (uint64_t)vaddr;
size_t value = 0;
off_t offset = (virtual_addr / 4096) * sizeof(value);
int got = pread(fd, &value, sizeof(value), offset);
if (got != sizeof(value)) {
return 0;
}
close(fd);
return (value << 12) | ((size_t)vaddr & 0xFFFULL);
}
// ---------------------------------------------------------------------------
size_t get_direct_physical_map() {
struct utsname buf;
uname(&buf);
int major = atoi(strtok(buf.release, "."));
int minor = atoi(strtok(NULL, "."));
if ((major == 4 && minor < 19) || major < 4) {
return 0xffff880000000000ull;
} else {
return 0xffff888000000000ull;
}
}
// ---------------------------------------------------------------------------
static jmp_buf trycatch_buf;
// ---------------------------------------------------------------------------
void unblock_signal(int signum __attribute__((__unused__))) {
sigset_t sigs;
sigemptyset(&sigs);
sigaddset(&sigs, signum);
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
}
// ---------------------------------------------------------------------------
void trycatch_segfault_handler(int signum) {
(void)signum;
unblock_signal(SIGSEGV);
unblock_signal(SIGFPE);
longjmp(trycatch_buf, 1);
}
#endif