From f6494a82b2ba3cb69a0dbceef78ce81ab3065e10 Mon Sep 17 00:00:00 2001 From: Guillaume DIDIER Date: Mon, 24 Jun 2024 16:58:32 +0200 Subject: [PATCH] Correct various issues in scan, and set core affinity properly. --- cache_slice/Cargo.toml | 2 +- cache_slice/src/bin/rdmsr.rs | 9 +++++---- cache_slice/src/bin/scan.rs | 27 +++++++++++++++++++++------ cache_slice/src/lib.rs | 31 +++++++++++++++++++++++-------- 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/cache_slice/Cargo.toml b/cache_slice/Cargo.toml index 5d8b255..857233e 100644 --- a/cache_slice/Cargo.toml +++ b/cache_slice/Cargo.toml @@ -5,4 +5,4 @@ edition = "2021" [dependencies] raw-cpuid = "11.0.2" -nix = "0.29.0" +nix = { version = "0.29.0", features = ["sched"] } diff --git a/cache_slice/src/bin/rdmsr.rs b/cache_slice/src/bin/rdmsr.rs index 15ce6d0..316c4ca 100644 --- a/cache_slice/src/bin/rdmsr.rs +++ b/cache_slice/src/bin/rdmsr.rs @@ -1,24 +1,25 @@ use cache_slice::msr; use std::env; + fn main() { let mut args = env::args().into_iter(); args.next(); for arg in args { - match arg.parse::() { + match arg.parse::() { Ok(msr) => { match msr::read_msr_on_cpu(msr, 0) { Ok(result) => { println!("MSR {}: {:x}", msr, result); - }, + } Err(e) => { eprintln!("Error, failed to read MSR {}: {}", msr, e); } } - }, + } Err(e) => { eprintln!("Error: {}", e); eprintln!("{} is not a valid MSR number", arg); } } } -} \ No newline at end of file +} diff --git a/cache_slice/src/bin/scan.rs b/cache_slice/src/bin/scan.rs index a862996..0564dd1 100644 --- a/cache_slice/src/bin/scan.rs +++ b/cache_slice/src/bin/scan.rs @@ -1,6 +1,7 @@ use cache_slice::monitor_address; use cache_slice::utils::core_per_package; -use nix::sched::{sched_getaffinity, CpuSet}; +use nix::sched::{sched_getaffinity, sched_setaffinity, CpuSet}; +use nix::unistd::Pid; pub fn main() { @@ -8,10 +9,23 @@ pub fn main() { println!("Found {} cores", nb_cores); let target = vec![0x0123456789abcdefu64, 64]; - for core in 0..CpuSet::count() { + + let old = sched_getaffinity(Pid::from_raw(0)).unwrap(); + let mut core_set = Vec::new(); + for i in 0..CpuSet::count() { + if old.is_set(i).unwrap() { + core_set.push(i); + } + } + + + for core in core_set { + let mut cpu_set = CpuSet::new(); + cpu_set.set(core).unwrap(); + sched_setaffinity(Pid::this(), &cpu_set).unwrap(); for addr in target.iter() { - let res = unsafe { monitor_address(addr as *const u64 as *const u8, core as u8, nb_cores) }; - let slice = res.iter().enumerate().max_by_key(|(i, val)| { val }); + let res = unsafe { monitor_address(addr as *const u64 as *const u8, core as u8, nb_cores) }.unwrap(); + let slice = res.iter().enumerate().max_by_key(|(_i, val)| { **val }); match slice { Some((slice, _)) => { println!("({:2}) Slice for addr {:x}: {}", core, addr as *const u64 as usize, slice) @@ -22,8 +36,8 @@ pub fn main() { } } for addr in target.iter() { - let res = unsafe { monitor_address(addr as *const u64 as *const u8, 0, nb_cores) }; - let slice = res.iter().enumerate().max_by_key(|(i, val)| { val }); + let res = unsafe { monitor_address(addr as *const u64 as *const u8, 0, nb_cores) }.unwrap(); + let slice = res.iter().enumerate().max_by_key(|(_i, val)| { **val }); match slice { Some((slice, _)) => { println!("({:2}) Slice for addr {:x}: {}", 0, addr as *const u64 as usize, slice) @@ -33,5 +47,6 @@ pub fn main() { } } } + sched_setaffinity(Pid::this(), &old).unwrap(); } } diff --git a/cache_slice/src/lib.rs b/cache_slice/src/lib.rs index 9883c32..bf36754 100644 --- a/cache_slice/src/lib.rs +++ b/cache_slice/src/lib.rs @@ -2,7 +2,7 @@ use std::arch::x86_64::_mm_clflush; use crate::arch::CpuClass::{IntelCore, IntelXeon, IntelXeonSP}; -use crate::arch::get_performance_counters_xeon; +use crate::arch::{get_performance_counters_core, get_performance_counters_xeon}; use crate::Error::UnsupportedCPU; use crate::msr::{read_msr_on_cpu, write_msr_on_cpu}; @@ -10,6 +10,7 @@ pub mod msr; pub mod utils; mod arch; +#[derive(Debug)] pub enum Error { UnsupportedCPU, InvalidParameter, @@ -30,7 +31,7 @@ unsafe fn poke(addr: *const u8) { } } -unsafe fn monitor_xeon(addr: *const u8, cpu: u8, max_cbox: usize) -> Result, Error> { +unsafe fn monitor_xeon(addr: *const u8, cpu: u8, max_cbox: usize) -> Result, Error> { let performance_counters = if let Some(p) = get_performance_counters_xeon() { p } else { @@ -75,24 +76,38 @@ unsafe fn monitor_xeon(addr: *const u8, cpu: u8, max_cbox: usize) -> Result Result, Error> { +fn monitor_core(addr: *const u8, cpu: u8, max_cbox: usize) -> Result, Error> { // Note, we need to add the workaround for one missing perf counter here. + let performance_counters = if let Some(p) = get_performance_counters_core() { + p + } else { + return Err(UnsupportedCPU); + }; + + let workaround = if (performance_counters.max_slice as usize) + 1 == max_cbox { + true + } else if (performance_counters.max_slice as usize) >= max_cbox { + false + } else { + return Err(Error::InvalidParameter); + }; + unimplemented!() } -pub unsafe fn monitor_address(addr: *const u8, cpu: u8, max_cbox: u16) -> Result, Error> { +pub unsafe fn monitor_address(addr: *const u8, cpu: u8, max_cbox: u16) -> Result, Error> { match arch::determine_cpu_class() { Some(IntelCore) => { - unimplemented!() + unsafe { monitor_core(addr, cpu, max_cbox as usize) } } Some(IntelXeon) => { unsafe { monitor_xeon(addr, cpu, max_cbox as usize) }