Compare commits

..

No commits in common. "2ea67d617477481bdd923e03cf4bef41c831ac8a" and "1dbf12c728740b67eaa46b473785d5f0273a9d49" have entirely different histories.

7 changed files with 558 additions and 588 deletions

View File

@ -1,78 +0,0 @@
# 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

View File

@ -4,7 +4,7 @@ LDIR=lib
BUILD=obj BUILD=obj
ODIR=src/.obj ODIR=src/.obj
CFLAGS=-I$(IDIR) -O3 #-ggdb CFLAGS=-I$(IDIR) #-ggdb
# CXX=g++ # CXX=g++
LDFLAGS= LDFLAGS=

View File

@ -1,12 +1,14 @@
#include "unistd.h"
#include "utils.h" #include "utils.h"
#include "unistd.h"
typedef struct { typedef struct {
char *v_addr; char* v_addr;
uint64_t p_addr; uint64_t p_addr;
} addr_tuple; } addr_tuple;
//---------------------------------------------------------- //----------------------------------------------------------
// Functions // 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);

View File

@ -3,13 +3,15 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#define BIT(x) (1ULL << (x))
#define KB(x) ((x) << 10ULL) #define BIT(x) (1ULL<<(x))
#define MB(x) ((x) << 20ULL) #define KB(x) ((x)<<10ULL)
#define GB(x) ((x) << 30ULL) #define MB(x) ((x)<<20ULL)
#define GB(x) ((x)<<30ULL)
#define CL_SHIFT 6 #define CL_SHIFT 6
#define CL_SIZE 64 #define CL_SIZE 64
#define F_CLEAR 0L #define F_CLEAR 0L
#define F_VERBOSE BIT(0) #define F_VERBOSE BIT(0)
#define F_EXPORT BIT(1) #define F_EXPORT BIT(1)
@ -17,66 +19,77 @@
#define MEM_SHIFT (30L) #define MEM_SHIFT (30L)
#define MEM_MASK 0b11111ULL << MEM_SHIFT #define MEM_MASK 0b11111ULL << MEM_SHIFT
#define F_ALLOC_HUGE BIT(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_1G F_ALLOC_HUGE | BIT(MEM_SHIFT+1)
#define F_ALLOC_HUGE_2M F_ALLOC_HUGE | BIT(MEM_SHIFT + 2) #define F_ALLOC_HUGE_2M F_ALLOC_HUGE | BIT(MEM_SHIFT+2)
#define F_POPULATE BIT(MEM_SHIFT + 3) #define F_POPULATE BIT(MEM_SHIFT+3)
//---------------------------------------------------------- //----------------------------------------------------------
// Static functions // Static functions
static inline __attribute__((always_inline)) void static inline __attribute__((always_inline)) void clflush(volatile void *p)
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; uint64_t lo, hi;
asm volatile("rdtscp\n" : "=a"(lo), "=d"(hi)::"%rcx"); asm volatile("rdtscp\n"
: "=a" (lo), "=d" (hi)
:: "%rcx");
return (hi << 32) | lo; 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; uint64_t lo, hi;
asm volatile("rdtsc\n" : "=a"(lo), "=d"(hi)::"%rcx"); asm volatile("rdtsc\n"
: "=a" (lo), "=d" (hi)
:: "%rcx");
return (hi << 32) | lo; return (hi << 32) | lo;
} }
//---------------------------------------------------------- //----------------------------------------------------------
// Memory alloc // Memory alloc
typedef struct { typedef struct {
char *buffer; char* buffer;
uint64_t size; uint64_t size;
uint64_t flags; uint64_t flags;
} mem_buff_t; } mem_buff_t;
int alloc_buffer(mem_buff_t *mem);
int free_buffer(mem_buff_t *mem); int alloc_buffer(mem_buff_t* mem);
int free_buffer(mem_buff_t* mem);
//---------------------------------------------------------- //----------------------------------------------------------
// Helpers // Helpers
int gt(const void *a, const void *b); 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); uint64_t median(uint64_t* vals, size_t size);
char* bit_string(uint64_t val);
char *bit_string(uint64_t val);

View File

