Code Documentation ================== src/common.rs ------------- GlobalParams ~~~~~~~~~~~~ GlobalParams holds the configuration parameters for the global settings of the application. # Fields - **sample_size** - Specifies the number of times each experiment is repeated. - **output_directory** - The directory where benchmark results and outputs are stored. This variable can be referenced in task configurations using {{ output_directory }}. - **extra_perf_events** - An optional vector of strings for additional performance monitoring events to be collected. - **debug** - A boolean flag for enabling debug logging for more detailed output. Defaults to false. - **deep_trace** - A boolean flag for enabling an extra experiment with tracing enabled. This can be very slow. Defaults to false. - **energy_sample_interval** - The interval for energy sampling, deserialized using deserialize_duration. Must be specified with a time unit (e.g., "250ms" for 250 milliseconds). Defaults to 500 milliseconds. .. collapse:: Show Code .. code-block:: rust pub struct GlobalParams { pub sample_size: u32, pub output_directory: PathBuf, pub extra_perf_events: Option>, #[serde(default)] pub debug: bool, #[serde(default)] pub deep_trace: bool, #[serde( deserialize_with = "deserialize_duration", default = "default_energy_sample_interval" )] pub energy_sample_interval: Duration, } StorageType ~~~~~~~~~~~ StorageType defines the types of storage that can be used. # Variants - **Encrypted** - Represents encrypted storage. - **Tmpfs** - Represents temporary file system storage. - **Untrusted** - Represents untrusted storage. .. collapse:: Show Code .. code-block:: rust pub enum StorageType { Encrypted, Untrusted, } Task ~~~~ Task represents a task to be executed, including its configuration and associated scripts. # Fields * **executable** - The path to the executable file for the task. * **args** - A vector of arguments to be passed to the executable. Defaults to an empty vector. - **num_threads** - A vector specifying the number of threads to be used in each experiment. - **enclave_size** - A vector of strings representing the possible enclave memory sizes. Each experiment will be run with every listed size. * **custom_manifest_path** - An optional path to a custom manifest file. * **storage_type** - A vector of storage types, deserialized using **deserialize_storage_type**. Defaults to **[StorageType::Untrusted]**. * **pre_run_executable** - An optional path to an executable to run before the main task. * **pre_run_args** - A vector of arguments for the pre-run executable. Defaults to an empty vector. * **post_run_executable** - An optional path to an executable to run after the main task. * **post_run_args** - A vector of arguments for the post-run executable. Defaults to an empty vector. .. collapse:: Show Code .. code-block:: rust pub struct Task { pub executable: PathBuf, #[serde(default)] pub args: Vec, #[serde(default = "default_num_threads")] pub num_threads: Vec, pub enclave_size: Vec, pub custom_manifest_path: Option, #[serde( default = "default_storage_type", deserialize_with = "deserialize_storage_type" )] pub storage_type: Vec, pub pre_run_executable: Option, #[serde(default)] pub pre_run_args: Vec, pub post_run_executable: Option, #[serde(default)] pub post_run_args: Vec, pub env: Option>, } src/constants.rs ---------------- DEFAULT_PERF_EVENTS ~~~~~~~~~~~~~~~~~~~ Default performance events to be monitored. These events are used to gather various performance metrics during the execution of an application within the Gramine enclave. The list includes CPU cycles, cache references, and other hardware-related events that can provide insights into the application's behavior and performance characteristics. # Events - `branch-misses`: Number of branch misses. - `cache-misses`: Number of cache misses. - `cpu-cycles`: CPU cycles. - `duration_time`: Total duration of the event. - `instructions`: Number of instructions executed. - `stalled-cycles-frontend`: Cycles where the frontend is stalled. - `system_time`: Time spent in system mode. - `user_time`: Time spent in user mode. .. collapse:: Show Code .. code-block:: rust pub const DEFAULT_PERF_EVENTS: [&str; 8] = [ "branch-misses", "cache-misses", "cpu-cycles", "duration_time", "instructions", "stalled-cycles-frontend", "system_time", "user_time", ]; MANIFEST ~~~~~~~~ The Gramine manifest configuration for an enclave application. This manifest defines various settings and parameters for running an application within a Gramine enclave. It includes configuration for the entry point, logging, environment variables, file system mounts, security settings, and SGX-specific options. # Variables - `{{ executable }}`: The path to the executable that serves as the entry point for the application. - `{{ debug }}`: The log level for the loader, which determines the verbosity of logging output. - `{{ env }}`: Environment variables for the application. - `{{ num_threads }}`: The number of OpenMP threads to be used by the application, set via the `OMP_NUM_THREADS` environment variable. - `{{ gramine.runtimedir() }}`: The directory path where Gramine runtime libraries are located, used for mounting the `/lib` path. - `{{ arch_libdir }}`: The architecture-specific library directory, used for mounting and trusted file paths. - `{{ encrypted_path }}`: The path to the directory containing encrypted files, mounted at `/encrypted/` with a specified key. - `{{ untrusted_path }}`: The path to the directory containing untrusted files, mounted at `/untrusted/`. - `{{ enclave_size }}`: The size of the enclave, specified in bytes. - `{{ num_threads_sgx }}`: The maximum number of threads that the SGX enclave can support. - `{{ 'true' if env.get('EDMM', '0') == '1' else 'false' }}`: A boolean value indicating whether Enhanced Dynamic Memory Management (EDMM) is enabled, based on the `EDMM` environment variable. # Configuration Details - `libos.entrypoint`: Specifies the entry point executable for the application. - `loader.log_level`: Sets the logging level for the Gramine loader. - `loader.env.LD_LIBRARY_PATH`: Sets the library path for dynamic linking within the enclave. - `loader.insecure__use_cmdline_argv`: Allows the use of command-line arguments in an insecure manner. - `fs.mounts`: Defines the file system mounts for the enclave, including paths for libraries, executables, tmpfs, encrypted, and untrusted files. - `fs.insecure__keys.default`: Specifies the default encryption key for accessing encrypted files. - `sgx.debug`: Enables or disables debug mode for the SGX enclave. - `sgx.profile.mode`: Sets the profiling mode for the SGX enclave, such as "ocall_outer". - `sgx.enable_stats`: Enables the collection of statistics within the SGX enclave. - `sys.enable_sigterm_injection`: Allows the injection of SIGTERM signals into the enclave. - `sgx.enclave_size`: Specifies the size of the SGX enclave. - `sgx.max_threads`: Sets the maximum number of threads for the SGX enclave. - `sgx.edmm_enable`: Enables or disables Enhanced Dynamic Memory Management (EDMM) for the SGX enclave. - `sgx.trusted_files`: Lists the files that are trusted and can be accessed securely within the enclave. - `sgx.allowed_files`: Lists the files that are allowed to be accessed, but are not necessarily trusted. .. collapse:: Show Code .. code-block:: rust pub const MANIFEST: &str = r#" libos.entrypoint = "{{ executable }}" loader.log_level = "{{ debug }}" loader.env.LD_LIBRARY_PATH = "/lib:{{ arch_libdir }}:/usr/lib" loader.insecure__use_cmdline_argv = true {% for key, val in env.items() %} loader.env.{{ key }} = "{{ val }}" {% endfor %} fs.mounts = [ { path = "/lib", uri = "file:{{ gramine.runtimedir() }}" }, { path = "/usr/lib", uri = "file:/usr/lib" }, { path = "{{ arch_libdir }}", uri = "file:{{ arch_libdir }}" }, { path = "{{ executable }}", uri = "file:{{ executable }}" }, { type = "tmpfs", path = "/tmp/" }, { type = "encrypted", path = "/encrypted/", uri = "file:{{ encrypted_path }}/", key_name = "default" }, { path = "/untrusted/", uri = "file:{{ untrusted_path }}/" }, { path = "/etc/passwd", uri = "file:/etc/passwd" } ] fs.insecure__keys.default = "ffeeddccbbaa99887766554433221100" sgx.debug = true sgx.profile.mode = "ocall_outer" sgx.enable_stats = true sys.enable_sigterm_injection = true sgx.enclave_size = "{{ enclave_size }}" sgx.max_threads = {{ num_threads_sgx }} sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} sgx.trusted_files = [ "file:{{ executable }}", "file:{{ gramine.runtimedir( libc ) }}/", "file:{{ executable_path }}/", "file:{{ arch_libdir }}/", "file:/usr/{{ arch_libdir }}/", "file:/etc/passwd" ] sgx.allowed_files = [ "file:{{ untrusted_path }}/", ] "#; src/profiler.rs --------------- Profiler ~~~~~~~~ A `Profiler` is responsible for managing the benchmarking of tasks within an SGX enclave environment. This structure is initialized with various configuration parameters such as the number of threads, enclave sizes, output directory, and a collector for gathering profiling data. It also manages the creation and storage of RSA private keys used for signing the enclave. # Fields * `private_key_path` - The file path where the RSA private key is stored. * `output_directory` - The directory where profiling results and other output files are stored. * `collector` - An `Arc` wrapped `DefaultCollector` used for collecting profiling data. * `debug` - A boolean flag indicating whether debugging is enabled. # Methods * `profile` - Initiates the benchmarking of a given task. This method configures the environment, builds and signs the enclave, and executes the task while collecting profiling data. .. collapse:: Show Code .. code-block:: rust pub struct Profiler { private_key_path: PathBuf, output_directory: PathBuf, collector: Arc, debug: bool, stop: AtomicBool, } src/stats.rs ------------ DeepTraceEvent ~~~~~~~~~~~~~~ An event from the deep trace eBPF program. .. collapse:: Show Code .. code-block:: rust pub struct DeepTraceEvent { pub ev_type: u32, pub timestamp: u64, } EnergySample ~~~~~~~~~~~~ A sample of energy consumption. .. collapse:: Show Code .. code-block:: rust pub struct EnergySample { pub timestamp: u128, pub energy_uj: u64, } Partition ~~~~~~~~~ Partitions are loaded from `/proc/partitions`. .. collapse:: Show Code .. code-block:: rust pub struct Partition { pub name: String, pub dev: u32, } from_str ~~~~~~~~ Creates a Partition from a line in `/proc/partitions` .. collapse:: Show Code .. code-block:: rust pub fn from_str(value: &str) -> Self { let parts = value.split_whitespace().collect::>(); assert_eq!(parts.len(), 4); let major = parts[0].parse::().unwrap(); let minor = parts[1].parse::().unwrap(); Self { name: parts[3].to_string(), // https://man7.org/linux/man-pages/man3/makedev.3.html dev: (major << 20) | minor, } } DiskStats ~~~~~~~~~ Disk statistics collected from the eBPF program. .. collapse:: Show Code .. code-block:: rust pub struct DiskStats { pub name: String, pub bytes: u64, pub perc_random: u32, pub perc_seq: u32, } LowLevelSgxCounters ~~~~~~~~~~~~~~~~~~~ A low-level view of SGX counters. .. collapse:: Show Code .. code-block:: rust pub struct LowLevelSgxCounters { pub encl_load_page: u64, pub encl_wb: u64, pub vma_access: u64, pub vma_fault: u64, }