/* -*- linux-c -*- * * Try to trigger DRAM disturbance errors, as described in * * https://www.ece.cmu.edu/~safari/pubs/kim-isca14.pdf * * Copyright 2014 Pavel Machek , GPLv2+. * * You need to run this on cca 2GB machine, or adjust size below. * CONFIG_STRICT_DEVMEM must not be set. * Boot with "nopat mem=2G" */ #include #include #include #include #include #include #include #include void disturb(char *w1, char *w2) { /* As far as I could tell... this loop should be run for cca 128msec, to run for one full refresh cycle. */ unsigned int i; for (i=0; i< 672000; i++) { __asm__ __volatile__( "movl 0(%0), %%eax \n" \ "movl 0(%1), %%eax \n" \ "clflush 0(%0) \n" \ "clflush 0(%1) \n" \ "mfence" :: "r" (w1), "r" (w2) : "eax" ); } } int main(int argc, char *argv[]) { /* Ok, so we have one memory for checking, but we do need direct access to /dev/mem to access physical memory. /* This needs at least 2GB RAM machine */ long size = 1*1024*1024*1024; long i; unsigned char *mem, *map; int fd; if (size & (size-1)) { printf("Need power of two size\n"); return 1; } mem = malloc(size); memset(mem, 0xff, size); fd = open("/dev/mem", O_RDONLY); // fd = open("/tmp/delme", O_RDONLY); errno = 0; /* We want to avoid low 1MB */ map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 1*1024*1024); if (errno) { printf("Can not mmap ram: %m\n"); return 1; } /* DRAM operates by whole cachelines, so it should not matter which byte in cacheline we access. */ #define MEG8 (8*1024*1024) for (i=0; i<(size-MEG8)/100; i+=4096-64) disturb(map+i, map+i+MEG8); for (i=0; i