Skip to content

Commit

Permalink
Measure the Costs of Traps, World Switches, and Misaligned Operations…
Browse files Browse the repository at this point in the history
… with the Protect Payload Policy

This commit extends the tracing firmware by introducing three new latency measurements in the Protect Payload policy and ensures that no additional performance losses are incurred.
  • Loading branch information
francois141 authored and CharlyCst committed Jan 9, 2025
1 parent 91dba20 commit fa7032b
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 8 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions config/test/spike-latency-benchmark-protect-payload.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# A simple configuration to run on the Spike platform

[log]
level = "info"
color = true

[vcpu]
max_pmp = 8
delegate_perf_counters=true

[platform]
name = "spike"

[target.miralis]
# Build profile for Miralis (dev profile is set by default)
profile = "release"

[target.firmware]
# Build profile for the firmware (dev profile is set by default)
profile = "release"

[policy]
name = "protect_payload"
1 change: 1 addition & 0 deletions firmware/tracing_firmware/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ path = "main.rs"

[dependencies]
miralis_abi = { path = "../../crates/abi" }
config_helpers = { path = "../../crates/config_helpers" }
76 changes: 74 additions & 2 deletions firmware/tracing_firmware/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@

use core::arch::{asm, global_asm};

use config_helpers::parse_str_or;
use miralis_abi::{failure, log, setup_binary, success};

setup_binary!(main);

const POLICY_NAME: &str = parse_str_or(option_env!("MIRALIS_POLICY_NAME"), "default_policy");

const PROTECT_PAYLOAD_POLICY: &str = "protect_payload";

