From 00984ee2e0eeba257c7f965dd9c90d2873fecef9 Mon Sep 17 00:00:00 2001 From: guillaume didier Date: Mon, 17 Feb 2020 15:28:10 +0100 Subject: [PATCH] Start working on cache calibration --- cache_utils/src/calibration.rs | 70 ++++++++++++++++++++++++++++++++++ cache_utils/src/lib.rs | 29 ++++++++++++++ src/main.rs | 2 + 3 files changed, 101 insertions(+) create mode 100644 cache_utils/src/calibration.rs diff --git a/cache_utils/src/calibration.rs b/cache_utils/src/calibration.rs new file mode 100644 index 0000000..e7baede --- /dev/null +++ b/cache_utils/src/calibration.rs @@ -0,0 +1,70 @@ +use crate::{flush, maccess, rdtsc_fence, rdtsc_nofence}; +use polling_serial::{serial_print, serial_println}; +use vga_buffer::println; + +extern crate alloc; +use alloc::vec::Vec; +use core::cmp::min; + +// calibration, todo +// this will require getting a nice page to do some amusing stuff on it. +// it will have to return some results later. + +unsafe fn only_reload(p: *const u8) -> u64 { + let t = rdtsc_fence(); + maccess(p); + let d = rdtsc_fence() - t; + d +} + +unsafe fn flush_and_reload(p: *const u8) -> u64 { + flush(p); + let t = rdtsc_fence(); + maccess(p); + let d = rdtsc_fence() - t; + d +} + +pub fn calibrate_access() -> u64 { + serial_println!("Calibrating..."); + + let mut array = Vec::::with_capacity(5 << 10); + array.resize(5 << 10, 1); + + let array = array.into_boxed_slice(); + + let mut hit_histogram = Vec::::with_capacity(80); + hit_histogram.resize(80, 0); + + let mut miss_histogram = hit_histogram.clone(); + + let pointer = (&array[2048] as *const usize) as *const u8; + // sanity check + println!( + "&array[0]: {:p}, array[2048]{:p}", + (&array[0] as *const usize) as *const u8, + (&array[2048] as *const usize) as *const u8 + ); + + unsafe { maccess(pointer) }; + for _ in 0..(4 << 20) { + let d = unsafe { only_reload(pointer) }; + hit_histogram[min(79, d / 5) as usize] += 1; + } + + unsafe { flush(pointer) }; + for _ in 0..(4 << 20) { + let d = unsafe { flush_and_reload(pointer) }; + miss_histogram[min(79, d / 5) as usize] += 1; + } + + // Todo plot and analyze histogram + + serial_println!("Threshold {}", -1); + serial_println!("Calibration done."); + (-1_i64) as u64 +} + +pub fn calibrate_flush() -> u64 { + (-1_i64) as u64 +} diff --git a/cache_utils/src/lib.rs b/cache_utils/src/lib.rs index 3d3634a..e7798da 100644 --- a/cache_utils/src/lib.rs +++ b/cache_utils/src/lib.rs @@ -1,4 +1,33 @@ #![no_std] pub mod cache_info; +pub mod calibration; pub mod prefetcher; + +use core::arch::x86_64 as arch_x86; +use core::ptr; + +// rdtsc no fence +pub unsafe fn rdtsc_nofence() -> u64 { + arch_x86::_rdtsc() +} +// rdtsc (has mfence before and after) +pub unsafe fn rdtsc_fence() -> u64 { + arch_x86::_mm_mfence(); + let tsc: u64 = arch_x86::_rdtsc(); + arch_x86::_mm_mfence(); + tsc +} + +pub unsafe fn maccess(p: *const T) -> () { + ptr::read_volatile(p); +} + +// flush (cflush) +pub unsafe fn flush(p: *const u8) -> () { + arch_x86::_mm_clflush(p); +} + +// future enhancements +// prefetch +// long nop (64 nops) diff --git a/src/main.rs b/src/main.rs index 5bda228..4688f24 100644 --- a/src/main.rs +++ b/src/main.rs @@ -92,6 +92,8 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { cache_utils::prefetcher::prefetcher_status() ); + cache_utils::calibration::calibrate_access(); + // Calibration // disable pretechers // Calibrate hit / miss rdtsc threshold