Add the first attempt at detectecting prefetch

This commit is contained in:
guillaume didier 2020-02-25 08:27:40 +01:00
parent f5312321c8
commit 2ce9de1482
3 changed files with 74 additions and 6 deletions

View File

@ -10,32 +10,37 @@ use core::cmp::min;
// this will require getting a nice page to do some amusing stuff on it. // this will require getting a nice page to do some amusing stuff on it.
// it will have to return some results later. // it will have to return some results later.
unsafe fn only_reload(p: *const u8) -> u64 { pub unsafe fn only_reload(p: *const u8) -> u64 {
let t = rdtsc_fence(); let t = rdtsc_fence();
maccess(p); maccess(p);
rdtsc_fence() - t rdtsc_fence() - t
} }
unsafe fn flush_and_reload(p: *const u8) -> u64 { pub unsafe fn flush_and_reload(p: *const u8) -> u64 {
flush(p); flush(p);
let t = rdtsc_fence(); let t = rdtsc_fence();
maccess(p); maccess(p);
rdtsc_fence() - t rdtsc_fence() - t
} }
unsafe fn load_and_flush(p: *const u8) -> u64 { pub unsafe fn load_and_flush(p: *const u8) -> u64 {
maccess(p); maccess(p);
let t = rdtsc_fence(); let t = rdtsc_fence();
flush(p); flush(p);
rdtsc_fence() - t rdtsc_fence() - t
} }
unsafe fn flush_and_flush(p: *const u8) -> u64 { pub unsafe fn flush_and_flush(p: *const u8) -> u64 {
flush(p); flush(p);
let t = rdtsc_fence(); let t = rdtsc_fence();
flush(p); flush(p);
rdtsc_fence() - t rdtsc_fence() - t
} }
pub unsafe fn only_flush(p: *const u8) -> u64 {
let t = rdtsc_fence();
flush(p);
rdtsc_fence() - t
}
const BUCKET_SIZE: usize = 5; const BUCKET_SIZE: usize = 5;
const BUCKET_NUMBER: usize = 250; const BUCKET_NUMBER: usize = 250;

View File

@ -1,7 +1,17 @@
use x86_64::registers::model_specific::Msr; use x86_64::registers::model_specific::Msr;
use crate::calibration::only_flush;
use crate::flush;
use crate::maccess;
extern crate alloc;
use alloc::vec;
use alloc::vec::Vec;
const MSR_MISC_FEATURE8CONTROL: u32 = 0x1a4; const MSR_MISC_FEATURE8CONTROL: u32 = 0x1a4;
const N: i32 = 10;
pub fn prefetcher_status() -> bool { pub fn prefetcher_status() -> bool {
let msr = Msr::new(MSR_MISC_FEATURE8CONTROL); let msr = Msr::new(MSR_MISC_FEATURE8CONTROL);
let value = unsafe { msr.read() }; let value = unsafe { msr.read() };
@ -17,3 +27,21 @@ 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> {
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)) };
if threshold_ff < t {
// hit
results[(j / 64) as usize] += 1;
} else if threshold_ff > t {
results[(j / 64) as usize] -= 1;
}
}
}
results
}

View File

@ -22,12 +22,14 @@ use dendrobates_tinctoreus_azureus::hlt_loop;
use bootloader::bootinfo::MemoryRegionType::{InUse, Usable}; use bootloader::bootinfo::MemoryRegionType::{InUse, Usable};
use bootloader::bootinfo::{FrameRange, MemoryMap, MemoryRegion}; use bootloader::bootinfo::{FrameRange, MemoryMap, MemoryRegion};
use cache_utils::maccess;
use cache_utils::prefetcher::{enable_prefetchers, prefetcher_fun};
use dendrobates_tinctoreus_azureus::memory; use dendrobates_tinctoreus_azureus::memory;
#[cfg(not(test))] #[cfg(not(test))]
use vga_buffer::{set_colors, Color, ForegroundColor}; use vga_buffer::{set_colors, Color, ForegroundColor};
use x86_64::structures::paging::frame::PhysFrameRange; use x86_64::structures::paging::frame::PhysFrameRange;
use x86_64::structures::paging::{ use x86_64::structures::paging::{
Mapper, Page, PageSize, PageTableFlags, PhysFrame, Size4KiB, UnusedPhysFrame, Mapper, MapperAllSizes, Page, PageSize, PageTableFlags, PhysFrame, Size4KiB, UnusedPhysFrame,
}; };
use x86_64::PhysAddr; use x86_64::PhysAddr;
use x86_64::VirtAddr; use x86_64::VirtAddr;
@ -51,6 +53,8 @@ fn distance<T: Sub<Output = T> + Ord>(a: T, b: T) -> T {
} }
} }
const victim4k_start: u64 = 0x0ccc_0000_0000_u64;
const victim4k_end: u64 = victim4k_start + (1 << 21);
entry_point!(kernel_main); entry_point!(kernel_main);
// Kernel entry point // Kernel entry point
@ -75,6 +79,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 {
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
@ -157,13 +164,14 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
serial_println!("{:?} -> {:?}", virt, phys); serial_println!("{:?} -> {:?}", virt, phys);
} }
*/ */
for (page, frame) in (0xcccc_0000_0000_u64..0xcccc_0020_0000) for (page, frame) in (victim4k_start..victim4k_end)
.step_by(Size4KiB::SIZE as usize) .step_by(Size4KiB::SIZE as usize)
.zip(PhysFrameRange { .zip(PhysFrameRange {
start: PhysFrame::containing_address(PhysAddr::new(victim.range.start_addr())), start: PhysFrame::containing_address(PhysAddr::new(victim.range.start_addr())),
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);
mapper mapper
.map_to( .map_to(
Page::<Size4KiB>::containing_address(VirtAddr::new(page)), Page::<Size4KiB>::containing_address(VirtAddr::new(page)),
@ -173,6 +181,15 @@ 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));
serial_println!(
"Mapped page {:p}({:?}) on frame {:?}",
page as *mut u8,
VirtAddr::new(page),
phys
);
unsafe { maccess(page as *mut u8) };
} }
allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed"); allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed");
@ -202,6 +219,24 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
panic!("Inconsistent thresholds"); panic!("Inconsistent thresholds");
} }
serial_println!("0");
let r_no_prefetch = prefetcher_fun(
victim4k_start as *mut u8,
unsafe { (victim.range.start_addr() as *mut u8).offset(phys_mem_offset.as_u64() as isize) },
threshold_flush,
);
serial_println!("1");
enable_prefetchers(true);
let r_prefetch = prefetcher_fun(
victim4k_start as *mut u8,
unsafe { (victim.range.start_addr() as *mut u8).offset(phys_mem_offset.as_u64() as isize) },
threshold_flush,
);
for (i, (&npf, pf)) in r_no_prefetch.iter().zip(r_prefetch).enumerate() {
serial_println!("{} {} {}", i, npf, pf);
}
// Calibration // Calibration
// disable pretechers // disable pretechers
// Calibrate hit / miss rdtsc threshold // Calibrate hit / miss rdtsc threshold