@ -1,67 +1,72 @@
#include "stdio.h" #include "stdio.h"
// #include <x86intrin.h> /* for rdtsc, rdtscp, clflush */ // #include <x86intrin.h> /* for rdtsc, rdtscp, clflush */
#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
#include <sched.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <stdlib.h>
#include <sys/types.h>
#include <time.h> #include <time.h>
#include <sched.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>
#include <getopt.h>
#include "rev-mc.h"
#include "utils.h" #include "utils.h"
#include "rev-mc.h"
#define SETS_std (2 * 16)// 1rk-1ch
#define SETS_std (2*16) // 1rk-1ch
#define ROUNDS_std 1000 #define ROUNDS_std 1000
#define THRESHOLD_std 340 #define THRESHOLD_std 340
#define MEM_SIZE_std GB(5L) #define MEM_SIZE_std GB(5L)
#define O_FILE_std "access.csv" #define O_FILE_std "access.csv"
#define FIELDS "base,probe,rounds,time" #define FIELDS "base,probe,rounds,time"
//----------------------------------------------- //-----------------------------------------------
// GLOBALS // GLOBALS
//----------------------------------------------- //-----------------------------------------------
void void print_usage() {
print_usage() fprintf(stderr, "[ LOG ] - Usage ./test [-h] [-s sets] [-r rounds] [-t threshold] [-o o_file] [-v] [--mem mem_size]\n");
{
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, " -h = this help message\n");
fprintf(stderr, " -s sets = number of expected sets (default: %d)\n", SETS_std); 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", fprintf(stderr, " -r rounds = number of rounds per tuple (default: %d)\n", ROUNDS_std);
ROUNDS_std); fprintf(stderr, " -t threshold = time threshold for conflicts (default: %d)\n", THRESHOLD_std);
fprintf(stderr, " -t threshold = time threshold for conflicts (default: %d)\n", fprintf(stderr, " -o o_file = output file for mem profiling (default: %s)\n", O_FILE_std);
THRESHOLD_std); fprintf(stderr, " --mem mem_size = allocation size (default: %ld)\n", (uint64_t) MEM_SIZE_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"); fprintf(stderr, " -v = verbose\n\n");
} }
//----------------------------------------------- //-----------------------------------------------
int int main(int argc, char** argv) {
main(int argc, char **argv)
{
uint64_t flags = 0ULL; uint64_t flags = 0ULL;
size_t sets_cnt = SETS_std; size_t sets_cnt = SETS_std;
size_t rounds = ROUNDS_std; size_t rounds = ROUNDS_std;
size_t m_size = MEM_SIZE_std; size_t m_size = MEM_SIZE_std;
size_t threshold = THRESHOLD_std; size_t threshold = THRESHOLD_std;
char *o_file = (char *) O_FILE_std; char* o_file = (char*) O_FILE_std;
flags |= F_POPULATE; flags |= F_POPULATE;
if (geteuid() != 0) { if(geteuid() != 0) {
fprintf(stderr, "[ERROR] - You need to run as root to access pagemap!\n"); fprintf(stderr, "[ERROR] - You need to run as root to access pagemap!\n");
exit(1); exit(1);
} }
@ -69,27 +74,30 @@ main(int argc, char **argv)
while (1) { while (1) {
int this_option_optind = optind ? optind : 1; int this_option_optind = optind ? optind : 1;
int option_index = 0; int option_index = 0;
static struct option long_options[] = { static struct option long_options[] =
{
/* These options set a flag. */ /* These options set a flag. */
{"mem", required_argument, 0, 0}, {"mem", required_argument, 0, 0},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
int arg = getopt_long(argc, argv, "o:s:r:t:hv", long_options, &option_index); 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: case 0:
switch (option_index) { switch (option_index){
case 0: case 0:
m_size = atoi(optarg);// TODO proper parsing of this m_size = atoi(optarg); // TODO proper parsing of this
break; break;
default: default:
break; break;
} }
break; break;
case 'o': case 'o':
o_file = (char *) malloc(sizeof(char) * strlen(optarg)); o_file = (char*) malloc(sizeof(char)*strlen(optarg));
strncpy(o_file, optarg, strlen(optarg)); strncpy(o_file, optarg, strlen(optarg));
flags |= F_EXPORT; flags |= F_EXPORT;
break; break;
@ -109,11 +117,18 @@ main(int argc, char **argv)
default: default:
print_usage(); print_usage();
return 0; return 0;
} }
} }
rev_mc(sets_cnt, threshold, rounds, m_size, o_file, flags); rev_mc(sets_cnt, threshold, rounds, m_size, o_file, flags);
return 0; return 0;
} }
/*I'm refactoring the set struct to add also timing in there. */ /*I'm refactoring the set struct to add also timing in there. */

