Threshold computation & calibration enhancements
This commit is contained in:
parent
5cd3150a4b
commit
a2d494d610
@ -1,7 +1,7 @@
|
|||||||
use cache_utils::calibration::{
|
use cache_utils::calibration::{
|
||||||
calibrate_fixed_freq_2_thread, flush_and_reload, load_and_flush, only_flush, only_reload,
|
calibrate_fixed_freq_2_thread, flush_and_reload, get_cache_slicing, load_and_flush, only_flush,
|
||||||
reload_and_flush, CalibrateOperation2T, CalibrationOptions, HistParams, Verbosity,
|
only_reload, reload_and_flush, CalibrateOperation2T, CalibrateResult2T, CalibrationOptions,
|
||||||
CFLUSH_BUCKET_NUMBER, CFLUSH_BUCKET_SIZE, CFLUSH_NUM_ITER,
|
HistParams, Verbosity, CFLUSH_BUCKET_NUMBER, CFLUSH_BUCKET_SIZE, CFLUSH_NUM_ITER,
|
||||||
};
|
};
|
||||||
use cache_utils::mmap::MMappedMemory;
|
use cache_utils::mmap::MMappedMemory;
|
||||||
use cache_utils::{flush, maccess, noop};
|
use cache_utils::{flush, maccess, noop};
|
||||||
@ -9,6 +9,8 @@ use nix::sched::{sched_getaffinity, CpuSet};
|
|||||||
use nix::unistd::Pid;
|
use nix::unistd::Pid;
|
||||||
|
|
||||||
use core::arch::x86_64 as arch_x86;
|
use core::arch::x86_64 as arch_x86;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
|
|
||||||
@ -26,6 +28,39 @@ unsafe fn multiple_access(p: *const u8) {
|
|||||||
|
|
||||||
const SIZE: usize = 2 << 20;
|
const SIZE: usize = 2 << 20;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Hash, Eq, PartialEq, Debug)]
|
||||||
|
struct ASV {
|
||||||
|
pub attacker: u8,
|
||||||
|
pub slice: u8,
|
||||||
|
pub victim: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ResultAnalysis {
|
||||||
|
// indexed by bucket size
|
||||||
|
pub miss: Vec<u32>,
|
||||||
|
pub miss_cum_sum: Vec<u32>,
|
||||||
|
pub miss_total: u32,
|
||||||
|
pub hit: Vec<u32>,
|
||||||
|
pub hit_cum_sum: Vec<u32>,
|
||||||
|
pub hit_total: u32,
|
||||||
|
pub error_miss_less_than_hit: Vec<u32>,
|
||||||
|
pub error_hit_less_than_miss: Vec<u32>,
|
||||||
|
pub min_error_hlm: u32,
|
||||||
|
pub min_error_mlh: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct Threshold {
|
||||||
|
pub error_rate: f32,
|
||||||
|
pub threshold: usize,
|
||||||
|
// extend with other possible algorithm ?
|
||||||
|
pub is_hlm: bool,
|
||||||
|
pub num_true_hit: u32,
|
||||||
|
pub num_false_hit: u32,
|
||||||
|
pub num_true_miss: u32,
|
||||||
|
pub num_false_miss: u32,
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Grab a slice of memory
|
// Grab a slice of memory
|
||||||
|
|
||||||
@ -75,73 +110,76 @@ fn main() {
|
|||||||
if pointer as usize & (cache_line_size - 1) != 0 {
|
if pointer as usize & (cache_line_size - 1) != 0 {
|
||||||
panic!("not aligned nicely");
|
panic!("not aligned nicely");
|
||||||
}
|
}
|
||||||
calibrate_fixed_freq_2_thread(
|
|
||||||
|
let operations = [
|
||||||
|
CalibrateOperation2T {
|
||||||
|
prepare: maccess::<u8>,
|
||||||
|
op: only_flush,
|
||||||
|
name: "clflush_remote_hit",
|
||||||
|
display_name: "clflush remote hit",
|
||||||
|
},
|
||||||
|
CalibrateOperation2T {
|
||||||
|
prepare: maccess::<u8>,
|
||||||
|
op: load_and_flush,
|
||||||
|
name: "clflush_shared_hit",
|
||||||
|
display_name: "clflush shared hit",
|
||||||
|
},
|
||||||
|
CalibrateOperation2T {
|
||||||
|
prepare: flush,
|
||||||
|
op: only_flush,
|
||||||
|
name: "clflush_miss_f",
|
||||||
|
display_name: "clflush miss - f",
|
||||||
|
},
|
||||||
|
CalibrateOperation2T {
|
||||||
|
prepare: flush,
|
||||||
|
op: load_and_flush,
|
||||||
|
name: "clflush_local_hit_f",
|
||||||
|
display_name: "clflush local hit - f",
|
||||||
|
},
|
||||||
|
CalibrateOperation2T {
|
||||||
|
prepare: noop::<u8>,
|
||||||
|
op: only_flush,
|
||||||
|
name: "clflush_miss_n",
|
||||||
|
display_name: "clflush miss - n",
|
||||||
|
},
|
||||||
|
CalibrateOperation2T {
|
||||||
|
prepare: noop::<u8>,
|
||||||
|
op: load_and_flush,
|
||||||
|
name: "clflush_local_hit_n",
|
||||||
|
display_name: "clflush local hit - n",
|
||||||
|
},
|
||||||
|
CalibrateOperation2T {
|
||||||
|
prepare: noop::<u8>,
|
||||||
|
op: flush_and_reload,
|
||||||
|
name: "reload_miss",
|
||||||
|
display_name: "reload miss",
|
||||||
|
},
|
||||||
|
CalibrateOperation2T {
|
||||||
|
prepare: maccess::<u8>,
|
||||||
|
op: reload_and_flush,
|
||||||
|
name: "reload_remote_hit",
|
||||||
|
display_name: "reload remote hit",
|
||||||
|
},
|
||||||
|
CalibrateOperation2T {
|
||||||
|
prepare: maccess::<u8>,
|
||||||
|
op: only_reload,
|
||||||
|
name: "reload_shared_hit",
|
||||||
|
display_name: "reload shared hit",
|
||||||
|
},
|
||||||
|
CalibrateOperation2T {
|
||||||
|
prepare: noop::<u8>,
|
||||||
|
op: only_reload,
|
||||||
|
name: "reload_local_hit",
|
||||||
|
display_name: "reload local hit",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let r = calibrate_fixed_freq_2_thread(
|
||||||
pointer,
|
pointer,
|
||||||
64,
|
64,
|
||||||
array.len() as isize >> 3,
|
array.len() as isize >> 3,
|
||||||
&mut core_pairs.into_iter(),
|
&mut core_pairs.into_iter(),
|
||||||
&[
|
&operations,
|
||||||
CalibrateOperation2T {
|
|
||||||
prepare: multiple_access,
|
|
||||||
op: only_flush,
|
|
||||||
name: "clflush_remote_hit",
|
|
||||||
display_name: "clflush remote hit",
|
|
||||||
},
|
|
||||||
CalibrateOperation2T {
|
|
||||||
prepare: multiple_access,
|
|
||||||
op: load_and_flush,
|
|
||||||
name: "clflush_shared_hit",
|
|
||||||
display_name: "clflush shared hit",
|
|
||||||
},
|
|
||||||
CalibrateOperation2T {
|
|
||||||
prepare: flush,
|
|
||||||
op: only_flush,
|
|
||||||
name: "clflush_miss_f",
|
|
||||||
display_name: "clflush miss - f",
|
|
||||||
},
|
|
||||||
CalibrateOperation2T {
|
|
||||||
prepare: flush,
|
|
||||||
op: load_and_flush,
|
|
||||||
name: "clflush_local_hit_f",
|
|
||||||
display_name: "clflush local hit - f",
|
|
||||||
},
|
|
||||||
CalibrateOperation2T {
|
|
||||||
prepare: noop::<u8>,
|
|
||||||
op: only_flush,
|
|
||||||
name: "clflush_miss_n",
|
|
||||||
display_name: "clflush miss - n",
|
|
||||||
},
|
|
||||||
CalibrateOperation2T {
|
|
||||||
prepare: noop::<u8>,
|
|
||||||
op: load_and_flush,
|
|
||||||
name: "clflush_local_hit_n",
|
|
||||||
display_name: "clflush local hit - n",
|
|
||||||
},
|
|
||||||
CalibrateOperation2T {
|
|
||||||
prepare: noop::<u8>,
|
|
||||||
op: flush_and_reload,
|
|
||||||
name: "reload_miss",
|
|
||||||
display_name: "reload miss",
|
|
||||||
},
|
|
||||||
CalibrateOperation2T {
|
|
||||||
prepare: multiple_access,
|
|
||||||
op: reload_and_flush,
|
|
||||||
name: "reload_remote_hit",
|
|
||||||
display_name: "reload remote hit",
|
|
||||||
},
|
|
||||||
CalibrateOperation2T {
|
|
||||||
prepare: multiple_access,
|
|
||||||
op: only_reload,
|
|
||||||
name: "reload_shared_hit",
|
|
||||||
display_name: "reload shared hit",
|
|
||||||
},
|
|
||||||
CalibrateOperation2T {
|
|
||||||
prepare: noop::<u8>,
|
|
||||||
op: only_reload,
|
|
||||||
name: "reload_local_hit",
|
|
||||||
display_name: "reload local hit",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
CalibrationOptions {
|
CalibrationOptions {
|
||||||
hist_params: HistParams {
|
hist_params: HistParams {
|
||||||
bucket_number: CFLUSH_BUCKET_NUMBER,
|
bucket_number: CFLUSH_BUCKET_NUMBER,
|
||||||
@ -153,5 +191,151 @@ fn main() {
|
|||||||
},
|
},
|
||||||
core_per_socket,
|
core_per_socket,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut analysis = HashMap::<ASV, ResultAnalysis>::new();
|
||||||
|
|
||||||
|
let miss_name = "clflush_miss_n";
|
||||||
|
let hit_name = "clflush_remote_hit";
|
||||||
|
|
||||||
|
let miss_index = operations
|
||||||
|
.iter()
|
||||||
|
.position(|op| op.name == miss_name)
|
||||||
|
.unwrap();
|
||||||
|
let hit_index = operations
|
||||||
|
.iter()
|
||||||
|
.position(|op| op.name == hit_name)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let slicing = get_cache_slicing(core_per_socket);
|
||||||
|
|
||||||
|
let h = if let Some(s) = slicing {
|
||||||
|
if s.can_hash() {
|
||||||
|
|addr: usize| -> u8 { slicing.unwrap().hash(addr).unwrap() }
|
||||||
|
} else {
|
||||||
|
panic!("No slicing function known");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("No slicing function known");
|
||||||
|
};
|
||||||
|
|
||||||
|
for result in r {
|
||||||
|
match result.res {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Ooops : {:#?}", e);
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
Ok(results) => {
|
||||||
|
for r in results {
|
||||||
|
let offset = r.offset;
|
||||||
|
let miss_hist = r.histogram[miss_index].clone();
|
||||||
|
let hit_hist = r.histogram[hit_index].clone();
|
||||||
|
|
||||||
|
if miss_hist.len() != hit_hist.len() {
|
||||||
|
panic!("Maformed results");
|
||||||
|
}
|
||||||
|
let len = miss_hist.len();
|
||||||
|
let mut miss_cum_sum = vec![0; len];
|
||||||
|
let mut hit_cum_sum = vec![0; len];
|
||||||
|
miss_cum_sum[0] = miss_hist[0];
|
||||||
|
hit_cum_sum[0] = hit_hist[0];
|
||||||
|
for i in 1..len {
|
||||||
|
miss_cum_sum[i] = miss_hist[i] + miss_cum_sum[i - 1];
|
||||||
|
hit_cum_sum[i] = hit_hist[i] + hit_cum_sum[i - 1];
|
||||||
|
}
|
||||||
|
let miss_total = miss_cum_sum[len - 1];
|
||||||
|
let hit_total = hit_cum_sum[len - 1];
|
||||||
|
|
||||||
|
let mut error_miss_less_than_hit = vec![0; len - 1];
|
||||||
|
let mut error_hit_less_than_miss = vec![0; len - 1];
|
||||||
|
|
||||||
|
let mut min_error_hlm = u32::max_value();
|
||||||
|
let mut min_error_mlh = u32::max_value();
|
||||||
|
|
||||||
|
for i in 0..(len - 1) {
|
||||||
|
error_hit_less_than_miss[i] =
|
||||||
|
miss_cum_sum[i] + (hit_total - hit_cum_sum[i]);
|
||||||
|
error_miss_less_than_hit[i] =
|
||||||
|
hit_cum_sum[i] + (miss_total - miss_cum_sum[i]);
|
||||||
|
|
||||||
|
if error_hit_less_than_miss[i] < min_error_hlm {
|
||||||
|
min_error_hlm = error_hit_less_than_miss[i];
|
||||||
|
}
|
||||||
|
if error_miss_less_than_hit[i] < min_error_mlh {
|
||||||
|
min_error_mlh = error_miss_less_than_hit[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
analysis.insert(
|
||||||
|
ASV {
|
||||||
|
attacker: result.main_core as u8,
|
||||||
|
slice: h(offset as usize),
|
||||||
|
victim: result.helper_core as u8,
|
||||||
|
},
|
||||||
|
ResultAnalysis {
|
||||||
|
miss: miss_hist,
|
||||||
|
miss_cum_sum,
|
||||||
|
miss_total,
|
||||||
|
hit: hit_hist,
|
||||||
|
hit_cum_sum,
|
||||||
|
hit_total,
|
||||||
|
error_miss_less_than_hit,
|
||||||
|
error_hit_less_than_miss,
|
||||||
|
min_error_hlm,
|
||||||
|
min_error_mlh,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut thresholds = HashMap::new();
|
||||||
|
for (asv, results) in analysis {
|
||||||
|
let hlm = results.min_error_hlm < results.min_error_mlh;
|
||||||
|
let (errors, min_error) = if hlm {
|
||||||
|
(&results.error_hit_less_than_miss, results.min_error_hlm)
|
||||||
|
} else {
|
||||||
|
(&results.error_miss_less_than_hit, results.min_error_mlh)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut threshold_vec = Vec::new();
|
||||||
|
|
||||||
|
// refactor some of this logic into methods of analysis ?
|
||||||
|
|
||||||
|
for i in 0..errors.len() {
|
||||||
|
if errors[i] == min_error {
|
||||||
|
let num_true_hit;
|
||||||
|
let num_false_hit;
|
||||||
|
let num_true_miss;
|
||||||
|
let num_false_miss;
|
||||||
|
if hlm {
|
||||||
|
num_true_hit = results.hit_cum_sum[i];
|
||||||
|
num_false_hit = results.miss_cum_sum[i];
|
||||||
|
num_true_miss = results.miss_total - num_false_hit;
|
||||||
|
num_false_miss = results.hit_total - num_true_hit;
|
||||||
|
} else {
|
||||||
|
num_true_miss = results.miss_cum_sum[i];
|
||||||
|
num_false_miss = results.hit_cum_sum[i];
|
||||||
|
num_true_hit = results.hit_total - num_false_miss;
|
||||||
|
num_false_hit = results.miss_total - num_true_miss;
|
||||||
|
}
|
||||||
|
threshold_vec.push(Threshold {
|
||||||
|
threshold: i,
|
||||||
|
is_hlm: hlm,
|
||||||
|
num_true_hit,
|
||||||
|
num_false_hit,
|
||||||
|
num_true_miss,
|
||||||
|
num_false_miss,
|
||||||
|
error_rate: min_error as f32
|
||||||
|
/ (results.hit_total + results.miss_total) as f32,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
thresholds.insert(asv, threshold_vec);
|
||||||
|
}
|
||||||
|
eprintln!("Thresholds :\n{:#?}", thresholds);
|
||||||
|
println!("Thresholds :\n{:#?}", thresholds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![allow(clippy::missing_safety_doc)]
|
#![allow(clippy::missing_safety_doc)]
|
||||||
|
|
||||||
use crate::complex_addressing::cache_slicing;
|
use crate::complex_addressing::{cache_slicing, CacheSlicing};
|
||||||
use crate::{flush, maccess, rdtsc_fence};
|
use crate::{flush, maccess, rdtsc_fence};
|
||||||
|
|
||||||
use cpuid::{CPUVendor, MicroArchitecture};
|
use cpuid::{CPUVendor, MicroArchitecture};
|
||||||
@ -234,11 +234,11 @@ pub fn calibrate_flush(
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CalibrateResult {
|
pub struct CalibrateResult {
|
||||||
offset: isize,
|
pub offset: isize,
|
||||||
histogram: Vec<Vec<u32>>,
|
pub histogram: Vec<Vec<u32>>,
|
||||||
median: Vec<u64>,
|
pub median: Vec<u64>,
|
||||||
min: Vec<u64>,
|
pub min: Vec<u64>,
|
||||||
max: Vec<u64>,
|
pub max: Vec<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CalibrateOperation<'a> {
|
pub struct CalibrateOperation<'a> {
|
||||||
@ -293,6 +293,7 @@ fn calibrate_impl_fixed_freq(
|
|||||||
let to_bucket = |time: u64| -> usize { time as usize / hist_params.bucket_size };
|
let to_bucket = |time: u64| -> usize { time as usize / hist_params.bucket_size };
|
||||||
let from_bucket = |bucket: usize| -> u64 { (bucket * hist_params.bucket_size) as u64 };
|
let from_bucket = |bucket: usize| -> u64 { (bucket * hist_params.bucket_size) as u64 };
|
||||||
|
|
||||||
|
// FIXME : Core per socket
|
||||||
let slicing = if let Some(uarch) = MicroArchitecture::get_micro_architecture() {
|
let slicing = if let Some(uarch) = MicroArchitecture::get_micro_architecture() {
|
||||||
if let Some(vendor_family_model_stepping) = MicroArchitecture::get_family_model_stepping() {
|
if let Some(vendor_family_model_stepping) = MicroArchitecture::get_family_model_stepping() {
|
||||||
Some(cache_slicing(
|
Some(cache_slicing(
|
||||||
@ -510,7 +511,25 @@ pub unsafe fn calibrate_fixed_freq_2_thread<I: Iterator<Item = (usize, usize)>>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const OPTIMISED_ADDR_ITER_FACTOR: u32 = 64;
|
pub fn get_cache_slicing(core_per_socket: u8) -> Option<CacheSlicing> {
|
||||||
|
if let Some(uarch) = MicroArchitecture::get_micro_architecture() {
|
||||||
|
if let Some(vendor_family_model_stepping) = MicroArchitecture::get_family_model_stepping() {
|
||||||
|
Some(cache_slicing(
|
||||||
|
uarch,
|
||||||
|
core_per_socket,
|
||||||
|
vendor_family_model_stepping.0,
|
||||||
|
vendor_family_model_stepping.1,
|
||||||
|
vendor_family_model_stepping.2,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const OPTIMISED_ADDR_ITER_FACTOR: u32 = 16;
|
||||||
|
|
||||||
// TODO : Add the optimised address support
|
// TODO : Add the optimised address support
|
||||||
// TODO : Modularisation / factorisation of some of the common code with the single threaded no_std version ?
|
// TODO : Modularisation / factorisation of some of the common code with the single threaded no_std version ?
|
||||||
@ -540,21 +559,7 @@ fn calibrate_fixed_freq_2_thread_impl<I: Iterator<Item = (usize, usize)>>(
|
|||||||
let to_bucket = |time: u64| -> usize { time as usize / bucket_size };
|
let to_bucket = |time: u64| -> usize { time as usize / bucket_size };
|
||||||
let from_bucket = |bucket: usize| -> u64 { (bucket * bucket_size) as u64 };
|
let from_bucket = |bucket: usize| -> u64 { (bucket * bucket_size) as u64 };
|
||||||
|
|
||||||
let slicing = if let Some(uarch) = MicroArchitecture::get_micro_architecture() {
|
let slicing = get_cache_slicing(core_per_socket);
|
||||||
if let Some(vendor_family_model_stepping) = MicroArchitecture::get_family_model_stepping() {
|
|
||||||
Some(cache_slicing(
|
|
||||||
uarch,
|
|
||||||
core_per_socket,
|
|
||||||
vendor_family_model_stepping.0,
|
|
||||||
vendor_family_model_stepping.1,
|
|
||||||
vendor_family_model_stepping.2,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let h = if let Some(s) = slicing {
|
let h = if let Some(s) = slicing {
|
||||||
if s.can_hash() {
|
if s.can_hash() {
|
||||||
|
Loading…
Reference in New Issue
Block a user