// vim: set sw=4 ts=4 sts=4 expandtab cindent: #include #include #include #include #include #include #include #include #include #include #include #include #include #define BUFFER_SIZE (1ULL<<30) #define MMAP_FLAGS (MAP_ANONYMOUS|MAP_PRIVATE|MAP_POPULATE|MAP_HUGETLB|(30< cutoff_val) break; } // at this point, addr is an address which conflicts with base. for (int i = 0; i < 30; ++i) { fprintf(stderr, "bit %d/30\r", i+1); void* modified_addr = (void*)((uintptr_t)addr ^ (1 << i)); size_t time = time_accesses(base, modified_addr, NROUNDS); if (time < cutoff_val) { // it now no longer conflicts. therefore, the i'th bit // (partially) determines the bank. bitmask |= (1 << i); } } // export the bitmask of all the BANK bits in the following format: fprintf(stdout, "\n0x%lx\n",bitmask); } /* Returns the ratio of elements which are above the cutoff. */ float cutoff_ratio(int* times, int cutoff) { // to avoid division by zero int above = 1, under = 1; for (int i = 0; i < NSAMPLES; ++i) { if (times[i] > cutoff) above++; else under++; } return ((float)above / (above + under)); } //----------------------------------------------------------------- /* TASK 3: * You can reuse the same code as the one for task 1 to collect * measurements. On top of that after collecting the times you need * to figure out a cutoff value to detect bank hits from bank * conflicts. * */ size_t detect_cutoff(char* buff) { int* times = malloc(NSAMPLES * sizeof(int)); srand(time(NULL)); if (RAND_MAX < BUFFER_SIZE) { fprintf(stderr, "RAND_MAX too low!\n"); exit(-1); } void* base = buff; for (int i = 0; i < NSAMPLES; ++i) { void* addr = buff + (rand() % BUFFER_SIZE); times[i] = time_accesses(base, addr, NROUNDS); fprintf(stderr, "%d/%d\r", i, NSAMPLES); } fprintf(stderr, "\n"); int cutoff = 0; do { float r = cutoff_ratio(times, cutoff); if (r < CONFLICT_RATIO) break; } while (cutoff += 1); fprintf(stderr, "using cutoff: %d\n", cutoff); return cutoff; } //----------------------------------------------------------------- /* * You should not touch the main function. Everything can be * implemented in the different functions stubs we provide. * */ int main(int argc, char** argv) { unsigned char* buff; int fd_hugepage; // allocating a 1GB hugepage fd_hugepage = open(HUGETLBFS, O_CREAT|O_RDWR); assert(fd_hugepage != -1); buff = (unsigned char*) mmap(NULL, BUFFER_SIZE, PROT_READ|PROT_WRITE, MMAP_FLAGS, fd_hugepage, 0 ); assert(buff != (void*)-1); #ifdef TASK_1 export_times(buff); #endif // TASK_1 #ifdef TASK_2 // checking if we passed the cutoff value as argv[1] and extract it assert(argc == 2); size_t cutoff_val = strtoul(argv[1],NULL,10); fprintf(stderr, "cutoff_val: %ld\n", cutoff_val); find_bank_bits(buff, cutoff_val); #endif // TASK_2 #ifdef TASK_3 // automatically detect the cutoff val size_t cutoff_val = detect_cutoff(buff); assert(cutoff_val != TASK_NOT_IMPLEMENTED); // same as TASK_2 find_bank_bits(buff, cutoff_val); #endif // TASK_3 assert (munmap(buff, BUFFER_SIZE) == 0); close(fd_hugepage); return 0; }