Start working on cache calibration
This commit is contained in:
parent
aa72d2fa49
commit
00984ee2e0
70
cache_utils/src/calibration.rs
Normal file
70
cache_utils/src/calibration.rs
Normal file
@ -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::<usize>::with_capacity(5 << 10);
|
||||||
|
array.resize(5 << 10, 1);
|
||||||
|
|
||||||
|
let array = array.into_boxed_slice();
|
||||||
|
|
||||||
|
let mut hit_histogram = Vec::<u32>::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
|
||||||
|
}
|
@ -1,4 +1,33 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
pub mod cache_info;
|
pub mod cache_info;
|
||||||
|
pub mod calibration;
|
||||||
pub mod prefetcher;
|
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<T>(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)
|
||||||
|
@ -92,6 +92,8 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
|
|||||||
cache_utils::prefetcher::prefetcher_status()
|
cache_utils::prefetcher::prefetcher_status()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cache_utils::calibration::calibrate_access();
|
||||||
|
|
||||||
// Calibration
|
// Calibration
|
||||||
// disable pretechers
|
// disable pretechers
|
||||||
// Calibrate hit / miss rdtsc threshold
|
// Calibrate hit / miss rdtsc threshold
|
||||||
|
Loading…
Reference in New Issue
Block a user