fn enable_mcycle_in_smode() {
unsafe {
// This allows to read cycle in S-mode - for the payload
Expand Down Expand Up @@ -122,6 +127,11 @@ fn operating_system() {
}

measure(false);

if POLICY_NAME == PROTECT_PAYLOAD_POLICY {
measure_misaligned();
}

success();
}

Expand All @@ -136,14 +146,29 @@ fn measure(is_firmware: bool) {
let average_measure = trigger_ctx_switch_to_firmware_batched();

if is_firmware {
log::info!("Firmware cost : {}", average_measure);
log::info!("Firmware cost {} : {}", POLICY_NAME, average_measure);
} else {
log::info!("Payload cost : {}", average_measure);
log::info!("Payload cost {} : {}", POLICY_NAME, average_measure);
}

print_statistics(stats);
}

fn measure_misaligned() {
let mut values: [usize; NB_REPEATS] = [0; NB_REPEATS];

for i in 0..NB_REPEATS {
values[i] = trigger_misaligned_op()
}

let stats = get_statistics(values);
let average_measure = trigger_ctx_switch_to_firmware_batched();

log::info!("Misaligned cost {} : {}", POLICY_NAME, average_measure);

print_statistics(stats);
}

fn trigger_ctx_switch_to_firmware() -> usize {
let begin: u64;
let end: u64;
Expand Down Expand Up @@ -179,6 +204,53 @@ fn trigger_ctx_switch_to_firmware_batched() -> usize {
(end - begin) as usize / NB_REPEATS
}

pub fn trigger_misaligned_op() -> usize {
let begin: u64;
let end: u64;

let misaligned_address_8_bytes: usize = 0x80600301;

unsafe {
// Read the `mcycle` register (assuming 64-bit RISC-V)
asm!("csrr {}, cycle", out(reg) begin);
// We trigger a misaligned operation
asm!(
"ld {r}, 0({addr})",
addr = in(reg) misaligned_address_8_bytes,
r = out(reg) _,
);
// Read the `mcycle` register (assuming 64-bit RISC-V)
asm!("csrr {}, cycle", out(reg) end);
}

(end - begin) as usize
}

pub fn trigger_misaligned_op_batched() -> usize {
let begin: u64;
let end: u64;

let misaligned_address_8_bytes: usize = 0x80600301;

unsafe {
// Read the `mcycle` register (assuming 64-bit RISC-V)
asm!("csrr {}, cycle", out(reg) begin);

for _ in 0..NB_REPEATS {
// We trigger a misaligned operation
asm!(
"ld {r}, 0({addr})",
addr = in(reg) misaligned_address_8_bytes,
r = out(reg) _,
);
}
// Read the `mcycle` register (assuming 64-bit RISC-V)
asm!("csrr {}, cycle", out(reg) end);
}

(end - begin) as usize / NB_REPEATS
}

#[derive(Debug)]
pub struct Statistics {
mean: usize,
Expand Down
8 changes: 8 additions & 0 deletions miralis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ path = "config/test/spike-protect-payload.toml"
[config.spike-benchmark]
path = "./config/test/spike-latency-benchmark.toml"

[config.spike-benchmark-protect-payload]
path = "./config/test/spike-latency-benchmark-protect-payload.toml"

## ——————————————————————————— Integration Tests ———————————————————————————— ##

[test.ecall]
Expand Down Expand Up @@ -226,3 +229,8 @@ description = "The most basic test, which directly exit with an ecall to Miralis
firmware = "tracing_firmware"
config = "spike-benchmark"
description = "The firmware and configuration we use to measure cycles in the CI"

[test.spike-benchmark-protect-payload]
firmware = "tracing_firmware"
config = "spike-benchmark-protect-payload"
description = "The firmware and configuration we use to measure cycles in the CI using the protect payload policy"
36 changes: 32 additions & 4 deletions misc/push_stats.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ file="cycles.txt"
cargo run -- run --firmware tracing_firmware --config ./config/test/spike-latency-benchmark.toml > $file

# Extract the number after "firmware cost:"
firmware_cost=$(grep -i "Firmware cost :" "$file" | sed -E 's/.*Firmware cost : ([0-9]+).*/\1/')
payload_cost=$(grep -i "Payload cost :" "$file" | sed -E 's/.*Payload cost : ([0-9]+).*/\1/')
firmware_cost=$(grep -i "Firmware cost default_policy :" "$file" | sed -E 's/.*Firmware cost default_policy : ([0-9]+).*/\1/')
payload_cost=$(grep -i "Payload cost default_policy :" "$file" | sed -E 's/.*Payload cost default_policy : ([0-9]+).*/\1/')
firmware_cost_protect=$(grep -i "Firmware cost protect_payload:" "$file" | sed -E 's/.*Firmware cost protect_payload : ([0-9]+).*/\1/')
payload_cost_protect=$(grep -i "Payload cost protect_payload :" "$file" | sed -E 's/.*Payload cost protect_payload : ([0-9]+).*/\1/')
misaligned_cost_protect=$(grep -i "Misaligned cost protect_payload :" "$file" | sed -E 's/.*Misaligned cost protect_payload : ([0-9]+).*/\1/')

# Check if a number was found
if [ -n "$firmware_cost" ]; then
Expand All @@ -66,17 +69,42 @@ else
echo "No firmware cost found in the file."
fi

# Check if a number was found
if [ -n "$firmware_cost_protect" ]; then
echo "Firmware cost: $firmware_cost_protect"
else
echo "No firmware cost found in the file."
fi

# Check if a number was found
if [ -n "$payload_cost_protect" ]; then
echo "Payload cost: $payload_cost_protect"
else
echo "No firmware cost found in the file."
fi

# Check if a number was found
if [ -n "$misaligned_cost_protect" ]; then
echo "Payload cost: $misaligned_cost_protect"
else
echo "No firmware cost found in the file."
fi


# ———————————————————————————————— Push stats ———————————————————————————————— #

echo "Commit: $git_commit"
echo "Current date: $current_date"
echo "Miralis size: $miralis_size bytes"
echo "Build time: $build_time"
echo "Miralis <--> Firmware latency in cycles: " firmware_cost
echo "Miralis <--> Firmware latency in cycles: " $firmware_cost
echo "Payload <--> Firmware latency in cycles: " $payload_cost
echo "[PROTECT PAYLOAD] Miralis <--> Firmware latency in cycles: " $firmware_cost_protect
echo "[PROTECT PAYLOAD] Payload <--> Firmware latency in cycles: " $payload_cost_protect
echo "[PROTECT PAYLOAD] Cost of a misaligned emulation: " $misaligned_cost_protect

if [ "$1" = "--commit" ]; then
csv_entry="$git_commit, $current_date, $miralis_size, $build_time, $firmware_cost, $payload_cost"
csv_entry="$git_commit, $current_date, $miralis_size, $build_time, $firmware_cost, $payload_cost,$firmware_cost_protect,$payload_cost_protect,$misaligned_cost_protect"
echo $csv_entry >> "$miralis_stats_csv_path"
echo "Added CSV entry to $miralis_stats_csv_path"
fi
4 changes: 2 additions & 2 deletions runner/src/artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ pub fn build_target(target: Target, cfg: &Config) -> PathBuf {
let linker_args = format!("-C link-arg=-Tmisc/linker-script.x -C link-arg=--defsym=_start_address={firmware_address}");
build_cmd.env("RUSTFLAGS", linker_args);
build_cmd.env("IS_TARGET_FIRMWARE", "true");
build_cmd.envs(cfg.benchmark.build_envs());
build_cmd.envs(cfg.build_envs());
build_cmd.arg("--package").arg(firmware);

if firmware == "miralis" {
Expand All @@ -365,7 +365,7 @@ pub fn build_target(target: Target, cfg: &Config) -> PathBuf {
let linker_args = format!("-C link-arg=-Tmisc/linker-script.x -C link-arg=--defsym=_start_address={payload_address}");
build_cmd.env("RUSTFLAGS", linker_args);
build_cmd.env("IS_TARGET_FIRMWARE", "false");
build_cmd.envs(cfg.benchmark.build_envs());
build_cmd.envs(cfg.build_envs());
build_cmd.arg("--package").arg(payload_name);
}
}
Expand Down

0 comments on commit fa7032b

Please sign in to comment.