From 421658724fff22953901d2ee343c0a86aca07d0a Mon Sep 17 00:00:00 2001 From: Robert Norton Date: Wed, 19 Apr 2023 17:36:11 +0100 Subject: [PATCH] Add a variant of compartment call benchmark that actually uses some stack. This is to check the effect of the stack low water mark. Also tests to make sure the stack is being properly cleared. --- benchmarks/stack-usage/callee.cc | 15 ++++++++++++ benchmarks/stack-usage/callee.h | 4 ++++ benchmarks/stack-usage/caller.cc | 22 ++++++++++++++++++ benchmarks/stack-usage/xmake.lua | 39 ++++++++++++++++++++++++++++++++ benchmarks/timing.h | 24 ++++++++++++++++++++ 5 files changed, 104 insertions(+) create mode 100644 benchmarks/stack-usage/callee.cc create mode 100644 benchmarks/stack-usage/callee.h create mode 100644 benchmarks/stack-usage/caller.cc create mode 100644 benchmarks/stack-usage/xmake.lua diff --git a/benchmarks/stack-usage/callee.cc b/benchmarks/stack-usage/callee.cc new file mode 100644 index 000000000..da57abdf2 --- /dev/null +++ b/benchmarks/stack-usage/callee.cc @@ -0,0 +1,15 @@ +#include "callee.h" +#include "../timing.h" + +int noop_return(size_t s) +{ + use_stack(s); + return rdcycle(); +} + +int noop_call(int start) +{ + int end = rdcycle(); + check_stack_zeroed(); + return end - start; +} diff --git a/benchmarks/stack-usage/callee.h b/benchmarks/stack-usage/callee.h new file mode 100644 index 000000000..5ee9e8226 --- /dev/null +++ b/benchmarks/stack-usage/callee.h @@ -0,0 +1,4 @@ +#include + +int __cheri_compartment("callee") noop_return(size_t s); +int __cheri_compartment("callee") noop_call(int start); diff --git a/benchmarks/stack-usage/caller.cc b/benchmarks/stack-usage/caller.cc new file mode 100644 index 000000000..a02b2d5c1 --- /dev/null +++ b/benchmarks/stack-usage/caller.cc @@ -0,0 +1,22 @@ +#include "../timing.h" +#include "callee.h" +#include +#include + +void __cheri_compartment("caller") run() +{ + MessageBuilder out; + out.format("#board\tstack_use\tcall\treturn\n"); + for (size_t s = 1; s < 0x1000; s <<= 1) + { + auto [callPath, returnPath] = CHERI::with_interrupts_disabled([&]() { + use_stack(s); + auto callPath = noop_call(rdcycle()); + auto returnPath = noop_return(s); + returnPath = rdcycle() - returnPath; + check_stack_zeroed(); + return std::tuple{callPath, returnPath}; + }); + out.format(__XSTRING(BOARD) "\t{}\t{}\t{}\n", s, callPath, returnPath); + } +} diff --git a/benchmarks/stack-usage/xmake.lua b/benchmarks/stack-usage/xmake.lua new file mode 100644 index 000000000..6b15f2cc2 --- /dev/null +++ b/benchmarks/stack-usage/xmake.lua @@ -0,0 +1,39 @@ +-- Copyright Microsoft and CHERIoT Contributors. +-- SPDX-License-Identifier: MIT + +set_project("CHERIoT stack-usage benchmark"); +sdkdir = "../../sdk" +includes(sdkdir) +set_toolchains("cheriot-clang") + +-- Support libraries +includes(path.join(sdkdir, "lib/freestanding"), + path.join(sdkdir, "lib/atomic"), + path.join(sdkdir, "lib/crt")) + +option("board") + set_default("sail") + +compartment("callee") + add_files("callee.cc") + +compartment("caller") + add_defines("BOARD=" .. tostring(get_config("board"))) + add_files("caller.cc") + +-- Firmware image for the example. +firmware("stack-usage-benchmark") + add_deps("crt", "freestanding", "atomic") + add_deps("caller", "callee") + on_load(function(target) + target:values_set("board", "$(board)") + target:values_set("threads", { + { + compartment = "caller", + priority = 1, + entry_point = "run", + stack_size = 0x1000, + trusted_stack_frames = 3 + } + }, {expand = false}) + end) diff --git a/benchmarks/timing.h b/benchmarks/timing.h index 2f50819d3..066323e4d 100644 --- a/benchmarks/timing.h +++ b/benchmarks/timing.h @@ -36,4 +36,28 @@ namespace CHERI::Capability stack{cspRegister}; return stack.length(); } + + void use_stack(size_t s) + { + volatile uint8_t stack_array[s]; + stack_array[0] = 1; + } + + void check_stack_zeroed() + { + register void **cspRegister asm("csp"); + asm("" : "=C"(cspRegister)); + CHERI::Capability stack{cspRegister}; + CHERI::Capability stackP{stack}; + stackP.address() = stack.base(); + while(stackP.address() < stack.address()) + { + CHERI::Capability value{*stackP}; + if (value != NULL) + { + __builtin_trap(); + } + stackP += 1; + } + } } // namespace