View File

@ -19,20 +19,23 @@
#define BOOL_XOR(a, b) ((a) != (b)) #define BOOL_XOR(a, b) ((a) != (b))
#define O_HEADER "base,probe,time\n" #define O_HEADER "base,probe,time\n"
#define ALIGN_TO(X, Y) ((X) & (~((1LL << (Y)) - 1LL)))// Mask out the lower Y 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 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 VALID_THRESH 0.75f
#define SET_THRESH 0.95f #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 #define ROW_SET_CNT 5
// from // from
// https://stackoverflow.com/questions/1644868/define-macro-for-debug-printing-in-c // https://stackoverflow.com/questions/1644868/define-macro-for-debug-printing-in-c
#define verbose_printerr(fmt, ...) \ #define verbose_printerr(fmt, ...) \
do { \ do { \
if (flags & F_VERBOSE) { fprintf(stderr, fmt, ##__VA_ARGS__); } \ if (flags & F_VERBOSE) { \
fprintf(stderr, fmt, ##__VA_ARGS__); \
} \
} while (0) } while (0)
typedef std::vector<addr_tuple> set_t; typedef std::vector<addr_tuple> set_t;
@ -49,13 +52,11 @@ void verify_sets(std::vector<set_t> &sets, uint64_t threshold, size_t rounds);
#pragma push_options #pragma push_options
#pragma optimize("O0") #pragma optimize("O0")
static std::vector<uint64_t> time_vals; static std::vector<uint64_t> time_vals;
uint64_t time_tuple(volatile char *a1, volatile char *a2, size_t rounds) {
uint64_t
time_tuple(volatile char *a1, volatile char *a2, size_t rounds)
{
// uint64_t* time_vals = (uint64_t*) calloc(rounds, sizeof(uint64_t)); // uint64_t* time_vals = (uint64_t*) calloc(rounds, sizeof(uint64_t));
if (rounds > time_vals.size()) time_vals.resize(rounds); if (rounds > time_vals.size())
time_vals.resize(rounds);
uint64_t t0; uint64_t t0;
sched_yield(); sched_yield();
@ -74,27 +75,19 @@ time_tuple(volatile char *a1, volatile char *a2, size_t rounds)
// free(time_vals); // free(time_vals);
return mdn; return mdn;
} }
#pragma pop_options #pragma pop_options
//---------------------------------------------------------- //----------------------------------------------------------
char * char *get_rnd_addr(char *base, size_t m_size, size_t align) {
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);
return (char *) ALIGN_TO((uint64_t) base, (uint64_t) align) + ALIGN_TO(rand() % m_size, (uint64_t) align);
} }
//---------------------------------------------------------- //----------------------------------------------------------
uint64_t uint64_t get_pfn(uint64_t entry) { return ((entry) & 0x3fffffffffffff); }
get_pfn(uint64_t entry)
{
return ((entry) & 0x3fffffffffffff);
}
//---------------------------------------------------------- //----------------------------------------------------------
uint64_t uint64_t get_phys_addr(uint64_t v_addr) {
get_phys_addr(uint64_t v_addr)
{
uint64_t entry; uint64_t entry;
uint64_t offset = (v_addr / 4096) * sizeof(entry); uint64_t offset = (v_addr / 4096) * sizeof(entry);
uint64_t pfn; uint64_t pfn;
@ -110,19 +103,15 @@ get_phys_addr(uint64_t v_addr)
} }
//---------------------------------------------------------- //----------------------------------------------------------
addr_tuple addr_tuple gen_addr_tuple(char *v_addr) {
gen_addr_tuple(char *v_addr) return (addr_tuple){v_addr, get_phys_addr((uint64_t)v_addr)};
{
return (addr_tuple){v_addr, get_phys_addr((uint64_t) v_addr)};
} }
//---------------------------------------------------------- //----------------------------------------------------------
// https://www.cs.umd.edu/~gasarch/TOPICS/factoring/fastgauss.pdf // https://www.cs.umd.edu/~gasarch/TOPICS/factoring/fastgauss.pdf
// gaussian elimination in GF2 // gaussian elimination in GF2
std::vector<uint64_t> std::vector<uint64_t> reduce_masks(std::vector<uint64_t> masks) {
reduce_masks(std::vector<uint64_t> masks)
{
size_t height, width, height_t, width_t; size_t height, width, height_t, width_t;
@ -141,11 +130,15 @@ reduce_masks(std::vector<uint64_t> masks)
std::vector<uint64_t> filtered_masks; std::vector<uint64_t> filtered_masks;
for (size_t i = 0; i < height; i++) { 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))); } for (size_t j = 0; j < width; j++) {
mtx[i][width - j - 1] = (masks[i] & (1ULL << (j)));
}
} }
for (size_t i = 0; i < height; i++) { for (size_t i = 0; i < height; i++) {
for (size_t j = 0; j < width; j++) { mtx_t[j][i] = mtx[i][j]; } for (size_t j = 0; j < width; j++) {
mtx_t[j][i] = mtx[i][j];
}
} }
int64_t pvt_col = 0; int64_t pvt_col = 0;
@ -155,11 +148,15 @@ reduce_masks(std::vector<uint64_t> masks)
if (mtx_t[row][pvt_col]) { if (mtx_t[row][pvt_col]) {
filtered_masks.push_back(masks[pvt_col]); filtered_masks.push_back(masks[pvt_col]);
for (size_t c = 0; c < width_t; c++) { for (size_t c = 0; c < width_t; c++) {
if (c == pvt_col) continue; if (c == pvt_col)
if (!(mtx_t[row][c])) continue; continue;
if (!(mtx_t[row][c]))
continue;
// column sum // 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]); } 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;
} }
@ -172,23 +169,23 @@ reduce_masks(std::vector<uint64_t> masks)
//---------------------------------------------------------- //----------------------------------------------------------
// from https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation // from https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
uint64_t uint64_t next_bit_permutation(uint64_t v) {
next_bit_permutation(uint64_t v)
{
uint64_t t = v | (v - 1); uint64_t t = v | (v - 1);
return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctzl(v) + 1)); return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctzl(v) + 1));
} }
//---------------------------------------------------------- //----------------------------------------------------------
std::vector<uint64_t> std::vector<uint64_t> find_functions(std::vector<set_t> sets,
find_functions(std::vector<set_t> sets, size_t max_fn_bits, size_t msb, uint64_t flags) size_t max_fn_bits, size_t msb,
{ uint64_t flags) {
std::vector<uint64_t> masks; std::vector<uint64_t> masks;
verbose_printerr("~~~~~~~~~~ Candidate functions ~~~~~~~~~~\n"); verbose_printerr("~~~~~~~~~~ Candidate functions ~~~~~~~~~~\n");
for (size_t bits = 1L; bits <= max_fn_bits; bits++) { 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 fn_mask =
((1L << (bits)) -
1); // avoid the first 6 bits since they are the cacheline bits
uint64_t last_mask = (fn_mask << (msb - bits)); uint64_t last_mask = (fn_mask << (msb - bits));
fn_mask <<= CL_SHIFT; fn_mask <<= CL_SHIFT;
verbose_printerr("[ LOG ] - #Bits: %ld \n", bits); verbose_printerr("[ LOG ] - #Bits: %ld \n", bits);
@ -203,10 +200,13 @@ find_functions(std::vector<set_t> sets, size_t max_fn_bits, size_t msb, uint64_t
for (size_t i = 1; i < curr_set.size(); i++) { 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_base = __builtin_parityl(curr_set[0].p_addr & fn_mask);
uint64_t res_probe = __builtin_parityl(curr_set[i].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; } 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)); }
verbose_printerr("\t Candidate: 0x%0lx \t\t bits: %s\n", fn_mask,
bit_string(fn_mask));
masks.push_back(fn_mask); masks.push_back(fn_mask);
next_mask: next_mask:
@ -216,18 +216,22 @@ find_functions(std::vector<set_t> sets, size_t max_fn_bits, size_t msb, uint64_t
verbose_printerr("~~~~~~~~~~ Found Functions ~~~~~~~~~~\n"); verbose_printerr("~~~~~~~~~~ Found Functions ~~~~~~~~~~\n");
masks = reduce_masks(masks); masks = reduce_masks(masks);
if (flags & F_VERBOSE) { 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(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);
} }
for (auto m : masks) { fprintf(stdout, "0x%lx\n", m); }
return masks; return masks;
} }
std::vector<int> std::vector<int> find_set_bits(uint64_t val) {
find_set_bits(uint64_t val)
{
std::vector<int> set_bits; std::vector<int> set_bits;
for (int i = 0; i < 64; i++) { for (int i = 0; i < 64; i++) {
if (!(val & (1ULL << i))) continue; if (!(val & (1ULL << i)))
continue;
set_bits.push_back(i); set_bits.push_back(i);
} }
@ -235,11 +239,12 @@ find_set_bits(uint64_t val)
} }
//---------------------------------------------------------- //----------------------------------------------------------
std::vector<uint8_t> std::vector<uint8_t> get_dram_fn(uint64_t addr,
get_dram_fn(uint64_t addr, std::vector<uint64_t> fn_masks) std::vector<uint64_t> fn_masks) {
{
std::vector<uint8_t> addr_dram; std::vector<uint8_t> addr_dram;
for (auto fn : fn_masks) { addr_dram.push_back(__builtin_parityl(addr & fn)); } for (auto fn : fn_masks) {
addr_dram.push_back(__builtin_parityl(addr & fn));
}
return addr_dram; return addr_dram;
} }
@ -249,13 +254,8 @@ 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 @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 which are from the bank selection. This is currently done manually
*/ */
uint64_t uint64_t find_row_mask(std::vector<set_t> &sets, std::vector<uint64_t> fn_masks,
find_row_mask(std::vector<set_t> &sets, mem_buff_t mem, uint64_t threshold, uint64_t flags) {
std::vector<uint64_t> 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)); addr_tuple base_addr = gen_addr_tuple(get_rnd_addr(mem.buffer, mem.size, 0));
std::vector<set_t> same_row_sets; std::vector<set_t> same_row_sets;
@ -265,28 +265,34 @@ find_row_mask(std::vector<set_t> &sets,
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
verbose_printerr("[LOG] - Set #%d\n", i); verbose_printerr("[LOG] - Set #%d\n", i);
addr_tuple base_addr = sets[i][0]; addr_tuple base_addr = sets[i][0];
std::vector<uint8_t> base_dram = get_dram_fn((uint64_t) base_addr.p_addr, fn_masks); std::vector<uint8_t> base_dram =
get_dram_fn((uint64_t)base_addr.p_addr, fn_masks);
same_row_sets.push_back({base_addr}); same_row_sets.push_back({base_addr});
uint64_t cnt = 0; uint64_t cnt = 0;
while (cnt < ROW_SET_CNT) { while (cnt < ROW_SET_CNT) {
addr_tuple tmp = gen_addr_tuple(get_rnd_addr(mem.buffer, mem.size, 0)); 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; 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); same_row_sets[i].push_back(tmp);
cnt++; cnt++;
} }
} }
uint64_t row_mask = LS_BITMASK(16);// use 16 bits for the row uint64_t row_mask = LS_BITMASK(16); // use 16 bits for the row
uint64_t last_mask = (row_mask << (40 - 16)); uint64_t last_mask = (row_mask << (40 - 16));
row_mask <<= CL_SHIFT;// skip the lowest 6 bits since they're used for CL addressing row_mask <<=
CL_SHIFT; // skip the lowest 6 bits since they're used for CL addressing
while (row_mask < last_mask) { while (row_mask < last_mask) {
if (row_mask & LS_BITMASK(CL_SHIFT)) { if (row_mask & LS_BITMASK(CL_SHIFT)) {
@ -298,7 +304,9 @@ find_row_mask(std::vector<set_t> &sets,
addr_tuple base_addr = addr_pool[0]; addr_tuple base_addr = addr_pool[0];
for (int i = 1; i < addr_pool.size(); i++) { for (int i = 1; i < addr_pool.size(); i++) {
addr_tuple tmp = addr_pool[i]; addr_tuple tmp = addr_pool[i];
if ((tmp.p_addr & row_mask) != (base_addr.p_addr & row_mask)) { goto next_mask; } if ((tmp.p_addr & row_mask) != (base_addr.p_addr & row_mask)) {
goto next_mask;
}
} }
} }
@ -311,17 +319,19 @@ find_row_mask(std::vector<set_t> &sets,
// super hackish way to recover the real row mask // super hackish way to recover the real row mask
for (auto m : fn_masks) { for (auto m : fn_masks) {
uint64_t lsb = (1 << (__builtin_ctzl(m) + 1)); uint64_t lsb = (1 << (__builtin_ctzl(m) + 1));
if (lsb & row_mask) { row_mask ^= (1 << __builtin_ctzl(m)); } 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)); }
verbose_printerr("[LOG] - Row mask: 0x%0lx \t\t bits: %s\n", row_mask,
bit_string(row_mask));
printf("0x%lx\n", row_mask); printf("0x%lx\n", row_mask);
return row_mask; return row_mask;
} }
//---------------------------------------------------------- //----------------------------------------------------------
void void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size,
rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, char *o_file, uint64_t flags) char *o_file, uint64_t flags) {
{
time_t t; time_t t;
@ -332,7 +342,7 @@ rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, char *o_
std::set<char *> used_addr; std::set<char *> used_addr;
std::vector<uint64_t> fn_masks; std::vector<uint64_t> fn_masks;
srand((unsigned) time(&t)); srand((unsigned)time(&t));
if (flags & F_EXPORT) { if (flags & F_EXPORT) {
if (o_file == NULL) { if (o_file == NULL) {
@ -356,7 +366,8 @@ rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, char *o_
while (!found_enough(sets, sets_cnt, SET_SIZE)) { while (!found_enough(sets, sets_cnt, SET_SIZE)) {
char *rnd_addr = get_rnd_addr(mem.buffer, mem.size, CL_SHIFT); char *rnd_addr = get_rnd_addr(mem.buffer, mem.size, CL_SHIFT);
if (is_in(rnd_addr, used_addr)) continue; if (is_in(rnd_addr, used_addr))
continue;
// used_addr.push_back(rnd_addr); // used_addr.push_back(rnd_addr);
used_addr.insert(rnd_addr); used_addr.insert(rnd_addr);
@ -366,11 +377,15 @@ rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, char *o_
for (size_t idx = 0; idx < sets.size(); idx++) { for (size_t idx = 0; idx < sets.size(); idx++) {
uint64_t time = 0; uint64_t time = 0;
addr_tuple tmp = sets[idx][0]; addr_tuple tmp = sets[idx][0];
time = time_tuple((volatile char *) tmp.v_addr, (volatile char *) tp.v_addr, rounds); time = time_tuple((volatile char *)tmp.v_addr, (volatile char *)tp.v_addr,
if (flags & F_EXPORT) { dprintf(o_fd, "%lx,%lx,%ld\n", (uint64_t) tp.v_addr, (uint64_t) tmp.v_addr, time); } 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) { if (time > threshold) {
verbose_printerr("[LOG] - [%ld] Set: %03ld -\t %lx - %lx\t Time: %ld\n", used_addr.size(), idx, verbose_printerr("[LOG] - [%ld] Set: %03ld -\t %lx - %lx\t Time: %ld\n",
tp.p_addr, tmp.p_addr, time); used_addr.size(), idx, tp.p_addr, tmp.p_addr, time);
sets[idx].push_back(tp); sets[idx].push_back(tp);
found_set = true; found_set = true;
break; break;
@ -387,16 +402,17 @@ rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, char *o_
filter_sets(sets, SET_SIZE); filter_sets(sets, SET_SIZE);
#ifdef DEBUG_SETS #ifdef DEBUG_SETS
fprintf(stderr, "[ LOG ] - Cleansing sets. This may take a while... stay put\n"); fprintf(stderr,
"[ LOG ] - Cleansing sets. This may take a while... stay put\n");
verify_sets(sets, threshold, rounds); verify_sets(sets, threshold, rounds);
fprintf(stderr, "[ LOG ] - Done\n"); fprintf(stderr, "[ LOG ] - Done\n");
#endif #endif
if (flags & F_VERBOSE) { print_sets(sets); } if (flags & F_VERBOSE) {
print_sets(sets);
}
fprintf(stderr, "Start Find Function\n");
fn_masks = find_functions(sets, 6, 30, flags); fn_masks = find_functions(sets, 6, 30, flags);
fprintf(stderr, "Start Find RowMask\n");
uint64_t row_mask = find_row_mask(sets, fn_masks, mem, threshold, flags); uint64_t row_mask = find_row_mask(sets, fn_masks, mem, threshold, flags);
free_buffer(&mem); free_buffer(&mem);
@ -407,85 +423,84 @@ rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, char *o_
//---------------------------------------------------------- //----------------------------------------------------------
// Helpers // Helpers
bool bool is_in(char *val, std::set<char *> arr) {
is_in(char *val, std::set<char *> arr)
{
return arr.find(val) != arr.end(); return arr.find(val) != arr.end();
} }
bool bool is_in(char *val, std::vector<char *> arr) {
is_in(char *val, std::vector<char *> arr)
{
for (auto v : arr) { for (auto v : arr) {
if (val == v) { return true; } if (val == v) {
return true;
}
} }
return false; return false;
} }
//---------------------------------------------------------- //----------------------------------------------------------
bool bool found_enough(std::vector<set_t> sets, uint64_t set_cnt, size_t set_size) {
found_enough(std::vector<set_t> 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++) { for (int i = 0; i < sets.size(); i++) {
set_t curr_set = sets[i]; set_t curr_set = sets[i];
if (curr_set.size() > set_size) { found_sets += 1; } if (curr_set.size() > set_size) {
found_sets += 1;
}
} }
if (found_sets > set_cnt) { if (found_sets > set_cnt) {
fprintf(stderr, "[ERROR] - Found too many sets. Is %ld the correct number of sets?\n", set_cnt); fprintf(
stderr,
"[ERROR] - Found too many sets. Is %ld the correct number of sets?\n",
set_cnt);
exit(1); exit(1);
} }
return (found_sets >= (set_cnt * SET_THRESH)) ? true : false; return (found_sets >= (set_cnt * SET_THRESH)) ? true : false;
} }
void void filter_sets(std::vector<set_t> &sets, size_t set_size) {
filter_sets(std::vector<set_t> &sets, size_t set_size)
{
for (auto s = sets.begin(); s < sets.end();) { for (auto s = sets.begin(); s < sets.end(); s++) {
if (s->size() < set_size) { if (s->size() < set_size) {
s = sets.erase(s); sets.erase(s);
// s -= 1; s -= 1;
} else {
++s;
} }
} }
} }
void void print_sets(std::vector<set_t> sets) {
print_sets(std::vector<set_t> sets)
{
for (int idx = 0; idx < sets.size(); idx++) { for (int idx = 0; idx < sets.size(); idx++) {
fprintf(stderr, "[LOG] - Set: %d\tSize: %ld\n", idx, sets[idx].size()); 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 (auto tmp : sets[idx]) {
fprintf(stderr, "\tv_addr:%p - p_addr:%p\n", tmp.v_addr,
(void *)tmp.p_addr);
}
} }
} }
#ifdef DEBUG_SETS #ifdef DEBUG_SETS
void void verify_sets(std::vector<set_t> &sets, uint64_t threshold, size_t rounds) {
verify_sets(std::vector<set_t> &sets, uint64_t threshold, size_t rounds)
{
for (auto s : sets) { for (auto s : sets) {
// test every address against all the addresses in the set // test every address against all the addresses in the set
for (auto tp_base = s.begin(); tp_base < s.end(); tp_base++) { for (auto tp_base = s.begin(); tp_base < s.end(); tp_base++) {
uint64_t conflicts = 0; uint64_t conflicts = 0;
for (auto tp_probe = s.begin(); tp_probe < s.end(); tp_probe++) { for (auto tp_probe = s.begin(); tp_probe < s.end(); tp_probe++) {
if (tp_base == tp_probe) continue; if (tp_base == tp_probe)
continue;
uint64_t time = uint64_t time = time_tuple((volatile char *)tp_base->v_addr,
time_tuple((volatile char *) tp_base->v_addr, (volatile char *) tp_probe->v_addr, rounds); (volatile char *)tp_probe->v_addr, rounds);
if (time > threshold) { conflicts += 1; } if (time > threshold) {
conflicts += 1;
}
} }
if (!(conflicts > VALID_THRESH * s.size())) { if (!(conflicts > VALID_THRESH * s.size())) {
fprintf(stderr, "[ LOG ] - Removing: %p\n", tp_base->v_addr); fprintf(stderr, "[ LOG ] - Removing: %p\n", tp_base->v_addr);
s.erase(tp_base--);// reset the iterator s.erase(tp_base--); // reset the iterator
} }
} }
} }

View File

@ -1,27 +1,28 @@
#include <assert.h> #include <sys/types.h>
#include <errno.h> #include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include "utils.h" #include "utils.h"
//----------------------------------------------- //-----------------------------------------------
// Memory alloc // Memory alloc
int int alloc_buffer(mem_buff_t* mem) {
alloc_buffer(mem_buff_t *mem) if (mem->buffer != NULL) {
{ fprintf(stderr, "[ERROR] - Memory already allocated\n");
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); mem->buffer = (char*) mmap(NULL, mem->size, PROT_READ | PROT_WRITE, alloc_flags, -1, 0);
if (mem->buffer == MAP_FAILED) { if (mem->buffer == MAP_FAILED) {
perror("[ERROR] - mmap() failed"); perror("[ERROR] - mmap() failed");
exit(1); exit(1);
@ -34,47 +35,49 @@ alloc_buffer(mem_buff_t *mem)
fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
} }
return 0; return 0;
} }
int
free_buffer(mem_buff_t *mem)
{ int free_buffer(mem_buff_t* mem) {
return munmap(mem->buffer, mem->size); return munmap(mem->buffer, mem->size);
} }
//----------------------------------------------- //-----------------------------------------------
// Helpers // Helpers
double double mean(uint64_t* vals, size_t size) {
mean(uint64_t *vals, size_t size)
{
uint64_t avg = 0; uint64_t avg = 0;
for (size_t i = 0; i < size; i++) { avg += vals[i]; } for (size_t i = 0; i < size; i++) {
return ((double) avg) / size; avg += vals[i];
}
return ((double)avg) / size;
} }
int int gt(const void * a, const void * b) {
gt(const void *a, const void *b) return ( *(int*)a - *(int*)b );
{
return (*(int *) a - *(int *) b);
} }
uint64_t uint64_t median(uint64_t* vals, size_t size) {
median(uint64_t *vals, size_t size)
{
qsort(vals, size, sizeof(uint64_t), gt); 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; 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) char* bit_string(uint64_t val) {
{
static char bit_str[256]; static char bit_str[256];
char itoa_str[8]; char itoa_str[8];
strcpy(bit_str, ""); strcpy(bit_str, "");
for (int shift = 0; shift < 64; shift++) { for (int shift = 0; shift < 64; shift++) {
if ((val >> shift) & 1) { if ((val >> shift) & 1) {
if (strcmp(bit_str, "") != 0) { strcat(bit_str, "+ "); } if (strcmp(bit_str, "") != 0) {
strcat(bit_str, "+ ");
}
sprintf(itoa_str, "%d ", shift); sprintf(itoa_str, "%d ", shift);
strcat(bit_str, itoa_str); strcat(bit_str, itoa_str);
} }