From 81a517de6bbc186efbd84eeb6d2522a2517e9a91 Mon Sep 17 00:00:00 2001 From: guillaume didier Date: Mon, 17 Feb 2020 09:17:44 +0100 Subject: [PATCH] Refactor cache_info into a separate module --- cache_utils/src/cache_info.rs | 94 ++++++++++++++++++++++++++++++++++ cache_utils/src/lib.rs | 96 +---------------------------------- src/main.rs | 15 ++++-- 3 files changed, 106 insertions(+), 99 deletions(-) create mode 100644 cache_utils/src/cache_info.rs diff --git a/cache_utils/src/cache_info.rs b/cache_utils/src/cache_info.rs new file mode 100644 index 0000000..4930d9d --- /dev/null +++ b/cache_utils/src/cache_info.rs @@ -0,0 +1,94 @@ +/// Stuff to do in here : +/// This module is meant to compute and return info about the caching structure +/// Should include if needed the work for reverse engineering L3 complex addressing +/// May also have a module to deal with prefetchers +extern crate alloc; + +use alloc::vec::Vec; +use core::arch::x86_64 as arch_x86; + +const CACHE_INFO_CPUID_LEAF: u32 = 0x4; + +pub fn get_cache_info() -> Vec { + let mut ret = Vec::new(); + let mut i = 0; + + while let Some(cache_info) = + CacheInfo::from_cpuid_result(&unsafe { arch_x86::__cpuid_count(CACHE_INFO_CPUID_LEAF, i) }) + { + ret.push(cache_info); + i += 1; + } + ret +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum CacheType { + Null = 0, + Data = 1, + Instruction = 2, + Unified = 3, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct CacheInfo { + cache_type: CacheType, + level: u8, + self_init: bool, + fully_assoc: bool, + core_for_cache: u16, + core_in_package: u16, + cache_line_size: u16, + physical_line_partition: u16, + associativity: u16, + sets: u32, + wbinvd_no_guarantee: bool, + inclusive: bool, + complex_cache_indexing: bool, +} + +impl CacheInfo { + pub fn from_cpuid_result(cr: &arch_x86::CpuidResult) -> Option { + let ctype = cr.eax & 0x1f; + let cache_type = match ctype { + 0 => { + return None; + } + 1 => CacheType::Data, + 2 => CacheType::Instruction, + 3 => CacheType::Unified, + _ => { + return None; + } + }; + let level: u8 = (cr.eax >> 5 & 0x7) as u8; + let self_init = (cr.eax >> 8 & 0x1) != 0; + let fully_assoc = (cr.eax >> 9 & 0x1) != 0; + let core_for_cache = (cr.eax >> 14 & 0xfff) as u16 + 1; + let core_in_package = (cr.eax >> 26 & 0x3f) as u16 + 1; + let cache_line_size = (cr.ebx & 0xfff) as u16 + 1; + let physical_line_partition = (cr.ebx >> 12 & 0x3ff) as u16 + 1; + let associativity = (cr.ebx >> 22 & 0x3ff) as u16 + 1; + let sets = cr.ecx + 1; + let wbinvd_no_guarantee = (cr.edx & 0x1) != 0; + let inclusive = (cr.edx & 0x2) != 0; + let complex_cache_indexing = (cr.edx & 0x4) != 0; + + Some(CacheInfo { + cache_type, + level, + self_init, + fully_assoc, + core_for_cache, + core_in_package, + cache_line_size, + physical_line_partition, + associativity, + sets, + wbinvd_no_guarantee, + inclusive, + complex_cache_indexing, + }) + } +} diff --git a/cache_utils/src/lib.rs b/cache_utils/src/lib.rs index d44deac..3d3634a 100644 --- a/cache_utils/src/lib.rs +++ b/cache_utils/src/lib.rs @@ -1,98 +1,4 @@ #![no_std] -/// Stuff to do in here : -/// This module is meant to compute and return info about the caching structure -/// Should include if needed the work for reverse engineering L3 complex addressing -/// May also have a module to deal with prefetchers -extern crate alloc; - -use alloc::vec::Vec; -use core::arch::x86_64 as arch_x86; - +pub mod cache_info; pub mod prefetcher; - -const CACHE_INFO_CPUID_LEAF: u32 = 0x4; - -pub fn get_cache_info() -> Vec { - let mut ret = Vec::new(); - let mut i = 0; - - while let Some(cache_info) = - CacheInfo::from_cpuid_result(&unsafe { arch_x86::__cpuid_count(CACHE_INFO_CPUID_LEAF, i) }) - { - ret.push(cache_info); - i += 1; - } - ret -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u8)] -pub enum CacheType { - Null = 0, - Data = 1, - Instruction = 2, - Unified = 3, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct CacheInfo { - cache_type: CacheType, - level: u8, - self_init: bool, - fully_assoc: bool, - core_for_cache: u16, - core_in_package: u16, - cache_line_size: u16, - physical_line_partition: u16, - associativity: u16, - sets: u32, - wbinvd_no_guarantee: bool, - inclusive: bool, - complex_cache_indexing: bool, -} - -impl CacheInfo { - pub fn from_cpuid_result(cr: &arch_x86::CpuidResult) -> Option { - let ctype = cr.eax & 0x1f; - let cache_type = match ctype { - 0 => { - return None; - } - 1 => CacheType::Data, - 2 => CacheType::Instruction, - 3 => CacheType::Unified, - _ => { - return None; - } - }; - let level: u8 = (cr.eax >> 5 & 0x7) as u8; - let self_init = (cr.eax >> 8 & 0x1) != 0; - let fully_assoc = (cr.eax >> 9 & 0x1) != 0; - let core_for_cache = (cr.eax >> 14 & 0xfff) as u16 + 1; - let core_in_package = (cr.eax >> 26 & 0x3f) as u16 + 1; - let cache_line_size = (cr.ebx & 0xfff) as u16 + 1; - let physical_line_partition = (cr.ebx >> 12 & 0x3ff) as u16 + 1; - let associativity = (cr.ebx >> 22 & 0x3ff) as u16 + 1; - let sets = cr.ecx + 1; - let wbinvd_no_guarantee = (cr.edx & 0x1) != 0; - let inclusive = (cr.edx & 0x2) != 0; - let complex_cache_indexing = (cr.edx & 0x4) != 0; - - Some(CacheInfo { - cache_type, - level, - self_init, - fully_assoc, - core_for_cache, - core_in_package, - cache_line_size, - physical_line_partition, - associativity, - sets, - wbinvd_no_guarantee, - inclusive, - complex_cache_indexing, - }) - } -} diff --git a/src/main.rs b/src/main.rs index cb8da35..40426dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -81,24 +81,31 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed"); - let caches = cache_utils::get_cache_info(); + let caches = cache_utils::cache_info::get_cache_info(); serial_println!("Caches:"); serial_println!("{:#?}", caches); println!("Caches: {:?}", caches); - serial_print!("Input a character: "); + println!( + "prefetcher status: {}", + cache_utils::prefetcher::prefetcher_status() + ); - let c = { polling_serial::SERIAL1.lock().read() }; + // serial_print!("Input a character: "); - serial_println!("\nYoutyped '{:x}'", c); + // let c = { polling_serial::SERIAL1.lock().read() }; + // serial_println!("\nYoutyped '{:x}'", c); + + /* serial_println!("Preparing nasty fault..."); unsafe { *(0xdead_beef as *mut u64) = 42; } serial_println!("Survived ? oO"); + */ // magic break ? // x86_64::instructions::bochs_breakpoint();