From a978dc069c8e0c3a7f6fd03ffe7db36c79f80a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Costa?= Date: Wed, 27 Nov 2024 10:24:24 +0100 Subject: [PATCH] Introduce current the read counters SBI call The READ_COUNTERS SBI call returns the performance counters as recorded by the benchmark module. The specific ABI and counters returns depend on the benchmark module compiled with Miralis. Co-authored-by: Charly Castes --- crates/core/src/lib.rs | 2 ++ src/benchmark/default.rs | 17 ++++++++++++++++- src/benchmark/empty.rs | 3 +++ src/benchmark/mod.rs | 7 +++++++ src/config.rs | 2 +- src/lib.rs | 2 +- src/virt/emulator.rs | 11 +++++++---- 7 files changed, 37 insertions(+), 7 deletions(-) diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index 970e58aa..20d8198a 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -24,6 +24,8 @@ pub mod abi { pub const MIRALIS_LOG_FID: usize = 2; /// Benchmark prints and exit. pub const MIRALIS_BENCHMARK_FID: usize = 3; + /// Returns the performance counters managed by Miralis. + pub const MIRALIS_READ_COUNTERS_FID: usize = 4; /// Log level constants, with the same semantic as the `log` crate. pub mod log { diff --git a/src/benchmark/default.rs b/src/benchmark/default.rs index 5d066fb5..57789d16 100644 --- a/src/benchmark/default.rs +++ b/src/benchmark/default.rs @@ -4,10 +4,12 @@ //! the number of instruction for example. use spin::Mutex; -use crate::arch::{Arch, Architecture, Csr}; +use crate::arch::{Arch, Architecture, Csr, Register}; use crate::benchmark::{BenchmarkModule, Counter, Scope}; use crate::config; use crate::platform::{Plat, Platform}; +use crate::virt::traits::*; +use crate::virt::VirtContext; #[macro_export] macro_rules! _benchmark_print { @@ -180,6 +182,19 @@ impl BenchmarkModule for DefaultBenchmark { BENCH.lock().counters[index] += 1; } + fn read_counters(ctx: &mut VirtContext) { + let benchmark = BENCH.lock(); + + ctx.set( + Register::X10, + benchmark.counters[Counter::FirmwareExits as usize], + ); + ctx.set( + Register::X11, + benchmark.counters[Counter::WorldSwitches as usize], + ); + } + /// Print formated string with value of the counters fn display_counters() { let bench = BENCH.lock(); diff --git a/src/benchmark/empty.rs b/src/benchmark/empty.rs index df984d8e..f50b3c76 100644 --- a/src/benchmark/empty.rs +++ b/src/benchmark/empty.rs @@ -1,5 +1,6 @@ use crate::benchmark::default::IntervalCounter; use crate::benchmark::{BenchmarkModule, Counter, Scope}; +use crate::virt::VirtContext; pub struct EmptyBenchmark {} @@ -26,6 +27,8 @@ impl BenchmarkModule for EmptyBenchmark { ) { } + fn read_counters(_ctx: &mut VirtContext) {} + fn display_counters() {} fn get_counter_value(_counter: Counter) -> usize { diff --git a/src/benchmark/mod.rs b/src/benchmark/mod.rs index 20049baf..f66d8d03 100644 --- a/src/benchmark/mod.rs +++ b/src/benchmark/mod.rs @@ -8,6 +8,7 @@ mod empty; use config_select::select_env; use crate::benchmark::default::IntervalCounter; +use crate::virt::VirtContext; pub type Benchmark = select_env!["MIRALIS_BENCHMARK_TYPE": "default" => default::DefaultBenchmark @@ -28,9 +29,15 @@ pub trait BenchmarkModule { scope: &Scope, value: usize, ); + /// Print formated string with value of the counters fn display_counters(); + /// Read the performance counters into the virtual registers. + /// + /// Note: the specific ABI is depends on the benchmark back-end. + fn read_counters(ctx: &mut VirtContext); + fn get_counter_value(counter: Counter) -> usize; } diff --git a/src/config.rs b/src/config.rs index 5ebbe3e3..204fb0e7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -103,7 +103,7 @@ pub const TARGET_PAYLOAD_ADDRESS: usize = pub const TARGET_STACK_SIZE: usize = parse_usize_or(option_env!("MIRALIS_TARGET_STACK_SIZE"), 0x8000); -/// The choosen policy name +/// The chosen policy name /// /// For now this variable is unused, but we keep it still to force re-compilation when the policy /// name changes. We can get rid of it once it becomes possible to track dependencies on diff --git a/src/lib.rs b/src/lib.rs index 1cfbe86f..b8b07f4a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,7 +51,7 @@ pub unsafe fn main_loop(ctx: &mut VirtContext, mctx: &mut MiralisContext, policy Benchmark::stop_interval_counters(Scope::RunVCPU); Benchmark::start_interval_counters(Scope::HandleTrap); - if handle_trap(ctx, mctx, policy) == ExitResult::Donne { + if handle_trap(ctx, mctx, policy) == ExitResult::Done { return; } diff --git a/src/virt/emulator.rs b/src/virt/emulator.rs index 95dbf9b0..4ddf7f12 100644 --- a/src/virt/emulator.rs +++ b/src/virt/emulator.rs @@ -26,7 +26,7 @@ pub enum ExitResult { /// Continue execution of the virtual firmware or payload. Continue, /// Terminate execution successfully. - Donne, + Done, } impl VirtContext { @@ -510,7 +510,7 @@ impl VirtContext { log::info!("Success!"); log::info!("Number of exits: {}", self.nb_exits); // Terminate execution - return ExitResult::Donne; + return ExitResult::Done; } abi::MIRALIS_LOG_FID => { let log_level = self.get(Register::X10); @@ -533,18 +533,21 @@ impl VirtContext { } } - // For now we don't return error code or the lenght written + // For now we don't return error code or the length written self.set(Register::X10, 0); self.set(Register::X11, 0); - self.pc += 4; } abi::MIRALIS_BENCHMARK_FID => { Benchmark::display_counters(); Plat::exit_success(); } + abi::MIRALIS_READ_COUNTERS_FID => { + Benchmark::read_counters(self); + } _ => panic!("Invalid Miralis FID: 0x{:x}", fid), } + self.pc += 4; ExitResult::Continue } }