Implement calibration on full 4k page
This commit is contained in:
parent
2ce9de1482
commit
60fe76e366
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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::<usize>::with_capacity(5 << 10);
|
||||
array.resize(5 << 10, 1);
|
||||
// let mut array = Vec::<usize>::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::<usize>::with_capacity(5 << 10);
|
||||
array.resize(5 << 10, 1);
|
||||
//let mut array = Vec::<usize>::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
|
||||
}
|
||||
|
@ -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<i32> {
|
||||
pub fn prefetcher_fun(
|
||||
victim4k_addr: *mut u8,
|
||||
victim2M_addr: *mut u8,
|
||||
threshold_ff: u64,
|
||||
) -> Vec<i32> {
|
||||
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;
|
||||
|
44
src/main.rs
44
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::<Size4KiB>::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
|
||||
|
Loading…
Reference in New Issue
Block a user