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.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# 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]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -36,6 +41,7 @@ dependencies = [
|
|||||||
name = "dendrobates_tinctoreus_azureus"
|
name = "dendrobates_tinctoreus_azureus"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
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)",
|
"bootloader 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cache_utils 0.1.0",
|
"cache_utils 0.1.0",
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -121,6 +127,7 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
[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.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 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"
|
"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"
|
volatile = "0.2.6"
|
||||||
linked_list_allocator = "0.7.0"
|
linked_list_allocator = "0.7.0"
|
||||||
cache_utils = { path = "cache_utils" }
|
cache_utils = { path = "cache_utils" }
|
||||||
|
arrayref = "0.3.6"
|
||||||
|
|
||||||
[dependencies.lazy_static]
|
[dependencies.lazy_static]
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -45,15 +45,15 @@ pub unsafe fn only_flush(p: *const u8) -> u64 {
|
|||||||
const BUCKET_SIZE: usize = 5;
|
const BUCKET_SIZE: usize = 5;
|
||||||
const BUCKET_NUMBER: usize = 250;
|
const BUCKET_NUMBER: usize = 250;
|
||||||
|
|
||||||
pub fn calibrate_access() -> u64 {
|
pub fn calibrate_access(array: &[u8; 4096]) -> u64 {
|
||||||
serial_println!("Calibrating...");
|
serial_println!("Calibrating...");
|
||||||
|
|
||||||
// Allocate a target array
|
// Allocate a target array
|
||||||
// TBD why size, why the position in the array, why the type (usize)
|
// TBD why size, why the position in the array, why the type (usize)
|
||||||
let mut array = Vec::<usize>::with_capacity(5 << 10);
|
// let mut array = Vec::<usize>::with_capacity(5 << 10);
|
||||||
array.resize(5 << 10, 1);
|
// 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
|
// Histograms bucket of 5 and max at 400 cycles
|
||||||
// Magic numbers to be justified
|
// Magic numbers to be justified
|
||||||
@ -64,20 +64,30 @@ pub fn calibrate_access() -> u64 {
|
|||||||
let mut miss_histogram = hit_histogram.clone();
|
let mut miss_histogram = hit_histogram.clone();
|
||||||
|
|
||||||
// the address in memory we are going to target
|
// 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
|
// do a large sample of accesses to a cached line
|
||||||
unsafe { maccess(pointer) };
|
unsafe { maccess(pointer) };
|
||||||
for _ in 0..(4 << 20) {
|
for i in 0..(4 << 10) {
|
||||||
let d = unsafe { only_reload(pointer) } as usize;
|
for _ in 0..(1 << 10) {
|
||||||
hit_histogram[min(BUCKET_NUMBER - 1, d / BUCKET_SIZE) as usize] += 1;
|
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
|
// do a large numer of accesses to uncached line
|
||||||
unsafe { flush(pointer) };
|
unsafe { flush(pointer) };
|
||||||
for _ in 0..(4 << 20) {
|
for i in 0..(4 << 10) {
|
||||||
let d = unsafe { flush_and_reload(pointer) } as usize;
|
for _ in 0..(1 << 10) {
|
||||||
miss_histogram[min(BUCKET_NUMBER - 1, d / BUCKET_SIZE) as usize] += 1;
|
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;
|
let mut hit_max = 0;
|
||||||
@ -118,66 +128,76 @@ pub fn calibrate_access() -> u64 {
|
|||||||
const CFLUSH_BUCKET_SIZE: usize = 1;
|
const CFLUSH_BUCKET_SIZE: usize = 1;
|
||||||
const CFLUSH_BUCKET_NUMBER: usize = 250;
|
const CFLUSH_BUCKET_NUMBER: usize = 250;
|
||||||
|
|
||||||
pub fn calibrate_flush() -> u64 {
|
pub fn calibrate_flush(array: &[u8; 4096]) -> u64 {
|
||||||
serial_println!("Calibrating cflush...");
|
serial_println!("Calibrating cflush...");
|
||||||
|
|
||||||
// Allocate a target array
|
// Allocate a target array
|
||||||
// TBD why size, why the position in the array, why the type (usize)
|
// TBD why size, why the position in the array, why the type (usize)
|
||||||
let mut array = Vec::<usize>::with_capacity(5 << 10);
|
//let mut array = Vec::<usize>::with_capacity(5 << 10);
|
||||||
array.resize(5 << 10, 1);
|
//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
|
// Histograms bucket of 5 and max at 400 cycles
|
||||||
// Magic numbers to be justified
|
// Magic numbers to be justified
|
||||||
// 80 is a size of screen
|
// 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
|
// 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
|
// do a large sample of accesses to a cached line
|
||||||
for _ in 0..(4 << 20) {
|
for i in 0..(4 << 10) {
|
||||||
let d = unsafe { load_and_flush(pointer) } as usize;
|
let mut hit_histogram = vec![0; CFLUSH_BUCKET_NUMBER];
|
||||||
hit_histogram[min(CFLUSH_BUCKET_NUMBER - 1, d / CFLUSH_BUCKET_SIZE) as usize] += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do a large numer of accesses to uncached line
|
let mut miss_histogram = hit_histogram.clone();
|
||||||
unsafe { flush(pointer) };
|
serial_println!("Calibration for {:p}", unsafe { pointer.offset(i) });
|
||||||
for _ in 0..(4 << 20) {
|
unsafe { load_and_flush(pointer.offset(i)) }; // align down on 64 bytes
|
||||||
let d = unsafe { flush_and_flush(pointer) } as usize;
|
for _ in 1..(1 << 10) {
|
||||||
miss_histogram[min(CFLUSH_BUCKET_NUMBER - 1, d / CFLUSH_BUCKET_SIZE) as usize] += 1;
|
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;
|
||||||
|
|
||||||
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);
|
// do a large numer of accesses to uncached line
|
||||||
serial_println!("Calibration done.");
|
unsafe { flush(pointer.offset(i)) };
|
||||||
(threshold.0 * CFLUSH_BUCKET_SIZE) as u64
|
|
||||||
|
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) };
|
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];
|
let mut results = vec![0; 4096 / 64];
|
||||||
|
|
||||||
for _ in 0..N {
|
for _ in 0..N {
|
||||||
//unsafe { maccess(victim4kaddr) };
|
//unsafe { maccess(victim4kaddr) };
|
||||||
for j in (0..4096).step_by(64).rev() {
|
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 {
|
if threshold_ff < t {
|
||||||
// hit
|
// hit
|
||||||
results[(j / 64) as usize] += 1;
|
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::PhysAddr;
|
||||||
use x86_64::VirtAddr;
|
use x86_64::VirtAddr;
|
||||||
|
|
||||||
|
use arrayref;
|
||||||
|
|
||||||
// Custom panic handler, required for freestanding program
|
// Custom panic handler, required for freestanding program
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
@ -79,9 +81,9 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
|
|||||||
let mut victim = None;
|
let mut victim = None;
|
||||||
|
|
||||||
for region in boot_info.memory_map.iter() {
|
for region in boot_info.memory_map.iter() {
|
||||||
if region.region_type == Usable {
|
/*if region.region_type == Usable {
|
||||||
serial_println!("Usable Region: {:?}", region);
|
serial_println!("Usable Region: {:?}", region);
|
||||||
}
|
}*/
|
||||||
let new_region = {
|
let new_region = {
|
||||||
if victim.is_none()
|
if victim.is_none()
|
||||||
&& region.region_type == Usable
|
&& 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())),
|
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
|
mapper
|
||||||
.map_to(
|
.map_to(
|
||||||
Page::<Size4KiB>::containing_address(VirtAddr::new(page)),
|
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")
|
.expect("Failed to map the experiment buffer")
|
||||||
.flush();
|
.flush();
|
||||||
let phys = mapper.translate_addr(VirtAddr::new(page));
|
let phys = mapper.translate_addr(VirtAddr::new(page));
|
||||||
serial_println!(
|
/*serial_println!(
|
||||||
"Mapped page {:p}({:?}) on frame {:?}",
|
"Mapped page {:p}({:?}) on frame {:?}",
|
||||||
page as *mut u8,
|
page as *mut u8,
|
||||||
VirtAddr::new(page),
|
VirtAddr::new(page),
|
||||||
phys
|
phys
|
||||||
);
|
);*/
|
||||||
|
|
||||||
unsafe { maccess(page as *mut u8) };
|
unsafe { maccess(page as *mut u8) };
|
||||||
}
|
}
|
||||||
@ -205,12 +207,36 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
|
|||||||
cache_utils::prefetcher::prefetcher_status()
|
cache_utils::prefetcher::prefetcher_status()
|
||||||
);
|
);
|
||||||
|
|
||||||
let threshold_access_p = cache_utils::calibration::calibrate_access();
|
let threshold_access_p = cache_utils::calibration::calibrate_access(unsafe {
|
||||||
let threshold_flush_p = cache_utils::calibration::calibrate_flush();
|
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);
|
cache_utils::prefetcher::enable_prefetchers(false);
|
||||||
serial_println!("Prefetcher disabled");
|
serial_println!("Prefetcher disabled");
|
||||||
let threshold_access = cache_utils::calibration::calibrate_access();
|
let threshold_access = cache_utils::calibration::calibrate_access(unsafe {
|
||||||
let threshold_flush = cache_utils::calibration::calibrate_flush();
|
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");
|
serial_println!("Please compare histograms for sanity");
|
||||||
|
|
||||||
if distance(threshold_access_p, threshold_access) > 10
|
if distance(threshold_access_p, threshold_access) > 10
|
||||||
|
Loading…
Reference in New Issue
Block a user