From 2ce9de148264656e3c74575d77585de681e3d3d8 Mon Sep 17 00:00:00 2001 From: guillaume didier Date: Tue, 25 Feb 2020 08:27:40 +0100 Subject: [PATCH] Add the first attempt at detectecting prefetch --- cache_utils/src/calibration.rs | 13 ++++++++---- cache_utils/src/prefetcher.rs | 28 ++++++++++++++++++++++++ src/main.rs | 39 ++++++++++++++++++++++++++++++++-- 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/cache_utils/src/calibration.rs b/cache_utils/src/calibration.rs index d26ce64..a7548e4 100644 --- a/cache_utils/src/calibration.rs +++ b/cache_utils/src/calibration.rs @@ -10,32 +10,37 @@ use core::cmp::min; // 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 { +pub unsafe fn only_reload(p: *const u8) -> u64 { let t = rdtsc_fence(); maccess(p); rdtsc_fence() - t } -unsafe fn flush_and_reload(p: *const u8) -> u64 { +pub unsafe fn flush_and_reload(p: *const u8) -> u64 { flush(p); let t = rdtsc_fence(); maccess(p); rdtsc_fence() - t } -unsafe fn load_and_flush(p: *const u8) -> u64 { +pub unsafe fn load_and_flush(p: *const u8) -> u64 { maccess(p); let t = rdtsc_fence(); flush(p); rdtsc_fence() - t } -unsafe fn flush_and_flush(p: *const u8) -> u64 { +pub unsafe fn flush_and_flush(p: *const u8) -> u64 { flush(p); let t = rdtsc_fence(); flush(p); 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_NUMBER: usize = 250; diff --git a/cache_utils/src/prefetcher.rs b/cache_utils/src/prefetcher.rs index 4da983a..724c56b 100644 --- a/cache_utils/src/prefetcher.rs +++ b/cache_utils/src/prefetcher.rs @@ -1,7 +1,17 @@ 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 N: i32 = 10; + pub fn prefetcher_status() -> bool { let msr = Msr::new(MSR_MISC_FEATURE8CONTROL); let value = unsafe { msr.read() }; @@ -17,3 +27,21 @@ pub fn enable_prefetchers(status: bool) { } unsafe { msr.write(value) }; } + +pub fn prefetcher_fun(victim4kaddr: *mut u8, victim2Maddr: *mut u8, threshold_ff: u64) -> Vec { + 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 +} diff --git a/src/main.rs b/src/main.rs index c3d9fda..91eb475 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,12 +22,14 @@ use dendrobates_tinctoreus_azureus::hlt_loop; use bootloader::bootinfo::MemoryRegionType::{InUse, Usable}; use bootloader::bootinfo::{FrameRange, MemoryMap, MemoryRegion}; +use cache_utils::maccess; +use cache_utils::prefetcher::{enable_prefetchers, prefetcher_fun}; use dendrobates_tinctoreus_azureus::memory; #[cfg(not(test))] use vga_buffer::{set_colors, Color, ForegroundColor}; use x86_64::structures::paging::frame::PhysFrameRange; 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::VirtAddr; @@ -51,6 +53,8 @@ fn distance + 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); // Kernel entry point @@ -75,6 +79,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 { + serial_println!("Usable Region: {:?}", region); + } let new_region = { if victim.is_none() && region.region_type == Usable @@ -157,13 +164,14 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { 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) .zip(PhysFrameRange { start: PhysFrame::containing_address(PhysAddr::new(victim.range.start_addr())), end: PhysFrame::containing_address(PhysAddr::new(victim.range.end_addr())), }) { + serial_println!("Mapping page {:x} on frame {:?}", page, frame); mapper .map_to( Page::::containing_address(VirtAddr::new(page)), @@ -173,6 +181,15 @@ 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!( + "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"); @@ -202,6 +219,24 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { 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 // disable pretechers // Calibrate hit / miss rdtsc threshold