Ensure the calibration infrastructure works correctly.

This commit is contained in:
Guillume DIDIER 2021-09-27 11:35:51 +02:00
parent 646db42766
commit 01ae16b015
2 changed files with 168 additions and 39 deletions

View File

@ -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<I: Iterator<Item = (usize, usize)>, T>(
p: *const u8,
increment: usize,
cache_line_length: usize,
len: isize,
cores: &mut I,
operations: &[CalibrateOperation2T<T>],
@ -89,15 +90,7 @@ fn calibrate_fixed_freq_2_thread_impl<I: Iterator<Item = (usize, usize)>, 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<I: Iterator<Item = (usize, usize)>, 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<I: Iterator<Item = (usize, usize)>, 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,13 +136,14 @@ fn calibrate_fixed_freq_2_thread_impl<I: Iterator<Item = (usize, usize)>, T>(
);
}
let image_antecedent = match slicing {
Some(s) => s.image_antecedent(len as usize - 1),
None => None,
};
if image_antecedent.is_some() {
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<I: Iterator<Item = (usize, usize)>, T>(
// do the calibration
let mut calibrate_result_vec = Vec::new();
let offsets = image_antecedent.values().copied();
/*
let offsets: Box<dyn Iterator<Item = isize>> = 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<I: Iterator<Item = (usize, usize)>, 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<I: Iterator<Item = (usize, usize)>, 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(", "),

View File

@ -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<HashMap<u8, isize>> {
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<HashMap<u8, isize>> {
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<usize> {
match self {
CacheAttackSlicing::ComplexAddressing(_)
| CacheAttackSlicing::SimpleAddressing(_)
| CacheAttackSlicing::Unsupported(_) => {
let matrix = self.pivot(mask as isize);
let mut result = HashSet::<usize>::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<usize, isize> {
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<usize, isize> {
let mut result = HashMap::<usize, isize>::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
}
}