diff --git a/Cargo.lock b/Cargo.lock index b2589a7..19126c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,10 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bit_field" version = "0.9.0" @@ -36,6 +41,7 @@ dependencies = [ name = "dendrobates_tinctoreus_azureus" version = "0.1.0" dependencies = [ + "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "bootloader 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", "cache_utils 0.1.0", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -121,6 +127,7 @@ dependencies = [ ] [metadata] +"checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" "checksum bit_field 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" diff --git a/Cargo.toml b/Cargo.toml index 4541fe7..8c18f09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ polling_serial = { path = "polling_serial" } volatile = "0.2.6" linked_list_allocator = "0.7.0" cache_utils = { path = "cache_utils" } +arrayref = "0.3.6" [dependencies.lazy_static] version = "1.4.0" diff --git a/cache_utils/src/calibration.rs b/cache_utils/src/calibration.rs index a7548e4..c5d99b9 100644 --- a/cache_utils/src/calibration.rs +++ b/cache_utils/src/calibration.rs @@ -45,15 +45,15 @@ pub unsafe fn only_flush(p: *const u8) -> u64 { const BUCKET_SIZE: usize = 5; const BUCKET_NUMBER: usize = 250; -pub fn calibrate_access() -> u64 { +pub fn calibrate_access(array: &[u8; 4096]) -> u64 { serial_println!("Calibrating..."); // Allocate a target array // TBD why size, why the position in the array, why the type (usize) - let mut array = Vec::::with_capacity(5 << 10); - array.resize(5 << 10, 1); + // let mut array = Vec::::with_capacity(5 << 10); + // array.resize(5 << 10, 1); - let array = array.into_boxed_slice(); + // let array = array.into_boxed_slice(); // Histograms bucket of 5 and max at 400 cycles // Magic numbers to be justified @@ -64,20 +64,30 @@ pub fn calibrate_access() -> u64 { let mut miss_histogram = hit_histogram.clone(); // the address in memory we are going to target - let pointer = (&array[2048] as *const usize) as *const u8; + let pointer = &array[0] as *const u8; + + serial_println!("buffer start {:p}", pointer); + + if pointer as usize & 0x3f != 0 { + panic!("not aligned nicely"); + } // do a large sample of accesses to a cached line unsafe { maccess(pointer) }; - for _ in 0..(4 << 20) { - let d = unsafe { only_reload(pointer) } as usize; - hit_histogram[min(BUCKET_NUMBER - 1, d / BUCKET_SIZE) as usize] += 1; + for i in 0..(4 << 10) { + for _ in 0..(1 << 10) { + let d = unsafe { only_reload(pointer.offset(i & (!0x3f))) } as usize; + hit_histogram[min(BUCKET_NUMBER - 1, d / BUCKET_SIZE) as usize] += 1; + } } // do a large numer of accesses to uncached line unsafe { flush(pointer) }; - for _ in 0..(4 << 20) { - let d = unsafe { flush_and_reload(pointer) } as usize; - miss_histogram[min(BUCKET_NUMBER - 1, d / BUCKET_SIZE) as usize] += 1; + for i in 0..(4 << 10) { + for _ in 0..(1 << 10) { + let d = unsafe { flush_and_reload(pointer.offset(i & (!0x3f))) } as usize; + miss_histogram[min(BUCKET_NUMBER - 1, d / BUCKET_SIZE) as usize] += 1; + } } let mut hit_max = 0; @@ -118,66 +128,76 @@ pub fn calibrate_access() -> u64 { const CFLUSH_BUCKET_SIZE: usize = 1; const CFLUSH_BUCKET_NUMBER: usize = 250; -pub fn calibrate_flush() -> u64 { +pub fn calibrate_flush(array: &[u8; 4096]) -> u64 { serial_println!("Calibrating cflush..."); // Allocate a target array // TBD why size, why the position in the array, why the type (usize) - let mut array = Vec::::with_capacity(5 << 10); - array.resize(5 << 10, 1); + //let mut array = Vec::::with_capacity(5 << 10); + //array.resize(5 << 10, 1); - let array = array.into_boxed_slice(); + //let array = array.into_boxed_slice(); // Histograms bucket of 5 and max at 400 cycles // Magic numbers to be justified // 80 is a size of screen - let mut hit_histogram = vec![0; CFLUSH_BUCKET_NUMBER]; - - let mut miss_histogram = hit_histogram.clone(); // the address in memory we are going to target - let pointer = (&array[2048] as *const usize) as *const u8; + let pointer = (&array[0]) as *const u8; + if pointer as usize & 0x3f != 0 { + panic!("not aligned nicely"); + } // do a large sample of accesses to a cached line - for _ in 0..(4 << 20) { - let d = unsafe { load_and_flush(pointer) } as usize; - hit_histogram[min(CFLUSH_BUCKET_NUMBER - 1, d / CFLUSH_BUCKET_SIZE) as usize] += 1; - } + for i in 0..(4 << 10) { + let mut hit_histogram = vec![0; CFLUSH_BUCKET_NUMBER]; - // do a large numer of accesses to uncached line - unsafe { flush(pointer) }; - for _ in 0..(4 << 20) { - let d = unsafe { flush_and_flush(pointer) } as usize; - miss_histogram[min(CFLUSH_BUCKET_NUMBER - 1, d / CFLUSH_BUCKET_SIZE) as usize] += 1; - } - - let mut hit_max: (usize, u32) = (0, 0); - let mut miss_max: (usize, u32) = (0, 0); - - for i in 0..hit_histogram.len() { - serial_println!( - "{:3}: {:10} {:10}", - i * CFLUSH_BUCKET_SIZE, - hit_histogram[i], - miss_histogram[i] - ); - if hit_max.1 < hit_histogram[i] { - hit_max = (i, hit_histogram[i]); + let mut miss_histogram = hit_histogram.clone(); + serial_println!("Calibration for {:p}", unsafe { pointer.offset(i) }); + unsafe { load_and_flush(pointer.offset(i)) }; // align down on 64 bytes + for _ in 1..(1 << 10) { + let d = unsafe { load_and_flush(pointer.offset(i)) } as usize; + hit_histogram[min(CFLUSH_BUCKET_NUMBER - 1, d / CFLUSH_BUCKET_SIZE) as usize] += 1; } - if miss_max.1 < miss_histogram[i] { - miss_max = (i, miss_histogram[i]); - } - } - serial_println!("Miss max {}", miss_max.0 * CFLUSH_BUCKET_SIZE); - serial_println!("Max hit {}", hit_max.0 * CFLUSH_BUCKET_SIZE); - let mut threshold: (usize, u32) = (0, u32::max_value()); - for i in miss_max.0..hit_max.0 { - if hit_histogram[i] + miss_histogram[i] < threshold.1 { - threshold = (i, hit_histogram[i] + miss_histogram[i]); - } - } - serial_println!("Threshold {}", threshold.0 * CFLUSH_BUCKET_SIZE); - serial_println!("Calibration done."); - (threshold.0 * CFLUSH_BUCKET_SIZE) as u64 + // do a large numer of accesses to uncached line + unsafe { flush(pointer.offset(i)) }; + + unsafe { load_and_flush(pointer.offset(i)) }; + for _ in 0..(1 << 10) { + let d = unsafe { flush_and_flush(pointer.offset(i)) } as usize; + miss_histogram[min(CFLUSH_BUCKET_NUMBER - 1, d / CFLUSH_BUCKET_SIZE) as usize] += 1; + } + + let mut hit_max: (usize, u32) = (0, 0); + let mut miss_max: (usize, u32) = (0, 0); + + for i in 0..hit_histogram.len() { + serial_println!( + "{:3}: {:10} {:10}", + i * CFLUSH_BUCKET_SIZE, + hit_histogram[i], + miss_histogram[i] + ); + if hit_max.1 < hit_histogram[i] { + hit_max = (i, hit_histogram[i]); + } + if miss_max.1 < miss_histogram[i] { + miss_max = (i, miss_histogram[i]); + } + } + serial_println!("Miss max {}", miss_max.0 * CFLUSH_BUCKET_SIZE); + serial_println!("Max hit {}", hit_max.0 * CFLUSH_BUCKET_SIZE); + let mut threshold: (usize, u32) = (0, u32::max_value()); + for i in miss_max.0..hit_max.0 { + if hit_histogram[i] + miss_histogram[i] < threshold.1 { + threshold = (i, hit_histogram[i] + miss_histogram[i]); + } + } + + serial_println!("Threshold {}", threshold.0 * CFLUSH_BUCKET_SIZE); + serial_println!("Calibration done."); + } + //(threshold.0 * CFLUSH_BUCKET_SIZE) as u64 + 0 } diff --git a/cache_utils/src/prefetcher.rs b/cache_utils/src/prefetcher.rs index 724c56b..cf0a0de 100644 --- a/cache_utils/src/prefetcher.rs +++ b/cache_utils/src/prefetcher.rs @@ -28,13 +28,17 @@ pub fn enable_prefetchers(status: bool) { unsafe { msr.write(value) }; } -pub fn prefetcher_fun(victim4kaddr: *mut u8, victim2Maddr: *mut u8, threshold_ff: u64) -> Vec { +pub fn prefetcher_fun( + victim4k_addr: *mut u8, + victim2M_addr: *mut u8, + threshold_ff: u64, +) -> Vec { let mut results = vec![0; 4096 / 64]; for _ in 0..N { //unsafe { maccess(victim4kaddr) }; for j in (0..4096).step_by(64).rev() { - let t = unsafe { only_flush(victim4kaddr.offset(j)) }; + let t = unsafe { only_flush(victim4k_addr.offset(j)) }; if threshold_ff < t { // hit results[(j / 64) as usize] += 1; diff --git a/src/main.rs b/src/main.rs index 91eb475..b9da481 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,6 +34,8 @@ use x86_64::structures::paging::{ use x86_64::PhysAddr; use x86_64::VirtAddr; +use arrayref; + // Custom panic handler, required for freestanding program #[cfg(not(test))] #[panic_handler] @@ -79,9 +81,9 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { let mut victim = None; for region in boot_info.memory_map.iter() { - if region.region_type == Usable { + /*if region.region_type == Usable { serial_println!("Usable Region: {:?}", region); - } + }*/ let new_region = { if victim.is_none() && region.region_type == Usable @@ -171,7 +173,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { end: PhysFrame::containing_address(PhysAddr::new(victim.range.end_addr())), }) { - serial_println!("Mapping page {:x} on frame {:?}", page, frame); + //serial_println!("Mapping page {:x} on frame {:?}", page, frame); mapper .map_to( Page::::containing_address(VirtAddr::new(page)), @@ -182,12 +184,12 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { .expect("Failed to map the experiment buffer") .flush(); let phys = mapper.translate_addr(VirtAddr::new(page)); - serial_println!( + /*serial_println!( "Mapped page {:p}({:?}) on frame {:?}", page as *mut u8, VirtAddr::new(page), phys - ); + );*/ unsafe { maccess(page as *mut u8) }; } @@ -205,12 +207,36 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { cache_utils::prefetcher::prefetcher_status() ); - let threshold_access_p = cache_utils::calibration::calibrate_access(); - let threshold_flush_p = cache_utils::calibration::calibrate_flush(); + let threshold_access_p = cache_utils::calibration::calibrate_access(unsafe { + arrayref::array_ref![ + core::slice::from_raw_parts(victim4k_start as *mut u8, 4096), + 0, + 4096 + ] + }); + let threshold_flush_p = cache_utils::calibration::calibrate_flush(unsafe { + arrayref::array_ref![ + core::slice::from_raw_parts(victim4k_start as *mut u8, 4096), + 0, + 4096 + ] + }); cache_utils::prefetcher::enable_prefetchers(false); serial_println!("Prefetcher disabled"); - let threshold_access = cache_utils::calibration::calibrate_access(); - let threshold_flush = cache_utils::calibration::calibrate_flush(); + let threshold_access = cache_utils::calibration::calibrate_access(unsafe { + arrayref::array_ref![ + core::slice::from_raw_parts(victim4k_start as *mut u8, 4096), + 0, + 4096 + ] + }); + let threshold_flush = cache_utils::calibration::calibrate_flush(unsafe { + arrayref::array_ref![ + core::slice::from_raw_parts(victim4k_start as *mut u8, 4096), + 0, + 4096 + ] + }); serial_println!("Please compare histograms for sanity"); if distance(threshold_access_p, threshold_access) > 10