From 30227947527bf6aee6f3f429e9707677307321e4 Mon Sep 17 00:00:00 2001 From: Guillume DIDIER Date: Mon, 19 Jul 2021 09:02:08 +0200 Subject: [PATCH] Hotfix - Use naive F+R instead of F+R F+R currently has a calibration bug --- prefetcher_reverse/src/lib.rs | 259 +++++++++++++++++++++++++++++---- prefetcher_reverse/src/main.rs | 31 ++-- 2 files changed, 252 insertions(+), 38 deletions(-) diff --git a/prefetcher_reverse/src/lib.rs b/prefetcher_reverse/src/lib.rs index 50f17c2..9be9acc 100644 --- a/prefetcher_reverse/src/lib.rs +++ b/prefetcher_reverse/src/lib.rs @@ -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>, ff_handles: Vec>, - fr_handles: Vec>, + fr_handles: Vec>, page_indexes: Peekable>>, 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, 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; +#[derive(Debug)] pub enum ProbeResult { - Load(u32), - Flush(u32), - FullFlush(Vec), + Load(SinglePR), + Flush(SinglePR), + FullFlush(FullPR), } +#[derive(Debug)] pub struct ProbePatternResult { pub num_iteration: u32, pub pattern_result: Vec, pub probe_result: ProbeResult, } -struct DPRItem { - pattern_result: Vec, - probe_result: u32, +#[derive(Debug)] +pub struct DPRItem { + pub pattern_result: Vec, + 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, + pub flush: DPRItem, } +#[derive(Debug)] pub struct FullPageDualProbeResults { - num_iteration: u32, - results: Vec, + pub pattern: Vec, + pub num_iteration: u32, + pub single_probe_results: Vec, + pub full_flush_results: DPRItem, } -struct SingleProbeResult { - probe_offset: usize, - pattern_result: Vec, - probe_result: u32, +#[derive(Debug)] +pub struct SingleProbeResult { + pub probe_offset: usize, + pub pattern_result: Vec, + pub probe_result: u32, } +#[derive(Debug)] pub struct FullPageSingleProbeResult { - probe_type: Probe, - num_iteration: u32, - results: Vec, + pub pattern: Vec, + pub probe_type: ProbeType, + pub num_iteration: u32, + pub results: Vec, } // Helper function @@ -106,7 +130,7 @@ fn max_stride(offset: usize, len: usize) -> (isize, isize) { } impl Prober { - fn new(num_pages: usize) -> Result { + pub fn new(num_pages: usize) -> Result { 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::::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, + 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) + } } diff --git a/prefetcher_reverse/src/main.rs b/prefetcher_reverse/src/main.rs index 4c32308..d71ffa2 100644 --- a/prefetcher_reverse/src/main.rs +++ b/prefetcher_reverse/src/main.rs @@ -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)); + */ }