diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..6082673 --- /dev/null +++ b/.clang-format @@ -0,0 +1,78 @@ +# Generated from CLion C/C++ Code Style settings +BinPackParameters: false +BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignArrayOfStructures: Left +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: true + AcrossComments: false + +AlignOperands: DontAlign +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakTemplateDeclarations: Yes +# 函数和返回类型分两行,方便阅读 +AlwaysBreakAfterReturnType: TopLevelDefinitions +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +ConstructorInitializerAllOnOneLineOrOnePerLine: true +BreakInheritanceList: BeforeColon +ColumnLimit: 120 +CompactNamespaces: false +ContinuationIndentWidth: 4 +EmptyLineBeforeAccessModifier: LogicalBlock +SeparateDefinitionBlocks: Always +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 4 +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PointerAlignment: Right +ReflowComments: false +SortIncludes: CaseSensitive +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 0 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: Never +PenaltyIndentedWhitespace: 1 diff --git a/drama/src/include/rev-mc.h b/drama/src/include/rev-mc.h index 66aae3f..13c4e08 100644 --- a/drama/src/include/rev-mc.h +++ b/drama/src/include/rev-mc.h @@ -1,14 +1,12 @@ -#include "utils.h" #include "unistd.h" - +#include "utils.h" typedef struct { - char* v_addr; - uint64_t p_addr; + char *v_addr; + uint64_t p_addr; } addr_tuple; //---------------------------------------------------------- // Functions - -void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, char* o_file, uint64_t flags); +void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, char *o_file, uint64_t flags); diff --git a/drama/src/include/utils.h b/drama/src/include/utils.h index 34c46e2..2be7d46 100644 --- a/drama/src/include/utils.h +++ b/drama/src/include/utils.h @@ -1,95 +1,82 @@ -#pragma once +#pragma once #include #include - -#define BIT(x) (1ULL<<(x)) -#define KB(x) ((x)<<10ULL) -#define MB(x) ((x)<<20ULL) -#define GB(x) ((x)<<30ULL) +#define BIT(x) (1ULL << (x)) +#define KB(x) ((x) << 10ULL) +#define MB(x) ((x) << 20ULL) +#define GB(x) ((x) << 30ULL) #define CL_SHIFT 6 #define CL_SIZE 64 +#define F_CLEAR 0L +#define F_VERBOSE BIT(0) +#define F_EXPORT BIT(1) -#define F_CLEAR 0L -#define F_VERBOSE BIT(0) -#define F_EXPORT BIT(1) - -#define MEM_SHIFT (30L) -#define MEM_MASK 0b11111ULL << MEM_SHIFT -#define F_ALLOC_HUGE BIT(MEM_SHIFT) -#define F_ALLOC_HUGE_1G F_ALLOC_HUGE | BIT(MEM_SHIFT+1) -#define F_ALLOC_HUGE_2M F_ALLOC_HUGE | BIT(MEM_SHIFT+2) -#define F_POPULATE BIT(MEM_SHIFT+3) - - +#define MEM_SHIFT (30L) +#define MEM_MASK 0b11111ULL << MEM_SHIFT +#define F_ALLOC_HUGE BIT(MEM_SHIFT) +#define F_ALLOC_HUGE_1G F_ALLOC_HUGE | BIT(MEM_SHIFT + 1) +#define F_ALLOC_HUGE_2M F_ALLOC_HUGE | BIT(MEM_SHIFT + 2) +#define F_POPULATE BIT(MEM_SHIFT + 3) //---------------------------------------------------------- // Static functions -static inline __attribute__((always_inline)) void clflush(volatile void *p) +static inline __attribute__((always_inline)) void +clflush(volatile void *p) { - asm volatile("clflush (%0)\n" - :: "r" (p) : "memory"); + asm volatile("clflush (%0)\n" ::"r"(p) : "memory"); } - -static inline __attribute__((always_inline)) void mfence() +static inline __attribute__((always_inline)) void +mfence() { - asm volatile ("mfence" : : : "memory"); + asm volatile("mfence" : : : "memory"); } - -static inline __attribute__((always_inline)) void lfence() +static inline __attribute__((always_inline)) void +lfence() { - asm volatile ("lfence" : : : "memory"); + asm volatile("lfence" : : : "memory"); } - -static inline __attribute__((always_inline)) uint64_t rdtscp(void) +static inline __attribute__((always_inline)) uint64_t +rdtscp(void) { - uint64_t lo, hi; - asm volatile("rdtscp\n" - : "=a" (lo), "=d" (hi) - :: "%rcx"); - return (hi << 32) | lo; + uint64_t lo, hi; + asm volatile("rdtscp\n" : "=a"(lo), "=d"(hi)::"%rcx"); + return (hi << 32) | lo; } - -static inline __attribute__((always_inline)) uint64_t rdtsc(void) +static inline __attribute__((always_inline)) uint64_t +rdtsc(void) { - uint64_t lo, hi; - asm volatile("rdtsc\n" - : "=a" (lo), "=d" (hi) - :: "%rcx"); - return (hi << 32) | lo; + uint64_t lo, hi; + asm volatile("rdtsc\n" : "=a"(lo), "=d"(hi)::"%rcx"); + return (hi << 32) | lo; } - //---------------------------------------------------------- // Memory alloc - typedef struct { - char* buffer; - uint64_t size; - uint64_t flags; + char *buffer; + uint64_t size; + uint64_t flags; } mem_buff_t; +int alloc_buffer(mem_buff_t *mem); -int alloc_buffer(mem_buff_t* mem); - -int free_buffer(mem_buff_t* mem); - +int free_buffer(mem_buff_t *mem); //---------------------------------------------------------- -// Helpers -int gt(const void * a, const void * b); +// Helpers +int gt(const void *a, const void *b); -double mean(uint64_t* vals, size_t size); +double mean(uint64_t *vals, size_t size); -uint64_t median(uint64_t* vals, size_t size); - -char* bit_string(uint64_t val); +uint64_t median(uint64_t *vals, size_t size); +char *bit_string(uint64_t val); diff --git a/drama/src/main.c b/drama/src/main.c index f24f0e0..aba8089 100644 --- a/drama/src/main.c +++ b/drama/src/main.c @@ -1,134 +1,119 @@ #include "stdio.h" // #include /* for rdtsc, rdtscp, clflush */ -#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "utils.h" #include "rev-mc.h" +#include "utils.h" - -#define SETS_std (2*16) // 1rk-1ch -#define ROUNDS_std 1000 -#define THRESHOLD_std 340 -#define MEM_SIZE_std GB(5L) -#define O_FILE_std "access.csv" - +#define SETS_std (2 * 16)// 1rk-1ch +#define ROUNDS_std 1000 +#define THRESHOLD_std 340 +#define MEM_SIZE_std GB(5L) +#define O_FILE_std "access.csv" #define FIELDS "base,probe,rounds,time" - //----------------------------------------------- // GLOBALS - - //----------------------------------------------- -void print_usage() { - fprintf(stderr, "[ LOG ] - Usage ./test [-h] [-s sets] [-r rounds] [-t threshold] [-o o_file] [-v] [--mem mem_size]\n"); +void +print_usage() +{ + fprintf(stderr, + "[ LOG ] - Usage ./test [-h] [-s sets] [-r rounds] [-t threshold] [-o o_file] [-v] [--mem mem_size]\n"); fprintf(stderr, " -h = this help message\n"); fprintf(stderr, " -s sets = number of expected sets (default: %d)\n", SETS_std); - fprintf(stderr, " -r rounds = number of rounds per tuple (default: %d)\n", ROUNDS_std); - fprintf(stderr, " -t threshold = time threshold for conflicts (default: %d)\n", THRESHOLD_std); - fprintf(stderr, " -o o_file = output file for mem profiling (default: %s)\n", O_FILE_std); - fprintf(stderr, " --mem mem_size = allocation size (default: %ld)\n", (uint64_t) MEM_SIZE_std); + fprintf(stderr, " -r rounds = number of rounds per tuple (default: %d)\n", + ROUNDS_std); + fprintf(stderr, " -t threshold = time threshold for conflicts (default: %d)\n", + THRESHOLD_std); + fprintf(stderr, " -o o_file = output file for mem profiling (default: %s)\n", + O_FILE_std); + fprintf(stderr, " --mem mem_size = allocation size (default: %ld)\n", + (uint64_t) MEM_SIZE_std); fprintf(stderr, " -v = verbose\n\n"); } - - - - - - - - - //----------------------------------------------- -int main(int argc, char** argv) { +int +main(int argc, char **argv) +{ - uint64_t flags = 0ULL; - size_t sets_cnt = SETS_std; - size_t rounds = ROUNDS_std; - size_t m_size = MEM_SIZE_std; - size_t threshold = THRESHOLD_std; - char* o_file = (char*) O_FILE_std; + uint64_t flags = 0ULL; + size_t sets_cnt = SETS_std; + size_t rounds = ROUNDS_std; + size_t m_size = MEM_SIZE_std; + size_t threshold = THRESHOLD_std; + char *o_file = (char *) O_FILE_std; flags |= F_POPULATE; - - if(geteuid() != 0) { - fprintf(stderr, "[ERROR] - You need to run as root to access pagemap!\n"); - exit(1); + + if (geteuid() != 0) { + fprintf(stderr, "[ERROR] - You need to run as root to access pagemap!\n"); + exit(1); } while (1) { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - /* These options set a flag. */ - {"mem", required_argument, 0, 0}, - {0, 0, 0, 0} - }; - int arg = getopt_long (argc, argv, "o:s:r:t:hv", - long_options, &option_index); + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + /* These options set a flag. */ + {"mem", required_argument, 0, 0}, + {0, 0, 0, 0} + }; + int arg = getopt_long(argc, argv, "o:s:r:t:hv", long_options, &option_index); - if (arg == -1) - break; + if (arg == -1) break; - switch(arg) { + switch (arg) { + case 0: + switch (option_index) { case 0: - switch (option_index){ - case 0: - m_size = atoi(optarg); // TODO proper parsing of this - break; - default: - break; - } + m_size = atoi(optarg);// TODO proper parsing of this break; - case 'o': - o_file = (char*) malloc(sizeof(char)*strlen(optarg)); - strncpy(o_file, optarg, strlen(optarg)); - flags |= F_EXPORT; - break; - case 's': - sets_cnt = atoi(optarg); - break; - case 'r': - rounds = atoi(optarg); - break; - case 't': - threshold = atoi(optarg); - break; - case 'v': - flags |= F_VERBOSE; - break; - case 'h': default: - print_usage(); - return 0; - + break; + } + break; + case 'o': + o_file = (char *) malloc(sizeof(char) * strlen(optarg)); + strncpy(o_file, optarg, strlen(optarg)); + flags |= F_EXPORT; + break; + case 's': + sets_cnt = atoi(optarg); + break; + case 'r': + rounds = atoi(optarg); + break; + case 't': + threshold = atoi(optarg); + break; + case 'v': + flags |= F_VERBOSE; + break; + case 'h': + default: + print_usage(); + return 0; } } - - rev_mc(sets_cnt, threshold, rounds, m_size, o_file, flags); return 0; - } - - - /*I'm refactoring the set struct to add also timing in there. */ diff --git a/drama/src/rev-mc.c b/drama/src/rev-mc.c index c11eb4d..3efb209 100644 --- a/drama/src/rev-mc.c +++ b/drama/src/rev-mc.c @@ -19,24 +19,21 @@ #define BOOL_XOR(a, b) ((a) != (b)) #define O_HEADER "base,probe,time\n" -#define ALIGN_TO(X, Y) \ - ((X) & (~((1LL << (Y)) - 1LL))) // Mask out the lower Y bits -#define LS_BITMASK(X) ((1LL << (X)) - 1LL) // Mask only the lower X bits +#define ALIGN_TO(X, Y) ((X) & (~((1LL << (Y)) - 1LL)))// Mask out the lower Y bits +#define LS_BITMASK(X) ((1LL << (X)) - 1LL) // Mask only the lower X bits -#define SET_SIZE 40 // elements per set +#define SET_SIZE 40// elements per set #define VALID_THRESH 0.75f #define SET_THRESH 0.95f -#define BITSET_SIZE 256 // bitset used to exploit bitwise operations +#define BITSET_SIZE 256// bitset used to exploit bitwise operations #define ROW_SET_CNT 5 // from // https://stackoverflow.com/questions/1644868/define-macro-for-debug-printing-in-c -#define verbose_printerr(fmt, ...) \ - do { \ - if (flags & F_VERBOSE) { \ - fprintf(stderr, fmt, ##__VA_ARGS__); \ - } \ - } while (0) +#define verbose_printerr(fmt, ...) \ + do { \ + if (flags & F_VERBOSE) { fprintf(stderr, fmt, ##__VA_ARGS__); } \ + } while (0) typedef std::vector set_t; @@ -52,200 +49,198 @@ void verify_sets(std::vector &sets, uint64_t threshold, size_t rounds); #pragma push_options #pragma optimize("O0") static std::vector time_vals; -uint64_t time_tuple(volatile char *a1, volatile char *a2, size_t rounds) { - // uint64_t* time_vals = (uint64_t*) calloc(rounds, sizeof(uint64_t)); - if (rounds > time_vals.size()) - time_vals.resize(rounds); +uint64_t +time_tuple(volatile char *a1, volatile char *a2, size_t rounds) +{ - uint64_t t0; - sched_yield(); - for (size_t i = 0; i < rounds; i++) { - mfence(); - t0 = rdtscp(); - *a1; - *a2; - time_vals[i] = rdtscp() - t0; - lfence(); - clflush(a1); - clflush(a2); - } + // uint64_t* time_vals = (uint64_t*) calloc(rounds, sizeof(uint64_t)); + if (rounds > time_vals.size()) time_vals.resize(rounds); - uint64_t mdn = median(time_vals.data(), rounds); - // free(time_vals); - return mdn; + uint64_t t0; + sched_yield(); + for (size_t i = 0; i < rounds; i++) { + mfence(); + t0 = rdtscp(); + *a1; + *a2; + time_vals[i] = rdtscp() - t0; + lfence(); + clflush(a1); + clflush(a2); + } + + uint64_t mdn = median(time_vals.data(), rounds); + // free(time_vals); + return mdn; } + #pragma pop_options //---------------------------------------------------------- -char *get_rnd_addr(char *base, size_t m_size, size_t align) { - return (char *)ALIGN_TO((uint64_t)base, (uint64_t)align) + - ALIGN_TO(rand() % m_size, (uint64_t)align); +char * +get_rnd_addr(char *base, size_t m_size, size_t align) +{ + return (char *) ALIGN_TO((uint64_t) base, (uint64_t) align) + ALIGN_TO(rand() % m_size, (uint64_t) align); } //---------------------------------------------------------- -uint64_t get_pfn(uint64_t entry) { return ((entry) & 0x3fffffffffffff); } - -//---------------------------------------------------------- -uint64_t get_phys_addr(uint64_t v_addr) { - uint64_t entry; - uint64_t offset = (v_addr / 4096) * sizeof(entry); - uint64_t pfn; - int fd = open("/proc/self/pagemap", O_RDONLY); - assert(fd >= 0); - int bytes_read = pread(fd, &entry, sizeof(entry), offset); - close(fd); - assert(bytes_read == 8); - assert(entry & (1ULL << 63)); - pfn = get_pfn(entry); - assert(pfn != 0 && "pfn is zero !!!!!"); - return (pfn * 4096) | (v_addr & 4095); +uint64_t +get_pfn(uint64_t entry) +{ + return ((entry) & 0x3fffffffffffff); } //---------------------------------------------------------- -addr_tuple gen_addr_tuple(char *v_addr) { - return (addr_tuple){v_addr, get_phys_addr((uint64_t)v_addr)}; +uint64_t +get_phys_addr(uint64_t v_addr) +{ + uint64_t entry; + uint64_t offset = (v_addr / 4096) * sizeof(entry); + uint64_t pfn; + int fd = open("/proc/self/pagemap", O_RDONLY); + assert(fd >= 0); + int bytes_read = pread(fd, &entry, sizeof(entry), offset); + close(fd); + assert(bytes_read == 8); + assert(entry & (1ULL << 63)); + pfn = get_pfn(entry); + assert(pfn != 0 && "pfn is zero !!!!!"); + return (pfn * 4096) | (v_addr & 4095); +} + +//---------------------------------------------------------- +addr_tuple +gen_addr_tuple(char *v_addr) +{ + return (addr_tuple){v_addr, get_phys_addr((uint64_t) v_addr)}; } //---------------------------------------------------------- // https://www.cs.umd.edu/~gasarch/TOPICS/factoring/fastgauss.pdf // gaussian elimination in GF2 -std::vector reduce_masks(std::vector masks) { +std::vector +reduce_masks(std::vector masks) +{ - size_t height, width, height_t, width_t; + size_t height, width, height_t, width_t; - height = masks.size(); - width = 0; - for (auto m : masks) { - uint64_t max_one = 64 - __builtin_clzl(m); - width = (max_one > width) ? max_one : width; - } - - height_t = width; - width_t = height; - - std::vector> mtx(height, std::vector(width)); - std::vector> mtx_t(height_t, std::vector(width_t)); - std::vector filtered_masks; - - for (size_t i = 0; i < height; i++) { - for (size_t j = 0; j < width; j++) { - mtx[i][width - j - 1] = (masks[i] & (1ULL << (j))); + height = masks.size(); + width = 0; + for (auto m : masks) { + uint64_t max_one = 64 - __builtin_clzl(m); + width = (max_one > width) ? max_one : width; } - } - for (size_t i = 0; i < height; i++) { - for (size_t j = 0; j < width; j++) { - mtx_t[j][i] = mtx[i][j]; + height_t = width; + width_t = height; + + std::vector> mtx(height, std::vector(width)); + std::vector> mtx_t(height_t, std::vector(width_t)); + std::vector filtered_masks; + + for (size_t i = 0; i < height; i++) { + for (size_t j = 0; j < width; j++) { mtx[i][width - j - 1] = (masks[i] & (1ULL << (j))); } } - } - int64_t pvt_col = 0; + for (size_t i = 0; i < height; i++) { + for (size_t j = 0; j < width; j++) { mtx_t[j][i] = mtx[i][j]; } + } - while (pvt_col < width_t) { - for (uint64_t row = 0; row < height_t; row++) { - if (mtx_t[row][pvt_col]) { - filtered_masks.push_back(masks[pvt_col]); - for (size_t c = 0; c < width_t; c++) { - if (c == pvt_col) - continue; - if (!(mtx_t[row][c])) - continue; + int64_t pvt_col = 0; - // column sum - for (size_t r = 0; r < height_t; r++) { - mtx_t[r][c] = BOOL_XOR(mtx_t[r][c], mtx_t[r][pvt_col]); - } + while (pvt_col < width_t) { + for (uint64_t row = 0; row < height_t; row++) { + if (mtx_t[row][pvt_col]) { + filtered_masks.push_back(masks[pvt_col]); + for (size_t c = 0; c < width_t; c++) { + if (c == pvt_col) continue; + if (!(mtx_t[row][c])) continue; + + // column sum + for (size_t r = 0; r < height_t; r++) { mtx_t[r][c] = BOOL_XOR(mtx_t[r][c], mtx_t[r][pvt_col]); } + } + break; + } } - break; - } + pvt_col++; } - pvt_col++; - } - return filtered_masks; + return filtered_masks; } //---------------------------------------------------------- // from https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation -uint64_t next_bit_permutation(uint64_t v) { - uint64_t t = v | (v - 1); - return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctzl(v) + 1)); +uint64_t +next_bit_permutation(uint64_t v) +{ + uint64_t t = v | (v - 1); + return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctzl(v) + 1)); } //---------------------------------------------------------- -std::vector find_functions(std::vector sets, - size_t max_fn_bits, size_t msb, - uint64_t flags) { +std::vector +find_functions(std::vector sets, size_t max_fn_bits, size_t msb, uint64_t flags) +{ - std::vector masks; - verbose_printerr("~~~~~~~~~~ Candidate functions ~~~~~~~~~~\n"); + std::vector masks; + verbose_printerr("~~~~~~~~~~ Candidate functions ~~~~~~~~~~\n"); - for (size_t bits = 1L; bits <= max_fn_bits; bits++) { - uint64_t fn_mask = - ((1L << (bits)) - - 1); // avoid the first 6 bits since they are the cacheline bits - uint64_t last_mask = (fn_mask << (msb - bits)); - fn_mask <<= CL_SHIFT; - verbose_printerr("[ LOG ] - #Bits: %ld \n", bits); - while (fn_mask != last_mask) { - if (fn_mask & LS_BITMASK(6)) { - fn_mask = next_bit_permutation(fn_mask); - continue; - } - for (size_t idx = 0; idx < sets.size(); idx++) { - set_t curr_set = sets[idx]; - size_t inner_cnt = 0; - for (size_t i = 1; i < curr_set.size(); i++) { - uint64_t res_base = __builtin_parityl(curr_set[0].p_addr & fn_mask); - uint64_t res_probe = __builtin_parityl(curr_set[i].p_addr & fn_mask); - if (res_base != res_probe) { - goto next_mask; - } + for (size_t bits = 1L; bits <= max_fn_bits; bits++) { + uint64_t fn_mask = ((1L << (bits)) - 1);// avoid the first 6 bits since they are the cacheline bits + uint64_t last_mask = (fn_mask << (msb - bits)); + fn_mask <<= CL_SHIFT; + verbose_printerr("[ LOG ] - #Bits: %ld \n", bits); + while (fn_mask != last_mask) { + if (fn_mask & LS_BITMASK(6)) { + fn_mask = next_bit_permutation(fn_mask); + continue; + } + for (size_t idx = 0; idx < sets.size(); idx++) { + set_t curr_set = sets[idx]; + size_t inner_cnt = 0; + for (size_t i = 1; i < curr_set.size(); i++) { + uint64_t res_base = __builtin_parityl(curr_set[0].p_addr & fn_mask); + uint64_t res_probe = __builtin_parityl(curr_set[i].p_addr & fn_mask); + if (res_base != res_probe) { goto next_mask; } + } + } + verbose_printerr("\t Candidate: 0x%0lx \t\t bits: %s\n", fn_mask, bit_string(fn_mask)); + masks.push_back(fn_mask); + + next_mask: + fn_mask = next_bit_permutation(fn_mask); } - } - verbose_printerr("\t Candidate: 0x%0lx \t\t bits: %s\n", fn_mask, - bit_string(fn_mask)); - masks.push_back(fn_mask); - - next_mask: - fn_mask = next_bit_permutation(fn_mask); } - } - verbose_printerr("~~~~~~~~~~ Found Functions ~~~~~~~~~~\n"); - masks = reduce_masks(masks); - if (flags & F_VERBOSE) { - for (auto m : masks) { - fprintf(stderr, "\t Valid Function: 0x%0lx \t\t bits: %s\n", m, - bit_string(m)); + verbose_printerr("~~~~~~~~~~ Found Functions ~~~~~~~~~~\n"); + masks = reduce_masks(masks); + if (flags & F_VERBOSE) { + for (auto m : masks) { fprintf(stderr, "\t Valid Function: 0x%0lx \t\t bits: %s\n", m, bit_string(m)); } } - } - for (auto m : masks) { - fprintf(stdout, "0x%lx\n", m); - } - return masks; + for (auto m : masks) { fprintf(stdout, "0x%lx\n", m); } + return masks; } -std::vector find_set_bits(uint64_t val) { - std::vector set_bits; - for (int i = 0; i < 64; i++) { - if (!(val & (1ULL << i))) - continue; +std::vector +find_set_bits(uint64_t val) +{ + std::vector set_bits; + for (int i = 0; i < 64; i++) { + if (!(val & (1ULL << i))) continue; - set_bits.push_back(i); - } - return set_bits; + set_bits.push_back(i); + } + return set_bits; } //---------------------------------------------------------- -std::vector get_dram_fn(uint64_t addr, - std::vector fn_masks) { - std::vector addr_dram; - for (auto fn : fn_masks) { - addr_dram.push_back(__builtin_parityl(addr & fn)); - } - return addr_dram; +std::vector +get_dram_fn(uint64_t addr, std::vector fn_masks) +{ + std::vector addr_dram; + for (auto fn : fn_masks) { addr_dram.push_back(__builtin_parityl(addr & fn)); } + return addr_dram; } //---------------------------------------------------------- @@ -254,168 +249,155 @@ It currently finds some of the interesting bits for the row addressing. @TODO still need to figure out which bits are used for the row addressing and which are from the bank selection. This is currently done manually */ -uint64_t find_row_mask(std::vector &sets, std::vector fn_masks, - mem_buff_t mem, uint64_t threshold, uint64_t flags) { +uint64_t +find_row_mask(std::vector &sets, + std::vector fn_masks, + mem_buff_t mem, + uint64_t threshold, + uint64_t flags) +{ - addr_tuple base_addr = gen_addr_tuple(get_rnd_addr(mem.buffer, mem.size, 0)); - std::vector same_row_sets; + addr_tuple base_addr = gen_addr_tuple(get_rnd_addr(mem.buffer, mem.size, 0)); + std::vector same_row_sets; - verbose_printerr("~~~~~~~~~~ Looking for row bits ~~~~~~~~~~\n"); + verbose_printerr("~~~~~~~~~~ Looking for row bits ~~~~~~~~~~\n"); - for (int i = 0; i < 2; i++) { - verbose_printerr("[LOG] - Set #%d\n", i); - addr_tuple base_addr = sets[i][0]; - std::vector base_dram = - get_dram_fn((uint64_t)base_addr.p_addr, fn_masks); - same_row_sets.push_back({base_addr}); - uint64_t cnt = 0; - while (cnt < ROW_SET_CNT) { + for (int i = 0; i < 2; i++) { + verbose_printerr("[LOG] - Set #%d\n", i); + addr_tuple base_addr = sets[i][0]; + std::vector base_dram = get_dram_fn((uint64_t) base_addr.p_addr, fn_masks); + same_row_sets.push_back({base_addr}); + uint64_t cnt = 0; + while (cnt < ROW_SET_CNT) { - addr_tuple tmp = gen_addr_tuple(get_rnd_addr(mem.buffer, mem.size, 0)); - if (get_dram_fn((uint64_t)tmp.p_addr, fn_masks) != base_dram) - continue; + addr_tuple tmp = gen_addr_tuple(get_rnd_addr(mem.buffer, mem.size, 0)); + if (get_dram_fn((uint64_t) tmp.p_addr, fn_masks) != base_dram) continue; - uint64_t time = time_tuple((volatile char *)base_addr.v_addr, - (volatile char *)tmp.v_addr, 1000); + uint64_t time = time_tuple((volatile char *) base_addr.v_addr, (volatile char *) tmp.v_addr, 1000); - if (time > threshold) - continue; + if (time > threshold) continue; - verbose_printerr("[LOG] - %lx - %lx\t Time: %ld <== GOTCHA\n", - base_addr.p_addr, tmp.p_addr, time); + verbose_printerr("[LOG] - %lx - %lx\t Time: %ld <== GOTCHA\n", base_addr.p_addr, tmp.p_addr, time); - same_row_sets[i].push_back(tmp); - cnt++; - } - } - - uint64_t row_mask = LS_BITMASK(16); // use 16 bits for the row - uint64_t last_mask = (row_mask << (40 - 16)); - row_mask <<= - CL_SHIFT; // skip the lowest 6 bits since they're used for CL addressing - - while (row_mask < last_mask) { - if (row_mask & LS_BITMASK(CL_SHIFT)) { - row_mask = next_bit_permutation(row_mask); - continue; - } - - for (auto addr_pool : same_row_sets) { - addr_tuple base_addr = addr_pool[0]; - for (int i = 1; i < addr_pool.size(); i++) { - addr_tuple tmp = addr_pool[i]; - if ((tmp.p_addr & row_mask) != (base_addr.p_addr & row_mask)) { - goto next_mask; + same_row_sets[i].push_back(tmp); + cnt++; } - } } - break; + uint64_t row_mask = LS_BITMASK(16);// use 16 bits for the row + uint64_t last_mask = (row_mask << (40 - 16)); + row_mask <<= CL_SHIFT;// skip the lowest 6 bits since they're used for CL addressing - next_mask: - row_mask = next_bit_permutation(row_mask); - } + while (row_mask < last_mask) { + if (row_mask & LS_BITMASK(CL_SHIFT)) { + row_mask = next_bit_permutation(row_mask); + continue; + } - // super hackish way to recover the real row mask - for (auto m : fn_masks) { - uint64_t lsb = (1 << (__builtin_ctzl(m) + 1)); - if (lsb & row_mask) { - row_mask ^= (1 << __builtin_ctzl(m)); + for (auto addr_pool : same_row_sets) { + addr_tuple base_addr = addr_pool[0]; + for (int i = 1; i < addr_pool.size(); i++) { + addr_tuple tmp = addr_pool[i]; + if ((tmp.p_addr & row_mask) != (base_addr.p_addr & row_mask)) { goto next_mask; } + } + } + + break; + + next_mask: + row_mask = next_bit_permutation(row_mask); } - } - verbose_printerr("[LOG] - Row mask: 0x%0lx \t\t bits: %s\n", row_mask, - bit_string(row_mask)); - printf("0x%lx\n", row_mask); - return row_mask; + + // super hackish way to recover the real row mask + for (auto m : fn_masks) { + uint64_t lsb = (1 << (__builtin_ctzl(m) + 1)); + if (lsb & row_mask) { row_mask ^= (1 << __builtin_ctzl(m)); } + } + verbose_printerr("[LOG] - Row mask: 0x%0lx \t\t bits: %s\n", row_mask, bit_string(row_mask)); + printf("0x%lx\n", row_mask); + return row_mask; } //---------------------------------------------------------- -void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, - char *o_file, uint64_t flags) { +void +rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, char *o_file, uint64_t flags) +{ - time_t t; + time_t t; - int o_fd = 0; - int huge_fd = 0; - std::vector sets; - // std::vector used_addr; - std::set used_addr; - std::vector fn_masks; + int o_fd = 0; + int huge_fd = 0; + std::vector sets; + // std::vector used_addr; + std::set used_addr; + std::vector fn_masks; - srand((unsigned)time(&t)); + srand((unsigned) time(&t)); - if (flags & F_EXPORT) { - if (o_file == NULL) { - fprintf(stderr, "[ERROR] - Missing export file name\n"); - exit(1); + if (flags & F_EXPORT) { + if (o_file == NULL) { + fprintf(stderr, "[ERROR] - Missing export file name\n"); + exit(1); + } + if ((o_fd = open(o_file, O_CREAT | O_RDWR, 0644)) == -1) { + perror("[ERROR] - Unable to create export file"); + exit(1); + } + dprintf(o_fd, O_HEADER); } - if ((o_fd = open(o_file, O_CREAT | O_RDWR, 0644)) == -1) { - perror("[ERROR] - Unable to create export file"); - exit(1); + + mem_buff_t mem = { + .buffer = NULL, + .size = m_size, + .flags = flags, + }; + + alloc_buffer(&mem); + + while (!found_enough(sets, sets_cnt, SET_SIZE)) { + char *rnd_addr = get_rnd_addr(mem.buffer, mem.size, CL_SHIFT); + if (is_in(rnd_addr, used_addr)) continue; + + // used_addr.push_back(rnd_addr); + used_addr.insert(rnd_addr); + + addr_tuple tp = gen_addr_tuple(rnd_addr); + bool found_set = false; + for (size_t idx = 0; idx < sets.size(); idx++) { + uint64_t time = 0; + addr_tuple tmp = sets[idx][0]; + time = time_tuple((volatile char *) tmp.v_addr, (volatile char *) tp.v_addr, rounds); + if (flags & F_EXPORT) { dprintf(o_fd, "%lx,%lx,%ld\n", (uint64_t) tp.v_addr, (uint64_t) tmp.v_addr, time); } + if (time > threshold) { + verbose_printerr("[LOG] - [%ld] Set: %03ld -\t %lx - %lx\t Time: %ld\n", used_addr.size(), idx, + tp.p_addr, tmp.p_addr, time); + sets[idx].push_back(tp); + found_set = true; + break; + } + } + if (!found_set) { + sets.push_back({tp}); + verbose_printerr("[LOG] - Set: %03ld -\t %p " + " <== NEW!!\n", + sets.size(), tp.v_addr); + } } - dprintf(o_fd, O_HEADER); - } - mem_buff_t mem = { - .buffer = NULL, - .size = m_size, - .flags = flags, - }; - - alloc_buffer(&mem); - - while (!found_enough(sets, sets_cnt, SET_SIZE)) { - char *rnd_addr = get_rnd_addr(mem.buffer, mem.size, CL_SHIFT); - if (is_in(rnd_addr, used_addr)) - continue; - - // used_addr.push_back(rnd_addr); - used_addr.insert(rnd_addr); - - addr_tuple tp = gen_addr_tuple(rnd_addr); - bool found_set = false; - for (size_t idx = 0; idx < sets.size(); idx++) { - uint64_t time = 0; - addr_tuple tmp = sets[idx][0]; - time = time_tuple((volatile char *)tmp.v_addr, (volatile char *)tp.v_addr, - rounds); - if (flags & F_EXPORT) { - dprintf(o_fd, "%lx,%lx,%ld\n", (uint64_t)tp.v_addr, - (uint64_t)tmp.v_addr, time); - } - if (time > threshold) { - verbose_printerr("[LOG] - [%ld] Set: %03ld -\t %lx - %lx\t Time: %ld\n", - used_addr.size(), idx, tp.p_addr, tmp.p_addr, time); - sets[idx].push_back(tp); - found_set = true; - break; - } - } - if (!found_set) { - sets.push_back({tp}); - verbose_printerr("[LOG] - Set: %03ld -\t %p " - " <== NEW!!\n", - sets.size(), tp.v_addr); - } - } - - filter_sets(sets, SET_SIZE); + filter_sets(sets, SET_SIZE); #ifdef DEBUG_SETS - fprintf(stderr, - "[ LOG ] - Cleansing sets. This may take a while... stay put\n"); - verify_sets(sets, threshold, rounds); - fprintf(stderr, "[ LOG ] - Done\n"); + fprintf(stderr, "[ LOG ] - Cleansing sets. This may take a while... stay put\n"); + verify_sets(sets, threshold, rounds); + fprintf(stderr, "[ LOG ] - Done\n"); #endif - if (flags & F_VERBOSE) { - print_sets(sets); - } + if (flags & F_VERBOSE) { print_sets(sets); } - fn_masks = find_functions(sets, 6, 30, flags); - uint64_t row_mask = find_row_mask(sets, fn_masks, mem, threshold, flags); + fn_masks = find_functions(sets, 6, 30, flags); + uint64_t row_mask = find_row_mask(sets, fn_masks, mem, threshold, flags); - free_buffer(&mem); + free_buffer(&mem); } // Fin. @@ -423,87 +405,86 @@ void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, //---------------------------------------------------------- // Helpers -bool is_in(char *val, std::set arr) { - return arr.find(val) != arr.end(); +bool +is_in(char *val, std::set arr) +{ + return arr.find(val) != arr.end(); } -bool is_in(char *val, std::vector arr) { - for (auto v : arr) { - if (val == v) { - return true; +bool +is_in(char *val, std::vector arr) +{ + for (auto v : arr) { + if (val == v) { return true; } } - } - return false; + return false; } //---------------------------------------------------------- -bool found_enough(std::vector sets, uint64_t set_cnt, size_t set_size) { +bool +found_enough(std::vector sets, uint64_t set_cnt, size_t set_size) +{ - size_t found_sets = 0; + size_t found_sets = 0; - for (int i = 0; i < sets.size(); i++) { - set_t curr_set = sets[i]; - if (curr_set.size() > set_size) { - found_sets += 1; + for (int i = 0; i < sets.size(); i++) { + set_t curr_set = sets[i]; + if (curr_set.size() > set_size) { found_sets += 1; } } - } - if (found_sets > set_cnt) { - fprintf( - stderr, - "[ERROR] - Found too many sets. Is %ld the correct number of sets?\n", - set_cnt); - exit(1); - } + if (found_sets > set_cnt) { + fprintf(stderr, "[ERROR] - Found too many sets. Is %ld the correct number of sets?\n", set_cnt); + exit(1); + } - return (found_sets >= (set_cnt * SET_THRESH)) ? true : false; + return (found_sets >= (set_cnt * SET_THRESH)) ? true : false; } -void filter_sets(std::vector &sets, size_t set_size) { +void +filter_sets(std::vector &sets, size_t set_size) +{ - for (auto s = sets.begin(); s < sets.end(); s++) { - if (s->size() < set_size) { - sets.erase(s); - s -= 1; + for (auto s = sets.begin(); s < sets.end(); s++) { + if (s->size() < set_size) { + sets.erase(s); + s -= 1; + } } - } } -void print_sets(std::vector sets) { +void +print_sets(std::vector sets) +{ - for (int idx = 0; idx < sets.size(); idx++) { - fprintf(stderr, "[LOG] - Set: %d\tSize: %ld\n", idx, sets[idx].size()); - for (auto tmp : sets[idx]) { - fprintf(stderr, "\tv_addr:%p - p_addr:%p\n", tmp.v_addr, - (void *)tmp.p_addr); + for (int idx = 0; idx < sets.size(); idx++) { + fprintf(stderr, "[LOG] - Set: %d\tSize: %ld\n", idx, sets[idx].size()); + for (auto tmp : sets[idx]) { fprintf(stderr, "\tv_addr:%p - p_addr:%p\n", tmp.v_addr, (void *) tmp.p_addr); } } - } } #ifdef DEBUG_SETS -void verify_sets(std::vector &sets, uint64_t threshold, size_t rounds) { +void +verify_sets(std::vector &sets, uint64_t threshold, size_t rounds) +{ - for (auto s : sets) { - // test every address against all the addresses in the set - for (auto tp_base = s.begin(); tp_base < s.end(); tp_base++) { - uint64_t conflicts = 0; - for (auto tp_probe = s.begin(); tp_probe < s.end(); tp_probe++) { - if (tp_base == tp_probe) - continue; + for (auto s : sets) { + // test every address against all the addresses in the set + for (auto tp_base = s.begin(); tp_base < s.end(); tp_base++) { + uint64_t conflicts = 0; + for (auto tp_probe = s.begin(); tp_probe < s.end(); tp_probe++) { + if (tp_base == tp_probe) continue; - uint64_t time = time_tuple((volatile char *)tp_base->v_addr, - (volatile char *)tp_probe->v_addr, rounds); - if (time > threshold) { - conflicts += 1; + uint64_t time = + time_tuple((volatile char *) tp_base->v_addr, (volatile char *) tp_probe->v_addr, rounds); + if (time > threshold) { conflicts += 1; } + } + if (!(conflicts > VALID_THRESH * s.size())) { + fprintf(stderr, "[ LOG ] - Removing: %p\n", tp_base->v_addr); + s.erase(tp_base--);// reset the iterator + } } - } - if (!(conflicts > VALID_THRESH * s.size())) { - fprintf(stderr, "[ LOG ] - Removing: %p\n", tp_base->v_addr); - s.erase(tp_base--); // reset the iterator - } } - } } #endif diff --git a/drama/src/utils.c b/drama/src/utils.c index 1e39a44..28e3075 100644 --- a/drama/src/utils.c +++ b/drama/src/utils.c @@ -1,87 +1,84 @@ -#include -#include -#include +#include +#include #include #include #include -#include -#include -#include #include +#include +#include +#include +#include #include "utils.h" - //----------------------------------------------- // Memory alloc -int alloc_buffer(mem_buff_t* mem) { - if (mem->buffer != NULL) { - fprintf(stderr, "[ERROR] - Memory already allocated\n"); - } +int +alloc_buffer(mem_buff_t *mem) +{ + if (mem->buffer != NULL) { fprintf(stderr, "[ERROR] - Memory already allocated\n"); } - uint64_t alloc_flags = MAP_PRIVATE | MAP_POPULATE | MAP_ANONYMOUS; + uint64_t alloc_flags = MAP_PRIVATE | MAP_POPULATE | MAP_ANONYMOUS; - mem->buffer = (char*) mmap(NULL, mem->size, PROT_READ | PROT_WRITE, alloc_flags, -1, 0); - if (mem->buffer == MAP_FAILED) { - perror("[ERROR] - mmap() failed"); - exit(1); - } - - if (mem->flags & F_VERBOSE) { - fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); - fprintf(stderr, "[ MEM ] - Buffer: %p\n", mem->buffer); - fprintf(stderr, "[ MEM ] - Size: %ld\n", mem->size); - fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); - } - return 0; + mem->buffer = (char *) mmap(NULL, mem->size, PROT_READ | PROT_WRITE, alloc_flags, -1, 0); + if (mem->buffer == MAP_FAILED) { + perror("[ERROR] - mmap() failed"); + exit(1); + } + if (mem->flags & F_VERBOSE) { + fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); + fprintf(stderr, "[ MEM ] - Buffer: %p\n", mem->buffer); + fprintf(stderr, "[ MEM ] - Size: %ld\n", mem->size); + fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); + } + return 0; } - - -int free_buffer(mem_buff_t* mem) { - return munmap(mem->buffer, mem->size); +int +free_buffer(mem_buff_t *mem) +{ + return munmap(mem->buffer, mem->size); } - - - - //----------------------------------------------- // Helpers -double mean(uint64_t* vals, size_t size) { - uint64_t avg = 0; - for (size_t i = 0; i < size; i++) { - avg += vals[i]; - } - return ((double)avg) / size; +double +mean(uint64_t *vals, size_t size) +{ + uint64_t avg = 0; + for (size_t i = 0; i < size; i++) { avg += vals[i]; } + return ((double) avg) / size; } -int gt(const void * a, const void * b) { - return ( *(int*)a - *(int*)b ); +int +gt(const void *a, const void *b) +{ + return (*(int *) a - *(int *) b); } -uint64_t median(uint64_t* vals, size_t size) { - qsort(vals, size, sizeof(uint64_t), gt); - return ((size%2)==0) ? vals[size/2] : (vals[(size_t)size/2]+vals[((size_t)size/2+1)])/2; +uint64_t +median(uint64_t *vals, size_t size) +{ + qsort(vals, size, sizeof(uint64_t), gt); + return ((size % 2) == 0) ? vals[size / 2] : (vals[(size_t) size / 2] + vals[((size_t) size / 2 + 1)]) / 2; } +char * +bit_string(uint64_t val) +{ + static char bit_str[256]; + char itoa_str[8]; + strcpy(bit_str, ""); + for (int shift = 0; shift < 64; shift++) { + if ((val >> shift) & 1) { + if (strcmp(bit_str, "") != 0) { strcat(bit_str, "+ "); } + sprintf(itoa_str, "%d ", shift); + strcat(bit_str, itoa_str); + } + } -char* bit_string(uint64_t val) { - static char bit_str[256]; - char itoa_str[8]; - strcpy(bit_str, ""); - for (int shift = 0; shift < 64; shift++) { - if ((val >> shift) & 1) { - if (strcmp(bit_str, "") != 0) { - strcat(bit_str, "+ "); - } - sprintf(itoa_str, "%d ", shift); - strcat(bit_str, itoa_str); - } - } - - return bit_str; + return bit_str; }