2022-01-25 14:18:03 +01:00

253 lines
9.0 KiB
Rust

#![deny(unsafe_op_in_unsafe_fn)]
use basic_timing_cache_channel::TopologyAwareError;
use cache_side_channel::CacheStatus::Hit;
use cache_side_channel::{
set_affinity, ChannelHandle, CoreSpec, MultipleAddrCacheSideChannel, SingleAddrCacheSideChannel,
};
use cache_utils::calibration::PAGE_LEN;
use cache_utils::ip_tool::{Function, TIMED_MACCESS};
use cache_utils::maccess;
use cache_utils::mmap;
use cache_utils::mmap::MMappedMemory;
use flush_flush::{FFHandle, FFPrimitives, FlushAndFlush};
use nix::Error;
use prefetcher_reverse::{
pattern_helper, PatternAccess, Prober, CACHE_LINE_LEN, PAGE_CACHELINE_LEN,
};
use rand::seq::SliceRandom;
use std::iter::Cycle;
pub const NUM_ITERATION: usize = 1 << 10;
pub const NUM_PAGES: usize = 256;
// TODO negative stride
fn generate_pattern(offset: usize, len: usize, stride: isize) -> Option<Vec<usize>> {
let end = (offset as isize + stride * len as isize) * CACHE_LINE_LEN as isize;
if end < 0 || end > PAGE_LEN as isize {
return None;
}
let mut res = Vec::with_capacity(len);
let mut addr = offset as isize;
for _ in 0..len {
res.push(addr as usize);
addr += stride;
}
Some(res)
}
fn execute_pattern(
channel: &mut FlushAndFlush,
page_handles: &mut Vec<&mut <FlushAndFlush as MultipleAddrCacheSideChannel>::Handle>,
pattern: &Vec<usize>,
) -> Vec<bool> {
for offset in pattern {
let pointer = page_handles[*offset].to_const_u8_pointer();
unsafe { maccess(pointer) };
}
let measures = unsafe { channel.test(page_handles, true) };
let mut res = vec![false; PAGE_CACHELINE_LEN];
for (i, status) in measures.unwrap().into_iter().enumerate() {
res[i] = status.1 == Hit;
}
res
}
fn execute_pattern_probe1(
channel: &mut FlushAndFlush,
page_handles: &mut Vec<&mut <FlushAndFlush as MultipleAddrCacheSideChannel>::Handle>,
pattern: &Vec<usize>,
probe_offset: usize,
) -> bool {
for offset in pattern {
let pointer = page_handles[*offset].to_const_u8_pointer();
unsafe { maccess(pointer) };
}
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();
let old_affinity = set_affinity(&channel.main_core());
for i in 0..NUM_PAGES {
let mut p = MMappedMemory::<u8>::new(PAGE_LEN, false);
for j in 0..PAGE_LEN {
p[j] = (i * PAGE_CACHELINE_LEN + j) as u8;
}
let page_addresses =
((0..PAGE_LEN).step_by(CACHE_LINE_LEN)).map(|offset| &p[offset] as *const u8);
let page_handles = unsafe { channel.calibrate(page_addresses) }.unwrap();
println!("{:p}", page_handles[0].to_const_u8_pointer());
vec.push(p);
handles.push(page_handles);
}
println!();
let mut page_indexes = (0..(handles.len())).cycle();
handles.shuffle(&mut rand::thread_rng());
let mut handles_mutref = Vec::new();
for page in handles.iter_mut() {
handles_mutref.push(
page.iter_mut()
.collect::<Vec<&mut <FlushAndFlush as MultipleAddrCacheSideChannel>::Handle>>(),
);
}
// Use an std::iter::Cycle iterator for pages.
/*
TODO List :
Calibration & core selection (select one or two cores with optimal error)
Then allocate a bunch of pages, and do accesses on each of them.
(Let's start with stride patterns: for len in 0..16, and then for stride in 1..maxs_stride(len),
generate a vec of addresses and get the victim to execute, then dump all the page)
Sanity check on one pattern : do full dump, vs do dump per address.
Both can be done using the FlushFlush channel
*/
let pattern = generate_pattern(1, 4, 4).unwrap();
println!("{:?}", pattern);
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]) }.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_first[j] += 1;
}
}
}
let mut probe1_result = [0; PAGE_CACHELINE_LEN];
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]) }.unwrap();
let res =
execute_pattern_probe1(&mut channel, &mut handles_mutref[page_index], &pattern, i);
if res {
probe1_result[i] += 1;
}
}
}
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]) }.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;
}
}
}
for i in 0..PAGE_CACHELINE_LEN {
println!(
"{:2} {:4} {:4} {:4}",
i, probe_all_result_first[i], probe1_result[i], probe_all_result[i]
);
}
let pattern = generate_pattern(0, 3, 12).unwrap();
println!("{:?}", pattern);
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]) }.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_first[j] += 1;
}
}
}
let mut probe1_result = [0; PAGE_CACHELINE_LEN];
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]) }.unwrap();
let res =
execute_pattern_probe1(&mut channel, &mut handles_mutref[page_index], &pattern, i);
if res {
probe1_result[i] += 1;
}
}
}
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]) }.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 reload = Function::try_new(1, 0, TIMED_MACCESS).unwrap();
let pattern = pattern_helper(&generate_pattern(0, 3, 12).unwrap(), &reload);
let pattern4 = pattern_helper(&generate_pattern(0, 4, 12).unwrap(), &reload);
let mut new_prober = Prober::<1>::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);
let result4 = new_prober.full_page_probe(pattern4, NUM_ITERATION as u32, 100);
println!("{}", result4);
let pattern5 = pattern_helper(&generate_pattern(0, 5, 8).unwrap(), &reload);
let result5 = new_prober.full_page_probe(pattern5, NUM_ITERATION as u32, 100);
println!("{}", result5);
let pattern5 = pattern_helper(&generate_pattern(0, 5, 4).unwrap(), &reload);
let result5 = new_prober.full_page_probe(pattern5, NUM_ITERATION as u32, 100);
println!("{}", result5);
let pattern = pattern_helper(&generate_pattern(0, 10, 4).unwrap(), &reload);
let result = new_prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
println!("{}", result);
let pattern = pattern_helper(&generate_pattern(0, 6, 8).unwrap(), &reload);
let result = new_prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
println!("{}", result);
let pattern = pattern_helper(&generate_pattern(2, 6, 0).unwrap(), &reload);
let result = new_prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
println!("{}", result);
let pattern = pattern_helper(&vec![0, 0, 8, 8, 16, 16, 24, 24], &reload);
let result = new_prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
println!("{}", result);
/*
for i in 0..PAGE_CACHELINE_LEN {
println!(
"{:2} {:4} {:4} {:4}",
i, probe_all_result_first[i], probe1_result[i], probe_all_result[i]
);
}
println!("{:?}", generate_pattern(0, 5, 1));
println!("{:?}", generate_pattern(5, 0, 1));
println!("{:?}", generate_pattern(1, 5, 5));
println!("{:?}", generate_pattern(0, 16, 16));
*/
}