diff --git a/cache_utils/src/calibrate_2t.rs b/cache_utils/src/calibrate_2t.rs index 4537f77..7d7974a 100644 --- a/cache_utils/src/calibrate_2t.rs +++ b/cache_utils/src/calibrate_2t.rs @@ -3,6 +3,7 @@ use crate::calibration::{ get_cache_slicing, get_vpn, CalibrateResult, CalibrationOptions, HashMap, ASVP, SPURIOUS_THRESHOLD, }; +use crate::complex_addressing::CacheAttackSlicing; use core::arch::x86_64 as arch_x86; use itertools::Itertools; use nix::sched::{sched_getaffinity, sched_setaffinity, CpuSet}; @@ -65,7 +66,7 @@ struct HelperThreadParams { #[cfg(feature = "use_std")] fn calibrate_fixed_freq_2_thread_impl, T>( p: *const u8, - increment: usize, + cache_line_length: usize, len: isize, cores: &mut I, operations: &[CalibrateOperation2T], @@ -89,15 +90,7 @@ fn calibrate_fixed_freq_2_thread_impl, T>( let slicing = get_cache_slicing(core_per_socket); - let h = if let Some(s) = slicing { - if s.can_hash() { - Some(|addr: usize| -> u8 { slicing.unwrap().hash(addr).unwrap() }) - } else { - None - } - } else { - None - }; + let cache_attack_slicing = CacheAttackSlicing::from(slicing.unwrap(), cache_line_length); let mut ret = Vec::new(); @@ -116,12 +109,8 @@ fn calibrate_fixed_freq_2_thread_impl, T>( let mut params = main_turn_handle.wait(); if options.verbosity >= Thresholds { - print!("CSV: main_core, helper_core, address, "); - if h.is_some() { - print!("hash, "); - } println!( - "{} min, {} median, {} max", + "CSV: main_core, helper_core, address, hash, {} min, {} median, {} max", operations .iter() .map(|operation| operation.name) @@ -138,12 +127,8 @@ fn calibrate_fixed_freq_2_thread_impl, T>( } if options.verbosity >= RawResult { - print!("RESULT:main_core,helper_core,address,"); - if h.is_some() { - print!("hash,"); - } println!( - "time,{}", + "RESULT:main_core,helper_core,address,hash,time,{}", operations .iter() .map(|operation| operation.name) @@ -151,12 +136,13 @@ fn calibrate_fixed_freq_2_thread_impl, T>( ); } - let image_antecedent = match slicing { - Some(s) => s.image_antecedent(len as usize - 1), - None => None, - }; - if image_antecedent.is_some() { - options.hist_params.iterations *= OPTIMISED_ADDR_ITER_FACTOR; + let image_antecedent = cache_attack_slicing.image_antecedent(len as usize - 1); + + match cache_attack_slicing { + CacheAttackSlicing::ComplexAddressing(_) | CacheAttackSlicing::SimpleAddressing(_) => { + options.hist_params.iterations *= OPTIMISED_ADDR_ITER_FACTOR; + } + _ => {} } let old = sched_getaffinity(Pid::from_raw(0)).unwrap(); @@ -216,22 +202,23 @@ fn calibrate_fixed_freq_2_thread_impl, T>( // do the calibration let mut calibrate_result_vec = Vec::new(); + let offsets = image_antecedent.values().copied(); + + /* let offsets: Box> = match image_antecedent { Some(ref ima) => Box::new(ima.values().copied()), - None => Box::new((0..len as isize).step_by(increment)), - }; + None => Box::new((0..len as isize).step_by(cache_line_length)), + };*/ for i in offsets { let pointer = unsafe { p.offset(i) }; params.address = pointer; - let hash = h.map(|h| h(pointer as usize)); + let hash = cache_attack_slicing.hash(pointer as usize); if options.verbosity >= Thresholds { print!("Calibration for {:p}", pointer); - if let Some(h) = hash { - print!(" (hash: {:x})", h) - } + print!(" (hash: {:x})", hash); println!(); } @@ -296,9 +283,7 @@ fn calibrate_fixed_freq_2_thread_impl, T>( for j in 0..options.hist_params.bucket_number - 1 { if options.verbosity >= RawResult { print!("RESULT:{},{},{:p},", main_core, helper_core, pointer); - if let Some(h) = hash { - print!("{:x},", h); - } + print!("{:x},", hash); print!("{}", from_bucket(j)); } // ignore the last bucket : spurious context switches etc. @@ -343,9 +328,7 @@ fn calibrate_fixed_freq_2_thread_impl, T>( ); } print!("CSV: {},{},{:p}, ", main_core, helper_core, pointer); - if let Some(h) = hash { - print!("{:x}, ", h) - } + print!("{:x}, ", hash); println!( "{}, {}, {}", calibrate_result.min.iter().format(", "), diff --git a/cache_utils/src/complex_addressing.rs b/cache_utils/src/complex_addressing.rs index 69c0073..919de0d 100644 --- a/cache_utils/src/complex_addressing.rs +++ b/cache_utils/src/complex_addressing.rs @@ -228,6 +228,8 @@ impl CacheSlicing { } } + // This gives a basis of the kernel complement (n elements) + pub fn kernel_compl_basis(&self, mask: usize) -> Option> { match self { ComplexAddressing(_functions) => { @@ -244,6 +246,9 @@ impl CacheSlicing { _ => None, } } + + // This gives a set that covers all possible values of the image. (All combination of basis elements on {0,1}) + // 2^n elements pub fn image_antecedent(&self, mask: usize) -> Option> { match self { ComplexAddressing(_functions) => { @@ -308,5 +313,146 @@ impl CacheAttackSlicing { } } - // TODO + // Only works for Complex Addressing rn + // May work in the future for simple. + fn pivot(&self, mask: isize) -> Vec<(usize, isize)> { + match self { + CacheAttackSlicing::ComplexAddressing(_) + | CacheAttackSlicing::SimpleAddressing(_) + | CacheAttackSlicing::Unsupported(_) => { + let mut matrix = Vec::new(); + + let mut i = 1; + let mut hashspace = 0; + while i != 0 { + if i & mask != 0 { + let h = self.hash(i as usize); + + hashspace |= h; + matrix.push((h, i)); + } + i <<= 1; + } + + let mut i = 0; // current line in the matrix. + let mut bit = 1; + while bit != 0 { + if bit & hashspace != 0 { + let mut found_pivot = false; + for j in i..matrix.len() { + if matrix[j].0 & bit != 0 { + found_pivot = true; + if j != i { + let mi = matrix[i]; + let mj = matrix[j]; + matrix[i] = mj; + matrix[j] = mi; + } + break; + } + } + if found_pivot { + for j in 0..matrix.len() { + if j != i && bit & matrix[j].0 != 0 { + matrix[j].0 ^= matrix[i].0; + matrix[j].1 ^= matrix[i].1; + } + } + i += 1; + } + } + bit <<= 1; + } + while i < matrix.len() { + if matrix[i].0 != 0 { + panic!("Something went wrong with the pivot algorithm") + } + i += 1; + } + + matrix + } + _ => panic!("Should not be called"), + } + } + + pub fn image(&self, mask: usize) -> HashSet { + match self { + CacheAttackSlicing::ComplexAddressing(_) + | CacheAttackSlicing::SimpleAddressing(_) + | CacheAttackSlicing::Unsupported(_) => { + let matrix = self.pivot(mask as isize); + + let mut result = HashSet::::new(); + result.insert(0); + + for (u, _) in matrix { + let mut tmp = HashSet::new(); + for v in &result { + tmp.insert(v ^ u); + } + result.extend(tmp); + } + result + } + _ => { + let mut r = HashSet::new(); + r.insert(0); + r + } + } + } + + // This gives a basis of the kernel complement (n elements) + + pub fn kernel_compl_basis(&self, mask: usize) -> HashMap { + let mut result = HashMap::new(); + match self { + CacheAttackSlicing::ComplexAddressing(_) + | CacheAttackSlicing::SimpleAddressing(_) + | CacheAttackSlicing::Unsupported(_) => { + let matrix = self.pivot(mask as isize); + + for (slice, addr) in matrix { + if slice != 0 { + result.insert(slice, addr); + } + } + } + _ => { + result.insert(0, 0); + } + } + result + } + + // This gives a set that covers all possible values of the image. (All combination of basis elements on {0,1}) + // 2^n elements + pub fn image_antecedent(&self, mask: usize) -> HashMap { + let mut result = HashMap::::new(); + + match self { + CacheAttackSlicing::ComplexAddressing(_) + | CacheAttackSlicing::SimpleAddressing(_) + | CacheAttackSlicing::Unsupported(_) => { + let matrix = self.pivot(mask as isize); + + result.insert(0, 0); + + for (slice_u, addr_u) in matrix { + if slice_u != 0 { + let mut tmp = HashMap::new(); + for (slice_v, addr_v) in &result { + tmp.insert(slice_v ^ slice_u, addr_v ^ addr_u); + } + result.extend(tmp); + } + } + } + _ => { + result.insert(0, 0); + } + } + result + } }