diff --git a/cache_utils/src/calibration.rs b/cache_utils/src/calibration.rs index 8d98fa4..f82db29 100644 --- a/cache_utils/src/calibration.rs +++ b/cache_utils/src/calibration.rs @@ -3,7 +3,7 @@ use crate::complex_addressing::cache_slicing; use crate::{flush, maccess, rdtsc_fence}; -use cpuid::MicroArchitecture; +use cpuid::{CPUVendor, MicroArchitecture}; use core::arch::x86_64 as arch_x86; #[cfg(feature = "no_std")] @@ -278,14 +278,24 @@ fn calibrate_impl_fixed_freq( let from_bucket = |bucket: usize| -> u64 { (bucket * hist_params.bucket_size) as u64 }; let slicing = if let Some(uarch) = MicroArchitecture::get_micro_architecture() { - Some(cache_slicing(uarch, 8)) + if let Some(vendor_family_model_stepping) = MicroArchitecture::get_family_model_stepping() { + Some(cache_slicing( + uarch, + 8, + vendor_family_model_stepping.0, + vendor_family_model_stepping.1, + vendor_family_model_stepping.2, + )) + } else { + None + } } else { None }; let h = if let Some(s) = slicing { if s.can_hash() { - Some(|addr: usize| -> usize { slicing.unwrap().hash(addr).unwrap() }) + Some(|addr: usize| -> u8 { slicing.unwrap().hash(addr).unwrap() }) } else { None } @@ -508,14 +518,24 @@ fn calibrate_fixed_freq_2_thread_impl>( let from_bucket = |bucket: usize| -> u64 { (bucket * hist_params.bucket_size) as u64 }; let slicing = if let Some(uarch) = MicroArchitecture::get_micro_architecture() { - Some(cache_slicing(uarch, 8)) + if let Some(vendor_family_model_stepping) = MicroArchitecture::get_family_model_stepping() { + Some(cache_slicing( + uarch, + 8, + vendor_family_model_stepping.0, + vendor_family_model_stepping.1, + vendor_family_model_stepping.2, + )) + } else { + None + } } else { None }; let h = if let Some(s) = slicing { if s.can_hash() { - Some(|addr: usize| -> usize { slicing.unwrap().hash(addr).unwrap() }) + Some(|addr: usize| -> u8 { slicing.unwrap().hash(addr).unwrap() }) } else { None } diff --git a/cache_utils/src/complex_addressing.rs b/cache_utils/src/complex_addressing.rs index f73d0ec..5d93328 100644 --- a/cache_utils/src/complex_addressing.rs +++ b/cache_utils/src/complex_addressing.rs @@ -1,13 +1,29 @@ use crate::complex_addressing::CacheSlicing::{ ComplexAddressing, NoSlice, SimpleAddressing, Unsupported, }; -use cpuid::MicroArchitecture; +use cpuid::{CPUVendor, MicroArchitecture}; + +#[cfg(feature = "no_std")] +use hashbrown::HashMap; +#[cfg(feature = "no_std")] +use hashbrown::HashSet; + +#[cfg(feature = "use_std")] +use std::collections::HashMap; +#[cfg(feature = "use_std")] +use std::collections::HashSet; + +#[derive(Debug, Copy, Clone)] +pub struct SimpleAddressingParams { + pub shift: u8, // How many trailing zeros + pub bits: u8, // How many ones +} #[derive(Debug, Copy, Clone)] pub enum CacheSlicing { Unsupported, ComplexAddressing(&'static [usize]), - SimpleAddressing(usize), + SimpleAddressing(SimpleAddressingParams), NoSlice, } const SANDYBRIDGE_TO_SKYLAKE_FUNCTIONS: [usize; 4] = [ @@ -16,47 +32,74 @@ const SANDYBRIDGE_TO_SKYLAKE_FUNCTIONS: [usize; 4] = [ 0b1111_0011_0011_0011_0010_0100_1100_0100_000000, 0b0, // TODO ]; + +const KABYLAKE_i9_FUNCTIONS: [usize; 4] = [ + 0b0000_1111_1111_1101_0101_1101_0101_0001_000000, + 0b0000_0110_1111_1011_1010_1100_0100_1000_000000, + 0b0000_1111_1110_0001_1111_1100_1011_0000_000000, + 0b0, // TODO +]; // missing functions for more than 8 cores. -pub fn cache_slicing(uarch: MicroArchitecture, physical_cores: u8) -> CacheSlicing { +// FIXME : Need to account for Family Model (and potentially stepping) +// Amongst other thing Crystal well products have a different function. (0x6_46) +// Same thing for Kaby Lake with 8 cores apparently. + +pub fn cache_slicing( + uarch: MicroArchitecture, + physical_cores: u8, + vendor: CPUVendor, + family_model_display: u32, + stepping: u32, +) -> CacheSlicing { let trailing_zeros = physical_cores.trailing_zeros(); if physical_cores != (1 << trailing_zeros) { return Unsupported; } match uarch { - MicroArchitecture::Skylake - | MicroArchitecture::KabyLake - | MicroArchitecture::CoffeeLake => { + MicroArchitecture::Skylake | MicroArchitecture::CoffeeLake => { ComplexAddressing(&SANDYBRIDGE_TO_SKYLAKE_FUNCTIONS[0..((trailing_zeros + 1) as usize)]) - }, + } + MicroArchitecture::KabyLake => { + ComplexAddressing(&KABYLAKE_i9_FUNCTIONS[0..((trailing_zeros + 1) as usize)]) + } MicroArchitecture::SandyBridge - | MicroArchitecture::Haswell | MicroArchitecture::HaswellE + | MicroArchitecture::HaswellE | MicroArchitecture::Broadwell - | MicroArchitecture::IvyBridge | MicroArchitecture::IvyBridgeE => { + | MicroArchitecture::IvyBridge + | MicroArchitecture::IvyBridgeE => { ComplexAddressing(&SANDYBRIDGE_TO_SKYLAKE_FUNCTIONS[0..((trailing_zeros) as usize)]) - }, + } + MicroArchitecture::Haswell => { + if family_model_display == 0x06_46 { + // Crystal Well + Unsupported + } else { + ComplexAddressing(&SANDYBRIDGE_TO_SKYLAKE_FUNCTIONS[0..((trailing_zeros) as usize)]) + } + } MicroArchitecture::Nehalem | MicroArchitecture::Westmere => { - SimpleAddressing(((physical_cores -1) as usize) << 6 + 8)// Hardcoded for 4 cores FIXME !!! + Unsupported //SimpleAddressing(((physical_cores - 1) as usize) << 6 + 8) // Hardcoded for 4 cores FIXME !!! } _ => Unsupported, } } -fn hash(addr: usize, mask: usize) -> usize { - ((addr & mask).count_ones() & 1) as usize +fn hash(addr: usize, mask: usize) -> u8 { + ((addr & mask).count_ones() & 1) as u8 } impl CacheSlicing { pub fn can_hash(&self) -> bool { match self { - Unsupported | NoSlice => false, - ComplexAddressing(_) | SimpleAddressing(_) => true, + Unsupported | NoSlice | SimpleAddressing(_) => false, + ComplexAddressing(_) => true, } } - pub fn hash(&self, addr: usize) -> Option { + pub fn hash(&self, addr: usize) -> Option { match self { - SimpleAddressing(mask) => Some(addr & *mask), + SimpleAddressing(mask) => None, //Some(addr & *mask), ComplexAddressing(masks) => { let mut res = 0; for mask in *masks { @@ -68,4 +111,12 @@ impl CacheSlicing { _ => None, } } + + pub fn image(&self, mask: usize) -> Option> { + None + } + + pub fn kernel_compl_basis(&self, mask: usize) -> Option> { + None + } }