Skip to content

Instantly share code, notes, and snippets.

@sandip4n
Created September 20, 2020 10:10
Show Gist options
  • Save sandip4n/ed74629a3060601ea725a04e7089be82 to your computer and use it in GitHub Desktop.
Save sandip4n/ed74629a3060601ea725a04e7089be82 to your computer and use it in GitHub Desktop.
#ifndef __powerpc64__
#error "unsupported architecture"
#endif
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>
#include <perfmon/pfmlib_perf_event.h>
static const char *evname[] = {
// "page-faults",
// "cpu-cycles",
// "L1-dcache-loads",
"L1-dcache-load-misses",
// "L1-dcache-stores",
// "dTLB-load-misses",
// "dTLB-store-misses",
};
static inline
void perf_event_reset(int fd)
{
assert(!ioctl(fd, PERF_EVENT_IOC_RESET, 0));
}
static inline
void perf_event_enable(int fd)
{
assert(!ioctl(fd, PERF_EVENT_IOC_ENABLE, 0));
}
static inline
void perf_event_disable(int fd)
{
assert(!ioctl(fd, PERF_EVENT_IOC_DISABLE, 0));
}
static inline
unsigned long perf_event_read(int fd)
{
unsigned long count;
assert(read(fd, &count, sizeof(unsigned long)) > 0);
return count;
}
static
int perf_event_prepare(const char *name, int level, int group)
{
struct perf_event_attr attr;
int fd;
memset(&attr, 0, sizeof(struct perf_event_attr));
assert(pfm_get_perf_event_encoding(name, level, &attr,
NULL, NULL) == PFM_SUCCESS);
attr.disabled = 1;
assert((fd = perf_event_open(&attr, 0, -1, group, 0)) > 0);
perf_event_reset(fd);
return fd;
}
__attribute__((optimize("0")))
int main(int argc, char **argv)
{
unsigned long pgsize, clsize, clmask;
volatile unsigned int *addr;
int *fd, evcount, idx, i;
void *claddr;
evcount = sizeof(evname) / sizeof(char *);
pfm_initialize();
pgsize = getpagesize();
clsize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
clmask = ~(clsize - 1);
printf("pid = %d, page size = %lu, "
"L1 dcache line size = %lu events = %d\n",
getpid(), pgsize, clsize, evcount);
assert((fd = (int *) malloc(evcount * sizeof(int))));
for (i = 0; i < evcount; i++)
fd[i] = perf_event_prepare(evname[i], PFM_PLM3,
!i ? -1 : fd[0]);
addr = (unsigned int *) mmap(NULL, pgsize, PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
perf_event_enable(fd[0]);
for (i = 0; i < clsize; i++) {
idx = i * clsize / sizeof(unsigned int);
*(addr + idx) = 0xdeadbeef;
claddr = (void *) (((unsigned long) (addr + idx)) & clmask);
__builtin___clear_cache(claddr, claddr + clsize);
}
// assert(!mprotect((void *) addr, pgsize, PROT_READ | PROT_WRITE | PROT_EXEC));
// __builtin___clear_cache(addr, addr + 1);
// addr[0] = 0xdeadbeef;
// __builtin___clear_cache(addr, addr + 1);
perf_event_disable(fd[0]);
for (i = 0; i < evcount; i++)
printf("%s = %lu\n", evname[i], perf_event_read(fd[i]));
munmap((void *) addr, pgsize);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment