Refactor cache_info into a separate module

This commit is contained in:
guillaume didier 2020-02-17 09:17:44 +01:00
parent 2da2e7bf8e
commit 81a517de6b
3 changed files with 106 additions and 99 deletions

View File

@ -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<CacheInfo> {
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<CacheInfo> {
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,
})
}
}

View File

@ -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<CacheInfo> {
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<CacheInfo> {
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,
})
}
}

View File

@ -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();