-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Measure the Costs of Traps, World Switches, and Misaligned Operations…
… 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
1 parent
851f56c
commit e66ee3a
Showing
11 changed files
with
443 additions
and
169 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "tracing" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
license = "MIT" | ||
|
||
[dependencies] | ||
miralis_core = { path = "../core" } | ||
log = { workspace = true } | ||
config_helpers = { path = "../config_helpers"} | ||
miralis_abi = { path = "../abi" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
//! Miralis ABI | ||
//! | ||
//! While miralis forwards standard SBI calls to the virtualized firmware, miralis do expose its own | ||
//! ABI for the firmware to interact with. | ||
//! | ||
//! The Miralis ABI tries to be compatible with the SBI specification as best as it can. | ||
//! See: https://github.com/riscv-non-isa/riscv-sbi-doc | ||
#![no_std] | ||
|
||
use core::arch::{asm, global_asm}; | ||
|
||
use miralis_abi::failure; | ||
|
||
pub fn print_statistics(stats: Statistics) { | ||
log::info!("{:?}", stats); | ||
} | ||
|
||
#[macro_export] | ||
macro_rules! measure { | ||
($policy_name:literal, $out:literal, $in:expr, $in2:expr) => { | ||
let mut values: [usize; NB_REPEATS] = [0; NB_REPEATS]; | ||
|
||
for i in 0..NB_REPEATS { | ||
values[i] = $in(); | ||
} | ||
|
||
let stats = get_statistics(values); | ||
|
||
let average_measure = $in2(); | ||
|
||
log::info!("{} cost {} : {}", $policy_name, $out, average_measure); | ||
|
||
print_statistics(stats); | ||
}; | ||
} | ||
|
||
pub fn enable_mcycle_in_smode() { | ||
unsafe { | ||
// This allows to read cycle in S-mode - for the payload | ||
let mcounteren: u32; | ||
asm!("csrr {}, mcounteren", out(reg) mcounteren); | ||
asm!("csrw mcounteren, {}", in(reg) mcounteren | 1); | ||
} | ||
} | ||
|
||
// —————————————————————————————— Trap Handler —————————————————————————————— // | ||
|
||
global_asm!( | ||
r#" | ||
.text | ||
.align 4 | ||
.global _empty_handler | ||
_empty_handler: | ||
// Skip illegal instruction (pc += 4) | ||
csrrw x5, mepc, x5 | ||
addi x5, x5, 4 | ||
csrrw x5, mepc, x5 | ||
// Return back to OS | ||
mret | ||
"#, | ||
); | ||
|
||
extern "C" { | ||
pub fn _empty_handler(); | ||
} | ||
|
||
// —————————————————————————————— Benchmark operating system —————————————————————————————— // | ||
|
||
pub const NB_REPEATS: usize = 1000; | ||
|
||
pub fn bubble_sort(arr: &mut [usize; NB_REPEATS]) { | ||
let len = arr.len(); | ||
let mut swapped; | ||
|
||
for i in 0..len { | ||
swapped = false; | ||
|
||
for j in 0..len - 1 - i { | ||
if arr[j] > arr[j + 1] { | ||
arr.swap(j, j + 1); | ||
swapped = true; | ||
} | ||
} | ||
|
||
if !swapped { | ||
break; | ||
} | ||
} | ||
|
||
for i in 1..len { | ||
if arr[i - 1] > arr[i] { | ||
log::error!("Error in sorting, results aren't reliable"); | ||
failure(); | ||
} | ||
} | ||
} | ||
|
||
pub fn trigger_ctx_switch_to_firmware() -> usize { | ||
let begin: u64; | ||
let end: u64; | ||
|
||
unsafe { | ||
// Read the `mcycle` register (assuming 64-bit RISC-V) | ||
asm!("csrr {}, cycle", out(reg) begin); | ||
// We trigger an illegal instruction | ||
asm!("csrw mscratch, zero"); | ||
// Read the `mcycle` register (assuming 64-bit RISC-V) | ||
asm!("csrr {}, cycle", out(reg) end); | ||
} | ||
|
||
(end - begin) as usize | ||
} | ||
|
||
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 | ||
} | ||
|
||
pub fn trigger_ctx_switch_to_firmware_batched() -> usize { | ||
let begin: u64; | ||
let end: u64; | ||
|
||
unsafe { | ||
// Read the `mcycle` register (assuming 64-bit RISC-V) | ||
asm!("csrr {}, cycle", out(reg) begin); | ||
for _ in 0..NB_REPEATS { | ||
// We can trigger an illegal instruction | ||
asm!("csrw mscratch, zero"); | ||
} | ||
|
||
// 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, | ||
min: usize, | ||
max: usize, | ||
|
||
p25: usize, | ||
p50: usize, | ||
p75: usize, | ||
p95: usize, | ||
p99: usize, | ||
} | ||
|
||
pub fn get_statistics(mut arr: [usize; NB_REPEATS]) -> Statistics { | ||
bubble_sort(&mut arr); | ||
|
||
let mut output: Statistics = Statistics { | ||
mean: 0, | ||
min: 0, | ||
max: 0, | ||
p25: 0, | ||
p50: 0, | ||
p75: 0, | ||
p95: 0, | ||
p99: 0, | ||
}; | ||
|
||
output.min = arr[0]; | ||
output.max = arr[arr.len() - 1]; | ||
output.mean = arr.iter().sum::<usize>() / arr.len(); | ||
|
||
let percentile = |per: f64| -> usize { arr[(per * arr.len() as f64) as usize] }; | ||
|
||
output.p25 = percentile(0.25); | ||
output.p50 = percentile(0.50); | ||
output.p75 = percentile(0.75); | ||
output.p95 = percentile(0.95); | ||
output.p99 = percentile(0.99); | ||
|
||
output | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.