Hotfix - Use naive F+R instead of F+R

F+R currently has a calibration bug
This commit is contained in:
Guillume DIDIER 2021-07-19 09:02:08 +02:00
parent 28f75075e3
commit 3022794752
2 changed files with 252 additions and 38 deletions

View File

@ -1,15 +1,18 @@
use crate::Probe::{Flush, Load};
#![deny(unsafe_op_in_unsafe_fn)]
use crate::Probe::{Flush, FullFlush, Load};
use basic_timing_cache_channel::{TopologyAwareError, TopologyAwareTimingChannel};
use cache_side_channel::CacheStatus::Hit;
use cache_side_channel::{
set_affinity, CacheStatus, CoreSpec, MultipleAddrCacheSideChannel, SingleAddrCacheSideChannel,
};
use cache_utils::calibration::PAGE_LEN;
use cache_utils::calibration::{Threshold, PAGE_LEN};
use cache_utils::mmap::MMappedMemory;
use flush_flush::{FFHandle, FFPrimitives, FlushAndFlush};
use flush_reload::naive::{NFRHandle, NaiveFlushAndReload};
use flush_reload::{FRHandle, FRPrimitives, FlushAndReload};
use nix::sys::stat::stat;
use rand::seq::SliceRandom;
use std::fmt::{Display, Error, Formatter};
use std::iter::{Cycle, Peekable};
use std::ops::Range;
@ -20,10 +23,10 @@ pub const PAGE_CACHELINE_LEN: usize = PAGE_LEN / CACHE_LINE_LEN;
pub struct Prober {
pages: Vec<MMappedMemory<u8>>,
ff_handles: Vec<Vec<FFHandle>>,
fr_handles: Vec<Vec<FRHandle>>,
fr_handles: Vec<Vec<NFRHandle>>,
page_indexes: Peekable<Cycle<Range<usize>>>,
ff_channel: FlushAndFlush,
fr_channel: FlushAndReload,
fr_channel: NaiveFlushAndReload,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -33,12 +36,21 @@ pub enum Probe {
FullFlush,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProbeType {
Load,
Flush,
FullFlush,
}
#[derive(Debug)]
pub struct ProbePattern {
pub pattern: Vec<usize>,
pub probe: Probe,
}
enum ProberError {
#[derive(Debug)]
pub enum ProberError {
NoMem(nix::Error),
TopologyError(TopologyAwareError),
Nix(nix::Error),
@ -47,45 +59,57 @@ enum ProberError {
/**
Result of running a probe pattern num_iteration times,
*/
pub type SinglePR = u32;
pub type FullPR = Vec<u32>;
#[derive(Debug)]
pub enum ProbeResult {
Load(u32),
Flush(u32),
FullFlush(Vec<u32>),
Load(SinglePR),
Flush(SinglePR),
FullFlush(FullPR),
}
#[derive(Debug)]
pub struct ProbePatternResult {
pub num_iteration: u32,
pub pattern_result: Vec<u32>,
pub probe_result: ProbeResult,
}
struct DPRItem {
pattern_result: Vec<u32>,
probe_result: u32,
#[derive(Debug)]
pub struct DPRItem<PR> {
pub pattern_result: Vec<u32>,
pub probe_result: PR,
}
struct DualProbeResult {
probe_offset: usize,
load: DPRItem,
flush: DPRItem,
#[derive(Debug)]
pub struct DualProbeResult {
pub probe_offset: usize,
pub load: DPRItem<SinglePR>,
pub flush: DPRItem<SinglePR>,
}
#[derive(Debug)]
pub struct FullPageDualProbeResults {
num_iteration: u32,
results: Vec<DualProbeResult>,
pub pattern: Vec<usize>,
pub num_iteration: u32,
pub single_probe_results: Vec<DualProbeResult>,
pub full_flush_results: DPRItem<FullPR>,
}
struct SingleProbeResult {
probe_offset: usize,
pattern_result: Vec<u32>,
probe_result: u32,
#[derive(Debug)]
pub struct SingleProbeResult {
pub probe_offset: usize,
pub pattern_result: Vec<u32>,
pub probe_result: u32,
}
#[derive(Debug)]
pub struct FullPageSingleProbeResult {
probe_type: Probe,
num_iteration: u32,
results: Vec<SingleProbeResult>,
pub pattern: Vec<usize>,
pub probe_type: ProbeType,
pub num_iteration: u32,
pub results: Vec<SingleProbeResult>,
}
// Helper function
@ -106,7 +130,7 @@ fn max_stride(offset: usize, len: usize) -> (isize, isize) {
}
impl Prober {
fn new(num_pages: usize) -> Result<Prober, ProberError> {
pub fn new(num_pages: usize) -> Result<Prober, ProberError> {
let mut vec = Vec::new();
let mut handles = Vec::new();
let (mut ff_channel, cpuset, core) = match FlushAndFlush::new_any_single_core() {
@ -119,12 +143,17 @@ impl Prober {
Ok(old) => old,
Err(nixerr) => return Err(ProberError::Nix(nixerr)),
};
let mut fr_channel = NaiveFlushAndReload::new(Threshold {
bucket_index: 250,
miss_faster_than_hit: false,
});
/*
let mut fr_channel = match FlushAndReload::new(core, core) {
Ok(res) => res,
Err(err) => {
return Err(ProberError::TopologyError(err));
}
};
};*/
for i in 0..num_pages {
let mut p = match MMappedMemory::<u8>::try_new(PAGE_LEN, false) {
@ -139,7 +168,7 @@ impl Prober {
let page_addresses =
((0..PAGE_LEN).step_by(CACHE_LINE_LEN)).map(|offset| &p[offset] as *const u8);
let ff_page_handles = unsafe { ff_channel.calibrate(page_addresses.clone()) }.unwrap();
let fr_page_handles = unsafe { fr_channel.calibrate(page_addresses) }.unwrap();
let fr_page_handles = unsafe { fr_channel.calibrate_single(page_addresses) }.unwrap();
vec.push(p);
handles.push((ff_page_handles, fr_page_handles));
@ -151,6 +180,7 @@ impl Prober {
let mut ff_handles = Vec::new();
let mut fr_handles = Vec::new();
for (ff_handle, fr_handle) in handles {
ff_handles.push(ff_handle);
fr_handles.push(fr_handle);
@ -278,4 +308,179 @@ impl Prober {
result
}
fn full_page_probe_helper(
&mut self,
pattern: &mut ProbePattern,
probe_type: ProbeType,
num_iteration: u32,
warmup: u32,
) -> FullPageSingleProbeResult {
let mut result = FullPageSingleProbeResult {
pattern: pattern.pattern.clone(),
probe_type,
num_iteration,
results: vec![],
};
for offset in 0..PAGE_CACHELINE_LEN {
pattern.probe = match probe_type {
ProbeType::Load => Probe::Load(offset),
ProbeType::Flush => Probe::Flush(offset),
ProbeType::FullFlush => FullFlush,
};
let r = self.probe_pattern(pattern, num_iteration, warmup);
result.results.push(SingleProbeResult {
probe_offset: offset,
pattern_result: r.pattern_result,
probe_result: match r.probe_result {
ProbeResult::Load(r) => r,
ProbeResult::Flush(r) => r,
ProbeResult::FullFlush(r) => r[offset],
},
});
}
result
}
pub fn full_page_probe(
&mut self,
pattern: Vec<usize>,
num_iteration: u32,
warmup: u32,
) -> FullPageDualProbeResults {
let mut probe_pattern = ProbePattern {
pattern: pattern,
probe: Probe::FullFlush,
};
let res_flush = self.full_page_probe_helper(
&mut probe_pattern,
ProbeType::Flush,
num_iteration,
warmup,
);
let res_load =
self.full_page_probe_helper(&mut probe_pattern, ProbeType::Load, num_iteration, warmup);
probe_pattern.probe = FullFlush;
let res_full_flush = self.probe_pattern(&probe_pattern, num_iteration, warmup);
// TODO results
FullPageDualProbeResults {
pattern: probe_pattern.pattern,
num_iteration,
single_probe_results: res_flush
.results
.into_iter()
.enumerate()
.zip(res_load.results.into_iter())
.map(|((offset, flush), load)| DualProbeResult {
probe_offset: offset,
load: DPRItem {
pattern_result: load.pattern_result,
probe_result: load.probe_result,
},
flush: DPRItem {
pattern_result: flush.pattern_result,
probe_result: flush.probe_result,
},
})
.collect(),
full_flush_results: DPRItem {
pattern_result: res_full_flush.pattern_result,
probe_result: match res_full_flush.probe_result {
ProbeResult::FullFlush(r) => r,
_ => {
unreachable!()
}
},
},
}
}
}
impl Display for FullPageDualProbeResults {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut indices = vec![None; PAGE_CACHELINE_LEN];
let pat_len = self.pattern.len();
let divider = (PAGE_CACHELINE_LEN * self.num_iteration as usize) as f32;
for (i, &offset) in self.pattern.iter().enumerate() {
indices[offset] = Some(i);
}
// Display header
let mut r = writeln!(f, "{:^3} {:^7} | {:^8} {:^8} {:^8} {:^8} | {:^8} {:^8} {:^8} {:^8} | {:^8} {:^8} {:^8} {:^8}",
"pat", "offset",
"SF Ac H", "SF Ac HR", "SF Pr H", "SF Pr HR",
"SR Ac H", "SR Ac HR", "SR Pr H", "SR Pr HR",
"FF Ac H", "FF Ac HR", "FF Pr H", "FF Pr HR");
match r {
Ok(_) => {}
Err(e) => {
return Err(e);
}
}
for i in 0..PAGE_CACHELINE_LEN {
let index = indices[i];
let (pat, sf_ac_h, sf_ac_hr, sr_ac_h, sr_ac_hr, ff_ac_h, ff_ac_hr) = match index {
None => (
String::from(""),
String::from(""),
String::from(""),
String::from(""),
String::from(""),
String::from(""),
String::from(""),
),
Some(index) => {
let pat = format!("{:3}", index);
let sf_ac: u32 = self
.single_probe_results
.iter()
.map(|d| d.flush.pattern_result[index])
.sum();
let sf_ac_h = format!("{:8}", sf_ac);
let sf_ac_hr = format!("{:8}", sf_ac as f32 / divider);
let sr_ac: u32 = self
.single_probe_results
.iter()
.map(|d| d.load.pattern_result[index])
.sum();
let sr_ac_h = format!("{:8}", sr_ac);
let sr_ac_hr = format!("{:8}", sr_ac as f32 / divider);
let ff_ac = self.full_flush_results.pattern_result[index];
let ff_ac_h = format!("{:8}", ff_ac);
let ff_ac_hr = format!("{:8}", ff_ac as f32 / self.num_iteration as f32);
(pat, sf_ac_h, sf_ac_hr, sr_ac_h, sr_ac_hr, ff_ac_h, ff_ac_hr)
}
};
let sf_pr = self.single_probe_results[i].flush.probe_result;
let sf_pr_h = format!("{:8}", sf_pr);
let sf_pr_hr = format!("{:8}", sf_pr as f32 / self.num_iteration as f32);
let sr_pr = self.single_probe_results[i].load.probe_result;
let sr_pr_h = format!("{:8}", sr_pr);
let sr_pr_hr = format!("{:8}", sr_pr as f32 / self.num_iteration as f32);
let ff_pr = self.full_flush_results.probe_result[i];
let ff_pr_h = format!("{:8}", ff_pr);
let ff_pr_hr = format!("{:8}", ff_pr as f32 / self.num_iteration as f32);
r = writeln!(f, "{:>3} {:>7} | {:>8} {:^8} {:>8} {:^8} | {:>8} {:^8} {:>8} {:^8} | {:>8} {:^8} {:>8} {:^8}",
pat, i,
sf_ac_h, sf_ac_hr, sf_pr_h, sf_pr_hr,
sr_ac_h, sr_ac_hr, sr_pr_h, sr_pr_hr,
ff_ac_h, ff_ac_hr, ff_pr_h, ff_pr_hr);
match r {
Ok(_) => {}
Err(e) => {
return Err(e);
}
};
// display lines
}
write!(f, "Num_iteration: {}", self.num_iteration)
}
}

View File

@ -1,4 +1,3 @@
#![feature(unsafe_block_in_unsafe_fn)]
#![deny(unsafe_op_in_unsafe_fn)]
use basic_timing_cache_channel::TopologyAwareError;
use cache_side_channel::CacheStatus::Hit;
@ -44,7 +43,7 @@ fn execute_pattern(
unsafe { maccess(pointer) };
}
let mut measures = unsafe { channel.test(page_handles, true) };
let measures = unsafe { channel.test(page_handles, true) };
let mut res = vec![false; PAGE_CACHELINE_LEN];
@ -65,12 +64,13 @@ fn execute_pattern_probe1(
unsafe { maccess(pointer) };
}
let mut measure = unsafe { channel.test_single(&mut page_handles[probe_offset], true) };
let measure = unsafe { channel.test_single(&mut page_handles[probe_offset], true) };
measure.unwrap() == Hit
}
fn main() {
/*
let mut vec = Vec::new();
let mut handles = Vec::new();
let (mut channel, cpuset, core) = FlushAndFlush::new_any_single_core().unwrap();
@ -121,7 +121,7 @@ fn main() {
let mut probe_all_result_first = [0; PAGE_CACHELINE_LEN];
for _ in 0..NUM_ITERATION {
let page_index = page_indexes.next().unwrap();
unsafe { channel.prepare(&mut handles_mutref[page_index]) };
unsafe { channel.prepare(&mut handles_mutref[page_index]) }.unwrap();
let res = execute_pattern(&mut channel, &mut handles_mutref[page_index], &pattern);
for j in 0..PAGE_CACHELINE_LEN {
if res[j] {
@ -133,7 +133,7 @@ fn main() {
for i in 0..PAGE_CACHELINE_LEN {
for _ in 0..NUM_ITERATION {
let page_index = page_indexes.next().unwrap();
unsafe { channel.prepare(&mut handles_mutref[page_index]) };
unsafe { channel.prepare(&mut handles_mutref[page_index]) }.unwrap();
let res =
execute_pattern_probe1(&mut channel, &mut handles_mutref[page_index], &pattern, i);
if res {
@ -144,7 +144,7 @@ fn main() {
let mut probe_all_result = [0; PAGE_CACHELINE_LEN];
for _ in 0..NUM_ITERATION {
let page_index = page_indexes.next().unwrap();
unsafe { channel.prepare(&mut handles_mutref[page_index]) };
unsafe { channel.prepare(&mut handles_mutref[page_index]) }.unwrap();
let res = execute_pattern(&mut channel, &mut handles_mutref[page_index], &pattern);
for j in 0..PAGE_CACHELINE_LEN {
if res[j] {
@ -165,7 +165,7 @@ fn main() {
let mut probe_all_result_first = [0; PAGE_CACHELINE_LEN];
for _ in 0..NUM_ITERATION {
let page_index = page_indexes.next().unwrap();
unsafe { channel.prepare(&mut handles_mutref[page_index]) };
unsafe { channel.prepare(&mut handles_mutref[page_index]) }.unwrap();
let res = execute_pattern(&mut channel, &mut handles_mutref[page_index], &pattern);
for j in 0..PAGE_CACHELINE_LEN {
if res[j] {
@ -177,7 +177,7 @@ fn main() {
for i in 0..PAGE_CACHELINE_LEN {
for _ in 0..NUM_ITERATION {
let page_index = page_indexes.next().unwrap();
unsafe { channel.prepare(&mut handles_mutref[page_index]) };
unsafe { channel.prepare(&mut handles_mutref[page_index]) }.unwrap();
let res =
execute_pattern_probe1(&mut channel, &mut handles_mutref[page_index], &pattern, i);
if res {
@ -188,15 +188,24 @@ fn main() {
let mut probe_all_result = [0; PAGE_CACHELINE_LEN];
for _ in 0..NUM_ITERATION {
let page_index = page_indexes.next().unwrap();
unsafe { channel.prepare(&mut handles_mutref[page_index]) };
unsafe { channel.prepare(&mut handles_mutref[page_index]) }.unwrap();
let res = execute_pattern(&mut channel, &mut handles_mutref[page_index], &pattern);
for j in 0..PAGE_CACHELINE_LEN {
if res[j] {
probe_all_result[j] += 1;
}
}
}
}*/
let pattern = generate_pattern(0, 3, 12).unwrap();
let mut new_prober = Prober::new(63).unwrap();
let result = new_prober.full_page_probe(pattern.clone(), NUM_ITERATION as u32, 100);
println!("{}", result);
println!("{:#?}", result);
let result2 = new_prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
println!("{}", result2);
/*
for i in 0..PAGE_CACHELINE_LEN {
println!(
"{:2} {:4} {:4} {:4}",
@ -204,9 +213,9 @@ fn main() {
);
}
println!("Hello, world!");
println!("{:?}", generate_pattern(0, 5, 1));
println!("{:?}", generate_pattern(5, 0, 1));
println!("{:?}", generate_pattern(1, 5, 5));
println!("{:?}", generate_pattern(0, 16, 16));
*/
}