#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #define RUN_TIME 60 #define SIZE 4096 #define NPROCS 4096 #define NCPU get_nprocs_conf() #define PAGEMAP_LENGTH 8 unsigned long get_pa(void *addr) { FILE *pagemap = fopen("/proc/self/pagemap", "rb"); unsigned long offset = (unsigned long)addr / getpagesize() * PAGEMAP_LENGTH; unsigned long pfn = 0; if(fseek(pagemap, (unsigned long)offset, SEEK_SET) != 0) { fprintf(stderr, "Failed to seek pagemap to proper location\n"); exit(1); } fread(&pfn, 1, PAGEMAP_LENGTH-1, pagemap); pfn &= 0x7FFFFFFFFFFFFF; fclose(pagemap); return pfn * getpagesize(); } int do_work() { int *map, pid; unsigned long pa; if (fork()) exit(0); pid = getpid(); map = mmap(NULL, SIZE, PROT_READ|PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); map[0] = pid; sched_yield(); if (map[0] != pid) { fprintf(stderr, "Corruption: pid %d map[0] %d cpu %d\n", pid, map[0], sched_getcpu()); kill(0, SIGTERM); return 1; } munmap(map, SIZE); return 0; } static void event_open(struct perf_event_attr *ctx_event_attr, int config) { int i, fd; ctx_event_attr->config = config; for (i = 0; i < NCPU; i++) { fd = syscall(__NR_perf_event_open, ctx_event_attr, -1, i, -1, 0); ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); } } static void perf_events() { struct perf_event_attr ctx_event_attr; memset(&ctx_event_attr, 0, sizeof(struct perf_event_attr)); ctx_event_attr.type = PERF_TYPE_SOFTWARE; ctx_event_attr.size = sizeof (struct perf_event_attr); ctx_event_attr.sample_period = 1; ctx_event_attr.sample_type = PERF_SAMPLE_CALLCHAIN; event_open(&ctx_event_attr, PERF_COUNT_SW_CPU_CLOCK); } int main(int argc, char **argv) { pid_t p[NPROCS]; int i, fd; cpu_set_t mask; CPU_ZERO(&mask); for (i = 0; i < NCPU; i++) CPU_SET(i, &mask); sched_setaffinity(0, sizeof(mask), &mask); perf_events(); for (i = 0; i < NPROCS; i++) { p[i] = fork(); if (p[i] == 0) { for (;;) { if (do_work()) { fprintf(stderr, "Bug is detected\n"); kill(0, SIGTERM); exit(1); } } } } sleep(RUN_TIME); printf("Test passed, all good\n"); kill(0, SIGTERM); return 0; }