├── .licenseignore ├── libsel4benchsupport ├── arch_include │ ├── x86 │ │ └── arch │ │ │ ├── signal.h │ │ │ ├── hardware.h │ │ │ ├── ipc.h │ │ │ ├── fault.h │ │ │ └── smp.h │ ├── arm │ │ └── arch │ │ │ ├── signal.h │ │ │ ├── hardware.h │ │ │ ├── ipc.h │ │ │ ├── fault.h │ │ │ └── smp.h │ └── riscv │ │ └── arch │ │ ├── hardware.h │ │ ├── signal.h │ │ ├── fault.h │ │ ├── smp.h │ │ └── ipc.h ├── src │ ├── support.h │ └── arch │ │ ├── arm │ │ └── support.c │ │ ├── riscv │ │ └── support.c │ │ └── x86 │ │ └── support.c ├── sel4_arch_include │ ├── aarch32 │ │ └── sel4_arch │ │ │ ├── hardware.h │ │ │ ├── signal.h │ │ │ ├── fault.h │ │ │ └── ipc.h │ ├── aarch64 │ │ └── sel4_arch │ │ │ ├── hardware.h │ │ │ ├── signal.h │ │ │ ├── fault.h │ │ │ └── ipc.h │ ├── ia32 │ │ └── sel4_arch │ │ │ ├── smp.h │ │ │ ├── hardware.h │ │ │ ├── signal.h │ │ │ ├── fault.h │ │ │ └── ipc.h │ └── x86_64 │ │ └── sel4_arch │ │ ├── smp.h │ │ ├── hardware.h │ │ ├── signal.h │ │ ├── fault.h │ │ └── ipc.h ├── include │ ├── hardware.h │ ├── benchmark_types.h │ ├── irq.h │ ├── sel4benchsupport │ │ └── signal.h │ ├── smp.h │ ├── fault.h │ ├── sync.h │ ├── scheduler.h │ ├── page_mapping.h │ ├── vcpu.h │ ├── ipc.h │ └── benchmark.h └── CMakeLists.txt ├── apps ├── sel4bench │ ├── src │ │ ├── plat │ │ │ ├── tx2 │ │ │ │ ├── plat.c │ │ │ │ └── vcpu.c │ │ │ ├── pc99 │ │ │ │ └── plat.c │ │ │ └── imx6 │ │ │ │ └── plat.c │ │ ├── printing.h │ │ ├── json.h │ │ ├── printing.c │ │ ├── vcpu.c │ │ ├── env.h │ │ ├── math.h │ │ ├── hardware.c │ │ ├── processing.h │ │ ├── signal.c │ │ ├── smp.c │ │ ├── processing.c │ │ ├── irq.c │ │ ├── page_mapping.c │ │ ├── fault.c │ │ ├── benchmark.h │ │ ├── sync.c │ │ ├── ipc.c │ │ ├── json.c │ │ ├── scheduler.c │ │ └── math.c │ └── CMakeLists.txt ├── sync │ └── CMakeLists.txt ├── signal │ └── CMakeLists.txt ├── hardware │ ├── CMakeLists.txt │ └── src │ │ └── main.c ├── scheduler │ └── CMakeLists.txt ├── irquser │ ├── CMakeLists.txt │ └── src │ │ └── main.c ├── smp │ ├── CMakeLists.txt │ └── src │ │ └── rnorrexp.h ├── vcpu │ ├── CMakeLists.txt │ └── src │ │ └── guest_asm.S ├── page_mapping │ └── CMakeLists.txt ├── fault │ └── CMakeLists.txt └── ipc │ └── CMakeLists.txt ├── .github ├── workflows │ ├── pr.yml │ ├── push.yml │ ├── hw-tests.yml │ └── sel4bench.yml ├── CODE_OF_CONDUCT.md └── CONTRIBUTING.md ├── Findsel4benchsupport.cmake ├── LICENSE.md ├── LICENSES ├── MIT.txt └── BSD-2-Clause.txt ├── easy-settings.cmake ├── CMakeLists.txt ├── README.md └── settings.cmake /.licenseignore: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | .git 8 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/x86/arch/signal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/x86/arch/hardware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/x86/arch/ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/arm/arch/signal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/x86/arch/fault.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | -------------------------------------------------------------------------------- /apps/sel4bench/src/plat/tx2/plat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include "../../env.h" 7 | 8 | void plat_setup(env_t *env) 9 | { 10 | /* nothing to do */ 11 | } 12 | -------------------------------------------------------------------------------- /apps/sel4bench/src/printing.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | void print_all(int size, ccnt_t array[size]); 12 | -------------------------------------------------------------------------------- /libsel4benchsupport/src/support.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | void benchmark_arch_get_simple(arch_simple_t *simple); 12 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/arm/arch/hardware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #define DO_NULLSYSCALL(swi) DO_NULLSYSCALL_OP(swi, seL4_SysBenchmarkNullSyscall) 11 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2025, Proofcraft Pty Ltd 2 | # 3 | # SPDX-License-Identifier: BSD-2-Clause 4 | 5 | # Actions to run on pull requests 6 | 7 | name: PR 8 | 9 | on: [pull_request, workflow_dispatch] 10 | 11 | jobs: 12 | pr-checks: 13 | name: Checks 14 | uses: seL4/ci-actions/.github/workflows/pr.yml@master 15 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Code of Conduct 8 | 9 | This repository and interactions with it fall under the [seL4 Code of Conduct][1] available from the [seL4 website][2]. 10 | 11 | [1]: https://docs.sel4.systems/processes/conduct.html 12 | [2]: https://sel4.systems 13 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/arm/arch/ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define READ_COUNTER_BEFORE SEL4BENCH_READ_CCNT 13 | #define READ_COUNTER_AFTER SEL4BENCH_READ_CCNT 14 | -------------------------------------------------------------------------------- /.github/workflows/push.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 2 | # 3 | # SPDX-License-Identifier: BSD-2-Clause 4 | 5 | # Actions to run on Push and Pull Request 6 | name: CI 7 | 8 | on: 9 | push: 10 | branches: 11 | - master 12 | pull_request: 13 | workflow_dispatch: 14 | 15 | jobs: 16 | checks: 17 | name: Checks 18 | uses: seL4/ci-actions/.github/workflows/push.yml@master 19 | -------------------------------------------------------------------------------- /apps/sel4bench/src/json.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "benchmark.h" 10 | #include 11 | #include 12 | #include 13 | 14 | json_t *result_set_to_json(result_set_t set); 15 | json_t *average_counters_to_json(char *name, result_t counters[NUM_AVERAGE_EVENTS]); 16 | -------------------------------------------------------------------------------- /apps/sel4bench/src/printing.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "benchmark.h" 12 | #include "printing.h" 13 | #include "ipc.h" 14 | 15 | void print_all(int size, ccnt_t array[size]) 16 | { 17 | uint32_t i; 18 | for (i = 0; i < size; i++) { 19 | printf("\t"CCNT_FORMAT"\n", array[i]); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/sel4bench/src/plat/pc99/plat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include "../../env.h" 7 | 8 | void plat_setup(env_t *env) 9 | { 10 | if (config_set(CONFIG_ARCH_X86_64)) { 11 | /* check if the cpu supports rdtscp */ 12 | int edx = 0; 13 | asm volatile("cpuid":"=d"(edx):"a"(0x80000001):"ecx"); 14 | ZF_LOGF_IF((edx & (BIT(27))) == 0, "CPU does not support rdtscp instruction"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/x86/arch/smp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #define CACHE_LN_SZ CONFIG_CACHE_LN_SZ 12 | 13 | #define READ_CYCLE_COUNTER(_r) do { \ 14 | (_r) = sel4bench_get_cycle_count(); \ 15 | } while(0) 16 | #define RESET_CYCLE_COUNTER 17 | #define OVERHEAD_FIXUP(_c, _o) (_c) 18 | 19 | static inline ccnt_t smp_benchmark_check_overhead(void) 20 | { 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /Findsel4benchsupport.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | set(SEL4_BENCH_SUPPORT_DIR 8 | "${CMAKE_CURRENT_LIST_DIR}/libsel4benchsupport" 9 | CACHE STRING "" 10 | ) 11 | mark_as_advanced(SEL4_BENCH_SUPPORT_DIR) 12 | 13 | macro(sel4benchsupport_import_libraries) 14 | add_subdirectory(${SEL4_BENCH_SUPPORT_DIR} sel4benchsupport) 15 | endmacro() 16 | 17 | include(FindPackageHandleStandardArgs) 18 | find_package_handle_standard_args(sel4benchsupport DEFAULT_MSG SEL4_BENCH_SUPPORT_DIR) 19 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # License 8 | 9 | The files in this repository are released under standard open source licenses, 10 | identified by [SPDX license tags][1]. See the individual file headers for 11 | details, or use one of the publicly available SPDX tools to generate a bill of 12 | materials. The directory [`LICENSES`][2] contains the text for all licenses 13 | that are mentioned by files in this repository. 14 | 15 | [1]: https://spdx.org 16 | [2]: LICENSES/ 17 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/riscv/arch/hardware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #define DO_NULLSYSCALL_OP(swi, syscall) do {\ 9 | register seL4_Word scno asm("a7") = syscall; \ 10 | asm volatile (NOPS swi NOPS :: "r"(scno)); \ 11 | } while (0); 12 | 13 | #define DO_NULLSYSCALL(swi) DO_NULLSYSCALL_OP(swi, seL4_SysBenchmarkNullSyscall) 14 | 15 | #define DO_REAL_NULLSYSCALL() DO_NULLSYSCALL("ecall") 16 | #define DO_NOP_NULLSYSCALL() DO_NULLSYSCALL("nop") -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/aarch32/sel4_arch/hardware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #define DO_NULLSYSCALL_OP(swi, syscall) do {\ 9 | register seL4_Word scno asm("r7") = syscall; \ 10 | asm volatile (NOPS swi NOPS \ 11 | : /* no outputs */ \ 12 | : "r"(scno) \ 13 | : /* no clobber */ \ 14 | ); \ 15 | } while (0); 16 | 17 | #define DO_REAL_NULLSYSCALL() DO_NULLSYSCALL("swi $0") 18 | #define DO_NOP_NULLSYSCALL() DO_NULLSYSCALL("nop") 19 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/aarch64/sel4_arch/hardware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #define DO_NULLSYSCALL_OP(swi, syscall) do {\ 9 | register seL4_Word scno asm("x7") = syscall; \ 10 | asm volatile (NOPS swi NOPS \ 11 | : /* no outputs */ \ 12 | : "r"(scno) \ 13 | : /* no clobber */ \ 14 | ); \ 15 | } while (0); 16 | 17 | #define DO_REAL_NULLSYSCALL() DO_NULLSYSCALL("svc #0") 18 | #define DO_NOP_NULLSYSCALL() DO_NULLSYSCALL("nop") 19 | -------------------------------------------------------------------------------- /apps/sel4bench/src/vcpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "benchmark.h" 13 | 14 | #ifndef CONFIG_APP_VCPU_BENCH 15 | static benchmark_t vcpu_benchmark = { 16 | .name = "vcpu", 17 | .enabled = config_set(CONFIG_APP_VCPU_BENCH), 18 | .results_pages = 0, 19 | .process = NULL, 20 | .init = blank_init 21 | }; 22 | 23 | benchmark_t *vcpu_benchmark_new(void) 24 | { 25 | return &vcpu_benchmark; 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/hardware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #define N_IGNORED 10 11 | #define N_RUNS (100 + N_IGNORED) 12 | 13 | typedef struct hardware_results { 14 | ccnt_t nullSyscall_results[N_RUNS]; 15 | ccnt_t nullSyscall_overhead[N_RUNS]; 16 | 17 | /* Data for early processing */ 18 | ccnt_t overhead_min; 19 | 20 | ccnt_t nullSyscall_ep_sum; 21 | ccnt_t nullSyscall_ep_sum2; 22 | ccnt_t nullSyscall_ep_num; 23 | ccnt_t nullSyscall_ep[N_RUNS]; 24 | } hardware_results_t; 25 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/ia32/sel4_arch/smp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | static inline void smp_benchmark_ping(seL4_CPtr ep) 12 | { 13 | seL4_CallWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL); 14 | } 15 | 16 | static inline void smp_benchmark_pong(seL4_CPtr ep, seL4_CPtr reply) 17 | { 18 | #ifdef CONFIG_KERNEL_MCS 19 | seL4_ReplyRecvWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL, reply); 20 | #else 21 | seL4_ReplyRecvWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL); 22 | #endif 23 | } 24 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/benchmark_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | /* types shared between sel4bench and its child apps */ 13 | 14 | #define SEL4BENCH_PROTOBUF_RPC (9000) 15 | typedef struct { 16 | size_t untyped_size_bits; 17 | uintptr_t stack_vaddr; 18 | size_t stack_pages; 19 | void *results; 20 | int nr_cores; 21 | void *fdt; 22 | seL4_CPtr first_free; 23 | seL4_CPtr untyped_cptr; 24 | seL4_CPtr sched_ctrl; 25 | seL4_CPtr serial_ep; 26 | } benchmark_args_t; 27 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/x86_64/sel4_arch/smp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | static inline void smp_benchmark_ping(seL4_CPtr ep) 12 | { 13 | seL4_CallWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL, NULL); 14 | } 15 | 16 | static inline void smp_benchmark_pong(seL4_CPtr ep, seL4_CPtr reply) 17 | { 18 | #ifdef CONFIG_KERNEL_MCS 19 | seL4_ReplyRecvWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL, NULL, NULL, reply); 20 | #else 21 | seL4_ReplyRecvWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL, NULL, NULL); 22 | #endif 23 | } 24 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/ia32/sel4_arch/hardware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #define DO_NULLSYSCALL_OP(sys, syscall) do {\ 9 | asm volatile ( \ 10 | "movl %%esp, %%ecx \n" \ 11 | "leal 1f, %%edx \n" \ 12 | "1: \n" \ 13 | sys" \n" \ 14 | : \ 15 | : "a" (syscall) \ 16 | : "ecx", "edx" \ 17 | ); \ 18 | } while (0); 19 | 20 | #define DO_NULLSYSCALL(swi) DO_NULLSYSCALL_OP(swi, seL4_SysBenchmarkNullSyscall) 21 | 22 | #define DO_REAL_NULLSYSCALL() DO_NULLSYSCALL("sysenter") 23 | #define DO_NOP_NULLSYSCALL() DO_NULLSYSCALL(".byte 0x66\n.byte 0x90") 24 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/x86_64/sel4_arch/hardware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #define DO_NULLSYSCALL_OP(sys, syscall) do {\ 9 | asm volatile ( \ 10 | "movq %%rsp, %%rbx \n" \ 11 | sys " \n" \ 12 | "movq %%rbx, %%rsp \n" \ 13 | : \ 14 | : "d" ((seL4_Word)syscall) \ 15 | : "%rcx", "%rbx", "%r11" \ 16 | ); \ 17 | } while (0); 18 | 19 | #define DO_NULLSYSCALL(swi) DO_NULLSYSCALL_OP(swi, seL4_SysBenchmarkNullSyscall) 20 | 21 | #define DO_REAL_NULLSYSCALL() DO_NULLSYSCALL("syscall") 22 | #define DO_NOP_NULLSYSCALL() DO_NULLSYSCALL(".byte 0x66\n.byte 0x90") 23 | -------------------------------------------------------------------------------- /libsel4benchsupport/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | cmake_minimum_required(VERSION 3.16.0) 7 | 8 | project(libsel4benchsupport C) 9 | 10 | file(GLOB deps src/*.c src/arch/${KernelArch}/*.c) 11 | 12 | list(SORT deps) 13 | 14 | add_library(sel4benchsupport EXCLUDE_FROM_ALL ${deps}) 15 | target_include_directories( 16 | sel4benchsupport PUBLIC "include/" "arch_include/${KernelArch}/" 17 | "sel4_arch_include/${KernelSel4Arch}/" 18 | ) 19 | target_link_libraries( 20 | sel4benchsupport 21 | sel4_autoconf 22 | muslc 23 | sel4runtime 24 | sel4allocman 25 | sel4bench 26 | sel4muslcsys 27 | sel4rpc 28 | sel4serialserver 29 | ) 30 | -------------------------------------------------------------------------------- /.github/workflows/hw-tests.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2024, Proofcraft Pty Ltd 2 | # 3 | # SPDX-License-Identifier: BSD-2-Clause 4 | 5 | # sel4test and sel4bench hardware builds and runs 6 | # 7 | # See sel4test-hw/builds.yml and sel4bench-hw/builds.yml in the repo 8 | # seL4/ci-actions for configs. 9 | 10 | name: HW 11 | 12 | on: 13 | # needs PR target for secrets access; guard by requiring label 14 | pull_request_target: 15 | types: [synchronize, labeled] 16 | 17 | jobs: 18 | sel4test: 19 | name: seL4Test 20 | uses: seL4/ci-actions/.github/workflows/sel4test-hw.yml@master 21 | secrets: inherit 22 | 23 | sel4bench: 24 | name: seL4Bench 25 | uses: seL4/ci-actions/.github/workflows/sel4bench-hw.yml@master 26 | with: 27 | always_build: true 28 | secrets: inherit 29 | -------------------------------------------------------------------------------- /apps/sync/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(sync C) 10 | 11 | set(configure_string "") 12 | config_option( 13 | AppSyncBench 14 | APP_SYNCBENCH 15 | "Application to benchmark seL4 sync." 16 | DEFAULT 17 | ON 18 | DEPENDS 19 | "DefaultBenchDeps" 20 | ) 21 | add_config_library(sel4benchsync "${configure_string}") 22 | 23 | file(GLOB deps src/*.c) 24 | list(SORT deps) 25 | add_executable(sync EXCLUDE_FROM_ALL ${deps}) 26 | target_link_libraries( 27 | sync sel4_autoconf sel4benchsync_Config sel4benchsupport sel4sync sel4muslcsys 28 | ) 29 | 30 | if(AppSyncBench) 31 | set_property(GLOBAL APPEND PROPERTY sel4benchapps_property "$") 32 | endif() 33 | -------------------------------------------------------------------------------- /apps/signal/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(signal C) 10 | 11 | set(configure_string "") 12 | config_option( 13 | AppSignalBench 14 | APP_SIGNALBENCH 15 | "Application to benchmark seL4 signals without modification to the kernel." 16 | DEFAULT 17 | ON 18 | DEPENDS 19 | "DefaultBenchDeps" 20 | ) 21 | 22 | add_config_library(sel4benchsignal "${configure_string}") 23 | 24 | file(GLOB deps src/*.c) 25 | list(SORT deps) 26 | add_executable(signal EXCLUDE_FROM_ALL ${deps}) 27 | target_link_libraries(signal sel4_autoconf sel4benchsignal_Config sel4benchsupport sel4muslcsys) 28 | 29 | if(AppSignalBench) 30 | set_property(GLOBAL APPEND PROPERTY sel4benchapps_property "$") 31 | endif() 32 | 33 | general_regs_only(signal) 34 | -------------------------------------------------------------------------------- /apps/sel4bench/src/plat/imx6/plat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | #include "../../env.h" 10 | 11 | #define IMX6_MAX_FREQ (996 * MHZ) 12 | 13 | void plat_setup(env_t *env) 14 | { 15 | /* set to highest cpu freq */ 16 | int error = sel4platsupport_new_io_mapper(&env->vspace, &env->vka, &env->ops.io_mapper); 17 | ZF_LOGF_IF(error != 0, "Failed to get io mapper"); 18 | 19 | clock_sys_t clock; 20 | error = clock_sys_init(&env->ops, &clock); 21 | ZF_LOGF_IF(error != 0, "clock_sys_init failed"); 22 | 23 | clk_t *clk = clk_get_clock(&clock, CLK_ARM); 24 | ZF_LOGF_IF(error != 0, "Failed to get clock"); 25 | 26 | freq_t freq = clk_set_freq(clk, IMX6_MAX_FREQ); 27 | ZF_LOGF_IF(freq != IMX6_MAX_FREQ, "Failed to set imx6 freq"); 28 | } 29 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/irq.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include "benchmark.h" 12 | 13 | #define N_IGNORED 10 14 | #define N_RUNS (100 + N_IGNORED) 15 | 16 | typedef struct irquser_results_t { 17 | ccnt_t overheads[N_RUNS]; 18 | ccnt_t thread_results[N_RUNS]; 19 | ccnt_t process_results[N_RUNS]; 20 | 21 | /* Data for early processing */ 22 | ccnt_t overhead_min; 23 | 24 | ccnt_t thread_results_ep_sum; 25 | ccnt_t thread_results_ep_sum2; 26 | ccnt_t thread_results_ep_num; 27 | ccnt_t thread_results_ep[N_RUNS]; 28 | 29 | ccnt_t process_results_ep_sum; 30 | ccnt_t process_results_ep_sum2; 31 | ccnt_t process_results_ep_num; 32 | ccnt_t process_results_ep[N_RUNS]; 33 | } irquser_results_t; 34 | -------------------------------------------------------------------------------- /apps/sel4bench/src/env.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /* Contains information about the benchmark environment. */ 19 | typedef struct env { 20 | /* An initialised vka that may be used by the test. */ 21 | vka_t vka; 22 | simple_t simple; 23 | vspace_t vspace; 24 | /* regular untyped memory to pass to benchmark apps */ 25 | vka_object_t untyped; 26 | timer_objects_t to; 27 | ps_io_ops_t ops; 28 | } env_t; 29 | 30 | /* do any platform specific set up */ 31 | void plat_setup(env_t *env) WEAK; 32 | int arch_init_timer_irq_cap(env_t *env, cspacepath_t *path); 33 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/riscv/arch/signal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | #include 8 | 9 | #define DO_NTFN_OP(ntfn, swi, syscall) do {\ 10 | register seL4_Word dest asm("a0") = (seL4_Word) ntfn; \ 11 | register seL4_Word scno asm("a7") = syscall; \ 12 | asm volatile (NOPS swi NOPS \ 13 | : /* no outputs */ \ 14 | : "r" (dest), "r"(scno) \ 15 | : /* no clobber */ \ 16 | ); \ 17 | } while (0); 18 | 19 | #ifdef CONFIG_KERNEL_MCS 20 | #define DO_WAIT(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysWait) 21 | #else 22 | #define DO_WAIT(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysRecv) 23 | #endif 24 | #define DO_SIGNAL(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysSend) 25 | 26 | #define DO_REAL_WAIT(ntfn) DO_WAIT(ntfn, "ecall") 27 | #define DO_NOP_WAIT(ntfn) DO_WAIT(ntfn, "nop") 28 | #define DO_REAL_SIGNAL(ntfn) DO_SIGNAL(ntfn, "ecall") 29 | #define DO_NOP_SIGNAL(ntfn) DO_SIGNAL(ntfn, "nop") 30 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/aarch64/sel4_arch/signal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | #include 8 | 9 | #define DO_NTFN_OP(ntfn, swi, syscall) do {\ 10 | register seL4_Word dest asm("x0") = (seL4_Word) ntfn; \ 11 | register seL4_Word scno asm("x7") = syscall; \ 12 | asm volatile (NOPS swi NOPS \ 13 | : /* no outputs */ \ 14 | : "r" (dest), "r"(scno) \ 15 | : /* no clobber */ \ 16 | ); \ 17 | } while (0); 18 | 19 | #ifdef CONFIG_KERNEL_MCS 20 | #define DO_WAIT(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysWait) 21 | #else 22 | #define DO_WAIT(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysRecv) 23 | #endif 24 | #define DO_SIGNAL(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysSend) 25 | 26 | #define DO_REAL_WAIT(ntfn) DO_WAIT(ntfn, "svc #0") 27 | #define DO_NOP_WAIT(ntfn) DO_WAIT(ntfn, "nop") 28 | #define DO_REAL_SIGNAL(ntfn) DO_SIGNAL(ntfn, "svc #0") 29 | #define DO_NOP_SIGNAL(ntfn) DO_SIGNAL(ntfn, "nop") 30 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/aarch32/sel4_arch/signal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #define DO_NTFN_OP(ntfn, swi, syscall) do {\ 11 | register seL4_Word dest asm("r0") = (seL4_Word) ntfn; \ 12 | register seL4_Word scno asm("r7") = syscall; \ 13 | asm volatile (NOPS swi NOPS \ 14 | : /* no outputs */ \ 15 | : "r" (dest), "r"(scno) \ 16 | : /* no clobber */ \ 17 | ); \ 18 | } while (0); 19 | 20 | #ifdef CONFIG_KERNEL_MCS 21 | #define DO_WAIT(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysWait) 22 | #else 23 | #define DO_WAIT(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysRecv) 24 | #endif 25 | #define DO_SIGNAL(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysSend) 26 | 27 | #define DO_REAL_WAIT(ntfn) DO_WAIT(ntfn, "swi $0") 28 | #define DO_NOP_WAIT(ntfn) DO_WAIT(ntfn, "nop") 29 | #define DO_REAL_SIGNAL(ntfn) DO_SIGNAL(ntfn, "swi $0") 30 | #define DO_NOP_SIGNAL(ntfn) DO_SIGNAL(ntfn, "nop") 31 | -------------------------------------------------------------------------------- /apps/hardware/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(hardware C) 10 | 11 | set(configure_string "") 12 | config_option( 13 | AppHardwareBench 14 | APP_HARDWAREBENCH 15 | "Application to benchmark hardware-related operations." 16 | DEFAULT 17 | OFF 18 | DEPENDS 19 | "KernelEnableBenchmarks;DefaultBenchDeps" 20 | ) 21 | add_config_library(hardware "${configure_string}") 22 | 23 | file(GLOB deps src/*.c) 24 | list(SORT deps) 25 | add_executable(hardware EXCLUDE_FROM_ALL ${deps}) 26 | target_link_libraries( 27 | hardware 28 | hardware_Config 29 | sel4 30 | muslc 31 | platsupport 32 | sel4platsupport 33 | sel4benchsupport 34 | elf 35 | sel4utils 36 | sel4simple 37 | sel4bench 38 | utils 39 | sel4debug 40 | sel4muslcsys 41 | ) 42 | if(AppHardwareBench) 43 | set_property(GLOBAL APPEND PROPERTY sel4benchapps_property "$") 44 | endif() 45 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/sel4benchsupport/signal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #define N_IGNORED 10 12 | #define N_RUNS (100 + N_IGNORED) 13 | 14 | typedef struct signal_results { 15 | /* Data for late processing */ 16 | ccnt_t lo_prio_results[N_RUNS]; 17 | ccnt_t hi_prio_results[N_RUNS]; 18 | ccnt_t hi_prio_average[N_RUNS][NUM_AVERAGE_EVENTS]; 19 | ccnt_t overhead[N_RUNS]; /* "overhead" is used by early processing as well */ 20 | /* Data for early processing */ 21 | ccnt_t lo_sum; /* sum of samples */ 22 | ccnt_t lo_sum2; /* sum of squared samples */ 23 | ccnt_t lo_num; /* number of samples to process */ 24 | ccnt_t overhead_min; /* min overhead found in "overhead" array */ 25 | /* array required by report output function 26 | Zeros, but can be used for diagnostic data */ 27 | ccnt_t diag_results[N_RUNS]; /* array required by report output function */ 28 | } signal_results_t; 29 | -------------------------------------------------------------------------------- /apps/scheduler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(scheduler C) 10 | 11 | set(configure_string "") 12 | config_option( 13 | AppSchedulerBench 14 | APP_SCHEDULERBENCH 15 | "Application to benchmark seL4 scheduler without modification to the kernel." 16 | DEFAULT 17 | ON 18 | DEPENDS 19 | "DefaultBenchDeps" 20 | ) 21 | add_config_library(sel4benchscheduler "${configure_string}") 22 | 23 | file(GLOB deps src/*.c) 24 | list(SORT deps) 25 | add_executable(scheduler EXCLUDE_FROM_ALL ${deps}) 26 | target_link_libraries( 27 | scheduler 28 | sel4_autoconf 29 | sel4benchscheduler_Config 30 | sel4 31 | muslc 32 | sel4vka 33 | sel4allocman 34 | sel4utils 35 | sel4simple 36 | sel4muslcsys 37 | sel4platsupport 38 | platsupport 39 | sel4vspace 40 | sel4benchsupport 41 | sel4debug 42 | ) 43 | 44 | if(AppSchedulerBench) 45 | set_property(GLOBAL APPEND PROPERTY sel4benchapps_property "$") 46 | endif() 47 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/ia32/sel4_arch/signal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #define DO_NTFN_OP(ntfn, sys, syscall) do {\ 11 | uint32_t ep_copy = ntfn; \ 12 | asm volatile ( \ 13 | "movl %%esp, %%ecx \n" \ 14 | "leal 1f, %%edx \n" \ 15 | "1: \n" \ 16 | sys" \n" \ 17 | : "+b" (ep_copy) \ 18 | : "a" (syscall) \ 19 | : "ecx", "edx" \ 20 | ); \ 21 | } while (0); 22 | 23 | #ifdef CONFIG_KERNEL_MCS 24 | #define DO_WAIT(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysWait) 25 | #else 26 | #define DO_WAIT(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysRecv) 27 | #endif 28 | #define DO_SIGNAL(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysSend) 29 | 30 | #define DO_REAL_WAIT(ntfn) DO_WAIT(ntfn, "sysenter") 31 | #define DO_NOP_WAIT(ntfn) DO_WAIT(ntfn, ".byte 0x66\n.byte 0x90") 32 | #define DO_REAL_SIGNAL(ntfn) DO_SIGNAL(ntfn, "sysenter") 33 | #define DO_NOP_SIGNAL(ntfn) DO_SIGNAL(ntfn, ".byte 0x66\n.byte 0x90") 34 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is furnished 10 | to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 18 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 20 | OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/riscv/arch/fault.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #define READ_COUNTER_BEFORE SEL4BENCH_READ_CCNT 11 | #define READ_COUNTER_AFTER SEL4BENCH_READ_CCNT 12 | 13 | #ifdef CONFIG_KERNEL_MCS 14 | static inline seL4_MessageInfo_t seL4_RecvWith1MR(seL4_CPtr src, seL4_Word *mr0, seL4_CPtr reply) 15 | { 16 | return seL4_RecvWithMRs(src, NULL, reply, mr0, NULL, NULL, NULL); 17 | } 18 | 19 | static inline void seL4_ReplyWith1MR(seL4_Word mr0, seL4_CPtr dest) 20 | { 21 | return seL4_SendWithMRs(dest, seL4_MessageInfo_new(0, 0, 0, 1), &mr0, NULL, NULL, NULL); 22 | } 23 | #else 24 | static inline seL4_MessageInfo_t seL4_RecvWith1MR(seL4_CPtr src, seL4_Word *mr0, UNUSED seL4_CPtr reply) 25 | { 26 | return seL4_RecvWithMRs(src, NULL, mr0, NULL, NULL, NULL); 27 | } 28 | 29 | static inline void seL4_ReplyWith1MR(seL4_Word mr0, UNUSED seL4_CPtr dest) 30 | { 31 | return seL4_ReplyWithMRs(seL4_MessageInfo_new(0, 0, 0, 1), &mr0, NULL, NULL, NULL); 32 | } 33 | #endif /* CONFIG_KERNEL_MCS */ 34 | -------------------------------------------------------------------------------- /apps/irquser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(irquser C) 10 | 11 | set(configure_string "") 12 | config_option( 13 | AppIrqUserBench 14 | APP_IRQUSERBENCH 15 | "Application to benchmark seL4 IRQs without modification to the kernel." 16 | DEFAULT 17 | ON 18 | DEPENDS 19 | "DefaultBenchDeps" 20 | ) 21 | add_config_library(sel4benchirquser "${configure_string}") 22 | 23 | file(GLOB deps src/*.c) 24 | list(SORT deps) 25 | add_executable(irquser EXCLUDE_FROM_ALL ${deps}) 26 | target_link_libraries( 27 | irquser 28 | sel4_autoconf 29 | sel4benchirquser_Config 30 | sel4 31 | muslc 32 | sel4vka 33 | sel4allocman 34 | sel4utils 35 | sel4simple 36 | sel4muslcsys 37 | sel4platsupport 38 | platsupport 39 | sel4vspace 40 | sel4benchsupport 41 | sel4debug 42 | ) 43 | 44 | if(AppIrqUserBench) 45 | set_property(GLOBAL APPEND PROPERTY sel4benchapps_property "$") 46 | endif() 47 | 48 | general_regs_only(irquser) 49 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/smp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #if CONFIG_MAX_NUM_NODES > 1 13 | #include 14 | #endif 15 | 16 | #define WARMUPS 2 17 | #define RUNS 5 18 | #define TESTS ARRAY_SIZE(smp_benchmark_params) 19 | 20 | typedef struct benchmark_params { 21 | const char *name; 22 | const double delay; 23 | } benchmark_params_t; 24 | 25 | static const 26 | benchmark_params_t smp_benchmark_params[] = { 27 | { .name = "500 cycles", .delay = 500.000, }, 28 | { .name = "1000 cycles", .delay = 1000.00, }, 29 | { .name = "2000 cycles", .delay = 2000.00, }, 30 | { .name = "4000 cycles", .delay = 4000.00, }, 31 | { .name = "8000 cycles", .delay = 8000.00, }, 32 | { .name = "16000 cycles", .delay = 16000.0, }, 33 | { .name = "32000 cycles", .delay = 32000.0, }, 34 | }; 35 | 36 | typedef struct smp_results { 37 | ccnt_t benchmarks_result[TESTS][CONFIG_MAX_NUM_NODES][RUNS]; 38 | } smp_results_t; 39 | -------------------------------------------------------------------------------- /apps/smp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(smp C) 10 | 11 | set(KernelMaxNumNodesGreaterThan1 (KernelMaxNumNodes GREATER \"1\")) 12 | set(configure_string "") 13 | config_option( 14 | AppSmpBench 15 | APP_SMPBENCH 16 | "Enable SMP benchmarks" 17 | DEFAULT 18 | OFF 19 | DEPENDS 20 | "DefaultBenchDeps;KernelMaxNumNodesGreaterThan1" 21 | ) 22 | add_config_library(smp "${configure_string}") 23 | 24 | file(GLOB deps src/*.c) 25 | add_executable(smp EXCLUDE_FROM_ALL ${deps}) 26 | target_link_libraries( 27 | smp 28 | sel4_autoconf 29 | smp_Config 30 | muslc 31 | sel4 32 | sel4benchsupport 33 | sel4platsupport 34 | sel4muslcsys 35 | jansson 36 | sel4sync 37 | sel4debug 38 | sel4allocman 39 | utils 40 | sel4utils 41 | sel4bench 42 | elf 43 | sel4simple 44 | cpio 45 | sel4vka 46 | sel4vspace 47 | ) 48 | 49 | if(AppSmpBench) 50 | set_property(GLOBAL APPEND PROPERTY sel4benchapps_property "$") 51 | endif() 52 | -------------------------------------------------------------------------------- /apps/vcpu/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(vcpu C) 10 | 11 | set(configure_string "") 12 | config_option( 13 | AppVcpuBench 14 | APP_VCPU_BENCH 15 | "Application to benchmark seL4 VCPU performance." 16 | DEFAULT 17 | OFF 18 | DEPENDS 19 | "DefaultBenchDeps;KernelSel4ArchAarch64;KernelArmHypervisorSupport;KernelBenchmarksTrackKernelEntries" 20 | ) 21 | add_config_library(sel4benchvcpu "${configure_string}") 22 | 23 | file(GLOB deps src/*.c src/guest_asm.S) 24 | list(SORT deps) 25 | add_executable(vcpu EXCLUDE_FROM_ALL ${deps}) 26 | target_link_libraries( 27 | vcpu 28 | sel4_autoconf 29 | sel4benchvcpu_Config 30 | sel4 31 | muslc 32 | cpio 33 | sel4vka 34 | sel4vspace 35 | sel4allocman 36 | sel4utils 37 | elf 38 | sel4simple 39 | sel4benchsupport 40 | sel4debug 41 | platsupport 42 | sel4platsupport 43 | sel4muslcsys 44 | ) 45 | 46 | if(AppVcpuBench) 47 | set_property(GLOBAL APPEND PROPERTY sel4benchapps_property "$") 48 | endif() 49 | -------------------------------------------------------------------------------- /apps/page_mapping/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(page_mapping C) 10 | 11 | set(configure_string "") 12 | config_option( 13 | AppPageMappingBench 14 | APP_PAGEMAPPINGBENCH 15 | "Application to benchmark seL4 mapping a series of pages." 16 | DEFAULT 17 | ON 18 | DEPENDS 19 | "DefaultBenchDeps" 20 | ) 21 | add_config_library(sel4benchpagemapping "${configure_string}") 22 | 23 | file(GLOB deps src/*.c) 24 | list(SORT deps) 25 | add_executable(page_mapping EXCLUDE_FROM_ALL ${deps}) 26 | target_link_libraries( 27 | page_mapping 28 | sel4_autoconf 29 | sel4benchpagemapping_Config 30 | sel4 31 | muslc 32 | cpio 33 | sel4vka 34 | sel4vspace 35 | sel4allocman 36 | sel4utils 37 | sel4muslcsys 38 | elf 39 | sel4simple 40 | sel4bench 41 | sel4benchsupport 42 | sel4debug 43 | platsupport 44 | sel4platsupport 45 | ) 46 | 47 | if(AppPageMappingBench) 48 | set_property(GLOBAL APPEND PROPERTY sel4benchapps_property "$") 49 | endif() 50 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/arm/arch/fault.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define READ_COUNTER_BEFORE SEL4BENCH_READ_CCNT 13 | #define READ_COUNTER_AFTER SEL4BENCH_READ_CCNT 14 | 15 | #ifdef CONFIG_KERNEL_MCS 16 | static inline seL4_MessageInfo_t seL4_RecvWith1MR(seL4_CPtr src, seL4_Word *mr0, seL4_CPtr reply) 17 | { 18 | return seL4_RecvWithMRs(src, NULL, reply, mr0, NULL, NULL, NULL); 19 | } 20 | 21 | static inline void seL4_ReplyWith1MR(seL4_Word mr0, seL4_CPtr dest) 22 | { 23 | return seL4_SendWithMRs(dest, seL4_MessageInfo_new(0, 0, 0, 1), &mr0, NULL, NULL, NULL); 24 | } 25 | #else 26 | static inline seL4_MessageInfo_t seL4_RecvWith1MR(seL4_CPtr src, seL4_Word *mr0, UNUSED seL4_CPtr reply) 27 | { 28 | return seL4_RecvWithMRs(src, NULL, mr0, NULL, NULL, NULL); 29 | } 30 | 31 | static inline void seL4_ReplyWith1MR(seL4_Word mr0, UNUSED seL4_CPtr dest) 32 | { 33 | return seL4_ReplyWithMRs(seL4_MessageInfo_new(0, 0, 0, 1), &mr0, NULL, NULL, NULL); 34 | } 35 | #endif /* CONFIG_KERNEL_MCS */ 36 | -------------------------------------------------------------------------------- /apps/sel4bench/src/math.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "benchmark.h" 10 | 11 | result_t calculate_results(const size_t n, ccnt_t data[n]); 12 | 13 | /* 14 | * The function calculates parameters of array elements received from 15 | * a benchmark which used early processing methodology 16 | * @param num - number of samples 17 | * @param sum - sum of samples 18 | * @param sum2 - sum of squared samples 19 | * @param array - array of raw data which are zeros for Early Processing methodology 20 | * but the array is required for results output function 21 | */ 22 | result_t calculate_results_early_proc(ccnt_t num, ccnt_t sum, ccnt_t sum2, 23 | ccnt_t array[num]); 24 | 25 | /* The function calculates variance using sum, sum of squared values and mean 26 | * @param num - number of samples 27 | * @param sum - sum of samples 28 | * @param sum2 - sum of squared samples 29 | * @param mean - mean of the samples 30 | */ 31 | static double results_variance_early_proc(const size_t num, const ccnt_t sum, 32 | const ccnt_t sum2, const ccnt_t mean); 33 | -------------------------------------------------------------------------------- /libsel4benchsupport/src/arch/arm/support.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include "../../support.h" 17 | 18 | static seL4_Error get_irq_trigger(void *data, int irq, int trigger, int core, seL4_CNode cnode, 19 | seL4_Word index, uint8_t depth) 20 | { 21 | env_t *env = data; 22 | 23 | RpcMessage msg = { 24 | .which_msg = RpcMessage_irq_tag, 25 | .msg.irq = { 26 | .which_type = IrqAllocMessage_simple_tag, 27 | .type.simple = { 28 | .setTrigger = true, 29 | .irq = irq, 30 | .trigger = trigger, 31 | }, 32 | }, 33 | }; 34 | 35 | int ret = sel4rpc_call(&env->rpc_client, &msg, cnode, index, depth); 36 | if (ret) { 37 | return ret; 38 | } 39 | 40 | return msg.msg.ret.errorCode; 41 | } 42 | 43 | void benchmark_arch_get_simple(arch_simple_t *simple) 44 | { 45 | simple->irq_trigger = get_irq_trigger; 46 | } 47 | -------------------------------------------------------------------------------- /libsel4benchsupport/src/arch/riscv/support.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include "../../support.h" 17 | 18 | static seL4_Error get_irq_trigger(void *data, int irq, int trigger, int core, seL4_CNode cnode, 19 | seL4_Word index, uint8_t depth) 20 | { 21 | env_t *env = data; 22 | 23 | RpcMessage msg = { 24 | .which_msg = RpcMessage_irq_tag, 25 | .msg.irq = { 26 | .which_type = IrqAllocMessage_simple_tag, 27 | .type.simple = { 28 | .setTrigger = true, 29 | .irq = irq, 30 | .trigger = trigger, 31 | }, 32 | }, 33 | }; 34 | 35 | int ret = sel4rpc_call(&env->rpc_client, &msg, cnode, index, depth); 36 | if (ret) { 37 | return ret; 38 | } 39 | 40 | return msg.msg.ret.errorCode; 41 | } 42 | 43 | void benchmark_arch_get_simple(arch_simple_t *simple) 44 | { 45 | simple->irq_trigger = get_irq_trigger; 46 | } 47 | -------------------------------------------------------------------------------- /apps/fault/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(fault C) 10 | 11 | set(configure_string "") 12 | config_option( 13 | AppFaultBench 14 | APP_FAULTBENCH 15 | "Application to benchmark seL4 faults without modification to the kernel." 16 | DEFAULT 17 | OFF 18 | DEPENDS 19 | "DefaultBenchDeps" 20 | ) 21 | add_config_library(sel4benchfault "${configure_string}") 22 | 23 | file(GLOB deps src/*.c) 24 | list(SORT deps) 25 | add_executable(fault EXCLUDE_FROM_ALL ${deps}) 26 | if("${PLATFORM}" STREQUAL "sabre") 27 | target_compile_options(fault PRIVATE -O1) 28 | endif() 29 | target_link_libraries( 30 | fault 31 | sel4_autoconf 32 | sel4benchfault_Config 33 | sel4 34 | sel4bench 35 | muslc 36 | sel4vka 37 | utils 38 | elf 39 | sel4allocman 40 | sel4utils 41 | sel4simple 42 | sel4muslcsys 43 | sel4platsupport 44 | platsupport 45 | sel4vspace 46 | sel4benchsupport 47 | sel4debug 48 | ) 49 | 50 | if(AppFaultBench) 51 | set_property(GLOBAL APPEND PROPERTY sel4benchapps_property "$") 52 | endif() 53 | 54 | general_regs_only(fault) 55 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/fault.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #define N_IGNORED 10 11 | #define N_RUNS (100 + N_IGNORED) 12 | 13 | typedef struct { 14 | ccnt_t reply_recv_overhead[N_RUNS]; 15 | ccnt_t ccnt_overhead[N_RUNS]; 16 | 17 | /* we ignore the last result for the following, 18 | * but need to be able to write to the buffer without 19 | * overriding anything, 20 | * so add 1 to the number recorded */ 21 | ccnt_t round_trip[N_RUNS + 1]; 22 | ccnt_t fault[N_RUNS + 1]; 23 | ccnt_t fault_reply[N_RUNS + 1]; 24 | 25 | /* Data for early processing */ 26 | ccnt_t round_trip_ep_sum; 27 | ccnt_t round_trip_ep_sum2; 28 | ccnt_t round_trip_ep_num; 29 | ccnt_t round_trip_ep_min_overhead; 30 | ccnt_t round_trip_ep[N_RUNS]; 31 | 32 | ccnt_t fault_ep_sum; 33 | ccnt_t fault_ep_sum2; 34 | ccnt_t fault_ep_num; 35 | ccnt_t fault_ep_min_overhead; 36 | ccnt_t fault_ep[N_RUNS]; 37 | 38 | ccnt_t fault_reply_ep_sum; 39 | ccnt_t fault_reply_ep_sum2; 40 | ccnt_t fault_reply_ep_num; 41 | ccnt_t fault_reply_ep_min_overhead; 42 | ccnt_t fault_reply_ep[N_RUNS]; 43 | } fault_results_t; 44 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/x86_64/sel4_arch/signal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #ifdef CONFIG_SYSCALL 12 | 13 | #define DO_NTFN_OP(ntfn, sys, syscall) do {\ 14 | uint64_t ep_copy = ntfn; \ 15 | asm volatile ( \ 16 | "movq %%rsp, %%rbx \n" \ 17 | sys " \n" \ 18 | "movq %%rbx, %%rsp \n" \ 19 | : "+D" (ep_copy) \ 20 | : "d" ((seL4_Word)syscall) \ 21 | : "%rcx", "%rbx", "%r11" \ 22 | ); \ 23 | } while (0); 24 | 25 | #ifdef CONFIG_KERNEL_MCS 26 | #define DO_WAIT(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysWait) 27 | #else 28 | #define DO_WAIT(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysRecv) 29 | #endif 30 | #define DO_SIGNAL(ntfn, swi) DO_NTFN_OP(ntfn, swi, seL4_SysSend) 31 | 32 | #define DO_REAL_WAIT(ntfn) DO_WAIT(ntfn, "syscall") 33 | #define DO_NOP_WAIT(ntfn) DO_WAIT(ntfn, ".byte 0x66\n.byte 0x90") 34 | #define DO_REAL_SIGNAL(ntfn) DO_SIGNAL(ntfn, "syscall") 35 | #define DO_NOP_SIGNAL(ntfn) DO_SIGNAL(ntfn, ".byte 0x66\n.byte 0x90") 36 | 37 | #else 38 | #error Only support benchmarking with syscall as sysenter is known to be slower 39 | #endif /* CONFIG_SYSCALL */ 40 | -------------------------------------------------------------------------------- /LICENSES/BSD-2-Clause.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 22 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Contributions Welcome 8 | 9 | Please see the [seL4 contributing guidelines][1] on the [seL4 website][2] for 10 | details. 11 | 12 | [1]: https://docs.sel4.systems/processes/contributing.html 13 | [2]: https://sel4.systems 14 | 15 | 16 | ## Contact 17 | 18 | If you have larger changes or additions, it is a good idea to get in contact 19 | with us as , so we can help you get started. 20 | 21 | The people responsible for the technical direction, procedures, and quality 22 | control are the [Technical Steering Committee][3] (TSC) of the seL4 23 | foundation. You can contact them either on the developer mailing list or on 24 | directly via email available from their profile pages. 25 | 26 | [3]: https://sel4.systems/Foundation/TSC 27 | 28 | 29 | ## Developer Certificate of Origin (DCO) 30 | 31 | This repository uses the same sign-off process as the Linux kernel. For every 32 | commit, use 33 | 34 | git commit -s 35 | 36 | to add a sign-off line to your commit message, which will come out as: 37 | 38 | Signed-off-by: name 39 | 40 | By adding this line, you make the declaration that you have the right to make 41 | this contribution under the open source license the files use that you changed 42 | or contributed. 43 | 44 | The full text of the declaration is at . 45 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/aarch32/sel4_arch/fault.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #ifdef CONFIG_KERNEL_MCS 11 | #define DO_REPLY_RECV_1(ep, ip, ro, swi) do { \ 12 | seL4_MessageInfo_t m = seL4_MessageInfo_new(0, 0, 0, 1); \ 13 | register seL4_Word src asm("r0") = (seL4_Word)ep; \ 14 | register seL4_Word info asm("r1") = m.words[0]; \ 15 | register seL4_Word scno asm("r7") = seL4_SysReplyRecv; \ 16 | register seL4_Word ro_copy asm("r6") = (seL4_Word) ro; \ 17 | register seL4_Word mr0 asm("r2") = ip; \ 18 | asm volatile(NOPS swi NOPS \ 19 | : "+r"(src), "+r"(info), "+r" (mr0) \ 20 | : "r"(scno), "r" (ro_copy)\ 21 | : "r3", "r4", "r5" \ 22 | ); \ 23 | ip = mr0; \ 24 | } while(0) 25 | 26 | 27 | #else 28 | #define DO_REPLY_RECV_1(ep, ip, ro, swi) do { \ 29 | seL4_MessageInfo_t m = seL4_MessageInfo_new(0, 0, 0, 1); \ 30 | register seL4_Word src asm("r0") = (seL4_Word)ep; \ 31 | register seL4_Word info asm("r1") = m.words[0]; \ 32 | register seL4_Word scno asm("r7") = seL4_SysReplyRecv; \ 33 | register seL4_Word mr0 asm("r2") = ip; \ 34 | asm volatile(NOPS swi NOPS \ 35 | : "+r"(src), "+r"(info), "+r" (mr0) \ 36 | : "r"(scno) \ 37 | : "r3", "r4", "r5" \ 38 | ); \ 39 | ip = mr0; \ 40 | } while(0) 41 | #endif /* CONFIG_KERNEL_MCS */ 42 | 43 | #define DO_REAL_REPLY_RECV_1(ep, mr0, ro) DO_REPLY_RECV_1(ep, mr0, ro, "swi $0") 44 | #define DO_NOP_REPLY_RECV_1(ep, mr0, ro) DO_REPLY_RECV_1(ep, mr0, ro, "nop") 45 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/aarch64/sel4_arch/fault.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #ifdef CONFIG_KERNEL_MCS 11 | #define DO_REPLY_RECV_1(ep, ip, ro, swi) do { \ 12 | seL4_MessageInfo_t m = seL4_MessageInfo_new(0, 0, 0, 1); \ 13 | register seL4_Word src asm("x0") = (seL4_Word)ep; \ 14 | register seL4_Word info asm("x1") = m.words[0]; \ 15 | register seL4_Word scno asm("x7") = seL4_SysReplyRecv; \ 16 | register seL4_Word ro_copy asm("x6") = (seL4_Word) ro; \ 17 | register seL4_Word mr0 asm("x2") = ip; \ 18 | asm volatile(NOPS swi NOPS \ 19 | : "+r"(src), "+r"(info), "+r" (mr0) \ 20 | : "r"(scno), "r" (ro_copy)\ 21 | : "x3", "x4", "x5" \ 22 | ); \ 23 | ip = mr0; \ 24 | } while(0) 25 | 26 | 27 | #else 28 | #define DO_REPLY_RECV_1(ep, ip, ro, swi) do { \ 29 | seL4_MessageInfo_t m = seL4_MessageInfo_new(0, 0, 0, 1); \ 30 | register seL4_Word src asm("x0") = (seL4_Word)ep; \ 31 | register seL4_Word info asm("x1") = m.words[0]; \ 32 | register seL4_Word scno asm("x7") = seL4_SysReplyRecv; \ 33 | register seL4_Word mr0 asm("x2") = ip; \ 34 | asm volatile(NOPS swi NOPS \ 35 | : "+r"(src), "+r"(info), "+r" (mr0) \ 36 | : "r"(scno) \ 37 | : "x3", "x4", "x5" \ 38 | ); \ 39 | ip = mr0; \ 40 | } while(0) 41 | 42 | #endif /* CONFIG_KERNEL_MCS */ 43 | 44 | #define DO_REAL_REPLY_RECV_1(ep, mr0, ro) DO_REPLY_RECV_1(ep, mr0, ro, "svc #0") 45 | #define DO_NOP_REPLY_RECV_1(ep, mr0, ro) DO_REPLY_RECV_1(ep, mr0, ro, "nop") 46 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/sync.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #define N_IGNORED 5 11 | #define N_RUNS (50 + N_IGNORED) 12 | #define N_WAITERS 25 13 | 14 | #define FIFO_SIZE 1 15 | 16 | #define N_BROADCAST_BENCHMARKS 1 17 | #define N_PROD_CONS_BENCHMARKS 1 18 | 19 | /* Key: 20 | * A - use (A)tomics instead of taking the lock after wake up 21 | * B - use lock release before signal in (B)roadcast 22 | * C - use (C)ombined syscals (SignalRecv) 23 | */ 24 | 25 | const char *broadcast_wait_names[] = { 26 | "Wait time" 27 | }; 28 | 29 | const char *broadcast_broadcast_names[] = { 30 | "Broadcast time" 31 | }; 32 | 33 | const char *producer_to_consumer_names[] = { 34 | "Producer to consumer" 35 | }; 36 | 37 | const char *consumer_to_producer_names[] = { 38 | "Consumer to producer" 39 | }; 40 | 41 | typedef struct sync_results { 42 | ccnt_t broadcast_wait_time[N_BROADCAST_BENCHMARKS][N_WAITERS][N_RUNS]; 43 | ccnt_t broadcast_broadcast_time[N_BROADCAST_BENCHMARKS][N_RUNS]; 44 | 45 | ccnt_t producer_to_consumer[N_PROD_CONS_BENCHMARKS][N_RUNS]; 46 | ccnt_t consumer_to_producer[N_PROD_CONS_BENCHMARKS][N_RUNS]; 47 | 48 | /* Data for early processing */ 49 | ccnt_t producer_to_consumer_ep_sum; 50 | ccnt_t producer_to_consumer_ep_sum2; 51 | ccnt_t producer_to_consumer_ep_num; 52 | ccnt_t producer_to_consumer_ep[N_RUNS]; 53 | 54 | ccnt_t consumer_to_producer_ep_sum; 55 | ccnt_t consumer_to_producer_ep_sum2; 56 | ccnt_t consumer_to_producer_ep_num; 57 | ccnt_t consumer_to_producer_ep[N_RUNS]; 58 | } sync_results_t; 59 | 60 | typedef void (*helper_func_t)(int argc, char *argv[]); 61 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/scheduler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #define N_IGNORED 10 12 | #define N_RUNS (100 + N_IGNORED) 13 | #define N_PRIOS ((seL4_MaxPrio + seL4_WordBits - 1) / seL4_WordBits) 14 | 15 | typedef struct scheduler_results_t { 16 | ccnt_t thread_results[N_PRIOS][N_RUNS]; 17 | ccnt_t process_results[N_PRIOS][N_RUNS]; 18 | ccnt_t overhead_signal[N_RUNS]; 19 | ccnt_t set_prio_average[N_RUNS][NUM_AVERAGE_EVENTS]; 20 | 21 | ccnt_t thread_yield[N_RUNS]; 22 | ccnt_t process_yield[N_RUNS]; 23 | ccnt_t overhead_ccnt[N_RUNS]; 24 | ccnt_t average_yield[N_RUNS][NUM_AVERAGE_EVENTS]; 25 | 26 | /* Data for early processing */ 27 | ccnt_t overhead_ccnt_min; 28 | 29 | ccnt_t thread_yield_ep_sum; 30 | ccnt_t thread_yield_ep_sum2; 31 | ccnt_t thread_yield_ep_num; 32 | ccnt_t thread_yield_ep[N_RUNS]; 33 | 34 | ccnt_t process_yield_ep_sum; 35 | ccnt_t process_yield_ep_sum2; 36 | ccnt_t process_yield_ep_num; 37 | ccnt_t process_yield_ep[N_RUNS]; 38 | } scheduler_results_t; 39 | 40 | static inline uint8_t gen_next_prio(int i) 41 | { 42 | /* for the master seL4 kernel, the only thing that effects the length of a 43 | * schedule call is how far apart the two prios are that we are switching between. 44 | * 45 | * So for this benchmark we record the amount of time taken for a 46 | * seL4_Signal to take place, causing a higher priority thread to run. 47 | * 48 | * Since the scheduler hits a different word in the 2nd level bitmap every wordBits 49 | * priority, we only test each wordBits prio. 50 | */ 51 | return seL4_MinPrio + 1 + (i * seL4_WordBits); 52 | } 53 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/arm/arch/smp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #define CACHE_LN_SZ 32 13 | #define OVERHEAD_MEAS_RUNS 16 14 | 15 | #define READ_CYCLE_COUNTER(_r) do { \ 16 | SEL4BENCH_READ_CCNT(_r); \ 17 | } while(0) 18 | #define RESET_CYCLE_COUNTER SEL4BENCH_RESET_CCNT 19 | #define OVERHEAD_FIXUP(_c, _o) ((_c) - (_o)) 20 | 21 | static inline void smp_benchmark_ping(seL4_CPtr ep) 22 | { 23 | seL4_CallWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL, NULL); 24 | } 25 | 26 | static inline void smp_benchmark_pong(seL4_CPtr ep, seL4_CPtr reply) 27 | { 28 | #if CONFIG_KERNEL_MCS 29 | seL4_ReplyRecvWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL, NULL, NULL, reply); 30 | #else 31 | seL4_ReplyRecvWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL, NULL, NULL); 32 | #endif 33 | } 34 | 35 | static inline ccnt_t smp_benchmark_check_overhead(void) 36 | { 37 | uint32_t ccnt_overhead; 38 | uint32_t begin, end, total = 0; 39 | 40 | sel4bench_init(); 41 | for (int i = 0; i < OVERHEAD_MEAS_RUNS; i++) { 42 | COMPILER_MEMORY_FENCE(); 43 | READ_CYCLE_COUNTER(begin); 44 | 45 | READ_CYCLE_COUNTER(end); 46 | COMPILER_MEMORY_FENCE(); 47 | total += (end - begin); 48 | } 49 | ccnt_overhead = total / OVERHEAD_MEAS_RUNS; 50 | total = 0; 51 | for (int i = 0; i < OVERHEAD_MEAS_RUNS; i++) { 52 | COMPILER_MEMORY_FENCE(); 53 | RESET_CYCLE_COUNTER; 54 | 55 | READ_CYCLE_COUNTER(end); 56 | COMPILER_MEMORY_FENCE(); 57 | total += (end - ccnt_overhead); 58 | } 59 | sel4bench_destroy(); 60 | 61 | return total / OVERHEAD_MEAS_RUNS; 62 | } 63 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/riscv/arch/smp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #define CACHE_LN_SZ 32 13 | #define OVERHEAD_MEAS_RUNS 16 14 | 15 | #define READ_CYCLE_COUNTER(_r) do { \ 16 | SEL4BENCH_READ_CCNT(_r); \ 17 | } while(0) 18 | #define RESET_CYCLE_COUNTER SEL4BENCH_RESET_CCNT 19 | #define OVERHEAD_FIXUP(_c, _o) ((_c) - (_o)) 20 | 21 | static inline void smp_benchmark_ping(seL4_CPtr ep) 22 | { 23 | seL4_CallWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL, NULL); 24 | } 25 | 26 | static inline void smp_benchmark_pong(seL4_CPtr ep, seL4_CPtr reply) 27 | { 28 | #if CONFIG_KERNEL_MCS 29 | seL4_ReplyRecvWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL, NULL, NULL, reply); 30 | #else 31 | seL4_ReplyRecvWithMRs(ep, seL4_MessageInfo_new(0, 0, 0, 0), NULL, NULL, NULL, NULL, NULL); 32 | #endif 33 | } 34 | 35 | static inline ccnt_t smp_benchmark_check_overhead(void) 36 | { 37 | uint32_t ccnt_overhead; 38 | uint32_t begin, end, total = 0; 39 | 40 | sel4bench_init(); 41 | for (int i = 0; i < OVERHEAD_MEAS_RUNS; i++) { 42 | COMPILER_MEMORY_FENCE(); 43 | READ_CYCLE_COUNTER(begin); 44 | 45 | READ_CYCLE_COUNTER(end); 46 | COMPILER_MEMORY_FENCE(); 47 | total += (end - begin); 48 | } 49 | ccnt_overhead = total / OVERHEAD_MEAS_RUNS; 50 | total = 0; 51 | for (int i = 0; i < OVERHEAD_MEAS_RUNS; i++) { 52 | COMPILER_MEMORY_FENCE(); 53 | RESET_CYCLE_COUNTER; 54 | 55 | READ_CYCLE_COUNTER(end); 56 | COMPILER_MEMORY_FENCE(); 57 | total += (end - ccnt_overhead); 58 | } 59 | sel4bench_destroy(); 60 | 61 | return total / OVERHEAD_MEAS_RUNS; 62 | } 63 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/page_mapping.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #define RUNS 16 13 | #define TESTS ARRAY_SIZE(page_mapping_benchmark_params) 14 | #define NPHASE ARRAY_SIZE(phase_name) 15 | 16 | typedef struct benchmark_params { 17 | /* name of the function we are benchmarking */ 18 | const char *name; 19 | const int npage; 20 | } benchmark_params_t; 21 | 22 | /* array of benchmarks to run */ 23 | static const 24 | benchmark_params_t page_mapping_benchmark_params[] = { 25 | { 26 | .name = "map 1", 27 | .npage = 1, 28 | }, 29 | { 30 | .name = "map 2", 31 | .npage = 2, 32 | }, 33 | { 34 | .name = "map 4", 35 | .npage = 4, 36 | }, 37 | { 38 | .name = "map 8", 39 | .npage = 8, 40 | }, 41 | { 42 | .name = "map 16", 43 | .npage = 16, 44 | }, 45 | { 46 | .name = "map 32", 47 | .npage = 32, 48 | }, 49 | { 50 | .name = "map 64", 51 | .npage = 64, 52 | }, 53 | { 54 | .name = "map 128", 55 | .npage = 128, 56 | }, 57 | { 58 | .name = "map 256", 59 | .npage = 256, 60 | }, 61 | { 62 | .name = "map 512", 63 | .npage = 512, 64 | }, 65 | { 66 | .name = "map 1024", 67 | .npage = 1024, 68 | }, 69 | { 70 | .name = "map 2048", 71 | .npage = 2048, 72 | }, 73 | }; 74 | 75 | char *phase_name[] = { 76 | "Prepare Page Tables", 77 | "Allocate Pages", 78 | "Mapping", 79 | "Protect Pages as Read Only", 80 | "Unprotect Pages" 81 | }; 82 | 83 | typedef struct page_mapping_results { 84 | /* Raw results from benchmarking. These get checked for sanity */ 85 | ccnt_t overhead_benchmarks[RUNS]; 86 | ccnt_t benchmarks_result[TESTS][NPHASE][RUNS]; 87 | } page_mapping_results_t; 88 | -------------------------------------------------------------------------------- /apps/sel4bench/src/hardware.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include "benchmark.h" 7 | #include "processing.h" 8 | #include "json.h" 9 | 10 | #include 11 | #include 12 | 13 | static json_t *hardware_process(void *results) 14 | { 15 | hardware_results_t *raw_results = results; 16 | 17 | result_desc_t desc = { 18 | .stable = false, 19 | .name = "Nop syscall overhead", 20 | .ignored = N_IGNORED 21 | }; 22 | 23 | result_t nopnulsyscall_result = process_result(N_RUNS, raw_results->nullSyscall_overhead, desc); 24 | 25 | /* Execlude ccnt, user-level and loop overheads */ 26 | desc.overhead = nopnulsyscall_result.min; 27 | 28 | result_t result = process_result(N_RUNS, raw_results->nullSyscall_results, desc); 29 | 30 | result_set_t set = { 31 | .name = "Hardware null_syscall thread", 32 | .n_results = 1, 33 | .n_extra_cols = 0, 34 | .results = &result 35 | }; 36 | 37 | json_t *array = json_array(); 38 | json_array_append_new(array, result_set_to_json(set)); 39 | 40 | set.name = "Hardware null_syscall thread (early processing)"; 41 | result = process_result_early_proc(raw_results->nullSyscall_ep_num, raw_results->nullSyscall_ep_sum, 42 | raw_results->nullSyscall_ep_sum2, raw_results->nullSyscall_ep); 43 | json_array_append_new(array, result_set_to_json(set)); 44 | 45 | set.name = "Nop syscall overhead"; 46 | set.results = &nopnulsyscall_result; 47 | json_array_append_new(array, result_set_to_json(set)); 48 | 49 | return array; 50 | } 51 | 52 | static benchmark_t hardware_benchmark = { 53 | .name = "hardware", 54 | .enabled = config_set(CONFIG_APP_HARDWAREBENCH), 55 | .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(hardware_results_t), seL4_PageBits), 56 | .process = hardware_process, 57 | .init = blank_init 58 | }; 59 | 60 | benchmark_t *hardware_benchmark_new(void) 61 | { 62 | return &hardware_benchmark; 63 | } 64 | -------------------------------------------------------------------------------- /apps/sel4bench/src/processing.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "benchmark.h" 10 | 11 | /* 12 | * Compute the variance, standard deviation, mean, min and max for a set of values. 13 | * 14 | * @param n number of values to process 15 | * @param array values to compute results for. 16 | * @param desc further (optional) details about the results 17 | */ 18 | result_t process_result(size_t n, ccnt_t array[n], result_desc_t desc); 19 | 20 | /* Compute the variance, standard deviation, mean for a set of values 21 | * for benchmarks using Early Processing methodology 22 | * @param num number of values to process 23 | * @param sum sum of values 24 | * @param sum2 sum of squared values 25 | * @param array raw values to compute results for 26 | */ 27 | result_t process_result_early_proc(ccnt_t num, ccnt_t sum, ccnt_t sum2, 28 | ccnt_t array[num]); 29 | 30 | /** 31 | * @param ncols size of the 1st dimension of array. 32 | * @param nrows size of the 2nd dimension of the array. 33 | * @param array 2d array of results to be processed. The assumption is that array[i] will yield a 34 | * set of results for a specific measurement, i.e array[i][j] and array[i][j+1] are 35 | * for the same result type. 36 | * @param desc further (optional) details about the results. 37 | * @param results array for output, must be ncols in size. 38 | */ 39 | void process_results(size_t ncols, size_t nrows, ccnt_t array[ncols][nrows], result_desc_t desc, 40 | result_t results[ncols]); 41 | 42 | /** 43 | * Process a table of results that need to be divided by AVERAGE_RUNS 44 | * 45 | * Each column in the table is a single result type. 46 | * 47 | * First divide all the results by AVERAGE_RUNS, then process each column. 48 | * 49 | * @param rows the number of rows in the results (should also be number of runs) 50 | * @param cols the number of columns in the results (also number of result types) 51 | * @param array raw results 52 | * @param results destination of the result of this function 53 | */ 54 | void process_average_results(int rows, int cols, ccnt_t array[rows][cols], result_t results[cols]); 55 | -------------------------------------------------------------------------------- /apps/vcpu/src/guest_asm.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | .text 8 | .balign 32 9 | 10 | 11 | .macro free_up_x0_and_load_it_with_vector_num _vectorno 12 | str x0, [sp, #-16]! 13 | mov x0, \_vectorno 14 | .endm 15 | 16 | .macro aligned_vector _vectorsym 17 | .balign 0x80 18 | b \_vectorsym 19 | .endm 20 | 21 | /* Vector table */ 22 | .globl aarch64_el1_vector_table 23 | .balign 0x100 24 | aarch64_el1_vector_table: 25 | aligned_vector guest_vector_dont_care 26 | aligned_vector guest_vector_dont_care 27 | aligned_vector guest_vector_dont_care 28 | aligned_vector guest_vector_dont_care 29 | 30 | aligned_vector guest_vector_cur_el_sync 31 | aligned_vector guest_vector_cur_el_irq 32 | aligned_vector guest_vector_dont_care 33 | aligned_vector guest_vector_dont_care 34 | 35 | aligned_vector guest_vector_lower_el64_sync 36 | aligned_vector guest_vector_lower_el64_irq 37 | aligned_vector guest_vector_dont_care 38 | aligned_vector guest_vector_dont_care 39 | 40 | aligned_vector guest_vector_dont_care 41 | aligned_vector guest_vector_dont_care 42 | aligned_vector guest_vector_dont_care 43 | aligned_vector guest_vector_dont_care 44 | 45 | 46 | .local guest_vector_dont_care 47 | guest_vector_dont_care: 48 | free_up_x0_and_load_it_with_vector_num #0 49 | bl guest_vector_common 50 | 51 | .local guest_vector_cur_el_sync 52 | guest_vector_cur_el_sync: 53 | free_up_x0_and_load_it_with_vector_num #4 54 | bl guest_vector_common 55 | 56 | .local guest_vector_cur_el_irq 57 | guest_vector_cur_el_irq: 58 | free_up_x0_and_load_it_with_vector_num #5 59 | bl guest_vector_common 60 | 61 | .local guest_vector_lower_el64_sync 62 | guest_vector_lower_el64_sync: 63 | free_up_x0_and_load_it_with_vector_num #8 64 | bl guest_vector_common 65 | 66 | .local guest_vector_lower_el64_irq 67 | guest_vector_lower_el64_irq: 68 | free_up_x0_and_load_it_with_vector_num #9 69 | bl guest_vector_common 70 | 71 | .globl guest__start 72 | guest__start: 73 | /* Mask all interrupts off at the local CPU */ 74 | msr daifset, #0xf 75 | /* Select the SP for the currentEL. */ 76 | msr spsel, #1 77 | 78 | bl guest_main 79 | 2: 80 | wfi 81 | b 2b 82 | -------------------------------------------------------------------------------- /apps/hardware/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #define NOPS "" 18 | 19 | #include 20 | 21 | void abort(void) 22 | { 23 | benchmark_finished(EXIT_FAILURE); 24 | } 25 | 26 | void measure_nullsyscall_overhead(ccnt_t *results) 27 | { 28 | ccnt_t start, end; 29 | for (int i = 0; i < N_RUNS; i++) { 30 | SEL4BENCH_READ_CCNT(start); 31 | DO_NOP_NULLSYSCALL(); 32 | SEL4BENCH_READ_CCNT(end); 33 | results[i] = (end - start); 34 | } 35 | } 36 | 37 | void measure_nullsyscall(ccnt_t *results) 38 | { 39 | ccnt_t start, end; 40 | for (int i = 0; i < N_RUNS; i++) { 41 | SEL4BENCH_READ_CCNT(start); 42 | DO_REAL_NULLSYSCALL(); 43 | SEL4BENCH_READ_CCNT(end); 44 | results[i] = (end - start); 45 | } 46 | 47 | } 48 | 49 | void measure_nullsyscall_ep(hardware_results_t *results) 50 | { 51 | ccnt_t start, end, sum = 0, sum2 = 0, overhead; 52 | 53 | overhead = results->overhead_min; 54 | DATACOLLECT_INIT(); 55 | 56 | for (seL4_Word i = 0; i < N_RUNS; i++) { 57 | SEL4BENCH_READ_CCNT(start); 58 | DO_REAL_NULLSYSCALL(); 59 | SEL4BENCH_READ_CCNT(end); 60 | DATACOLLECT_GET_SUMS(i, N_IGNORED, start, end, overhead, sum, sum2); 61 | } 62 | 63 | results->nullSyscall_ep_sum = sum; 64 | results->nullSyscall_ep_sum2 = sum2; 65 | results->nullSyscall_ep_num = N_RUNS - N_IGNORED; 66 | } 67 | 68 | int main(int argc, char **argv) 69 | { 70 | env_t *env; 71 | UNUSED int error; 72 | hardware_results_t *results; 73 | 74 | static size_t object_freq[seL4_ObjectTypeCount] = {0}; 75 | env = benchmark_get_env(argc, argv, sizeof(hardware_results_t), object_freq); 76 | results = (hardware_results_t *) env->results; 77 | 78 | sel4bench_init(); 79 | 80 | /* measure overhead */ 81 | measure_nullsyscall_overhead(results->nullSyscall_overhead); 82 | measure_nullsyscall(results->nullSyscall_results); 83 | measure_nullsyscall_ep(results); 84 | 85 | /* done -> results are stored in shared memory so we can now return */ 86 | benchmark_finished(EXIT_SUCCESS); 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /apps/sel4bench/src/signal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | #include "benchmark.h" 7 | #include "processing.h" 8 | #include "json.h" 9 | 10 | #include 11 | #include 12 | 13 | static json_t *signal_process(void *results) 14 | { 15 | signal_results_t *raw_results = results; 16 | 17 | result_desc_t desc = { 18 | .stable = true, 19 | .name = "signal overhead", 20 | .ignored = N_IGNORED 21 | }; 22 | 23 | result_t result = process_result(N_RUNS, raw_results->overhead, desc); 24 | 25 | result_set_t set = { 26 | .name = "Signal overhead", 27 | .n_results = 1, 28 | .n_extra_cols = 0, 29 | .results = &result 30 | }; 31 | 32 | json_t *array = json_array(); 33 | json_array_append_new(array, result_set_to_json(set)); 34 | 35 | desc.stable = false; 36 | desc.overhead = result.min; 37 | 38 | result = process_result_early_proc(raw_results->lo_num, 39 | raw_results->lo_sum, raw_results->lo_sum2, 40 | raw_results->diag_results); 41 | 42 | set.name = "Signal to high prio thread (early processing)"; 43 | json_array_append_new(array, result_set_to_json(set)); 44 | 45 | result = process_result(N_RUNS, raw_results->lo_prio_results, desc); 46 | set.name = "Signal to high prio thread"; 47 | json_array_append_new(array, result_set_to_json(set)); 48 | 49 | result = process_result(N_RUNS, raw_results->hi_prio_results, desc); 50 | set.name = "Signal to low prio thread"; 51 | json_array_append_new(array, result_set_to_json(set)); 52 | 53 | result_t average_results[NUM_AVERAGE_EVENTS]; 54 | process_average_results(N_RUNS, NUM_AVERAGE_EVENTS, raw_results->hi_prio_average, average_results); 55 | 56 | json_array_append_new(array, average_counters_to_json("Average signal to low prio thread", 57 | average_results)); 58 | 59 | return array; 60 | } 61 | 62 | static benchmark_t signal_benchmark = { 63 | .name = "signal", 64 | .enabled = config_set(CONFIG_APP_SIGNALBENCH), 65 | .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(signal_results_t), seL4_PageBits), 66 | .process = signal_process, 67 | .init = blank_init 68 | }; 69 | 70 | benchmark_t *signal_benchmark_new(void) 71 | { 72 | return &signal_benchmark; 73 | } 74 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/ia32/sel4_arch/fault.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #ifdef CONFIG_KERNEL_MCS 12 | #define DO_REPLY_RECV_1(ep, msg0, ro, sys) do { \ 13 | uint32_t ep_copy = ep; \ 14 | uint32_t ro_copy = ro; \ 15 | seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 1); \ 16 | asm volatile( \ 17 | "pushl %%ebp \n"\ 18 | "movl %%ecx, %%ebp \n"\ 19 | "movl %%esp, %%ecx \n"\ 20 | "leal 1f, %%edx \n"\ 21 | "1: \n" \ 22 | sys" \n" \ 23 | "popl %%ebp \n"\ 24 | : \ 25 | "+S" (tag), \ 26 | "+b" (ep_copy), \ 27 | "=D" (msg0), \ 28 | "+c" (ro_copy) \ 29 | : \ 30 | "a" (seL4_SysReplyRecv), \ 31 | "D" (msg0) \ 32 | : \ 33 | "edx" \ 34 | ); \ 35 | } while(0) 36 | 37 | static inline seL4_MessageInfo_t seL4_RecvWith1MR(seL4_CPtr src, seL4_Word *mr0, seL4_CPtr reply) 38 | { 39 | return seL4_RecvWithMRs(src, NULL, mr0, reply); 40 | } 41 | 42 | static inline void seL4_ReplyWith1MR(seL4_Word mr0, UNUSED seL4_CPtr dest) 43 | { 44 | return seL4_SendWithMRs(dest, seL4_MessageInfo_new(0, 0, 0, 1), &mr0); 45 | } 46 | 47 | #else 48 | 49 | #define DO_REPLY_RECV_1(ep, msg0, ro, sys) do { \ 50 | uint32_t ep_copy = ep; \ 51 | seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 1); \ 52 | asm volatile( \ 53 | "pushl %%ebp \n"\ 54 | "movl %%esp, %%ecx \n"\ 55 | "leal 1f, %%edx \n"\ 56 | "1: \n" \ 57 | sys" \n" \ 58 | "popl %%ebp \n"\ 59 | : \ 60 | "+S" (tag), \ 61 | "+b" (ep_copy), \ 62 | "=D" (msg0) \ 63 | : \ 64 | "a" (seL4_SysReplyRecv), \ 65 | "D" (msg0) \ 66 | : \ 67 | "ecx", \ 68 | "edx" \ 69 | ); \ 70 | } while(0) 71 | 72 | 73 | static inline seL4_MessageInfo_t seL4_RecvWith1MR(seL4_CPtr src, seL4_Word *mr0, UNUSED seL4_CPtr reply) 74 | { 75 | return seL4_RecvWithMRs(src, NULL, mr0, NULL); 76 | } 77 | 78 | static inline void seL4_ReplyWith1MR(seL4_Word mr0, UNUSED seL4_CPtr dest) 79 | { 80 | return seL4_ReplyWithMRs(seL4_MessageInfo_new(0, 0, 0, 1), &mr0, NULL); 81 | } 82 | #endif /* CONFIG_KERNEL_MCS */ 83 | 84 | #define DO_REAL_REPLY_RECV_1(ep, mr0, ro) DO_REPLY_RECV_1(ep, mr0, ro, "sysenter") 85 | #define DO_NOP_REPLY_RECV_1(ep, mr0, ro) DO_REPLY_RECV_1(ep, mr0, ro, ".byte 0x66\n.byte 0x90") 86 | -------------------------------------------------------------------------------- /easy-settings.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | # Define our top level settings. Whilst they have doc strings for readability 8 | # here, they are hidden in the cmake-gui as they cannot be reliably changed 9 | # after the initial configuration. Enterprising users can still change them if 10 | # they know what they are doing through advanced mode. 11 | # 12 | # Users should initialize a build directory by doing something like: 13 | # 14 | # mkdir build_sabre cd build_sabre 15 | # 16 | # Then 17 | # 18 | # ../griddle --PLATFORM=sabre --SIMULATION ninja 19 | # 20 | set(RELEASE 21 | ON 22 | CACHE BOOL "Performance optimized build" 23 | ) 24 | set(PLATFORM 25 | "x86_64" 26 | CACHE STRING "Platform to test" 27 | ) 28 | set(FASTPATH 29 | ON 30 | CACHE BOOL "Turn fastpath on or off" 31 | ) 32 | set(ARM_HYP 33 | OFF 34 | CACHE BOOL "ARM EL2 hypervisor features on or off" 35 | ) 36 | set(MCS 37 | OFF 38 | CACHE BOOL "MCS kernel" 39 | ) 40 | 41 | # Set the list of benchmark applications to be included into the image Add any 42 | # new benchmark applications to this list 43 | 44 | # default is OFF 45 | set(HARDWARE 46 | OFF 47 | CACHE BOOL "Application to benchmark hardware-related operations" 48 | ) 49 | 50 | # default is OFF 51 | set(FAULT 52 | OFF 53 | CACHE BOOL "Application to benchmark seL4 faults" 54 | ) 55 | 56 | # default is OFF 57 | set(VCPU 58 | OFF 59 | CACHE BOOL "Application to benchmark seL4 VCPU performance" 60 | ) 61 | 62 | # default is OFF 63 | set(SMP 64 | OFF 65 | CACHE BOOL "Application SMP benchmarks" 66 | ) 67 | 68 | # default is ON 69 | set(IPC 70 | ON 71 | CACHE BOOL "Application to benchmark seL4 IPC" 72 | ) 73 | 74 | # default is ON 75 | set(IRQUSER 76 | ON 77 | CACHE BOOL "Application to benchmark seL4 IRQs" 78 | ) 79 | 80 | # default is ON 81 | set(SCHED 82 | ON 83 | CACHE BOOL "Application to benchmark seL4 scheduler" 84 | ) 85 | 86 | # default is ON 87 | set(SIGNAL 88 | ON 89 | CACHE BOOL "Application to benchmark seL4 signals" 90 | ) 91 | 92 | # default is ON 93 | set(MAPPING 94 | ON 95 | CACHE BOOL "Application to benchmark seL4 mapping a series of pages" 96 | ) 97 | 98 | # default is ON 99 | set(SYNC 100 | ON 101 | CACHE BOOL "Application to benchmark seL4 sync" 102 | ) 103 | 104 | # Allow Early Processing methodology for Signal/"Signal to High Prio Thread" 105 | # benchmark set(AppSignalEarlyProcessing ON) 106 | -------------------------------------------------------------------------------- /libsel4benchsupport/src/arch/x86/support.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "../../support.h" 19 | 20 | static seL4_Error get_msi(void *data, seL4_CNode root, seL4_Word index, uint8_t depth, 21 | UNUSED seL4_Word pci_bus, UNUSED seL4_Word pci_dev, UNUSED seL4_Word pci_func, 22 | UNUSED seL4_Word handle, seL4_Word vector) 23 | { 24 | assert(data != NULL); 25 | env_t *env = data; 26 | 27 | RpcMessage msg = { 28 | .which_msg = RpcMessage_irq_tag, 29 | .msg.irq = { 30 | .which_type = IrqAllocMessage_msi_tag, 31 | .type.msi = { 32 | .pci_bus = pci_bus, 33 | .pci_dev = pci_dev, 34 | .pci_func = pci_func, 35 | .handle = handle, 36 | .vector = vector, 37 | }, 38 | }, 39 | }; 40 | 41 | int ret = sel4rpc_call(&env->rpc_client, &msg, root, index, depth); 42 | if (ret) { 43 | return ret; 44 | } 45 | 46 | assert(msg.msg.ret.errorCode == seL4_NoError); 47 | 48 | return seL4_NoError; 49 | } 50 | 51 | static seL4_Error get_ioapic(void *data, seL4_CNode root, seL4_Word index, uint8_t depth, 52 | UNUSED seL4_Word ioapic, UNUSED seL4_Word pin, UNUSED seL4_Word edge, 53 | UNUSED seL4_Word level, seL4_Word vector) 54 | { 55 | assert(data != NULL); 56 | env_t *env = data; 57 | 58 | RpcMessage msg = { 59 | .which_msg = RpcMessage_irq_tag, 60 | .msg.irq = { 61 | .which_type = IrqAllocMessage_ioapic_tag, 62 | .type.ioapic = { 63 | .ioapic = ioapic, 64 | .pin = pin, 65 | .polarity = edge, 66 | .level = level, 67 | .vector = vector, 68 | }, 69 | }, 70 | }; 71 | 72 | int ret = sel4rpc_call(&env->rpc_client, &msg, root, index, depth); 73 | if (ret) { 74 | return ret; 75 | } 76 | 77 | assert(msg.msg.ret.errorCode == seL4_NoError); 78 | 79 | return seL4_NoError; 80 | } 81 | 82 | void benchmark_arch_get_simple(arch_simple_t *simple) 83 | { 84 | simple->msi = get_msi; 85 | simple->ioapic = get_ioapic; 86 | } 87 | -------------------------------------------------------------------------------- /apps/sel4bench/src/smp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "benchmark.h" 14 | #include "json.h" 15 | #include "math.h" 16 | #include "printing.h" 17 | #include "processing.h" 18 | 19 | static int cores_collective_results; 20 | 21 | static void process_smp_results_init(UNUSED vka_t *vka, simple_t *simple, UNUSED sel4utils_process_t *process) 22 | { 23 | cores_collective_results = simple_get_core_count(simple); 24 | } 25 | 26 | static json_t *process_smp_results(void *r) 27 | { 28 | smp_results_t *raw_results = r; 29 | 30 | int n = TESTS * cores_collective_results; 31 | 32 | json_int_t cycle_col[n], cores_col[n]; 33 | for (int i = 0; i < n; i++) { 34 | cycle_col[i] = smp_benchmark_params[i / cores_collective_results].delay; 35 | cores_col[i] = (i % cores_collective_results) + 1; 36 | } 37 | 38 | column_t extra_cols[] = { 39 | { 40 | .header = "Cycles", 41 | .type = JSON_INTEGER, 42 | .integer_array = cycle_col, 43 | }, 44 | { 45 | .header = "Cores", 46 | .type = JSON_INTEGER, 47 | .integer_array = cores_col, 48 | }, 49 | }; 50 | 51 | result_t results[TESTS][cores_collective_results]; 52 | 53 | result_set_t result_set = { 54 | .name = "SMP Benchmark", 55 | .extra_cols = extra_cols, 56 | .n_extra_cols = ARRAY_SIZE(extra_cols), 57 | .results = (result_t *) results, 58 | .n_results = n, 59 | }; 60 | 61 | for (int i = 0; i < TESTS; i++) { 62 | for (int j = 0; j < cores_collective_results; j++) { 63 | result_desc_t desc = { 64 | .name = smp_benchmark_params[i].name, 65 | .overhead = 0, 66 | }; 67 | results[i][j] = process_result(RUNS, raw_results->benchmarks_result[i][j], desc); 68 | } 69 | } 70 | 71 | json_t *array = json_array(); 72 | json_array_append_new(array, result_set_to_json(result_set)); 73 | return array; 74 | } 75 | 76 | static benchmark_t smp_benchmark = { 77 | .name = "smp", 78 | .enabled = config_set(CONFIG_APP_SMPBENCH), 79 | .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(smp_results_t), seL4_PageBits), 80 | .process = process_smp_results, 81 | .init = process_smp_results_init 82 | }; 83 | 84 | benchmark_t *smp_benchmark_new(void) 85 | { 86 | return &smp_benchmark; 87 | } 88 | -------------------------------------------------------------------------------- /apps/sel4bench/src/processing.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "ipc.h" 12 | #include "processing.h" 13 | #include "math.h" 14 | #include "printing.h" 15 | 16 | void process_average_results(int rows, int cols, ccnt_t array[rows][cols], result_t results[cols]) 17 | { 18 | /* first divide results by no of runs */ 19 | for (int row = 0; row < rows; row++) { 20 | for (int col = 0; col < cols; col++) { 21 | array[row][col] /= AVERAGE_RUNS; 22 | } 23 | } 24 | 25 | /* now calculate */ 26 | for (int col = 0; col < cols; col++) { 27 | /* create an array of the specific column we want to process - we can't reorganise the data structure as 28 | * the 2D array is arranged to minimise benchmark impact such that we write to sequential memory addresses in each loop of the benchmark, 29 | * additionally we calloc the copy such that the raw data pointed to by the result does not exist on the stack. A different approach will be 30 | * required if we run out of memory */ 31 | ccnt_t *raw_data = calloc(rows, sizeof(ccnt_t)); 32 | assert(raw_data != NULL); 33 | 34 | for (int i = 0; i < rows; i++) { 35 | raw_data[i] = array[i][col]; 36 | } 37 | 38 | results[col] = calculate_results(rows, raw_data); 39 | } 40 | } 41 | 42 | result_t process_result(size_t n, ccnt_t array[n], result_desc_t desc) 43 | { 44 | array = &array[desc.ignored]; 45 | int size = n - desc.ignored; 46 | 47 | if (desc.stable && !results_stable(array, size)) { 48 | ZF_LOGW("%s cycles are not stable\n", desc.name == NULL ? "unknown" : desc.name); 49 | if (ZF_LOG_LEVEL <= ZF_LOG_VERBOSE) { 50 | print_all(size, array); 51 | } 52 | if (!config_set(CONFIG_ALLOW_UNSTABLE_OVERHEAD)) { 53 | return (result_t) { 54 | 0 55 | }; 56 | } 57 | } 58 | 59 | for (int i = 0; i < size; i++) { 60 | array[i] -= desc.overhead; 61 | } 62 | 63 | return calculate_results(size, array); 64 | } 65 | 66 | result_t process_result_early_proc(ccnt_t num, ccnt_t sum, ccnt_t sum2, ccnt_t array[num]) 67 | { 68 | return calculate_results_early_proc(num, sum, sum2, array); 69 | } 70 | 71 | void process_results(size_t ncols, size_t nrows, ccnt_t array[ncols][nrows], result_desc_t desc, 72 | result_t results[ncols]) 73 | { 74 | for (int i = 0; i < ncols; i++) { 75 | results[i] = process_result(nrows, array[i], desc); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /apps/sel4bench/src/irq.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | #include 7 | 8 | #include "benchmark.h" 9 | #include "processing.h" 10 | #include "json.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | static json_t *irquser_process(void *r) 18 | { 19 | irquser_results_t *raw_results = r; 20 | 21 | result_desc_t desc = { 22 | .ignored = N_IGNORED, 23 | .name = "IRQ user measurement overhead" 24 | }; 25 | 26 | result_t results[5]; 27 | 28 | results[0] = process_result(N_RUNS, raw_results->overheads, desc); 29 | 30 | desc.overhead = results[0].min; 31 | 32 | results[1] = process_result(N_RUNS, raw_results->thread_results, desc); 33 | results[2] = process_result_early_proc(raw_results->thread_results_ep_num, 34 | raw_results->thread_results_ep_sum, 35 | raw_results->thread_results_ep_sum2, 36 | raw_results->thread_results_ep); 37 | results[3] = process_result(N_RUNS, raw_results->process_results, desc); 38 | results[4] = process_result_early_proc(raw_results->process_results_ep_num, 39 | raw_results->process_results_ep_sum, 40 | raw_results->process_results_ep_sum2, 41 | raw_results->process_results_ep); 42 | 43 | char *types[] = {"Measurement overhead", "Without context switch", 44 | "Without context switch (early processing)", "With context switch", 45 | "With context switch (early processing)" 46 | }; 47 | 48 | column_t col = { 49 | .header = "Type", 50 | .type = JSON_STRING, 51 | .string_array = types 52 | }; 53 | 54 | result_set_t set = { 55 | .name = "IRQ path cycle count (measured from user level)", 56 | .n_results = 5, 57 | .results = results, 58 | .n_extra_cols = 1, 59 | .extra_cols = &col 60 | }; 61 | 62 | json_t *json = json_array(); 63 | json_array_append_new(json, result_set_to_json(set)); 64 | return json; 65 | } 66 | 67 | static benchmark_t irquser_benchmark = { 68 | .name = "irquser", 69 | .enabled = config_set(CONFIG_APP_IRQUSERBENCH), 70 | .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(irquser_results_t), seL4_PageBits), 71 | .process = irquser_process, 72 | .init = blank_init 73 | }; 74 | 75 | benchmark_t *irquser_benchmark_new(void) 76 | { 77 | return &irquser_benchmark; 78 | } 79 | -------------------------------------------------------------------------------- /apps/ipc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(ipc C) 10 | 11 | set(configure_string "") 12 | config_option( 13 | AppIpcBench 14 | APP_IPCBENCH 15 | "Application to benchmark seL4 IPC." 16 | DEFAULT 17 | ON 18 | DEPENDS 19 | "DefaultBenchDeps" 20 | ) 21 | config_choice( 22 | CounterToMeasure 23 | COUNTER_TO_MEASURE 24 | "Counter to measure" 25 | "Cycle count;Ipc_CycleCount;CYCLE_COUNT;AppIpcBench" 26 | "Generic counter;Ipc_GenericCounter;GENERIC_COUNTER;AppIpcBench" 27 | "Platform counter;Ipc_PlatformCounter;PLATFORM_COUNTER;AppIpcBench" 28 | ) 29 | config_choice( 30 | GenericCounterID 31 | GENERIC_COUNTER_ID 32 | "Select the generic counter to measure in ipc benchmarks" 33 | "0;Ipc_CacheL1IMiss;CACHE_L1I_MISS;Ipc_GenericCounter;AppIpcBench" 34 | "1;Ipc_CacheL1DMiss;CACHE_L1D_MISS;Ipc_GenericCounter;AppIpcBench" 35 | "2;Ipc_TLBL1IMiss;TLB_L1I_MISS;Ipc_GenericCounter;AppIpcBench" 36 | "3;Ipc_TLBL1DMiss;TLB_L1D_MISS;Ipc_GenericCounter;AppIpcBench" 37 | "4;Ipc_ExecuteInstruction;EXECUTE_INSTRUCTION;Ipc_GenericCounter;AppIpcBench" 38 | "5;Ipc_BranchMispredict;BRANCH_MISPREDICT;Ipc_GenericCounter;AppIpcBench" 39 | "6;Ipc_MemoryAccess;MEMORY_ACCESS;Ipc_GenericCounter;AppIpcBench" 40 | ) 41 | 42 | if(KernelArchARM) 43 | config_set(L1DCacheSize L1_DCACHE_SIZE "0x8000") 44 | endif() 45 | 46 | config_choice( 47 | CacheToMeasure 48 | CACHE_TO_MEASURE 49 | "cache to measure" 50 | "Hot Cache;Ipc_HotCache;HOT_CACHE;AppIpcBench" 51 | "Clean L1 ICache;Ipc_CleanL1ICache;CLEAN_L1_ICACHE;AppIpcBench;KernelArchARM;NOT AppSmpBench" 52 | "Clean L1 DCache;Ipc_CleanL1DCache;CLEAN_L1_DCACHE;AppIpcBench;KernelArchARM;NOT AppSmpBench" 53 | "Clean L1 IDCache;Ipc_CleanL1IDCache;CLEAN_L1_IDCACHE;AppIpcBench;KernelArchARM;NOT AppSmpBench" 54 | "Dirty L1 DCache;Ipc_DirtyL1DCache;DIRTY_L1_DCACHE;AppIpcBench;L1DCacheSize" 55 | ) 56 | 57 | config_string( 58 | PlatformCounterConstant 59 | PLATFORM_COUNTER_CONSTANT 60 | "Internal constant to use for the event" 61 | DEFAULT 62 | SEL4BENCH_EVENT_CYCLE_CORE 63 | DEPENDS 64 | "Ipc_PlatformCounter" 65 | UNDEF_DISABLED 66 | UNQUOTE 67 | ) 68 | add_config_library(sel4benchipc "${configure_string}") 69 | 70 | file(GLOB deps src/*.c) 71 | list(SORT deps) 72 | add_executable(ipc EXCLUDE_FROM_ALL ${deps}) 73 | target_link_libraries( 74 | ipc 75 | sel4_autoconf 76 | sel4benchipc_Config 77 | sel4 78 | muslc 79 | cpio 80 | sel4vka 81 | sel4vspace 82 | sel4allocman 83 | sel4utils 84 | elf 85 | sel4simple 86 | sel4benchsupport 87 | sel4debug 88 | platsupport 89 | sel4platsupport 90 | sel4muslcsys 91 | ) 92 | 93 | if(AppIpcBench) 94 | set_property(GLOBAL APPEND PROPERTY sel4benchapps_property "$") 95 | endif() 96 | 97 | general_regs_only(ipc) 98 | -------------------------------------------------------------------------------- /apps/sel4bench/src/page_mapping.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "benchmark.h" 13 | #include "json.h" 14 | #include "math.h" 15 | #include "printing.h" 16 | #include "processing.h" 17 | 18 | static json_t *process_mapping_results(void *r) 19 | { 20 | page_mapping_results_t *raw_results = r; 21 | ccnt_t overhead; 22 | 23 | /* check overheads */ 24 | result_desc_t desc = { 25 | .stable = false, 26 | .name = "overhead", 27 | .ignored = 0, 28 | .overhead = 0 29 | }; 30 | result_t overhead_result = process_result(RUNS, 31 | raw_results->overhead_benchmarks, 32 | desc); 33 | 34 | overhead = overhead_result.min; 35 | 36 | int nline = TESTS * NPHASE; 37 | 38 | char *phase_col[nline]; 39 | json_int_t npage_col[nline]; 40 | for (int i = 0; i < nline; i++) { 41 | phase_col[i] = phase_name[i % NPHASE]; 42 | npage_col[i] = page_mapping_benchmark_params[i / NPHASE].npage; 43 | } 44 | 45 | column_t extra_cols[] = { 46 | { 47 | .header = "Num of Page Mapped", 48 | .type = JSON_INTEGER, 49 | .integer_array = npage_col, 50 | }, 51 | { 52 | .header = "Phase", 53 | .type = JSON_STRING, 54 | .string_array = phase_col, 55 | }, 56 | }; 57 | 58 | result_t results[TESTS][NPHASE]; 59 | 60 | result_set_t result_set = { 61 | .name = "Mapping Benchmark", 62 | .extra_cols = extra_cols, 63 | .n_extra_cols = ARRAY_SIZE(extra_cols), 64 | .results = (result_t *)results, 65 | .n_results = nline, 66 | }; 67 | 68 | /* now calculate the results */ 69 | for (int i = 0; i < TESTS; i++) { 70 | for (int j = 0; j < NPHASE; j++) { 71 | result_desc_t desc = { 72 | .name = page_mapping_benchmark_params[i].name, 73 | .overhead = overhead, 74 | }; 75 | results[i][j] = 76 | process_result(RUNS, raw_results->benchmarks_result[i][j], desc); 77 | } 78 | } 79 | 80 | json_t *array = json_array(); 81 | json_array_append_new(array, result_set_to_json(result_set)); 82 | return array; 83 | } 84 | 85 | static benchmark_t page_mapping_benchmark = { 86 | .name = "page_mapping", 87 | .enabled = config_set(CONFIG_APP_PAGEMAPPINGBENCH), 88 | .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(page_mapping_results_t), 89 | seL4_PageBits), 90 | .process = process_mapping_results, 91 | .init = blank_init 92 | }; 93 | 94 | benchmark_t *page_mapping_benchmark_new(void) 95 | { 96 | return &page_mapping_benchmark; 97 | } 98 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/x86_64/sel4_arch/fault.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #ifdef CONFIG_SYSCALL 12 | 13 | #include 14 | 15 | #ifdef CONFIG_KERNEL_MCS 16 | #define DO_REPLY_RECV_1(ep, msg0, ro, sys) do { \ 17 | uint64_t ep_copy = ep; \ 18 | seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 1); \ 19 | register seL4_Word mr0 asm("r10") = msg0; \ 20 | register seL4_Word ro_copy asm("r12") = ro;\ 21 | asm volatile( \ 22 | "movq %%rsp, %%rbx \n" \ 23 | sys" \n" \ 24 | "mov %%rbx, %%rsp \n"\ 25 | : \ 26 | "+S" (tag), \ 27 | "+D" (ep_copy), \ 28 | "=r" (mr0) \ 29 | : \ 30 | "d" ((seL4_Word)seL4_SysReplyRecv), \ 31 | "r" (mr0), \ 32 | "r" (ro_copy)\ 33 | : \ 34 | "%rcx", \ 35 | "%rbx", \ 36 | "%r11", \ 37 | "%r8", \ 38 | "%r9", \ 39 | "%r15" \ 40 | ); \ 41 | msg0 = mr0; \ 42 | } while(0) 43 | 44 | static inline seL4_MessageInfo_t seL4_RecvWith1MR(seL4_CPtr src, seL4_Word *mr0, seL4_CPtr reply) 45 | { 46 | return seL4_RecvWithMRs(src, NULL, mr0, NULL, NULL, NULL, reply); 47 | } 48 | 49 | static inline void seL4_ReplyWith1MR(seL4_Word mr0, seL4_CPtr dest) 50 | { 51 | return seL4_SendWithMRs(dest, seL4_MessageInfo_new(0, 0, 0, 1), &mr0, NULL, NULL, NULL); 52 | } 53 | 54 | #else 55 | #define DO_REPLY_RECV_1(ep, msg0, ro, sys) do { \ 56 | uint64_t ep_copy = ep; \ 57 | seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 1); \ 58 | register seL4_Word mr0 asm("r10") = msg0; \ 59 | asm volatile( \ 60 | "movq %%rsp, %%rbx \n" \ 61 | sys" \n" \ 62 | "mov %%rbx, %%rsp \n"\ 63 | : \ 64 | "+S" (tag), \ 65 | "+D" (ep_copy), \ 66 | "=r" (mr0) \ 67 | : \ 68 | "d" ((seL4_Word)seL4_SysReplyRecv), \ 69 | "r" (mr0) \ 70 | : \ 71 | "%rcx", \ 72 | "%rbx", \ 73 | "%r11", \ 74 | "%r8", \ 75 | "%r9", \ 76 | "%r15" \ 77 | ); \ 78 | msg0 = mr0; \ 79 | } while(0) 80 | 81 | static inline seL4_MessageInfo_t seL4_RecvWith1MR(seL4_CPtr src, seL4_Word *mr0, UNUSED seL4_CPtr reply) 82 | { 83 | return seL4_RecvWithMRs(src, NULL, mr0, NULL, NULL, NULL); 84 | } 85 | 86 | static inline void seL4_ReplyWith1MR(seL4_Word mr0, UNUSED seL4_CPtr dest) 87 | { 88 | return seL4_ReplyWithMRs(seL4_MessageInfo_new(0, 0, 0, 1), &mr0, NULL, NULL, NULL); 89 | } 90 | #endif /* CONFIG_KERNEL_MCS */ 91 | 92 | 93 | #define DO_REAL_REPLY_RECV_1(ep, mr0, ro) DO_REPLY_RECV_1(ep, mr0, ro, "syscall") 94 | #define DO_NOP_REPLY_RECV_1(ep, mr0, ro) DO_REPLY_RECV_1(ep, mr0, ro, ".byte 0x66\n.byte 0x90") 95 | 96 | #else 97 | #error Only support benchmarking with syscall as sysenter is known to be slower 98 | #endif /* CONFIG_SYSCALL */ 99 | -------------------------------------------------------------------------------- /apps/sel4bench/src/fault.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | #include "benchmark.h" 7 | #include "processing.h" 8 | #include "json.h" 9 | 10 | #include 11 | #include 12 | 13 | static json_t *fault_process(void *results) 14 | { 15 | fault_results_t *raw_results = results; 16 | 17 | result_desc_t desc = { 18 | .stable = true, 19 | .name = "fault overhead", 20 | .ignored = N_IGNORED 21 | }; 22 | 23 | /* calculate overhead of reply_recv */ 24 | result_t result = process_result(N_RUNS, raw_results->reply_recv_overhead, desc); 25 | 26 | result_set_t set = { 27 | .name = "fault overhead", 28 | .n_results = 1, 29 | .n_extra_cols = 0, 30 | .results = &result 31 | }; 32 | 33 | json_t *array = json_array(); 34 | json_array_append_new(array, result_set_to_json(set)); 35 | 36 | desc.stable = false; 37 | desc.overhead = result.min; 38 | 39 | set.name = "fault round trip"; 40 | result = process_result(N_RUNS, raw_results->round_trip, desc); 41 | json_array_append_new(array, result_set_to_json(set)); 42 | 43 | set.name = "fault round trip (early processing)"; 44 | result = process_result_early_proc(raw_results->round_trip_ep_num, raw_results->round_trip_ep_sum, 45 | raw_results->round_trip_ep_sum2, raw_results->round_trip_ep); 46 | json_array_append_new(array, result_set_to_json(set)); 47 | 48 | set.name = "faulter -> fault handler"; 49 | result = process_result(N_RUNS, raw_results->fault, desc); 50 | json_array_append_new(array, result_set_to_json(set)); 51 | 52 | set.name = "faulter -> fault handler (early processing)"; 53 | result = process_result_early_proc(raw_results->fault_ep_num, raw_results->fault_ep_sum, 54 | raw_results->fault_ep_sum2, raw_results->fault_ep); 55 | json_array_append_new(array, result_set_to_json(set)); 56 | 57 | /* calculate the overhead of reading the cycle count (fault handler -> faulter path 58 | * does not include a call to seL4_ReplyRecv_ */ 59 | 60 | set.name = "read ccnt overhead"; 61 | desc.stable = true; 62 | desc.overhead = 0; 63 | result = process_result(N_RUNS, raw_results->ccnt_overhead, desc); 64 | json_array_append_new(array, result_set_to_json(set)); 65 | 66 | /* fault to fault handler does not */ 67 | set.name = "fault handler -> faulter"; 68 | desc.stable = false; 69 | desc.overhead = result.min; 70 | result = process_result(N_RUNS, raw_results->fault_reply, desc); 71 | json_array_append_new(array, result_set_to_json(set)); 72 | 73 | /* fault to fault handler does not */ 74 | set.name = "fault handler -> faulter (early processing)"; 75 | result = process_result_early_proc(raw_results->fault_reply_ep_num, raw_results->fault_reply_ep_sum, 76 | raw_results->fault_reply_ep_sum2, raw_results->fault_reply_ep); 77 | json_array_append_new(array, result_set_to_json(set)); 78 | 79 | return array; 80 | } 81 | 82 | static benchmark_t fault_benchmark = { 83 | .name = "fault", 84 | .enabled = config_set(CONFIG_APP_FAULTBENCH), 85 | .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(fault_results_t), seL4_PageBits), 86 | .process = fault_process, 87 | .init = blank_init 88 | }; 89 | 90 | benchmark_t *fault_benchmark_new(void) 91 | { 92 | return &fault_benchmark; 93 | } 94 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | include(settings.cmake) 10 | 11 | project(sel4bench C CXX ASM) 12 | 13 | find_package(seL4 REQUIRED) 14 | find_package(elfloader-tool REQUIRED) 15 | 16 | # Configuration that applies to all apps 17 | if(NOT Sel4benchAllowSettingsOverride) 18 | if(KernelArchARM) 19 | if(KernelPlatformOMAP3 OR KernelPlatformAM335X) 20 | set(KernelDangerousCodeInjection 21 | ON 22 | CACHE BOOL "" FORCE 23 | ) 24 | else() 25 | set(KernelArmExportPMUUser 26 | ON 27 | CACHE BOOL "" FORCE 28 | ) 29 | endif() 30 | else() 31 | set(KernelArmExportPMUUser 32 | OFF 33 | CACHE BOOL "" FORCE 34 | ) 35 | endif() 36 | if(KernelArchX86) 37 | set(KernelExportPMCUser 38 | ON 39 | CACHE BOOL "" FORCE 40 | ) 41 | set(KernelX86DangerousMSR 42 | ON 43 | CACHE BOOL "" FORCE 44 | ) 45 | set(AllowUnstableOverhead 46 | ON 47 | CACHE BOOL "" FORCE 48 | ) 49 | set(KernelX86MicroArch 50 | "haswell" 51 | CACHE STRING "" FORCE 52 | ) 53 | set(KernelXSaveFeatureSet 54 | 7 55 | CACHE STRING "" FORCE 56 | ) 57 | set(KernelXSaveSize 58 | 832 59 | CACHE STRING "" FORCE 60 | ) 61 | endif() 62 | set(KernelRootCNodeSizeBits 63 | 13 64 | CACHE STRING "" FORCE 65 | ) 66 | set(KernelTimeSlice 67 | 500 68 | CACHE STRING "" FORCE 69 | ) 70 | set(KernelTimerTickMS 71 | 1000 72 | CACHE STRING "" FORCE 73 | ) 74 | set(KernelVerificationBuild 75 | OFF 76 | CACHE BOOL "" FORCE 77 | ) 78 | endif() 79 | sel4_import_kernel() 80 | 81 | if((NOT Sel4benchAllowSettingsOverride) AND (KernelArchARM OR KernelArchRiscV)) 82 | # Elfloader settings that correspond to how Data61 sets its boards up. 83 | ApplyData61ElfLoaderSettings(${KernelPlatform} ${KernelSel4Arch}) 84 | endif() 85 | elfloader_import_project() 86 | 87 | # Avoid compilers from using SIMD instructions for integer code. 88 | # If the program faults on a SIMD instruction for your platform, 89 | # update this code or find another work-around. 90 | function(general_regs_only target) 91 | include(CheckCCompilerFlag OPTIONAL) 92 | check_c_compiler_flag(-mgeneral-regs-only HAS_GENERAL_REGS_ONLY) 93 | if(HAS_GENERAL_REGS_ONLY) 94 | target_compile_options(${target} PRIVATE -mgeneral-regs-only) 95 | endif() 96 | endfunction() 97 | 98 | add_subdirectory(apps/sel4bench) 99 | 100 | include(simulation) 101 | GenerateSimulateScript() 102 | 103 | # Platforms that don't have a timer can't use the benchmarks which need a timer. 104 | if(LibPlatSupportNoPlatformLtimer) 105 | if(AppIrqUserBench) 106 | message(WARNING "Platform has no timer, disabling IRQUSER bench") 107 | set(AppIrqUserBench 108 | OFF 109 | CACHE BOOL "" FORCE 110 | ) 111 | endif() 112 | if(AppSmpBench) 113 | message(WARNING "Platform has no timer, disabling SMP bench") 114 | set(AppSmpBench 115 | OFF 116 | CACHE BOOL "" FORCE 117 | ) 118 | endif() 119 | endif() 120 | -------------------------------------------------------------------------------- /apps/sel4bench/src/benchmark.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | typedef struct benchmark { 26 | /* name of the benchmark application */ 27 | char *name; 28 | /* should we run this benchmark */ 29 | bool enabled; 30 | /* size of data structure required to store results */ 31 | size_t results_pages; 32 | /* 33 | * Process and return the results 34 | * 35 | */ 36 | json_t *(*process)(void *results); 37 | /* carry out any extra init for this process */ 38 | void (*init)(vka_t *vka, simple_t *simple, sel4utils_process_t *process); 39 | } benchmark_t; 40 | 41 | /* generic result type */ 42 | typedef struct { 43 | double variance; 44 | double stddev; 45 | double mean; 46 | ccnt_t min; 47 | ccnt_t max; 48 | ccnt_t mode; 49 | double median; 50 | double first_quantile; 51 | double third_quantile; 52 | size_t samples; 53 | ccnt_t *raw_data; 54 | } result_t; 55 | 56 | typedef struct { 57 | /* header to print at top of column */ 58 | char *header; 59 | /* pointer to first element in array of column values - length must match n_results in the 60 | * result_set_t that this column is used with. */ 61 | union { 62 | char **string_array; 63 | json_int_t *integer_array; 64 | double *real_array; 65 | bool *bool_array; 66 | }; 67 | /* type of the column */ 68 | json_type type; 69 | } column_t; 70 | 71 | /* describes result output */ 72 | typedef struct { 73 | /* name of the result set */ 74 | const char *name; 75 | /* columns to prepend to result output */ 76 | column_t *extra_cols; 77 | /* number of extra columns */ 78 | int n_extra_cols; 79 | /* array of results */ 80 | result_t *results; 81 | /* number of results in this set */ 82 | int n_results; 83 | } result_set_t; 84 | 85 | /* description of how to process a result */ 86 | typedef struct { 87 | /* error if result should be stable */ 88 | bool stable; 89 | /* name of result */ 90 | const char *name; 91 | /* overhead to subtract from each result before calculations */ 92 | ccnt_t overhead; 93 | /* number of samples to ignore (for cold cache values). */ 94 | int ignored; 95 | } result_desc_t; 96 | 97 | benchmark_t *ipc_benchmark_new(void); 98 | benchmark_t *irquser_benchmark_new(void); 99 | benchmark_t *scheduler_benchmark_new(void); 100 | benchmark_t *signal_benchmark_new(void); 101 | benchmark_t *fault_benchmark_new(void); 102 | benchmark_t *hardware_benchmark_new(void); 103 | benchmark_t *sync_benchmark_new(void); 104 | benchmark_t *page_mapping_benchmark_new(void); 105 | benchmark_t *smp_benchmark_new(void); 106 | benchmark_t *vcpu_benchmark_new(void); 107 | /* Add new benchmarks here */ 108 | 109 | static inline void blank_init(UNUSED vka_t *vka, UNUSED simple_t *simple, UNUSED sel4utils_process_t *process) 110 | { 111 | /* for benchmarks with no specific init */ 112 | } 113 | -------------------------------------------------------------------------------- /apps/sel4bench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | project(sel4benchapp C) 10 | set(configure_string "") 11 | 12 | config_option( 13 | AllowUnstableOverhead ALLOW_UNSTABLE_OVERHEAD "Do not fail when stable values are not stable." 14 | DEFAULT OFF 15 | ) 16 | config_option( 17 | OutputRawResults OUTPUT_RAW_RESULTS 18 | "As well as outputting statistics, dump raw results in JSON format." DEFAULT ON 19 | ) 20 | config_string( 21 | JsonIndent 22 | JSON_INDENT 23 | "Set the indent for JSON. By default it is 0, which is very fast to output, however setting\ 24 | the indent higher allows for more human readable output. Ranges from 0 to 31." 25 | DEFAULT 26 | 0 27 | UNQUOTE 28 | ) 29 | 30 | # Default dependencies on kernel benchmarking features. Declared here so that 31 | # all the benchmark applications can use it 32 | if((KernelArchX86 33 | AND KernelExportPMCUser 34 | AND KernelX86DangerousMSR) 35 | OR (KernelArchARM AND KernelArmExportPMUUser) 36 | OR (KernelArchArmCortexA8 AND KernelDangerousCodeInjection) 37 | ) 38 | set(DefaultBenchDeps TRUE) 39 | else() 40 | set(DefaultBenchDeps FALSE) 41 | endif() 42 | 43 | find_package(musllibc REQUIRED) 44 | find_package(util_libs REQUIRED) 45 | find_package(seL4_libs REQUIRED) 46 | find_package(sel4_projects_libs REQUIRED) 47 | find_package(projects_libs REQUIRED) 48 | 49 | # This sets up environment build flags and imports musllibc and runtime 50 | # libraries. 51 | musllibc_setup_build_environment_with_sel4runtime() 52 | sel4_import_libsel4() 53 | util_libs_import_libraries() 54 | set(LibSel4MuslcSysMorecoreBytes 55 | 0 56 | CACHE STRING "" FORCE 57 | ) 58 | sel4_libs_import_libraries() 59 | projects_libs_import_libraries() 60 | set(LibNanopb 61 | ON 62 | CACHE BOOL "" FORCE 63 | ) 64 | sel4_projects_libs_import_libraries() 65 | 66 | add_subdirectory(../fault fault) 67 | add_subdirectory(../hardware hardware) 68 | add_subdirectory(../ipc ipc) 69 | add_subdirectory(../irquser irquser) 70 | add_subdirectory(../page_mapping page_mapping) 71 | add_subdirectory(../scheduler scheduler) 72 | add_subdirectory(../signal signal) 73 | add_subdirectory(../smp smp) 74 | add_subdirectory(../sync sync) 75 | add_subdirectory(../vcpu vcpu) 76 | # Add new benchmark applications here 77 | 78 | add_subdirectory(../../libsel4benchsupport libsel4benchsupport) 79 | 80 | config_option(Sel4Bench SEL4_BENCH "Enable seL4 benchmarking" DEFAULT ON) 81 | 82 | if(Sel4Bench) 83 | add_config_library(sel4benchapp "${configure_string}") 84 | 85 | file(GLOB static src/*.c src/plat/${KernelPlatform}/*.c) 86 | 87 | get_property(sel4benchapps GLOBAL PROPERTY sel4benchapps_property) 88 | include(cpio) 89 | makecpio(archive.o "${sel4benchapps}") 90 | add_executable(sel4benchapp EXCLUDE_FROM_ALL ${static} archive.o) 91 | 92 | target_link_libraries( 93 | sel4benchapp 94 | jansson 95 | sel4benchsupport 96 | sel4 97 | sel4muslcsys 98 | sel4rpc 99 | sel4_autoconf 100 | sel4benchapp_Config 101 | sel4benchfault_Config 102 | hardware_Config 103 | sel4benchipc_Config 104 | sel4benchirquser_Config 105 | sel4benchpagemapping_Config 106 | sel4benchscheduler_Config 107 | sel4benchsignal_Config 108 | smp_Config 109 | sel4benchsync_Config 110 | sel4benchvcpu_Config 111 | # Add new benchmark configs here 112 | ) 113 | include(rootserver) 114 | declarerootserver(sel4benchapp) 115 | endif() 116 | -------------------------------------------------------------------------------- /apps/sel4bench/src/sync.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include "benchmark.h" 7 | #include "processing.h" 8 | #include "json.h" 9 | 10 | #include 11 | #include 12 | 13 | static json_t *sync_process(void *results) 14 | { 15 | sync_results_t *raw_results = results; 16 | 17 | result_desc_t desc = { 18 | .stable = false, 19 | .name = "sync benchmarks", 20 | .ignored = N_IGNORED 21 | }; 22 | 23 | /* construct waiter column */ 24 | json_int_t column_values[N_WAITERS]; 25 | for (json_int_t i = 0; i < N_WAITERS; i++) { 26 | column_values[i] = i; 27 | } 28 | 29 | column_t extra = { 30 | .header = "Waiter", 31 | .type = JSON_INTEGER, 32 | .integer_array = &column_values[0] 33 | }; 34 | 35 | result_t wait_results[N_WAITERS]; 36 | 37 | result_set_t set = { 38 | .name = "", 39 | .extra_cols = &extra, 40 | .n_extra_cols = 1, 41 | .results = wait_results, 42 | .n_results = N_WAITERS, 43 | }; 44 | 45 | json_t *array = json_array(); 46 | 47 | for (int j = 0; j < N_BROADCAST_BENCHMARKS; ++j) { 48 | process_results(N_WAITERS, N_RUNS, raw_results->broadcast_wait_time[j], desc, wait_results); 49 | set.name = broadcast_wait_names[j]; 50 | json_array_append_new(array, result_set_to_json(set)); 51 | } 52 | 53 | result_t result; 54 | set.n_extra_cols = 0; 55 | set.extra_cols = NULL; 56 | set.results = &result; 57 | set.n_results = 1; 58 | 59 | for (int j = 0; j < N_BROADCAST_BENCHMARKS; ++j) { 60 | result = process_result(N_RUNS, raw_results->broadcast_broadcast_time[j], desc); 61 | set.name = broadcast_broadcast_names[j]; 62 | json_array_append_new(array, result_set_to_json(set)); 63 | } 64 | 65 | for (int j = 0; j < N_PROD_CONS_BENCHMARKS; ++j) { 66 | result = process_result(N_RUNS, raw_results->producer_to_consumer[j], desc); 67 | set.name = producer_to_consumer_names[j]; 68 | json_array_append_new(array, result_set_to_json(set)); 69 | } 70 | 71 | for (int j = 0; j < N_PROD_CONS_BENCHMARKS; ++j) { 72 | result = process_result(N_RUNS, raw_results->consumer_to_producer[j], desc); 73 | set.name = consumer_to_producer_names[j]; 74 | json_array_append_new(array, result_set_to_json(set)); 75 | } 76 | 77 | result = process_result_early_proc(raw_results->producer_to_consumer_ep_num, 78 | raw_results->producer_to_consumer_ep_sum, 79 | raw_results->producer_to_consumer_ep_sum2, 80 | raw_results->producer_to_consumer_ep); 81 | set.name = "Producer to consumer (early processing)"; 82 | json_array_append_new(array, result_set_to_json(set)); 83 | 84 | result = process_result_early_proc(raw_results->consumer_to_producer_ep_num, 85 | raw_results->consumer_to_producer_ep_sum, 86 | raw_results->consumer_to_producer_ep_sum2, 87 | raw_results->consumer_to_producer_ep); 88 | set.name = "Consumer to producer (early processing)"; 89 | json_array_append_new(array, result_set_to_json(set)); 90 | 91 | return array; 92 | } 93 | 94 | static benchmark_t sync_benchmark = { 95 | .name = "sync", 96 | .enabled = config_set(CONFIG_APP_SYNCBENCH), 97 | .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(sync_results_t), seL4_PageBits), 98 | .process = sync_process, 99 | .init = blank_init 100 | }; 101 | 102 | benchmark_t *sync_benchmark_new(void) 103 | { 104 | return &sync_benchmark; 105 | } 106 | -------------------------------------------------------------------------------- /apps/smp/src/rnorrexp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: GPL-2.0-or-later OR MIT 3 | * 4 | * Copyright 200 Marsaglia and Tsang 5 | * 6 | * The source https://www.jstatsoft.org/article/view/v005i08 7 | * says GPL 2 or later or GPL-compatible license (which MIT is). 8 | * 9 | * The ziggurat method for RNOR and REXP 10 | * 11 | * Combine the code below with the main program in which you want 12 | * normal or exponential variates. 13 | * 14 | * Then use of REXP in any expression will provide an exponential variate 15 | * with density exp(-x), x > 0. Before using REXP in your main, insert a 16 | * command such as 'zigset(86947731);' with your own choice of seed value > 0, 17 | * rather than 86947731. If you do not invoke 'zigset(...)' you will get 18 | * all zeros for REXP. 19 | * 20 | * For details of the method, see Marsaglia and Tsang, "The ziggurat method 21 | * for generating random variables", Journ. Statistical Software. 22 | * 23 | * Note: Original code changed to support multiple threads and reduce cache bounce. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static struct { 32 | uint32_t jz; 33 | uint32_t jsr; 34 | int32_t hz; 35 | uint32_t iz; 36 | uint32_t kn[128]; 37 | uint32_t ke[256]; 38 | float wn[128]; 39 | float fn[128]; 40 | float we[256]; 41 | float fe[256]; 42 | uint64_t paddingg[8]; 43 | } rs[CONFIG_MAX_NUM_NODES] __attribute__((aligned(CACHE_LN_SZ)));; 44 | 45 | #define SHR3(id) (rs[id].jz = rs[id].jsr, rs[id].jsr ^= (rs[id].jsr << 13), rs[id].jsr ^= (rs[id].jsr >> 17), rs[id].jsr ^= (rs[id].jsr << 5), rs[id].jz + rs[id].jsr) 46 | #define UNI(id) (0.5 + (int32_t) SHR3(id) * 0.2328306e-9) 47 | #define REXP(id) (rs[id].jz = SHR3(id), rs[id].iz = rs[id].jz & 255, (rs[id].jz < rs[id].ke[rs[id].iz]) ? rs[id].jz * rs[id].we[rs[id].iz] : efix(id)) 48 | 49 | static float efix(int id) 50 | { 51 | float x; 52 | 53 | for (; ;) { 54 | if (rs[id].iz == 0) { 55 | return (7.69711 - log(UNI(id))); 56 | } 57 | 58 | x = rs[id].jz * rs[id].we[rs[id].iz]; 59 | if (rs[id].fe[rs[id].iz] + UNI(id) * (rs[id].fe[rs[id].iz - 1] - rs[id].fe[rs[id].iz]) < exp(-x)) { 60 | return (x); 61 | } 62 | 63 | rs[id].jz = SHR3(id); 64 | rs[id].iz = (rs[id].jz & 255); 65 | if (rs[id].jz < rs[id].ke[rs[id].iz]) { 66 | return (rs[id].jz * rs[id].we[rs[id].iz]); 67 | } 68 | } 69 | } 70 | 71 | static void zigset(int tid, uint32_t jsrseed) 72 | { 73 | const double m1 = 2147483648.0, m2 = 4294967296.; 74 | double dn = 3.442619855899, tn = dn, vn = 9.91256303526217e-3, q; 75 | double de = 7.697117470131487, te = de, ve = 3.949659822581572e-3; 76 | int i; 77 | rs[tid].jsr = 123456789; 78 | rs[tid].jsr ^= jsrseed; 79 | 80 | q = vn / exp(-0.5 * dn * dn); 81 | rs[tid].kn[0] = (dn / q) * m1; 82 | rs[tid].kn[1] = 0; 83 | 84 | rs[tid].wn[0] = q / m1; 85 | rs[tid].wn[127] = dn / m1; 86 | 87 | rs[tid].fn[0] = 1.0; 88 | rs[tid].fn[127] = exp(-0.5 * dn * dn); 89 | 90 | for (i = 126; i >= 1; i--) { 91 | dn = sqrt(-2.0 * log(vn / dn + exp(-0.5 * dn * dn))); 92 | rs[tid].kn[i + 1] = (dn / tn) * m1; 93 | tn = dn; 94 | rs[tid].fn[i] = exp(-0.5 * dn * dn); 95 | rs[tid].wn[i] = dn / m1; 96 | } 97 | 98 | q = ve / exp(-de); 99 | rs[tid].ke[0] = (de / q) * m2; 100 | rs[tid].ke[1] = 0; 101 | 102 | rs[tid].we[0] = q / m2; 103 | rs[tid].we[255] = de / m2; 104 | 105 | rs[tid].fe[0] = 1.0; 106 | rs[tid].fe[255] = exp(-de); 107 | 108 | for (i = 254; i >= 1; i--) { 109 | de = -log(ve / de + exp(-de)); 110 | rs[tid].ke[i + 1] = (de / te) * m2; 111 | te = de; 112 | rs[tid].fe[i] = exp(-de); 113 | rs[tid].we[i] = de / m2; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 6 | # sel4bench 7 | 8 | _sel4bench_ is a benchmarking applications and support library for 9 | [seL4](https://sel4.systems/). 10 | 11 | To get this project, check out the [project 12 | manifest](https://github.com/seL4/sel4bench-manifest). 13 | 14 | # Applications 15 | 16 | We provide multiple applications for benchmarking different paths in the 17 | kernel. 18 | 19 | ## sel4bench 20 | 21 | This is the driver application: it launches each benchmark in a separate 22 | process and collects, processes, and outputs results. 23 | 24 | ## ipc 25 | 26 | This is a hot-cache benchmark of the IPC path. 27 | 28 | ## irquser 29 | 30 | This is a hot-cache benchmark of the IRQ path, measured from user space. 31 | 32 | ## scheduler 33 | 34 | This is a hot-cache benchmark of a scheduling decision. It works by 35 | using a producer/consumer pattern between two notification objects. 36 | This benchmark also measures `seL4_Yield()`. 37 | 38 | ## signal 39 | 40 | This is a hot-cache benchmark of the signal path in the kernel, measured 41 | from user space. 42 | 43 | ## smp 44 | 45 | This is an intra-core IPC round-trip benchmark to check overhead of 46 | kernel synchronization on IPC throughput. 47 | 48 | ## vcpu _(AArch64 only)_ 49 | 50 | This benchmark will execute a thread as a VCPU (an EL1 guest kernel) and 51 | then obtain numbers for the following actions: 52 | * Privilege escalation from EL1 to EL2 using the `HVC` instruction. 53 | * Privilege de-escalation from EL2 to EL1 using the `ERET` instruction. 54 | * The cost of a null invocation of the EL2 kernel using `HVC`. 55 | * The cost of an `seL4_Call()` from an EL1 guest thread to a native seL4 56 | thread. 57 | * The cost of an `seL4_Reply()` from an seL4 native thread to an EL1 58 | guest thread. 59 | 60 | *Note:* In order to run this benchmark, you must notify the build system 61 | that you wish to enable this benchmark by passing `-DVCPU=true` on the 62 | command line, which will cause the kernel to be compiled to run in EL2. 63 | You must also ensure that you pass `-DHARDWARE=false` to disable the 64 | hardware tests. 65 | 66 | Since this benchmark will cause the kernel image to be an EL2 image, it 67 | will have an impact on the observed numbers for the other benchmark 68 | applications as well, since they'll be using an unexpected kernel build. 69 | 70 | 71 | # Adding a new benchmark 72 | 73 | Contributing a new benchmark to seL4bench requires a few steps: 74 | 75 | * Under `apps`, create a directory for your new benchmark and: 76 | * Provide a `CMakelists.txt` file that defines a new executable. 77 | * Provide a `src` folder that contains the source code for your 78 | benchmark. 79 | * Under `apps/sel4bench`: 80 | * Update `CMakeLists.txt` to add your new benchmark to the list of 81 | benchmarks. 82 | * Under `src`: 83 | * Update `benchmark.h` to include your generated config for your benchmark, and provide a function declaration that will act as the entry point for your benchmark. 84 | * Provide a `.c` file that implements the above function declaration. This function should return a `benchmark_t` struct. Construct this struct accordingly. The struct expects a function to process the results of the benchmark, which you should provide in this file as well 85 | * Inside `main.c`, add your entry point function that was declared/defined above to the array of `benchmark_t` present. 86 | * Update `easy-settings.cmake` to add your new benchmark. You can define here whether the benchmark should be enabled by default or not. 87 | * Under `libsel4benchsupport/include`: 88 | * Provide a `` file that provides any extra definitions that your benchmark may need. You will also generally provide a `benchmark_name_results_t` struct here, which will be used to store the results of your benchmark when processing. 89 | * Update `settings.cmake` to include your new benchmark. -------------------------------------------------------------------------------- /apps/sel4bench/src/ipc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "benchmark.h" 13 | #include "json.h" 14 | #include "math.h" 15 | #include "printing.h" 16 | #include "processing.h" 17 | 18 | static json_t *process_ipc_results(void *r) 19 | { 20 | ipc_results_t *raw_results = r; 21 | ccnt_t overheads[NUM_OVERHEAD_BENCHMARKS]; 22 | 23 | /* check overheads */ 24 | for (int i = 0; i < NUM_OVERHEAD_BENCHMARKS; i++) { 25 | if (!results_stable(&raw_results->overhead_benchmarks[i][1], RUNS - 1)) { 26 | if (!config_set(CONFIG_ALLOW_UNSTABLE_OVERHEAD)) { 27 | printf("Benchmarking overhead of a %s is not stable! Cannot continue\n", 28 | overhead_benchmark_params[i].name); 29 | print_all(RUNS, raw_results->overhead_benchmarks[i]); 30 | return NULL; 31 | } 32 | } 33 | result_desc_t desc = { 34 | .stable = false, 35 | .name = "overhead", 36 | .ignored = 0, 37 | .overhead = 0 38 | }; 39 | result_t overhead_result; 40 | overhead_result = process_result(RUNS - 1, raw_results->overhead_benchmarks[i], desc); 41 | overheads[i] = overhead_result.min; 42 | } 43 | 44 | int n = ARRAY_SIZE(benchmark_params); 45 | char *functions[n]; 46 | char *directions[n]; 47 | json_int_t client_prios[n]; 48 | json_int_t server_prios[n]; 49 | bool same_vspace[n]; 50 | json_int_t length[n]; 51 | 52 | column_t extra_cols[] = { 53 | { 54 | .header = "Function", 55 | .type = JSON_STRING, 56 | .string_array = &functions[0] 57 | }, 58 | { 59 | .header = "Direction", 60 | .type = JSON_STRING, 61 | .string_array = &directions[0], 62 | }, 63 | { 64 | .header = "Client Prio", 65 | .type = JSON_INTEGER, 66 | .integer_array = &client_prios[0] 67 | }, 68 | { 69 | .header = "Server Prio", 70 | .type = JSON_INTEGER, 71 | .integer_array = &server_prios[0] 72 | }, 73 | { 74 | .header = "Same vspace?", 75 | .type = JSON_TRUE, 76 | .bool_array = &same_vspace[0] 77 | }, 78 | { 79 | .header = "IPC length", 80 | .type = JSON_INTEGER, 81 | .integer_array = &length[0] 82 | } 83 | }; 84 | 85 | result_t results[n]; 86 | 87 | result_set_t result_set = { 88 | .name = "One way IPC microbenchmarks", 89 | .extra_cols = extra_cols, 90 | .n_extra_cols = ARRAY_SIZE(extra_cols), 91 | .results = results, 92 | .n_results = n, 93 | }; 94 | 95 | /* now calculate the results */ 96 | for (int i = 0; i < n; i++) { 97 | result_desc_t desc = { 98 | .name = benchmark_params[i].name, 99 | .overhead = overheads[benchmark_params[i].overhead_id], 100 | }; 101 | 102 | functions[i] = (char *) benchmark_params[i].name; 103 | directions[i] = benchmark_params[i].direction == DIR_TO ? "client->server" : 104 | "server->client"; 105 | client_prios[i] = benchmark_params[i].client_prio; 106 | server_prios[i] = benchmark_params[i].server_prio; 107 | same_vspace[i] = benchmark_params[i].same_vspace; 108 | length[i] = benchmark_params[i].length; 109 | 110 | results[i] = process_result(RUNS, raw_results->benchmarks[i], desc); 111 | } 112 | 113 | json_t *array = json_array(); 114 | json_array_append_new(array, result_set_to_json(result_set)); 115 | return array; 116 | } 117 | 118 | static benchmark_t ipc_benchmark = { 119 | .name = "ipc", 120 | .enabled = config_set(CONFIG_APP_IPCBENCH), 121 | .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(ipc_results_t), seL4_PageBits), 122 | .process = process_ipc_results, 123 | .init = blank_init 124 | }; 125 | 126 | benchmark_t *ipc_benchmark_new(void) 127 | { 128 | return &ipc_benchmark; 129 | } 130 | -------------------------------------------------------------------------------- /apps/sel4bench/src/plat/tx2/vcpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "../../benchmark.h" 14 | #include "../../json.h" 15 | #include "../../math.h" 16 | #include "../../printing.h" 17 | #include "../../processing.h" 18 | 19 | #define VCPU_BENCHMARK_N_PARAMS (0) 20 | 21 | /** Processes the VCPU benchmark results. 22 | * 23 | * We don't parameterize the benchmarks or anything fancy, so nothing 24 | * particularly amazing is done in here. 25 | */ 26 | static json_t *process_vcpu_results(void *r) 27 | { 28 | vcpu_benchmark_overall_results_t *raw_results = r; 29 | const int n_params = VCPU_BENCHMARK_N_PARAMS + 1; 30 | 31 | result_t results[VCPU_BENCHMARK_N_BENCHMARKS]; 32 | 33 | result_set_t hvc_priv_esc_result_set = { 34 | .name = "HVC Privilege Escalation", 35 | .extra_cols = NULL, 36 | .n_extra_cols = 0, 37 | .results = &results[VCPU_BENCHMARK_HVC_PRIV_ESCALATE], 38 | .n_results = n_params, 39 | }; 40 | 41 | result_set_t eret_priv_deesc_result_set = { 42 | .name = "ERET Privilege De-escalation", 43 | .extra_cols = NULL, 44 | .n_extra_cols = 0, 45 | .results = &results[VCPU_BENCHMARK_ERET_PRIV_DESCALATE], 46 | .n_results = n_params, 47 | }; 48 | 49 | result_set_t hvc_null_kcall_result_set = { 50 | .name = "NULL HVC kernel hypercall invocation", 51 | .extra_cols = NULL, 52 | .n_extra_cols = 0, 53 | .results = &results[VCPU_BENCHMARK_HVC_NULL_SYSCALL], 54 | .n_results = n_params, 55 | }; 56 | 57 | result_set_t sel4_call_ipc_result_set = { 58 | .name = "seL4_Call IPC from VCPU thread", 59 | .extra_cols = NULL, 60 | .n_extra_cols = 0, 61 | .results = &results[VCPU_BENCHMARK_CALL_SYSCALL], 62 | .n_results = n_params, 63 | }; 64 | 65 | result_set_t sel4_reply_ipc_result_set = { 66 | .name = "seL4_Reply IPC to VCPU thread", 67 | .extra_cols = NULL, 68 | .n_extra_cols = 0, 69 | .results = &results[VCPU_BENCHMARK_REPLY_SYSCALL], 70 | .n_results = n_params, 71 | }; 72 | 73 | result_set_t *bm_result_sets[VCPU_BENCHMARK_N_BENCHMARKS] = { 74 | &hvc_priv_esc_result_set, 75 | &eret_priv_deesc_result_set, 76 | &hvc_null_kcall_result_set, 77 | &sel4_call_ipc_result_set, 78 | &sel4_reply_ipc_result_set 79 | }; 80 | 81 | result_desc_t all_bms_result_desc = { 82 | /* We already check for outlier results in the benchmark app. */ 83 | .stable = false, 84 | .name = "VCPU benchmark", 85 | /* The overhead here is the overhead of the cycle counter register 86 | * read operation and not the overhead of the extra code paths which 87 | * are enabled in the kernel by BENCHMARK_TRACK_KERNEL_ENTRIES. 88 | */ 89 | .overhead = raw_results->ccnt_read_overhead, 90 | .ignored = VCPU_BENCH_N_ITERATIONS_IGNORED 91 | }; 92 | 93 | json_t *array = json_array(); 94 | 95 | for (int i = 0; i < VCPU_BENCHMARK_N_BENCHMARKS; i++) { 96 | /* process_result basically takes a bunch of numbers and computes 97 | * averages, means, deviations, etc. 98 | */ 99 | results[i] = process_result(VCPU_BENCH_N_ITERATIONS, 100 | raw_results->results[i].deep_data.elapsed, 101 | all_bms_result_desc); 102 | 103 | json_array_append_new(array, result_set_to_json(*bm_result_sets[i])); 104 | } 105 | 106 | return array; 107 | } 108 | 109 | #ifdef CONFIG_APP_VCPU_BENCH 110 | static benchmark_t vcpu_benchmark = { 111 | .name = "vcpu", 112 | .enabled = config_set(CONFIG_APP_VCPU_BENCH), 113 | .results_pages = BYTES_TO_SIZE_BITS_PAGES( 114 | sizeof(vcpu_benchmark_overall_results_t), 115 | seL4_PageBits), 116 | .process = process_vcpu_results, 117 | .init = blank_init 118 | }; 119 | 120 | benchmark_t *vcpu_benchmark_new(void) 121 | { 122 | return &vcpu_benchmark; 123 | } 124 | #endif 125 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/vcpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #define VCPU_BENCH_COLLECT_DEEP_DATA 1 29 | #define VCPU_BENCH_SHDATA_MAGIC (0xDEADCAB) 30 | /* Assume 800 cycles is a sufficient anomalous deviance */ 31 | #define VCPU_BENCH_CYCLE_COUNTER_ANOMALY_THRESHOLD (800) 32 | #define VCPU_BENCH_NAME_SIZE (48) 33 | #define VCPU_BENCH_N_GUESTS (1) 34 | #define VCPU_BENCH_GUEST_STACK_SIZE (BIT(seL4_PageBits) * 2) 35 | #define VCPU_BENCH_GUEST_PRINTF_BUFFER_SIZE VCPU_BENCH_GUEST_STACK_SIZE 36 | 37 | #define VCPU_BENCH_N_ITERATIONS_IGNORED (10) 38 | #define VCPU_BENCH_N_ITERATIONS (100 + VCPU_BENCH_N_ITERATIONS_IGNORED) 39 | 40 | // TX2 is Cortex A57 which has a 64B cache line size. 41 | #define VCPU_BENCH_CACHE_LINE_SZ (64) 42 | 43 | #define VCPU_BENCH_MSG_IS_FAULT_BIT (BIT(5)) 44 | #define VCPU_BENCH_MAX_N_GUESTS (VCPU_BENCH_MSG_IS_FAULT_BIT-1) 45 | 46 | typedef struct vcpu_bm_shared_globals_ { 47 | /* This is given to the kernel for use as the log buffer for timestamps */ 48 | vka_object_t log_buffer_frame_vkao; 49 | 50 | #ifdef CONFIG_BENCHMARK_TRACK_KERNEL_ENTRIES 51 | /* This is our mapping of the log buffer so we can read the timestamps. */ 52 | volatile benchmark_track_kernel_entry_t *sel4_log_buffer; 53 | #endif 54 | } vcpu_bm_shared_globals_t; 55 | 56 | extern vcpu_bm_shared_globals_t sg; 57 | 58 | enum hypcalls { 59 | /* Even though we namespace them, don't allow collision with fault type 60 | * label values. 61 | */ 62 | HYPCALL_SYS_NOOP = 15, 63 | HYPCALL_SYS_PUTC, 64 | HYPCALL_SYS_PUTS, 65 | HYPCALL_SYS_GET_SEL4_CALL_END_STAMP, 66 | HYPCALL_SYS_GET_SEL4_REPLY_START_STAMP, 67 | HYPCALL_SYS_BM_REPORT_END_RESULTS, 68 | HYPCALL_SYS_BM_REPORT_DEEP_RESULTS, 69 | HYPCALL_SYS_EL1_FAULT, 70 | HYPCALL_SYS_EXIT_THREAD, 71 | }; 72 | 73 | /* These threads will act as the guest VM threads with VCPUs bound to them. */ 74 | typedef struct _guest { 75 | int magic; 76 | int id, exitstatus; 77 | sel4utils_thread_t thread; 78 | vka_object_t vcpu_vkao; 79 | cspacepath_t badged_fault_ep, badged_fault_ep_ipc_copy; 80 | __attribute__((aligned(64))) uint8_t stack[VCPU_BENCH_GUEST_STACK_SIZE]; 81 | char printf_buffer[VCPU_BENCH_GUEST_PRINTF_BUFFER_SIZE]; 82 | } guest_t; 83 | 84 | extern guest_t guests[]; 85 | extern const char *vcpu_benchmark_names[]; 86 | 87 | enum vcpu_benchmarks { 88 | VCPU_BENCHMARK_HVC_PRIV_ESCALATE = 0, 89 | VCPU_BENCHMARK_ERET_PRIV_DESCALATE, 90 | VCPU_BENCHMARK_HVC_NULL_SYSCALL, 91 | VCPU_BENCHMARK_CALL_SYSCALL, 92 | VCPU_BENCHMARK_REPLY_SYSCALL, 93 | VCPU_BENCHMARK_N_BENCHMARKS, 94 | }; 95 | 96 | typedef struct _vcpu_benchmark_deep_data { 97 | ccnt_t start[VCPU_BENCH_N_ITERATIONS], 98 | end[VCPU_BENCH_N_ITERATIONS], 99 | elapsed[VCPU_BENCH_N_ITERATIONS]; 100 | } vcpu_benchmark_deep_data_t; 101 | 102 | typedef struct _vcpu_benchmark_results { 103 | char name[VCPU_BENCH_NAME_SIZE]; 104 | /* These meta variables here are only used by this app internally for 105 | * debugging, so we can print and eyeball the numbers. 106 | * The process_vcpu_results() function computes averages using 107 | * process_result(). 108 | */ 109 | uint64_t min, max, clipped_avg, complete_avg, clipped_total, complete_total; 110 | int n_anomalies; 111 | #if VCPU_BENCH_COLLECT_DEEP_DATA != 0 112 | vcpu_benchmark_deep_data_t deep_data; 113 | #endif 114 | } vcpu_benchmark_results_t; 115 | 116 | typedef struct vcpu_benchmark_overall_results_ { 117 | ccnt_t ccnt_read_overhead; 118 | vcpu_benchmark_results_t results[VCPU_BENCHMARK_N_BENCHMARKS]; 119 | } vcpu_benchmark_overall_results_t; 120 | 121 | NORETURN void 122 | guest__start(void); 123 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/aarch32/sel4_arch/ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #define DO_CALL(ep, tag, swi) do { \ 11 | register seL4_Word dest asm("r0") = (seL4_Word)ep; \ 12 | register seL4_MessageInfo_t info asm("r1") = tag; \ 13 | register seL4_Word scno asm("r7") = seL4_SysCall; \ 14 | asm volatile(NOPS swi NOPS \ 15 | : "+r"(dest), "+r"(info) \ 16 | : "r"(scno) \ 17 | ); \ 18 | } while(0) 19 | 20 | #define DO_CALL_10(ep, tag, swi) do { \ 21 | register seL4_Word dest asm("r0") = (seL4_Word)ep; \ 22 | register seL4_MessageInfo_t info asm("r1") = tag; \ 23 | register seL4_Word scno asm("r7") = seL4_SysCall; \ 24 | asm volatile(NOPS swi NOPS \ 25 | : "+r"(dest), "+r"(info) \ 26 | : "r"(scno) \ 27 | : "r2", "r3", "r4", "r5" \ 28 | ); \ 29 | } while(0) 30 | 31 | #define DO_SEND(ep, tag, swi) do { \ 32 | register seL4_Word dest asm("r0") = (seL4_Word)ep; \ 33 | register seL4_MessageInfo_t info asm("r1") = tag; \ 34 | register seL4_Word scno asm("r7") = seL4_SysSend; \ 35 | asm volatile(NOPS swi NOPS \ 36 | : "+r"(dest), "+r"(info) \ 37 | : "r"(scno) \ 38 | ); \ 39 | } while(0) 40 | 41 | 42 | #ifdef CONFIG_KERNEL_MCS 43 | #define DO_REPLY_RECV_10(ep, tag, ro, swi) do { \ 44 | register seL4_Word src asm("r0") = (seL4_Word)ep; \ 45 | register seL4_MessageInfo_t info asm("r1") = tag; \ 46 | register seL4_Word scno asm("r7") = seL4_SysReplyRecv; \ 47 | register seL4_Word ro_copy asm("r6") = ro; \ 48 | asm volatile(NOPS swi NOPS \ 49 | : "+r"(src), "+r"(info) \ 50 | : "r"(scno), "r" (ro_copy) \ 51 | : "r2", "r3", "r4", "r5" \ 52 | ); \ 53 | } while(0) 54 | 55 | #define DO_REPLY_RECV(ep, tag, ro, swi) do { \ 56 | register seL4_Word src asm("r0") = (seL4_Word)ep; \ 57 | register seL4_MessageInfo_t info asm("r1") = tag; \ 58 | register seL4_Word scno asm("r7") = seL4_SysReplyRecv; \ 59 | register seL4_Word ro_copy asm("r6") = ro; \ 60 | asm volatile(NOPS swi NOPS \ 61 | : "+r"(src), "+r"(info) \ 62 | : "r"(scno), "r" (ro_copy) \ 63 | ); \ 64 | } while(0) 65 | 66 | #define DO_RECV(ep, ro, swi) do { \ 67 | register seL4_Word src asm("r0") = (seL4_Word)ep; \ 68 | register seL4_MessageInfo_t info asm("r1"); \ 69 | register seL4_Word scno asm("r7") = seL4_SysRecv; \ 70 | register seL4_Word ro_copy asm("r6") = ro; \ 71 | asm volatile(NOPS swi NOPS \ 72 | : "+r"(src), "=r"(info) \ 73 | : "r"(scno), "r" (ro_copy) \ 74 | ); \ 75 | } while(0) 76 | #else 77 | #define DO_REPLY_RECV_10(ep, tag, ro, swi) do { \ 78 | register seL4_Word src asm("r0") = (seL4_Word)ep; \ 79 | register seL4_MessageInfo_t info asm("r1") = tag; \ 80 | register seL4_Word scno asm("r7") = seL4_SysReplyRecv; \ 81 | asm volatile(NOPS swi NOPS \ 82 | : "+r"(src), "+r"(info) \ 83 | : "r"(scno) \ 84 | : "r2", "r3", "r4", "r5" \ 85 | ); \ 86 | } while(0) 87 | 88 | #define DO_REPLY_RECV(ep, tag, ro, swi) do { \ 89 | register seL4_Word src asm("r0") = (seL4_Word)ep; \ 90 | register seL4_MessageInfo_t info asm("r1") = tag; \ 91 | register seL4_Word scno asm("r7") = seL4_SysReplyRecv; \ 92 | asm volatile(NOPS swi NOPS \ 93 | : "+r"(src), "+r"(info) \ 94 | : "r"(scno) \ 95 | ); \ 96 | } while(0) 97 | 98 | #define DO_RECV(ep, ro, swi) do { \ 99 | register seL4_Word src asm("r0") = (seL4_Word)ep; \ 100 | register seL4_MessageInfo_t info asm("r1"); \ 101 | register seL4_Word scno asm("r7") = seL4_SysRecv; \ 102 | asm volatile(NOPS swi NOPS \ 103 | : "+r"(src), "=r"(info) \ 104 | : "r"(scno) \ 105 | ); \ 106 | } while(0) 107 | #endif /* CONFIG_KERNEL_MCS */ 108 | 109 | #define DO_REAL_CALL(ep, tag) DO_CALL(ep, tag, "swi $0") 110 | #define DO_NOP_CALL(ep, tag) DO_CALL(ep, tag, "nop") 111 | #define DO_REAL_CALL_10(ep, tag) DO_CALL_10(ep, tag, "swi $0") 112 | #define DO_NOP_CALL_10(ep, tag) DO_CALL_10(ep, tag, "nop") 113 | #define DO_REAL_SEND(ep, tag) DO_SEND(ep, tag, "swi $0") 114 | #define DO_NOP_SEND(ep, tag) DO_SEND(ep, tag, "nop") 115 | 116 | #define DO_REAL_REPLY_RECV(ep, tag, ro) DO_REPLY_RECV(ep, tag, ro, "swi $0") 117 | #define DO_NOP_REPLY_RECV(ep, tag, ro) DO_REPLY_RECV(ep, tag, ro, "nop") 118 | #define DO_REAL_REPLY_RECV_10(ep, tag, ro) DO_REPLY_RECV_10(ep, tag, ro, "swi $0") 119 | #define DO_NOP_REPLY_RECV_10(ep, tag, ro) DO_REPLY_RECV_10(ep, tag, ro, "nop") 120 | #define DO_REAL_RECV(ep, ro) DO_RECV(ep, ro, "swi $0") 121 | #define DO_NOP_RECV(ep, ro) DO_RECV(ep, ro, "nop") 122 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/aarch64/sel4_arch/ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #define DO_CALL(ep, tag, swi) do { \ 11 | register seL4_Word dest asm("x0") = (seL4_Word)ep; \ 12 | register seL4_MessageInfo_t info asm("x1") = tag; \ 13 | register seL4_Word scno asm("x7") = seL4_SysCall; \ 14 | asm volatile(NOPS swi NOPS \ 15 | : "+r"(dest), "+r"(info) \ 16 | : "r"(scno) \ 17 | ); \ 18 | } while(0) 19 | 20 | #define DO_CALL_10(ep, tag, swi) do { \ 21 | register seL4_Word dest asm("x0") = (seL4_Word)ep; \ 22 | register seL4_MessageInfo_t info asm("x1") = tag; \ 23 | register seL4_Word scno asm("x7") = seL4_SysCall; \ 24 | asm volatile(NOPS swi NOPS \ 25 | : "+r"(dest), "+r"(info) \ 26 | : "r"(scno) \ 27 | : "x2", "x3", "x4", "x5" \ 28 | ); \ 29 | } while(0) 30 | 31 | #define DO_SEND(ep, tag, swi) do { \ 32 | register seL4_Word dest asm("x0") = (seL4_Word)ep; \ 33 | register seL4_MessageInfo_t info asm("x1") = tag; \ 34 | register seL4_Word scno asm("x7") = seL4_SysSend; \ 35 | asm volatile(NOPS swi NOPS \ 36 | : "+r"(dest), "+r"(info) \ 37 | : "r"(scno) \ 38 | ); \ 39 | } while(0) 40 | 41 | 42 | #ifdef CONFIG_KERNEL_MCS 43 | #define DO_REPLY_RECV_10(ep, tag, ro, swi) do { \ 44 | register seL4_Word src asm("x0") = (seL4_Word)ep; \ 45 | register seL4_MessageInfo_t info asm("x1") = tag; \ 46 | register seL4_Word scno asm("x7") = seL4_SysReplyRecv; \ 47 | register seL4_Word ro_copy asm("x6") = ro; \ 48 | asm volatile(NOPS swi NOPS \ 49 | : "+r"(src), "+r"(info) \ 50 | : "r"(scno), "r" (ro_copy) \ 51 | : "x2", "x3", "x4", "x5" \ 52 | ); \ 53 | } while(0) 54 | 55 | #define DO_REPLY_RECV(ep, tag, ro, swi) do { \ 56 | register seL4_Word src asm("x0") = (seL4_Word)ep; \ 57 | register seL4_MessageInfo_t info asm("x1") = tag; \ 58 | register seL4_Word scno asm("x7") = seL4_SysReplyRecv; \ 59 | register seL4_Word ro_copy asm("x6") = ro; \ 60 | asm volatile(NOPS swi NOPS \ 61 | : "+r"(src), "+r"(info) \ 62 | : "r"(scno), "r" (ro_copy) \ 63 | ); \ 64 | } while(0) 65 | 66 | #define DO_RECV(ep, ro, swi) do { \ 67 | register seL4_Word src asm("x0") = (seL4_Word)ep; \ 68 | register seL4_MessageInfo_t info asm("x1"); \ 69 | register seL4_Word scno asm("x7") = seL4_SysRecv; \ 70 | register seL4_Word ro_copy asm("x6") = ro; \ 71 | asm volatile(NOPS swi NOPS \ 72 | : "+r"(src), "=r"(info) \ 73 | : "r"(scno), "r" (ro_copy) \ 74 | ); \ 75 | } while(0) 76 | #else 77 | #define DO_REPLY_RECV_10(ep, tag, ro, swi) do { \ 78 | register seL4_Word src asm("x0") = (seL4_Word)ep; \ 79 | register seL4_MessageInfo_t info asm("x1") = tag; \ 80 | register seL4_Word scno asm("x7") = seL4_SysReplyRecv; \ 81 | asm volatile(NOPS swi NOPS \ 82 | : "+r"(src), "+r"(info) \ 83 | : "r"(scno) \ 84 | : "x2", "x3", "x4", "x5" \ 85 | ); \ 86 | } while(0) 87 | 88 | #define DO_REPLY_RECV(ep, tag, ro, swi) do { \ 89 | register seL4_Word src asm("x0") = (seL4_Word)ep; \ 90 | register seL4_MessageInfo_t info asm("x1") = tag; \ 91 | register seL4_Word scno asm("x7") = seL4_SysReplyRecv; \ 92 | asm volatile(NOPS swi NOPS \ 93 | : "+r"(src), "+r"(info) \ 94 | : "r"(scno) \ 95 | ); \ 96 | } while(0) 97 | 98 | #define DO_RECV(ep, ro, swi) do { \ 99 | register seL4_Word src asm("x0") = (seL4_Word)ep; \ 100 | register seL4_MessageInfo_t info asm("x1"); \ 101 | register seL4_Word scno asm("x7") = seL4_SysRecv; \ 102 | asm volatile(NOPS swi NOPS \ 103 | : "+r"(src), "=r"(info) \ 104 | : "r"(scno) \ 105 | ); \ 106 | } while(0) 107 | #endif /* CONFIG_KERNEL_MCS */ 108 | 109 | #define DO_REAL_CALL(ep, tag) DO_CALL(ep, tag, "svc #0") 110 | #define DO_NOP_CALL(ep, tag) DO_CALL(ep, tag, "nop") 111 | #define DO_REAL_CALL_10(ep, tag) DO_CALL_10(ep, tag, "svc #0") 112 | #define DO_NOP_CALL_10(ep, tag) DO_CALL_10(ep, tag, "nop") 113 | #define DO_REAL_SEND(ep, tag) DO_SEND(ep, tag, "svc #0") 114 | #define DO_NOP_SEND(ep, tag) DO_SEND(ep, tag, "nop") 115 | 116 | #define DO_REAL_REPLY_RECV(ep, tag, ro) DO_REPLY_RECV(ep, tag, ro, "svc #0") 117 | #define DO_NOP_REPLY_RECV(ep, tag, ro) DO_REPLY_RECV(ep, tag, ro, "nop") 118 | #define DO_REAL_REPLY_RECV_10(ep, tag, ro) DO_REPLY_RECV_10(ep, tag, ro, "svc #0") 119 | #define DO_NOP_REPLY_RECV_10(ep, tag, ro) DO_REPLY_RECV_10(ep, tag, ro, "nop") 120 | #define DO_REAL_RECV(ep, ro) DO_RECV(ep, ro, "svc #0") 121 | #define DO_NOP_RECV(ep, ro) DO_RECV(ep, ro, "nop") 122 | -------------------------------------------------------------------------------- /libsel4benchsupport/arch_include/riscv/arch/ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #define DO_CALL(ep, tag, swi) do { \ 11 | register seL4_Word dest asm("a0") = (seL4_Word)ep; \ 12 | register seL4_MessageInfo_t info asm("a1") = tag; \ 13 | register seL4_Word scno asm("a7") = seL4_SysCall; \ 14 | asm volatile(NOPS swi NOPS \ 15 | : "+r"(dest), "+r"(info) \ 16 | : "r"(scno) \ 17 | ); \ 18 | } while(0) 19 | 20 | #define DO_CALL_10(ep, tag, swi) do { \ 21 | register seL4_Word dest asm("a0") = (seL4_Word)ep; \ 22 | register seL4_MessageInfo_t info asm("a1") = tag; \ 23 | register seL4_Word scno asm("a7") = seL4_SysCall; \ 24 | asm volatile(NOPS swi NOPS \ 25 | : "+r"(dest), "+r"(info) \ 26 | : "r"(scno) \ 27 | : "a2", "a3", "a4", "a5" \ 28 | ); \ 29 | } while(0) 30 | 31 | #define DO_SEND(ep, tag, swi) do { \ 32 | register seL4_Word dest asm("a0") = (seL4_Word)ep; \ 33 | register seL4_MessageInfo_t info asm("a1") = tag; \ 34 | register seL4_Word scno asm("a7") = seL4_SysSend; \ 35 | asm volatile(NOPS swi NOPS \ 36 | : "+r"(dest), "+r"(info) \ 37 | : "r"(scno) \ 38 | ); \ 39 | } while(0) 40 | 41 | 42 | #ifdef CONFIG_KERNEL_MCS 43 | #define DO_REPLY_RECV_10(ep, tag, ro, swi) do { \ 44 | register seL4_Word src asm("a0") = (seL4_Word)ep; \ 45 | register seL4_MessageInfo_t info asm("a1") = tag; \ 46 | register seL4_Word scno asm("a7") = seL4_SysReplyRecv; \ 47 | register seL4_Word ro_copy asm("a6") = ro; \ 48 | asm volatile(NOPS swi NOPS \ 49 | : "+r"(src), "+r"(info) \ 50 | : "r"(scno), "r" (ro_copy) \ 51 | : "a2", "a3", "a4", "a5" \ 52 | ); \ 53 | } while(0) 54 | 55 | #define DO_REPLY_RECV(ep, tag, ro, swi) do { \ 56 | register seL4_Word src asm("a0") = (seL4_Word)ep; \ 57 | register seL4_MessageInfo_t info asm("a1") = tag; \ 58 | register seL4_Word scno asm("a7") = seL4_SysReplyRecv; \ 59 | register seL4_Word ro_copy asm("a6") = ro; \ 60 | asm volatile(NOPS swi NOPS \ 61 | : "+r"(src), "+r"(info) \ 62 | : "r"(scno), "r" (ro_copy) \ 63 | ); \ 64 | } while(0) 65 | 66 | #define DO_RECV(ep, ro, swi) do { \ 67 | register seL4_Word src asm("a0") = (seL4_Word)ep; \ 68 | register seL4_MessageInfo_t info asm("a1"); \ 69 | register seL4_Word scno asm("a7") = seL4_SysRecv; \ 70 | register seL4_Word ro_copy asm("a6") = ro; \ 71 | asm volatile(NOPS swi NOPS \ 72 | : "+r"(src), "=r"(info) \ 73 | : "r"(scno), "r" (ro_copy) \ 74 | ); \ 75 | } while(0) 76 | #else 77 | #define DO_REPLY_RECV_10(ep, tag, ro, swi) do { \ 78 | register seL4_Word src asm("a0") = (seL4_Word)ep; \ 79 | register seL4_MessageInfo_t info asm("a1") = tag; \ 80 | register seL4_Word scno asm("a7") = seL4_SysReplyRecv; \ 81 | asm volatile(NOPS swi NOPS \ 82 | : "+r"(src), "+r"(info) \ 83 | : "r"(scno) \ 84 | : "a2", "a3", "a4", "a5" \ 85 | ); \ 86 | } while(0) 87 | 88 | #define DO_REPLY_RECV(ep, tag, ro, swi) do { \ 89 | register seL4_Word src asm("a0") = (seL4_Word)ep; \ 90 | register seL4_MessageInfo_t info asm("a1") = tag; \ 91 | register seL4_Word scno asm("a7") = seL4_SysReplyRecv; \ 92 | asm volatile(NOPS swi NOPS \ 93 | : "+r"(src), "+r"(info) \ 94 | : "r"(scno) \ 95 | ); \ 96 | } while(0) 97 | 98 | #define DO_RECV(ep, ro, swi) do { \ 99 | register seL4_Word src asm("a0") = (seL4_Word)ep; \ 100 | register seL4_MessageInfo_t info asm("a1"); \ 101 | register seL4_Word scno asm("a7") = seL4_SysRecv; \ 102 | asm volatile(NOPS swi NOPS \ 103 | : "+r"(src), "=r"(info) \ 104 | : "r"(scno) \ 105 | ); \ 106 | } while(0) 107 | #endif /* CONFIG_KERNEL_MCS */ 108 | 109 | #define DO_REAL_CALL(ep, tag) DO_CALL(ep, tag, "ecall") 110 | #define DO_NOP_CALL(ep, tag) DO_CALL(ep, tag, "nop") 111 | #define DO_REAL_CALL_10(ep, tag) DO_CALL_10(ep, tag, "ecall") 112 | #define DO_NOP_CALL_10(ep, tag) DO_CALL_10(ep, tag, "nop") 113 | #define DO_REAL_SEND(ep, tag) DO_SEND(ep, tag, "ecall") 114 | #define DO_NOP_SEND(ep, tag) DO_SEND(ep, tag, "nop") 115 | 116 | #define DO_REAL_REPLY_RECV(ep, tag, ro) DO_REPLY_RECV(ep, tag, ro, "ecall") 117 | #define DO_NOP_REPLY_RECV(ep, tag, ro) DO_REPLY_RECV(ep, tag, ro, "nop") 118 | #define DO_REAL_REPLY_RECV_10(ep, tag, ro) DO_REPLY_RECV_10(ep, tag, ro, "ecall") 119 | #define DO_NOP_REPLY_RECV_10(ep, tag, ro) DO_REPLY_RECV_10(ep, tag, ro, "nop") 120 | #define DO_REAL_RECV(ep, ro) DO_RECV(ep, ro, "ecall") 121 | #define DO_NOP_RECV(ep, ro) DO_RECV(ep, ro, "nop") 122 | 123 | #define READ_COUNTER_BEFORE SEL4BENCH_READ_CCNT 124 | #define READ_COUNTER_AFTER SEL4BENCH_READ_CCNT 125 | -------------------------------------------------------------------------------- /apps/sel4bench/src/json.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include "json.h" 10 | 11 | static inline json_t *json_real_check(double val) 12 | { 13 | json_t *real = json_real(val); 14 | if (!real) { 15 | return json_string(isnan(val) ? "nan" : "inf"); 16 | } 17 | return real; 18 | } 19 | 20 | static void result_to_json(result_t result, json_t *j) 21 | { 22 | UNUSED int error = json_object_set_new(j, "Min", json_integer(result.min)); 23 | assert(error == 0); 24 | 25 | error = json_object_set_new(j, "Max", json_integer(result.max)); 26 | assert(error == 0); 27 | 28 | error = json_object_set_new(j, "Mean", json_real_check(result.mean)); 29 | assert(error == 0); 30 | 31 | error = json_object_set_new(j, "Stddev", json_real_check(result.stddev)); 32 | assert(error == 0); 33 | 34 | error = json_object_set_new(j, "Variance", json_real_check(result.variance)); 35 | assert(error == 0); 36 | 37 | error = json_object_set_new(j, "Mode", json_real_check(result.mode)); 38 | assert(error == 0); 39 | 40 | error = json_object_set_new(j, "Median", json_real_check(result.median)); 41 | assert(error == 0); 42 | 43 | error = json_object_set_new(j, "1st quantile", json_real_check(result.first_quantile)); 44 | assert(error == 0); 45 | 46 | error = json_object_set_new(j, "3rd quantile", json_real_check(result.third_quantile)); 47 | assert(error == 0); 48 | 49 | error = json_object_set_new(j, "Samples", json_integer(result.samples)); 50 | assert(error == 0); 51 | 52 | json_t *raw_results = json_array(); 53 | assert(raw_results != NULL); 54 | 55 | if (config_set(CONFIG_OUTPUT_RAW_RESULTS)) { 56 | for (size_t i = 0; i < result.samples; i++) { 57 | error = json_array_append_new(raw_results, json_integer(result.raw_data[i])); 58 | assert(error == 0); 59 | } 60 | json_object_set_new(j, "Raw results", raw_results); 61 | assert(error == 0); 62 | } 63 | } 64 | 65 | static json_t *get_json_cell(column_t column, size_t index) 66 | { 67 | switch (column.type) { 68 | case JSON_STRING: 69 | return json_string(column.string_array[index]); 70 | case JSON_INTEGER: 71 | return json_integer(column.integer_array[index]); 72 | case JSON_REAL: 73 | return json_real_check(column.real_array[index]); 74 | case JSON_TRUE: 75 | case JSON_FALSE: 76 | return json_boolean(column.bool_array[index]); 77 | default: 78 | ZF_LOGE("Columns of type %d not supported", column.type); 79 | return json_null(); 80 | } 81 | } 82 | 83 | json_t *result_set_to_json(result_set_t set) 84 | { 85 | UNUSED int error; 86 | json_t *object = json_object(); 87 | assert(object != NULL); 88 | 89 | error = json_object_set_new(object, "Benchmark", json_string(set.name)); 90 | assert(error == 0); 91 | 92 | json_t *rows = json_array(); 93 | assert(rows != NULL); 94 | 95 | error = json_object_set_new(object, "Results", rows); 96 | assert(error == 0); 97 | 98 | for (int i = 0; i < set.n_results; i++) { 99 | json_t *row = json_object(); 100 | for (int c = 0; c < set.n_extra_cols; c++) { 101 | assert(set.extra_cols != NULL); 102 | json_t *cell = get_json_cell(set.extra_cols[c], i); 103 | assert(cell != NULL); 104 | 105 | error = json_object_set_new(row, set.extra_cols[c].header, cell); 106 | assert(error == 0); 107 | 108 | } 109 | result_to_json(set.results[i], row); 110 | 111 | error = json_array_append_new(rows, row); 112 | assert(error == 0); 113 | } 114 | 115 | return object; 116 | } 117 | 118 | json_t *average_counters_to_json(char *name, result_t results[NUM_AVERAGE_EVENTS]) 119 | { 120 | json_t *obj = json_object(); 121 | 122 | assert(obj != NULL); 123 | UNUSED int error = json_object_set_new(obj, "Benchmark", json_string(name)); 124 | assert(error == 0); 125 | 126 | json_t *rows = json_array(); 127 | assert(rows != 0); 128 | 129 | error = json_object_set_new(obj, "Results", rows); 130 | 131 | for (int i = 0; i < SEL4BENCH_NUM_GENERIC_EVENTS; i++) { 132 | json_t *row = json_object(); 133 | assert(row != NULL); 134 | 135 | error = json_object_set_new(row, "Event", json_string(GENERIC_EVENT_NAMES[i])); 136 | assert(error == 0); 137 | 138 | result_to_json(results[i], row); 139 | 140 | json_array_append_new(rows, row); 141 | } 142 | 143 | json_t *row = json_object(); 144 | assert(row != NULL); 145 | 146 | error = json_object_set_new(row, "Event", json_string("Cycle counter")); 147 | assert(error == 0); 148 | 149 | result_to_json(results[CYCLE_COUNT_EVENT], row); 150 | 151 | error = json_array_append_new(rows, row); 152 | assert(error == 0); 153 | 154 | return obj; 155 | } 156 | -------------------------------------------------------------------------------- /.github/workflows/sel4bench.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2021, Proofcraft Pty Ltd 2 | # 3 | # SPDX-License-Identifier: BSD-2-Clause 4 | 5 | # Deploy default.xml to sel4bench-manifest after successful runs. 6 | 7 | name: seL4Bench 8 | 9 | on: 10 | push: 11 | branches: [master] 12 | paths-ignore: 13 | - '**.md' 14 | 15 | # allow manual trigger 16 | workflow_dispatch: 17 | 18 | # allow explict trigger from other repos when dependencies have changed 19 | repository_dispatch: 20 | types: [deps-update] 21 | 22 | jobs: 23 | code: 24 | name: Freeze Code 25 | runs-on: ubuntu-latest 26 | outputs: 27 | xml: ${{ steps.repo.outputs.xml }} 28 | steps: 29 | - id: repo 30 | uses: seL4/ci-actions/repo-checkout@master 31 | with: 32 | manifest_repo: sel4bench-manifest 33 | manifest: master.xml 34 | 35 | build: 36 | name: Build 37 | needs: code 38 | runs-on: ubuntu-latest 39 | strategy: 40 | fail-fast: false 41 | matrix: 42 | march: [armv7a, armv8a, nehalem, rv64imac] 43 | steps: 44 | - name: Build 45 | uses: seL4/ci-actions/sel4bench@master 46 | with: 47 | xml: ${{ needs.code.outputs.xml }} 48 | march: ${{ matrix.march }} 49 | - name: Upload images 50 | uses: actions/upload-artifact@v4 51 | with: 52 | name: images-${{ matrix.march }} 53 | path: '*-images.tar.gz' 54 | 55 | hw-run: 56 | name: HW Run 57 | if: ${{ github.repository_owner == 'seL4' }} 58 | runs-on: ubuntu-latest 59 | needs: [build] 60 | strategy: 61 | fail-fast: false 62 | matrix: 63 | platform: 64 | - sabre 65 | - imx8mm_evk 66 | - odroid_c2 67 | - odroid_xu4 68 | - am335x_boneblack 69 | - tx1 70 | - tx2 71 | - hifive 72 | include: 73 | - platform: pc99 74 | req: skylake 75 | - platform: pc99 76 | req: haswell3 77 | # do not run concurrently with other workflows, but do run concurrently in the build matrix 78 | concurrency: sel4bench-hw-${{ strategy.job-index }} 79 | steps: 80 | - name: Get machine queue 81 | uses: actions/checkout@v4 82 | with: 83 | repository: seL4/machine_queue 84 | path: machine_queue 85 | - name: Get march 86 | id: plat 87 | uses: seL4/ci-actions/march-of-platform@master 88 | with: 89 | platform: ${{ matrix.platform }} 90 | - name: Download image 91 | uses: actions/download-artifact@v4 92 | with: 93 | name: images-${{ steps.plat.outputs.march }} 94 | - name: Run 95 | uses: seL4/ci-actions/sel4bench-hw@master 96 | with: 97 | platform: ${{ matrix.platform }} 98 | req: ${{ matrix.req }} 99 | index: $${{ strategy.job-index }} 100 | env: 101 | HW_SSH: ${{ secrets.HW_SSH }} 102 | - name: Upload results 103 | uses: actions/upload-artifact@v4 104 | with: 105 | # funky expression below is to work around lack of ternary operator 106 | name: sel4bench-results-${{ matrix.platform }}${{ matrix.req != '' && format('-{0}', matrix.req) || '' }} 107 | path: '*.json' 108 | 109 | deploy: 110 | name: Deploy 111 | if: ${{ github.repository_owner == 'seL4' }} 112 | runs-on: ubuntu-22.04 113 | needs: [code, hw-run] 114 | steps: 115 | - name: Deploy manifest 116 | id: deploy 117 | uses: seL4/ci-actions/manifest-deploy@master 118 | with: 119 | xml: ${{ needs.code.outputs.xml }} 120 | manifest_repo: sel4bench-manifest 121 | env: 122 | GH_SSH: ${{ secrets.CI_SSH }} 123 | - name: Check out website repo 124 | uses: actions/checkout@v4 125 | with: 126 | repository: seL4/website 127 | token: ${{ secrets.PRIV_REPO_TOKEN }} 128 | - name: Get results for web deployment (sabre) 129 | uses: actions/download-artifact@v4 130 | with: 131 | name: sel4bench-results-sabre 132 | - name: Get results for web deployment (haswell) 133 | uses: actions/download-artifact@v4 134 | with: 135 | name: sel4bench-results-pc99-haswell3 136 | - name: Get results for web deployment (skylake) 137 | uses: actions/download-artifact@v4 138 | with: 139 | name: sel4bench-results-pc99-skylake 140 | - name: Get results for web deployment (tx1) 141 | uses: actions/download-artifact@v4 142 | with: 143 | name: sel4bench-results-tx1 144 | - name: Get results for web deployment (hifive) 145 | uses: actions/download-artifact@v4 146 | with: 147 | name: sel4bench-results-hifive 148 | - name: Generate json results 149 | uses: seL4/ci-actions/sel4bench-web@master 150 | with: 151 | manifest_sha: ${{ steps.deploy.outputs.manifest_sha }} 152 | - name: Deploy to web site 153 | run: | 154 | mv benchmarks.json _data/ 155 | git config user.name "seL4 CI" 156 | git config user.email "ci@sel4.systems" 157 | git add _data/benchmarks.json 158 | git commit -s -m "CI: update performance results" 159 | git push origin master 160 | -------------------------------------------------------------------------------- /apps/sel4bench/src/scheduler.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | #include "benchmark.h" 7 | #include "processing.h" 8 | #include "json.h" 9 | 10 | #include 11 | #include 12 | 13 | static void process_yield_results(scheduler_results_t *results, ccnt_t overhead, json_t *array) 14 | { 15 | result_desc_t desc = { 16 | .ignored = N_IGNORED, 17 | .overhead = overhead, 18 | }; 19 | 20 | result_t result; 21 | result_set_t set = { 22 | .name = "Thread yield", 23 | .n_extra_cols = 0, 24 | .results = &result, 25 | .n_results = 1, 26 | }; 27 | 28 | result = process_result(N_RUNS, results->thread_yield, desc); 29 | json_array_append_new(array, result_set_to_json(set)); 30 | 31 | set.name = "Thread yield (early processing)"; 32 | result = process_result_early_proc(results->thread_yield_ep_num, results->thread_yield_ep_sum, 33 | results->thread_yield_ep_sum2, results->thread_yield_ep); 34 | json_array_append_new(array, result_set_to_json(set)); 35 | 36 | set.name = "Process yield"; 37 | result = process_result(N_RUNS, results->process_yield, desc); 38 | json_array_append_new(array, result_set_to_json(set)); 39 | 40 | set.name = "Process yield (early processing)"; 41 | result = process_result_early_proc(results->process_yield_ep_num, results->process_yield_ep_sum, 42 | results->process_yield_ep_sum2, results->process_yield_ep); 43 | json_array_append_new(array, result_set_to_json(set)); 44 | 45 | result_t average_results[NUM_AVERAGE_EVENTS]; 46 | process_average_results(N_RUNS, NUM_AVERAGE_EVENTS, results->average_yield, average_results); 47 | json_array_append_new(array, average_counters_to_json("Average seL4_Yield (no thread switch)", 48 | average_results)); 49 | } 50 | 51 | static void process_scheduler_results(scheduler_results_t *results, json_t *array) 52 | { 53 | result_desc_t desc = { 54 | .stable = true, 55 | .name = "Signal overhead", 56 | .ignored = N_IGNORED 57 | }; 58 | result_t result = process_result(N_RUNS, results->overhead_signal, desc); 59 | result_t per_prio_result[N_PRIOS]; 60 | 61 | /* signal overhead */ 62 | result_set_t set = { 63 | .name = "Signal overhead", 64 | .n_extra_cols = 0, 65 | .results = &result, 66 | .n_results = 1, 67 | }; 68 | json_array_append_new(array, result_set_to_json(set)); 69 | 70 | /* thread switch overhead */ 71 | desc.stable = false; 72 | desc.overhead = result.min; 73 | 74 | process_results(N_PRIOS, N_RUNS, results->thread_results, desc, per_prio_result); 75 | 76 | /* construct prio column */ 77 | json_int_t column_values[N_PRIOS]; 78 | for (json_int_t i = 0; i < N_PRIOS; i++) { 79 | /* generate the prios corresponding to the benchmarked prio values */ 80 | column_values[i] = gen_next_prio(i); 81 | } 82 | 83 | column_t extra = { 84 | .header = "Prio", 85 | .type = JSON_INTEGER, 86 | .integer_array = &column_values[0] 87 | }; 88 | 89 | set.name = "Signal to thread of higher prio"; 90 | set.extra_cols = &extra, 91 | set.n_extra_cols = 1, 92 | set.results = per_prio_result, 93 | set.n_results = N_PRIOS, 94 | json_array_append_new(array, result_set_to_json(set)); 95 | 96 | set.name = "Signal to process of higher prio"; 97 | process_results(N_PRIOS, N_RUNS, results->process_results, desc, per_prio_result); 98 | json_array_append_new(array, result_set_to_json(set)); 99 | 100 | result_t average_results[NUM_AVERAGE_EVENTS]; 101 | process_average_results(N_RUNS, NUM_AVERAGE_EVENTS, results->set_prio_average, average_results); 102 | json_array_append_new(array, average_counters_to_json("Average to reschedule current thread", 103 | average_results)); 104 | } 105 | 106 | static json_t *scheduler_process(void *results) 107 | { 108 | scheduler_results_t *raw_results = results; 109 | json_t *array = json_array(); 110 | 111 | process_scheduler_results(raw_results, array); 112 | 113 | result_desc_t desc = { 114 | .name = "Read ccnt overhead", 115 | .stable = true, 116 | .ignored = N_IGNORED, 117 | }; 118 | 119 | result_t ccnt_overhead = process_result(N_RUNS, raw_results->overhead_ccnt, desc); 120 | 121 | result_set_t set = { 122 | .name = "Read ccnt overhead", 123 | .n_extra_cols = 0, 124 | .results = &ccnt_overhead, 125 | .n_results = 1 126 | }; 127 | 128 | json_array_append_new(array, result_set_to_json(set)); 129 | 130 | process_yield_results(raw_results, ccnt_overhead.min, array); 131 | 132 | return array; 133 | } 134 | 135 | static benchmark_t sched_benchmark = { 136 | .name = "scheduler", 137 | .enabled = config_set(CONFIG_APP_SCHEDULERBENCH), 138 | .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(scheduler_results_t), seL4_PageBits), 139 | .process = scheduler_process, 140 | .init = blank_init 141 | }; 142 | 143 | benchmark_t *scheduler_benchmark_new(void) 144 | { 145 | return &sched_benchmark; 146 | } 147 | -------------------------------------------------------------------------------- /apps/sel4bench/src/math.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: GPL-2.0-only 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "benchmark.h" 13 | #include "math.h" 14 | 15 | /* these functions adapted from libgsl -- require code to be GPL */ 16 | static double results_mean(const size_t n, const ccnt_t array[n]) 17 | { 18 | size_t i; 19 | long double mean = 0; 20 | /* Compute the arithmetic mean of a dataset using the recurrence relation 21 | * mean_(n) = mean(n-1) + (data[n] - mean(n-1))/(n+1) */ 22 | 23 | for (i = 0; i < n; i++) { 24 | mean += (array[i] - mean) / (i + 1); 25 | } 26 | return mean; 27 | } 28 | 29 | static double results_variance(const size_t n, const ccnt_t array[n], const ccnt_t mean) 30 | { 31 | long double variance = 0; 32 | 33 | size_t i; 34 | 35 | /* find the sum of the squares */ 36 | for (i = 0; i < n; i++) { 37 | const long double delta = (long double) array[i] - (long double) mean; 38 | variance += (delta * delta - variance) / (i + 1); 39 | } 40 | 41 | return (double) variance; 42 | } 43 | 44 | static double results_stddev(const size_t n, const ccnt_t array[n], const long double variance) 45 | { 46 | return sqrt(variance * ((double) n / (double)(n - 1.0f))); 47 | } 48 | 49 | static double results_median(const size_t n, const ccnt_t sorted_data[n]) 50 | { 51 | double median; 52 | const size_t lhs = (n - 1) / 2; 53 | const size_t rhs = n / 2; 54 | size_t stride = 1; 55 | 56 | if (n == 0) { 57 | return 0.0; 58 | } 59 | 60 | if (lhs == rhs) { 61 | median = sorted_data[lhs * stride]; 62 | } else { 63 | median = (sorted_data[lhs * stride] + sorted_data[rhs * stride]) / 2.0; 64 | } 65 | 66 | return median; 67 | } 68 | 69 | static double results_quantile(const size_t n, const ccnt_t sorted_data[n], const double quantile) 70 | { 71 | const double index = quantile * (n - 1) ; 72 | const size_t lhs = (int)index ; 73 | const double delta = index - lhs ; 74 | double result; 75 | const size_t stride = 1; 76 | 77 | if (n == 0) { 78 | return 0.0; 79 | } 80 | 81 | if (lhs == n - 1) { 82 | result = sorted_data[lhs * stride] ; 83 | } else { 84 | result = (1 - delta) * sorted_data[lhs * stride] + delta * sorted_data[(lhs + 1) * stride] ; 85 | } 86 | 87 | return result; 88 | } 89 | 90 | static ccnt_t results_mode(const size_t n, const ccnt_t sorted_data[n]) 91 | { 92 | if (n == 0) { 93 | return 0; 94 | } else if (n == 1) { 95 | return sorted_data[0]; 96 | } 97 | 98 | ccnt_t mode = sorted_data[0]; 99 | ccnt_t current_value = sorted_data[0]; 100 | ccnt_t current_freq = 1; 101 | ccnt_t mode_freq = 0; 102 | 103 | for (size_t i = 1; i < n; i++) { 104 | if (current_value == sorted_data[i]) { 105 | current_freq++; 106 | } else { 107 | if (current_freq > mode_freq) { 108 | mode_freq = current_freq; 109 | mode = current_value; 110 | } 111 | 112 | current_value = sorted_data[i]; 113 | current_freq = 1; 114 | } 115 | } 116 | 117 | if (mode_freq == 0) { 118 | mode_freq = current_freq; 119 | } 120 | 121 | return mode; 122 | } 123 | 124 | static int ccnt_compare_fn(const void *a, const void *b) 125 | { 126 | ccnt_t first = *((ccnt_t *) a); 127 | ccnt_t second = *((ccnt_t *) b); 128 | 129 | return (first > second) - (first < second); 130 | } 131 | 132 | result_t calculate_results(const size_t n, ccnt_t data[n]) 133 | { 134 | /* create a copy of the data to sort */ 135 | ccnt_t sorted_data[n]; 136 | memcpy(sorted_data, data, n * sizeof(ccnt_t)); 137 | 138 | /* sort the data */ 139 | qsort(sorted_data, n, sizeof(ccnt_t), ccnt_compare_fn); 140 | 141 | result_t result; 142 | result.min = sorted_data[0]; 143 | result.max = sorted_data[n - 1]; 144 | assert(result.min <= result.max); 145 | result.mean = results_mean(n, sorted_data); 146 | result.variance = results_variance(n, sorted_data, result.mean); 147 | result.stddev = results_stddev(n, sorted_data, result.variance); 148 | result.median = results_median(n, sorted_data); 149 | result.first_quantile = results_quantile(n, sorted_data, 0.25f); 150 | result.third_quantile = results_quantile(n, sorted_data, 0.75f); 151 | result.mode = results_mode(n, sorted_data); 152 | result.raw_data = data; 153 | result.samples = n; 154 | 155 | return result; 156 | } 157 | 158 | static double results_variance_early_proc(const size_t num, const ccnt_t sum, 159 | const ccnt_t sum2, const ccnt_t mean) 160 | { 161 | long double variance = 0; 162 | long double dm = mean, dsum = sum, dsum2 = sum2; 163 | 164 | /* sigma = ( sum(x^2) - 2m*sum(x) + n*m^2 ) / num */ 165 | 166 | variance = (dsum2 - 2 * dm * dsum + num * dm * dm) / num; 167 | 168 | return variance; 169 | } 170 | 171 | result_t calculate_results_early_proc(ccnt_t num, ccnt_t sum, ccnt_t sum2, ccnt_t array[num]) 172 | { 173 | 174 | result_t result; 175 | 176 | memset((void *)&result, 0, sizeof(result)); 177 | result.mean = sum / num; 178 | result.variance = results_variance_early_proc(num, sum, sum2, result.mean); 179 | result.stddev = sqrt(result.variance * ((double) num / (double)(num - 1.0f)));; 180 | result.raw_data = array; 181 | result.samples = num; 182 | 183 | return result; 184 | 185 | } 186 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/ia32/sel4_arch/ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #define DO_CALL(ep, tag, sys) do { \ 12 | uint32_t ep_copy = ep; \ 13 | asm volatile( \ 14 | "movl %%esp, %%ecx \n"\ 15 | "leal 1f, %%edx \n"\ 16 | "1: \n" \ 17 | sys" \n" \ 18 | : \ 19 | "+S" (tag), \ 20 | "+b" (ep_copy) \ 21 | : \ 22 | "a" (seL4_SysCall) \ 23 | : \ 24 | "ecx", \ 25 | "edx" \ 26 | ); \ 27 | } while(0) 28 | 29 | #define DO_CALL_10(ep, tag, sys) do { \ 30 | uint32_t ep_copy = ep; \ 31 | asm volatile( \ 32 | "pushl %%ebp \n"\ 33 | "movl %%esp, %%ecx \n"\ 34 | "leal 1f, %%edx \n"\ 35 | "1: \n" \ 36 | sys" \n" \ 37 | "popl %%ebp \n"\ 38 | : \ 39 | "+S" (tag), \ 40 | "+b" (ep_copy) \ 41 | : \ 42 | "a" (seL4_SysCall) \ 43 | : \ 44 | "ecx", \ 45 | "edx", \ 46 | "edi" \ 47 | ); \ 48 | } while(0) 49 | 50 | #define DO_SEND(ep, tag, sys) do { \ 51 | uint32_t ep_copy = ep; \ 52 | uint32_t tag_copy = tag.words[0]; \ 53 | asm volatile( \ 54 | "movl %%esp, %%ecx \n"\ 55 | "leal 1f, %%edx \n"\ 56 | "1: \n" \ 57 | sys" \n" \ 58 | : \ 59 | "+S" (tag_copy), \ 60 | "+b" (ep_copy) \ 61 | : \ 62 | "a" (seL4_SysSend) \ 63 | : \ 64 | "ecx", \ 65 | "edx" \ 66 | ); \ 67 | } while(0) 68 | 69 | #ifdef CONFIG_KERNEL_MCS 70 | #define DO_REPLY_RECV(ep, tag, ro, sys) do { \ 71 | uint32_t ep_copy = ep; \ 72 | uint32_t ro_copy = ro; \ 73 | asm volatile( \ 74 | "pushl %%ebp \n"\ 75 | "movl %%ecx, %%ebp \n"\ 76 | "movl %%esp, %%ecx \n"\ 77 | "leal 1f, %%edx \n"\ 78 | "1: \n" \ 79 | sys" \n" \ 80 | "popl %%ebp \n"\ 81 | : \ 82 | "+S" (tag), \ 83 | "+b" (ep_copy), \ 84 | "+c" (ro_copy) \ 85 | : \ 86 | "a" (seL4_SysReplyRecv) \ 87 | : \ 88 | "edx" \ 89 | ); \ 90 | } while(0) 91 | 92 | #define DO_REPLY_RECV_10(ep, tag, ro, sys) do { \ 93 | uint32_t ep_copy = ep; \ 94 | uint32_t ro_copy = ro; \ 95 | asm volatile( \ 96 | "pushl %%ebp \n"\ 97 | "movl %%ecx, %%ebp \n"\ 98 | "movl %%esp, %%ecx \n"\ 99 | "leal 1f, %%edx \n"\ 100 | "1: \n" \ 101 | sys" \n" \ 102 | "popl %%ebp \n"\ 103 | : \ 104 | "+S" (tag), \ 105 | "+b" (ep_copy), \ 106 | "+c" (ro_copy) \ 107 | : \ 108 | "a" (seL4_SysReplyRecv) \ 109 | : \ 110 | "edx", \ 111 | "edi" \ 112 | ); \ 113 | } while(0) 114 | 115 | #define DO_RECV(ep, ro, sys) do { \ 116 | uint32_t ep_copy = ep; \ 117 | uint32_t ro_copy = ro; \ 118 | asm volatile( \ 119 | "pushl %%ebp \n"\ 120 | "movl %%ecx, %%ebp \n"\ 121 | "movl %%esp, %%ecx \n"\ 122 | "leal 1f, %%edx \n"\ 123 | "1: \n" \ 124 | sys" \n" \ 125 | "popl %%ebp \n"\ 126 | : \ 127 | "+b" (ep_copy), \ 128 | "+c" (ro_copy) \ 129 | : \ 130 | "a" (seL4_SysRecv) \ 131 | : \ 132 | "edx", \ 133 | "esi" \ 134 | ); \ 135 | } while(0) 136 | #else 137 | #define DO_REPLY_RECV(ep, tag, ro, sys) do { \ 138 | uint32_t ep_copy = ep; \ 139 | asm volatile( \ 140 | "movl %%esp, %%ecx \n"\ 141 | "leal 1f, %%edx \n"\ 142 | "1: \n" \ 143 | sys" \n" \ 144 | : \ 145 | "+S" (tag), \ 146 | "+b" (ep_copy) \ 147 | : \ 148 | "a" (seL4_SysReplyRecv) \ 149 | : \ 150 | "ecx", \ 151 | "edx" \ 152 | ); \ 153 | } while(0) 154 | 155 | #define DO_REPLY_RECV_10(ep, tag, ro, sys) do { \ 156 | uint32_t ep_copy = ep; \ 157 | asm volatile( \ 158 | "pushl %%ebp \n"\ 159 | "movl %%esp, %%ecx \n"\ 160 | "leal 1f, %%edx \n"\ 161 | "1: \n" \ 162 | sys" \n" \ 163 | "popl %%ebp \n"\ 164 | : \ 165 | "+S" (tag), \ 166 | "+b" (ep_copy) \ 167 | : \ 168 | "a" (seL4_SysReplyRecv) \ 169 | : \ 170 | "ecx", \ 171 | "edx", \ 172 | "edi" \ 173 | ); \ 174 | } while(0) 175 | 176 | #define DO_RECV(ep, ro, sys) do { \ 177 | uint32_t ep_copy = ep; \ 178 | asm volatile( \ 179 | "movl %%esp, %%ecx \n"\ 180 | "leal 1f, %%edx \n"\ 181 | "1: \n" \ 182 | sys" \n" \ 183 | : \ 184 | "+b" (ep_copy) \ 185 | : \ 186 | "a" (seL4_SysRecv) \ 187 | : \ 188 | "ecx", \ 189 | "edx", \ 190 | "esi" \ 191 | ); \ 192 | } while(0) 193 | 194 | #endif /* CONFIG_KERNEL_MCS */ 195 | 196 | #define READ_COUNTER_BEFORE SEL4BENCH_READ_CCNT 197 | #define READ_COUNTER_AFTER SEL4BENCH_READ_CCNT 198 | 199 | #define DO_REAL_CALL(ep, tag) DO_CALL(ep, tag, "sysenter") 200 | #define DO_NOP_CALL(ep, tag) DO_CALL(ep, tag, ".byte 0x66\n.byte 0x90") 201 | #define DO_REAL_CALL_10(ep, tag) DO_CALL_10(ep, tag, "sysenter") 202 | #define DO_NOP_CALL_10(ep, tag) DO_CALL_10(ep, tag, ".byte 0x66\n.byte 0x90") 203 | #define DO_REAL_SEND(ep, tag) DO_SEND(ep, tag, "sysenter") 204 | #define DO_NOP_SEND(ep, tag) DO_SEND(ep, tag, ".byte 0x66\n.byte 0x90") 205 | #define DO_REAL_REPLY_RECV(ep, tag, ro) DO_REPLY_RECV(ep, tag, ro, "sysenter") 206 | #define DO_NOP_REPLY_RECV(ep, tag, ro) DO_REPLY_RECV(ep, tag, ro, ".byte 0x66\n.byte 0x90") 207 | #define DO_REAL_REPLY_RECV_10(ep, tag, ro) DO_REPLY_RECV_10(ep, tag, ro, "sysenter") 208 | #define DO_NOP_REPLY_RECV_10(ep, tag, ro) DO_REPLY_RECV_10(ep, tag, ro, ".byte 0x66\n.byte 0x90") 209 | #define DO_REAL_RECV(ep, ro) DO_RECV(ep, ro, "sysenter") 210 | #define DO_NOP_RECV(ep, ro) DO_RECV(ep, ro, ".byte 0x66\n.byte 0x90") 211 | -------------------------------------------------------------------------------- /libsel4benchsupport/sel4_arch_include/x86_64/sel4_arch/ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | 10 | #ifdef CONFIG_SYSCALL 11 | 12 | #define DO_CALL(ep, tag, sys) do { \ 13 | uint64_t ep_copy = ep; \ 14 | asm volatile(\ 15 | "movq %%rsp, %%rbx \n" \ 16 | sys " \n" \ 17 | "movq %%rbx, %%rsp \n" \ 18 | : \ 19 | "+S" (tag), \ 20 | "+D" (ep_copy) \ 21 | : \ 22 | "d" ((seL4_Word)seL4_SysCall) \ 23 | : \ 24 | "rcx", "rbx", "r11"\ 25 | ); \ 26 | } while (0) 27 | 28 | #define DO_CALL_10(ep, tag, sys) do {\ 29 | uint64_t ep_copy = ep; \ 30 | asm volatile( \ 31 | "movq %%rsp, %%rbx \n" \ 32 | sys " \n" \ 33 | "movq %%rbx, %%rsp \n" \ 34 | : \ 35 | "+S" (tag), \ 36 | "+D" (ep_copy) \ 37 | : \ 38 | "d" ((seL4_Word)seL4_SysCall) \ 39 | : \ 40 | "rcx","rbx","r11","r10","r8", "r9", "r15" \ 41 | ); \ 42 | } while (0) 43 | 44 | #define DO_SEND(ep, tag, sys) do { \ 45 | uint64_t ep_copy = ep; \ 46 | uint64_t tag_copy = tag.words[0]; \ 47 | asm volatile( \ 48 | "movq %%rsp, %%rbx \n" \ 49 | sys "\n" \ 50 | "movq %%rbx, %%rsp \n" \ 51 | : \ 52 | "+S" (tag_copy), \ 53 | "+D" (ep_copy) \ 54 | : \ 55 | "d" ((seL4_Word)seL4_SysSend) \ 56 | : \ 57 | "rcx", "rbx","r11" \ 58 | ); \ 59 | } while (0) 60 | 61 | #ifdef CONFIG_KERNEL_MCS 62 | #define DO_REPLY_RECV(ep, tag, ro, sys) do { \ 63 | uint64_t ep_copy = ep; \ 64 | register seL4_Word ro_copy asm("r12") = ro;\ 65 | asm volatile( \ 66 | "movq %%rsp, %%rbx \n" \ 67 | sys "\n" \ 68 | "movq %%rbx, %%rsp \n" \ 69 | : \ 70 | "+S" (tag), \ 71 | "+D" (ep_copy) \ 72 | : \ 73 | "d"((seL4_Word)seL4_SysReplyRecv), \ 74 | "r" (ro_copy) \ 75 | : \ 76 | "rcx", "rbx","r11" \ 77 | ); \ 78 | } while (0) 79 | 80 | #define DO_REPLY_RECV_10(ep, tag, ro, sys) do { \ 81 | uint64_t ep_copy = ep; \ 82 | register seL4_Word ro_copy asm("r12") = ro;\ 83 | asm volatile( \ 84 | "movq %%rsp, %%rbx \n" \ 85 | sys" \n" \ 86 | "movq %%rbx, %%rsp \n" \ 87 | : \ 88 | "+S" (tag), \ 89 | "+D" (ep_copy) \ 90 | : \ 91 | "d" ((seL4_Word)seL4_SysReplyRecv), \ 92 | "r" (ro_copy) \ 93 | : \ 94 | "rcx","rbx","r11","r10","r8", "r9", "r15" \ 95 | ); \ 96 | } while (0) 97 | 98 | #define DO_RECV(ep, ro, sys) do { \ 99 | uint64_t ep_copy = ep; \ 100 | uint64_t tag = 0; \ 101 | register seL4_Word ro_copy asm("r12") = ro;\ 102 | asm volatile( \ 103 | "movq %%rsp, %%rbx \n" \ 104 | sys" \n" \ 105 | "movq %%rbx, %%rsp \n" \ 106 | : \ 107 | "+S" (tag) ,\ 108 | "+D" (ep_copy) \ 109 | : \ 110 | "d" ((seL4_Word)seL4_SysRecv), \ 111 | "r" (ro_copy) \ 112 | : "rcx", "rbx","r11" \ 113 | ); \ 114 | } while (0) 115 | #else 116 | #define DO_REPLY_RECV(ep, tag, ro, sys) do { \ 117 | uint64_t ep_copy = ep; \ 118 | asm volatile( \ 119 | "movq %%rsp, %%rbx \n" \ 120 | sys "\n" \ 121 | "movq %%rbx, %%rsp \n" \ 122 | : \ 123 | "+S" (tag), \ 124 | "+D" (ep_copy) \ 125 | : \ 126 | "d"((seL4_Word)seL4_SysReplyRecv) \ 127 | : \ 128 | "rcx", "rbx","r11" \ 129 | ); \ 130 | } while (0) 131 | 132 | #define DO_REPLY_RECV_10(ep, tag, ro, sys) do { \ 133 | uint64_t ep_copy = ep; \ 134 | asm volatile( \ 135 | "movq %%rsp, %%rbx \n" \ 136 | sys" \n" \ 137 | "movq %%rbx, %%rsp \n" \ 138 | : \ 139 | "+S" (tag), \ 140 | "+D" (ep_copy) \ 141 | : \ 142 | "d" ((seL4_Word)seL4_SysReplyRecv) \ 143 | : \ 144 | "rcx","rbx","r11","r10","r8", "r9", "r15" \ 145 | ); \ 146 | } while (0) 147 | 148 | #define DO_RECV(ep, ro, sys) do { \ 149 | uint64_t ep_copy = ep; \ 150 | uint64_t tag = 0; \ 151 | asm volatile( \ 152 | "movq %%rsp, %%rbx \n" \ 153 | sys" \n" \ 154 | "movq %%rbx, %%rsp \n" \ 155 | : \ 156 | "+S" (tag) ,\ 157 | "+D" (ep_copy) \ 158 | : \ 159 | "d" ((seL4_Word)seL4_SysRecv) \ 160 | : "rcx", "rbx","r11" \ 161 | ); \ 162 | } while (0) 163 | #endif /* CONFIG_KERNEL_MCS */ 164 | 165 | #define READ_COUNTER_BEFORE(var) do { \ 166 | uint32_t low, high; \ 167 | asm volatile( \ 168 | "cpuid \n" \ 169 | "rdtsc \n" \ 170 | "movl %%edx, %0 \n" \ 171 | "movl %%eax, %1 \n" \ 172 | : "=r"(high), "=r"(low) \ 173 | : \ 174 | : "%rax", "%rbx", "%rcx", "%rdx"); \ 175 | (var) = (((uint64_t)high) << 32ull) | ((uint64_t)low); \ 176 | } while (0) 177 | 178 | #define READ_COUNTER_AFTER(var) do { \ 179 | uint32_t low, high; \ 180 | asm volatile( \ 181 | "rdtscp \n" \ 182 | "movl %%edx, %0 \n" \ 183 | "movl %%eax, %1 \n" \ 184 | "cpuid \n" \ 185 | : "=r"(high), "=r"(low) \ 186 | : \ 187 | : "%rax", "rbx", "%rcx", "%rdx"); \ 188 | (var) = (((uint64_t)high) << 32ull) | ((uint64_t)low); \ 189 | } while (0) 190 | 191 | #define DO_REAL_CALL(ep, tag) DO_CALL(ep, tag, "syscall") 192 | #define DO_NOP_CALL(ep, tag) DO_CALL(ep, tag, ".byte 0x66\n.byte 0x90") 193 | #define DO_REAL_CALL_10(ep, tag) DO_CALL_10(ep, tag, "syscall") 194 | #define DO_NOP_CALL_10(ep, tag) DO_CALL_10(ep, tag, ".byte 0x66\n.byte 0x90") 195 | #define DO_REAL_SEND(ep, tag) DO_SEND(ep, tag, "syscall") 196 | #define DO_NOP_SEND(ep, tag) DO_SEND(ep, tag, ".byte 0x66\n.byte 0x90") 197 | #define DO_REAL_REPLY_RECV(ep, tag, ro) DO_REPLY_RECV(ep, tag, ro, "syscall") 198 | #define DO_NOP_REPLY_RECV(ep, tag, ro) DO_REPLY_RECV(ep, tag, ro, ".byte 0x66\n.byte 0x90") 199 | #define DO_REAL_REPLY_RECV_10(ep, tag, ro) DO_REPLY_RECV_10(ep, tag, ro, "syscall") 200 | #define DO_NOP_REPLY_RECV_10(ep, tag, ro) DO_REPLY_RECV_10(ep, tag, ro, ".byte 0x66\n.byte 0x90") 201 | #define DO_REAL_RECV(ep, ro) DO_RECV(ep, ro, "syscall") 202 | #define DO_NOP_RECV(ep, ro) DO_RECV(ep, ro, ".byte 0x66\n.byte 0x90") 203 | 204 | #else 205 | #error Only support benchmarking with syscall as sysenter is known to be slower 206 | #endif /* CONFIG_SYSCALL */ 207 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/ipc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #define OVERHEAD_BENCH_PARAMS(n) { .name = n } 12 | #define RUNS 16 13 | 14 | enum overheads { 15 | CALL_OVERHEAD, 16 | REPLY_RECV_OVERHEAD, 17 | SEND_OVERHEAD, 18 | RECV_OVERHEAD, 19 | CALL_10_OVERHEAD, 20 | REPLY_RECV_10_OVERHEAD, 21 | /******/ 22 | NUM_OVERHEAD_BENCHMARKS 23 | }; 24 | 25 | typedef enum dir { 26 | /* client ---> server */ 27 | DIR_TO, 28 | /* server --> client */ 29 | DIR_FROM 30 | } dir_t; 31 | 32 | typedef enum { 33 | IPC_CALL_FUNC = 0, 34 | IPC_CALL_FUNC2 = 1, 35 | IPC_CALL_10_FUNC = 2, 36 | IPC_CALL_10_FUNC2 = 3, 37 | IPC_REPLYRECV_FUNC2 = 4, 38 | IPC_REPLYRECV_FUNC = 5, 39 | IPC_REPLYRECV_10_FUNC2 = 6, 40 | IPC_REPLYRECV_10_FUNC = 7, 41 | IPC_SEND_FUNC = 8, 42 | IPC_RECV_FUNC = 9 43 | } helper_func_id_t; 44 | 45 | typedef seL4_Word(*helper_func_t)(int argc, char *argv[]); 46 | 47 | typedef struct benchmark_params { 48 | /* name of the function we are benchmarking */ 49 | const char *name; 50 | /* direction of the ipc */ 51 | dir_t direction; 52 | /* functions for client and server to run */ 53 | helper_func_id_t server_fn, client_fn; 54 | /* should client and server run in the same vspace? */ 55 | bool same_vspace; 56 | /* prio for client and server to run at */ 57 | uint8_t server_prio, client_prio; 58 | /* length of ipc to send */ 59 | uint8_t length; 60 | /* id of overhead calculation for this function */ 61 | enum overheads overhead_id; 62 | /* if CONFIG_KERNEL_MCS, should the server be passive? */ 63 | bool passive; 64 | bool server_fpu; 65 | } benchmark_params_t; 66 | 67 | struct overhead_benchmark_params { 68 | const char *name; 69 | }; 70 | 71 | /* array of benchmarks to run */ 72 | /* one way IPC benchmarks - varying size, direction and priority.*/ 73 | static const benchmark_params_t benchmark_params[] = { 74 | /* Call fastpath between client and server in the same address space */ 75 | { 76 | .name = "seL4_Call", 77 | .direction = DIR_TO, 78 | .client_fn = IPC_CALL_FUNC2, 79 | .server_fn = IPC_REPLYRECV_FUNC2, 80 | .same_vspace = true, 81 | .client_prio = seL4_MaxPrio - 1, 82 | .server_prio = seL4_MaxPrio - 1, 83 | .length = 0, 84 | .overhead_id = CALL_OVERHEAD, 85 | .passive = true, 86 | .server_fpu = false, 87 | }, 88 | /* ReplyRecv fastpath between server and client in the same address space */ 89 | { 90 | .name = "seL4_ReplyRecv", 91 | .direction = DIR_FROM, 92 | .client_fn = IPC_CALL_FUNC, 93 | .server_fn = IPC_REPLYRECV_FUNC, 94 | .same_vspace = true, 95 | .client_prio = seL4_MaxPrio - 1, 96 | .server_prio = seL4_MaxPrio - 1, 97 | .length = 0, 98 | .overhead_id = REPLY_RECV_OVERHEAD, 99 | .passive = true, 100 | .server_fpu = false, 101 | }, 102 | /* Call fastpath between client and server in different address spaces */ 103 | { 104 | .name = "seL4_Call", 105 | .direction = DIR_TO, 106 | .client_fn = IPC_CALL_FUNC2, 107 | .server_fn = IPC_REPLYRECV_FUNC2, 108 | .same_vspace = false, 109 | .client_prio = seL4_MaxPrio - 1, 110 | .server_prio = seL4_MaxPrio - 1, 111 | .length = 0, 112 | .overhead_id = CALL_OVERHEAD, 113 | .passive = true, 114 | .server_fpu = false, 115 | }, 116 | /* Call fastpath between client and FPU enabled server in different address spaces */ 117 | { 118 | .name = "seL4_Call (FPU)", 119 | .direction = DIR_TO, 120 | .client_fn = IPC_CALL_FUNC2, 121 | .server_fn = IPC_REPLYRECV_FUNC2, 122 | .same_vspace = false, 123 | .client_prio = seL4_MaxPrio - 1, 124 | .server_prio = seL4_MaxPrio - 1, 125 | .length = 0, 126 | .overhead_id = CALL_OVERHEAD, 127 | .passive = true, 128 | .server_fpu = true, 129 | }, 130 | /* ReplyRecv fastpath between server and client in different address spaces */ 131 | { 132 | .name = "seL4_ReplyRecv", 133 | .direction = DIR_FROM, 134 | .client_fn = IPC_CALL_FUNC, 135 | .server_fn = IPC_REPLYRECV_FUNC, 136 | .same_vspace = false, 137 | .client_prio = seL4_MaxPrio - 1, 138 | .server_prio = seL4_MaxPrio - 1, 139 | .length = 0, 140 | .overhead_id = REPLY_RECV_OVERHEAD, 141 | .passive = true, 142 | .server_fpu = false, 143 | }, 144 | /* ReplyRecv fastpath between FPU enabled server and client in different address spaces */ 145 | { 146 | .name = "seL4_ReplyRecv (FPU)", 147 | .direction = DIR_FROM, 148 | .client_fn = IPC_CALL_FUNC, 149 | .server_fn = IPC_REPLYRECV_FUNC, 150 | .same_vspace = false, 151 | .client_prio = seL4_MaxPrio - 1, 152 | .server_prio = seL4_MaxPrio - 1, 153 | .length = 0, 154 | .overhead_id = REPLY_RECV_OVERHEAD, 155 | .passive = true, 156 | .server_fpu = true, 157 | }, 158 | /* Send slowpath (no fastpath for send) same prio client-server, different address space */ 159 | { 160 | .name = "seL4_Send", 161 | .direction = DIR_TO, 162 | .client_fn = IPC_SEND_FUNC, 163 | .server_fn = IPC_RECV_FUNC, 164 | .same_vspace = false, 165 | .client_prio = seL4_MaxPrio - 2, 166 | .server_prio = seL4_MaxPrio - 1, 167 | .length = 0, 168 | .overhead_id = SEND_OVERHEAD, 169 | .passive = false, 170 | .server_fpu = false, 171 | }, 172 | /* Call slowpath, long IPC (10), same prio client to server, different address space */ 173 | { 174 | .name = "seL4_Call", 175 | .direction = DIR_TO, 176 | .client_fn = IPC_CALL_10_FUNC2, 177 | .server_fn = IPC_REPLYRECV_10_FUNC2, 178 | .same_vspace = false, 179 | .client_prio = seL4_MaxPrio - 1, 180 | .server_prio = seL4_MaxPrio - 1, 181 | .length = 10, 182 | .overhead_id = CALL_10_OVERHEAD, 183 | .passive = false, 184 | .server_fpu = false, 185 | }, 186 | /* ReplyRecv slowpath, long IPC (10), same prio server to client, on the slowpath, different address space */ 187 | { 188 | .name = "seL4_ReplyRecv", 189 | .direction = DIR_FROM, 190 | .client_fn = IPC_CALL_10_FUNC, 191 | .server_fn = IPC_REPLYRECV_10_FUNC, 192 | .same_vspace = false, 193 | .client_prio = seL4_MaxPrio - 1, 194 | .server_prio = seL4_MaxPrio - 1, 195 | .length = 10, 196 | .overhead_id = REPLY_RECV_10_OVERHEAD, 197 | .passive = false, 198 | .server_fpu = false, 199 | } 200 | }; 201 | 202 | static const struct overhead_benchmark_params overhead_benchmark_params[] = { 203 | [CALL_OVERHEAD] = {"call"}, 204 | [REPLY_RECV_OVERHEAD] = {"reply recv"}, 205 | [SEND_OVERHEAD] = {"send"}, 206 | [RECV_OVERHEAD] = {"recv"}, 207 | [CALL_10_OVERHEAD] = {"call"}, 208 | [REPLY_RECV_10_OVERHEAD] = {"reply recv"}, 209 | }; 210 | 211 | typedef struct ipc_results { 212 | /* Raw results from benchmarking. These get checked for sanity */ 213 | ccnt_t overhead_benchmarks[NUM_OVERHEAD_BENCHMARKS][RUNS]; 214 | ccnt_t benchmarks[ARRAY_SIZE(benchmark_params)][RUNS]; 215 | } ipc_results_t; 216 | 217 | static inline bool results_stable(ccnt_t *array, size_t size) 218 | { 219 | for (size_t i = 1; i < size; i++) { 220 | if (array[i] != array[i - 1]) { 221 | return false; 222 | } 223 | } 224 | 225 | return true; 226 | } 227 | -------------------------------------------------------------------------------- /settings.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.16.0) 8 | 9 | set(project_dir "${CMAKE_CURRENT_LIST_DIR}/../..") 10 | file(GLOB project_modules ${project_dir}/projects/*) 11 | list(APPEND CMAKE_MODULE_PATH ${project_dir}/kernel ${project_dir}/tools/seL4/cmake-tool/helpers/ 12 | ${project_dir}/tools/seL4/elfloader-tool/ ${project_modules} 13 | ) 14 | 15 | set(NANOPB_SRC_ROOT_FOLDER 16 | "${project_dir}/nanopb" 17 | CACHE STRING "NanoPB Folder location" 18 | ) 19 | set(OPENSBI_PATH 20 | "${project_dir}/tools/opensbi" 21 | CACHE STRING "OpenSBI Folder location" 22 | ) 23 | 24 | set(SEL4_CONFIG_DEFAULT_ADVANCED ON) 25 | include(application_settings) 26 | 27 | include(${CMAKE_CURRENT_LIST_DIR}/easy-settings.cmake) 28 | 29 | if(VCPU) 30 | set(ARM_HYP 31 | ON 32 | CACHE BOOL "ARM EL2 hypervisor features on or off" FORCE 33 | ) 34 | endif() 35 | correct_platform_strings() 36 | 37 | find_package(seL4 REQUIRED) 38 | sel4_configure_platform_settings() 39 | 40 | set(valid_platforms ${KernelPlatform_all_strings} ${correct_platform_strings_platform_aliases}) 41 | set_property(CACHE PLATFORM PROPERTY STRINGS ${valid_platforms}) 42 | if(NOT "${PLATFORM}" IN_LIST valid_platforms) 43 | message(FATAL_ERROR "Invalid PLATFORM selected: \"${PLATFORM}\" 44 | Valid platforms are: \"${valid_platforms}\"" 45 | ) 46 | endif() 47 | 48 | # Declare a cache variable that enables/disablings the forcing of cache 49 | # variables to the specific test values. By default it is disabled 50 | set(Sel4benchAllowSettingsOverride 51 | OFF 52 | CACHE BOOL "Allow user to override configuration settings" 53 | ) 54 | if(NOT Sel4benchAllowSettingsOverride) 55 | # We use 'FORCE' when settings these values instead of 'INTERNAL' so that they 56 | # still appear in the cmake-gui to prevent excessively confusing users 57 | # Determine the platform/architecture 58 | if(KernelArchARM) 59 | if(NOT VCPU) 60 | set(AppVcpuBench 61 | OFF 62 | CACHE BOOL "" FORCE 63 | ) 64 | endif() 65 | if(KernelSel4ArchAarch64) 66 | if(ARM_HYP) 67 | set(KernelArmHypervisorSupport 68 | ON 69 | CACHE BOOL "" FORCE 70 | ) 71 | endif() 72 | endif() 73 | 74 | endif() 75 | 76 | if(KernelSel4ArchAarch32) 77 | set(KernelArmTLSReg 78 | tpidruro 79 | CACHE STRING "" FORCE 80 | ) 81 | endif() 82 | if(KernelSel4ArchAarch64) 83 | set(KernelArmTLSReg 84 | tpidru 85 | CACHE STRING "" FORCE 86 | ) 87 | endif() 88 | 89 | # Setup flags for RELEASE (performance optimized builds) 90 | applycommonreleaseverificationsettings(${RELEASE} OFF) 91 | # This option is controlled by ApplyCommonReleaseVerificationSettings 92 | mark_as_advanced(CMAKE_BUILD_TYPE) 93 | if(RELEASE) 94 | if(NOT KernelArchRiscV) 95 | set(KernelFWholeProgram 96 | ON 97 | CACHE BOOL "" FORCE 98 | ) 99 | endif() 100 | endif() 101 | 102 | if(FASTPATH) 103 | set(KernelFastpath 104 | ON 105 | CACHE BOOL "" FORCE 106 | ) 107 | else() 108 | set(KernelFastpath 109 | OFF 110 | CACHE BOOL "" FORCE 111 | ) 112 | endif() 113 | 114 | # App-specific configuration 115 | if(FAULT) 116 | set(AppFaultBench 117 | ON 118 | CACHE BOOL "" FORCE 119 | ) 120 | else() 121 | set(AppFaultBench 122 | OFF 123 | CACHE BOOL "" FORCE 124 | ) 125 | endif() 126 | 127 | if(HARDWARE) 128 | set(KernelBenchmarks 129 | "generic" 130 | CACHE STRING "" FORCE 131 | ) 132 | set(AppHardwareBench 133 | ON 134 | CACHE BOOL "" FORCE 135 | ) 136 | elseif(VCPU) 137 | # The VCPU benchmarks require the kernel entry and exit timestamp feature. 138 | set(AppVcpuBench 139 | ON 140 | CACHE BOOL "" FORCE 141 | ) 142 | set(KernelBenchmarks 143 | "track_kernel_entries" 144 | CACHE STRING "" FORCE 145 | ) 146 | else() 147 | set(KernelBenchmarks 148 | "none" 149 | CACHE STRING "" FORCE 150 | ) 151 | set(AppHardwareBench 152 | OFF 153 | CACHE BOOL "" FORCE 154 | ) 155 | endif() 156 | 157 | if(SMP) 158 | if(RELEASE) 159 | if(KernelPlatformIMX93) 160 | set(KernelMaxNumNodes 161 | 2 162 | CACHE STRING "" FORCE 163 | ) 164 | else() 165 | set(KernelMaxNumNodes 166 | 4 167 | CACHE STRING "" FORCE 168 | ) 169 | endif() 170 | set(AppSmpBench 171 | ON 172 | CACHE BOOL "" FORCE 173 | ) 174 | if(KernelPlatImx6) 175 | set(ElfloaderMode 176 | "secure supervisor" 177 | CACHE STRING "" FORCE 178 | ) 179 | elseif(KernelPlatformTK1) 180 | set(ElfloaderMode 181 | "monitor" 182 | CACHE STRING "" FORCE 183 | ) 184 | endif() 185 | else() 186 | message(FATAL_ERROR "SMP requires release build (-DRELEASE=TRUE)") 187 | endif() 188 | else() 189 | set(KernelMaxNumNodes 190 | 1 191 | CACHE STRING "" FORCE 192 | ) 193 | set(AppSmpBench 194 | OFF 195 | CACHE BOOL "" FORCE 196 | ) 197 | if(KernelPlatformTK1) 198 | set(ElfloaderMode 199 | "monitor" 200 | CACHE STRING "" FORCE 201 | ) 202 | endif() 203 | endif() 204 | 205 | if(MCS) 206 | set(KernelIsMCS 207 | ON 208 | CACHE BOOL "" FORCE 209 | ) 210 | else() 211 | set(KernelIsMCS 212 | OFF 213 | CACHE BOOL "" FORCE 214 | ) 215 | endif() 216 | 217 | if(IPC) 218 | set(AppIpcBench 219 | ON 220 | CACHE BOOL "" FORCE 221 | ) 222 | else() 223 | set(AppIpcBench 224 | OFF 225 | CACHE BOOL "" FORCE 226 | ) 227 | endif() 228 | 229 | if(IRQUSER) 230 | set(AppIrqUserBench 231 | ON 232 | CACHE BOOL "" FORCE 233 | ) 234 | else() 235 | set(AppIrqUserBench 236 | OFF 237 | CACHE BOOL "" FORCE 238 | ) 239 | endif() 240 | 241 | if(SCHED) 242 | set(AppSchedulerBench 243 | ON 244 | CACHE BOOL "" FORCE 245 | ) 246 | else() 247 | set(AppSchedulerBench 248 | OFF 249 | CACHE BOOL "" FORCE 250 | ) 251 | endif() 252 | 253 | if(SIGNAL) 254 | set(AppSignalBench 255 | ON 256 | CACHE BOOL "" FORCE 257 | ) 258 | else() 259 | set(AppSignalBench 260 | OFF 261 | CACHE BOOL "" FORCE 262 | ) 263 | endif() 264 | 265 | if(MAPPING) 266 | set(AppPageMappingBench 267 | ON 268 | CACHE BOOL "" FORCE 269 | ) 270 | else() 271 | set(AppPageMappingBench 272 | OFF 273 | CACHE BOOL "" FORCE 274 | ) 275 | endif() 276 | 277 | if(SYNC) 278 | set(AppSyncBench 279 | ON 280 | CACHE BOOL "" FORCE 281 | ) 282 | else() 283 | set(AppSyncBench 284 | OFF 285 | CACHE BOOL "" FORCE 286 | ) 287 | endif() 288 | 289 | # Add new app-specific configuration here 290 | endif() 291 | -------------------------------------------------------------------------------- /libsel4benchsupport/include/benchmark.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | /* average events = sel4bench generic events + the cycle counter */ 25 | #define NUM_AVERAGE_EVENTS (SEL4BENCH_NUM_GENERIC_EVENTS + 1u) 26 | #define CYCLE_COUNT_EVENT SEL4BENCH_NUM_GENERIC_EVENTS 27 | #define AVERAGE_RUNS 10000 28 | 29 | #define MAX_TIMER_IRQS 4 30 | 31 | /* Data collection support macros, to be used in individual benchmark apps*/ 32 | 33 | /* Declare and init internal parameters: "sample" and "is_counted" */ 34 | #define DATACOLLECT_INIT() ccnt_t sample = 0; seL4_Word is_counted; 35 | 36 | /* Find out if "i"-th sample will be recorded (if "i" less than "n", 37 | * the sample will be ignored. 38 | * Then calculate sample using start value "s", end value "e" and 39 | * value of overhead "o". 40 | * Then accumulate sum of samples "par_sum" and sum of squared samples 41 | * "par_sum2". 42 | */ 43 | #define DATACOLLECT_GET_SUMS(i, n, s, e, o, par_sum, par_sum2) \ 44 | {\ 45 | is_counted = ( ~(i - n) ) >> (seL4_WordBits - 1);\ 46 | sample = is_counted * (e - s - o);\ 47 | par_sum += sample; par_sum2 += sample * sample;\ 48 | } 49 | 50 | /* 51 | * Execution flow for Early Processing: we have to calculate min value 52 | * of measured overheads before running benchmark. 53 | * 54 | * In "Late Processing" flow all the data is processed 55 | * after all the benchmarks have finished. 56 | * 57 | * @param overhead array of overhead measurements 58 | * @param overhead_size number of overhead measurements taken 59 | */ 60 | ccnt_t getMinOverhead(ccnt_t *overhead, seL4_Word overhead_size); 61 | 62 | /* benchmarking environment set up by root task */ 63 | typedef struct env { 64 | /* vka interface for allocating *fast* objects in the benchmark */ 65 | vka_t slab_vka; 66 | /* vka interface for everything else */ 67 | vka_t delegate_vka; 68 | /* vspace interface for managing virtual memory in the benchmark */ 69 | vspace_t vspace; 70 | /* initialised allocman that backs the vka interface */ 71 | allocman_t *allocman; 72 | /* minimal simple implementation that backs the default timer */ 73 | simple_t simple; 74 | /* static data to initialise vspace */ 75 | sel4utils_alloc_data_t data; 76 | /* code region so this app can shallow clone itself */ 77 | sel4utils_elf_region_t region; 78 | /* virtual address to write benchmark results to */ 79 | void *results; 80 | /* ltimer interface */ 81 | ltimer_t ltimer; 82 | /* has the timer been initialised? */ 83 | bool timer_initialised; 84 | /* notification that is bound to both timer irq handlers */ 85 | vka_object_t ntfn; 86 | /* args we started with */ 87 | benchmark_args_t *args; 88 | /* rpc client for communicating with benchmark driver */ 89 | sel4rpc_client_t rpc_client; 90 | /* platsupport IO ops structure to use for the timer driver */ 91 | ps_io_ops_t io_ops; 92 | /* ID of the notification managed by the mini IRQ interface */ 93 | ntfn_id_t ntfn_id; 94 | } env_t; 95 | 96 | /* initialise the benchmarking environment and return it */ 97 | env_t *benchmark_get_env(int argc, char **argv, size_t results_size, 98 | size_t object_freq[seL4_ObjectTypeCount]); 99 | /* signal to the benchmark driver process that we are done */ 100 | NORETURN void benchmark_finished(int exit_code); 101 | /* Write for benchmarks. prints via a serial server in the initial task */ 102 | size_t benchmark_write(void *buf, size_t count); 103 | 104 | /* Initialise the timer for the benchmark to use */ 105 | void benchmark_init_timer(env_t *env); 106 | 107 | /* Child thread/process helper functions */ 108 | 109 | /* Create a new process that is a shallow clone of the current process. 110 | * 111 | * This is *not* fork, and will only copy the text segment 112 | * into the new address space. This results in very light weight processes. 113 | * 114 | * This means you can start your new process at any function in the text segment, 115 | * but those functions cannot rely on any globally initialised data in the heap or the stack 116 | * Most significantly, any c library calls that rely on the vsyscall table will not work 117 | * (like abort, or printf). 118 | * 119 | * @param env environment from benchmark_get_env 120 | * @param[out] process the process to create 121 | * @param prio the priority to run the process at 122 | * @param entry_point a function in the text segment to start the process at 123 | * @param name a name for the thread for debugging (this will be passed to seL4_DebugNameThread) 124 | * @param fault_ep fault endpoint for the thread 125 | */ 126 | void benchmark_shallow_clone_process(env_t *env, sel4utils_process_t *process, uint8_t prio, 127 | void *entry_point, char *name); 128 | 129 | /* 130 | * Create a new thread in a shallow processes address space. 131 | * 132 | * @param env environment from benchmark_get_env 133 | * @param process to create the thread in the address space of 134 | * @param[out] thread the thread to create 135 | * @param prio the priority to run the process at 136 | * @param entry_point a function in the text segment to start the process at 137 | * @param name a name for the thread for debugging (this will be passed to seL4_DebugNameThread) 138 | */ 139 | void benchmark_configure_thread_in_process(env_t *env, sel4utils_process_t *process, 140 | sel4utils_process_t *thread, uint8_t prio, 141 | void *entry_point, char *name); 142 | 143 | /* 144 | * Configure a thread in the address space of the current environment. 145 | * 146 | * @param env environment from benchmark_get_env 147 | * @param fault_ep fault endpoint for the thread 148 | * @param prio the priority to run the process at 149 | * @param name a name for the thread for debugging (this will be passed to seL4_DebugNameThread) 150 | * @param[out] thread to create 151 | */ 152 | void benchmark_configure_thread(env_t *env, seL4_CPtr fault_ep, uint8_t prio, char *name, 153 | sel4utils_thread_t *thread); 154 | 155 | /* 156 | * Spawn a thread or process within a shallow address space. 157 | * 158 | * This ensures that TLS is configured correctly within the address space 159 | * when it executes. This is needed to allow the thread to determine the 160 | * address of its IPC buffer. 161 | */ 162 | int benchmark_spawn_process(sel4utils_process_t *process, vka_t *vka, vspace_t *vspace, int argc, 163 | char *argv[], int resume); 164 | 165 | /* 166 | * Wait for n child threads/processes to terminate successfully. 167 | * 168 | * The child thread/processes must signal on ep when finished, *and* have ep also 169 | * set as their fault endpoint. This way if a child terminates we will get an IPC. 170 | * 171 | * If any child terminates with a fault, abort. Otherwise, return when all children are 172 | * finished. 173 | * 174 | * @param ep the endpoint children will signal or fault on when done 175 | * @param name a name for the child for debugging output on fault. 176 | * @param num_children the number of children to wait for 177 | */ 178 | void benchmark_wait_children(seL4_CPtr ep, char *name, int num_children); 179 | 180 | /* 181 | * Send the cycle counter result through given endpoint 182 | * 183 | * @param ep The endpoint the result will be send through 184 | * @param result The conteng to be sent 185 | */ 186 | void send_result(seL4_CPtr ep, ccnt_t result); 187 | 188 | /* 189 | * Receive the cycle counter result from given endpoint 190 | * 191 | * @param ep The endpoint the result will be received from 192 | */ 193 | ccnt_t get_result(seL4_CPtr ep); 194 | 195 | /* Enable or disable the FPU for a task */ 196 | void configure_fpu(seL4_CPtr tcb, bool fpu_on); -------------------------------------------------------------------------------- /apps/irquser/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | #define INTERRUPT_PERIOD_NS (10 * NS_IN_MS) 25 | 26 | void abort(void) 27 | { 28 | benchmark_finished(EXIT_FAILURE); 29 | } 30 | 31 | void spinner_fn(int argc, char **argv) 32 | { 33 | sel4bench_init(); 34 | if (argc != 1) { 35 | abort(); 36 | } 37 | 38 | volatile ccnt_t *current_time = (volatile ccnt_t *) atol(argv[0]); 39 | 40 | while (1) { 41 | /* just take the low bits so the reads are atomic */ 42 | SEL4BENCH_READ_CCNT(*current_time); 43 | } 44 | } 45 | 46 | /* ep for ticker to Send on when done */ 47 | static seL4_CPtr done_ep; 48 | /* ntfn for ticker to wait for timer irqs on */ 49 | static seL4_CPtr timer_signal; 50 | /* tcb for ticker to enable/disable FPU */ 51 | static seL4_CPtr ticker_tcb; 52 | /* initialised IRQ interface */ 53 | static ps_irq_ops_t *irq_ops; 54 | /* ntfn_id of the timer notification provided to the IRQ interface */ 55 | static ntfn_id_t timer_ntfn_id; 56 | 57 | void ticker_fn(ccnt_t *results, volatile ccnt_t *current_time) 58 | { 59 | seL4_Word start, end_low; 60 | ccnt_t end; 61 | seL4_Word badge; 62 | 63 | for (int i = 0; i < N_RUNS; i++) { 64 | configure_fpu(ticker_tcb, false); 65 | /* wait for irq */ 66 | seL4_Wait(timer_signal, &badge); 67 | /* record result */ 68 | SEL4BENCH_READ_CCNT(end); 69 | configure_fpu(ticker_tcb, true); 70 | sel4platsupport_irq_handle(irq_ops, timer_ntfn_id, badge); 71 | end_low = (seL4_Word) end; 72 | start = (seL4_Word) * current_time; 73 | results[i] = end_low - start; 74 | } 75 | 76 | seL4_Send(done_ep, seL4_MessageInfo_new(0, 0, 0, 0)); 77 | } 78 | 79 | void ticker_fn_ep(int argc, char **argv) 80 | { 81 | if (argc != 5) { 82 | abort(); 83 | } 84 | ccnt_t overhead = (ccnt_t) atol(argv[0]); 85 | ccnt_t *results_sum = (ccnt_t *) atol(argv[1]); 86 | ccnt_t *results_sum2 = (ccnt_t *) atol(argv[2]); 87 | ccnt_t *results_num = (ccnt_t *) atol(argv[3]); 88 | volatile ccnt_t *current_time = (volatile ccnt_t *) atol(argv[4]); 89 | 90 | seL4_Word start, end_low; 91 | ccnt_t end, sum = 0, sum2 = 0; 92 | seL4_Word badge; 93 | 94 | DATACOLLECT_INIT(); 95 | 96 | for (seL4_Word i = 0; i < N_RUNS; i++) { 97 | /* wait for irq */ 98 | seL4_Wait(timer_signal, &badge); 99 | /* record result */ 100 | SEL4BENCH_READ_CCNT(end); 101 | sel4platsupport_irq_handle(irq_ops, timer_ntfn_id, badge); 102 | end_low = (seL4_Word) end; 103 | start = (seL4_Word) * current_time; 104 | DATACOLLECT_GET_SUMS(i, N_IGNORED, start, end_low, overhead, sum, sum2); 105 | } 106 | 107 | *results_sum = sum; 108 | *results_sum2 = sum2; 109 | *results_num = N_RUNS - N_IGNORED; 110 | 111 | seL4_Send(done_ep, seL4_MessageInfo_new(0, 0, 0, 0)); 112 | } 113 | 114 | int main(int argc, char **argv) 115 | { 116 | env_t *env; 117 | irquser_results_t *results; 118 | vka_object_t endpoint = {0}; 119 | 120 | static size_t object_freq[seL4_ObjectTypeCount] = { 121 | [seL4_TCBObject] = 2, 122 | [seL4_EndpointObject] = 1, 123 | #ifdef CONFIG_KERNEL_MCS 124 | [seL4_SchedContextObject] = 2, 125 | [seL4_ReplyObject] = 2 126 | #endif 127 | }; 128 | 129 | env = benchmark_get_env(argc, argv, sizeof(irquser_results_t), object_freq); 130 | benchmark_init_timer(env); 131 | results = (irquser_results_t *) env->results; 132 | 133 | if (vka_alloc_endpoint(&env->slab_vka, &endpoint) != 0) { 134 | ZF_LOGF("Failed to allocate endpoint\n"); 135 | } 136 | 137 | /* set up globals */ 138 | done_ep = endpoint.cptr; 139 | timer_signal = env->ntfn.cptr; 140 | irq_ops = &env->io_ops.irq_ops; 141 | timer_ntfn_id = env->ntfn_id; 142 | 143 | int error = ltimer_reset(&env->ltimer); 144 | ZF_LOGF_IF(error, "Failed to start timer"); 145 | 146 | error = ltimer_set_timeout(&env->ltimer, INTERRUPT_PERIOD_NS, TIMEOUT_PERIODIC); 147 | ZF_LOGF_IF(error, "Failed to configure timer"); 148 | 149 | sel4bench_init(); 150 | 151 | sel4utils_thread_t ticker, spinner; 152 | 153 | /* measurement overhead */ 154 | ccnt_t start, end; 155 | for (int i = 0; i < N_RUNS; i++) { 156 | SEL4BENCH_READ_CCNT(start); 157 | SEL4BENCH_READ_CCNT(end); 158 | results->overheads[i] = end - start; 159 | } 160 | 161 | /* find the minimum overhead for early processing run */ 162 | results->overhead_min = getMinOverhead(results->overheads, N_RUNS); 163 | 164 | /* create a frame for the shared time variable so we can share it between processes */ 165 | ccnt_t *local_current_time = (ccnt_t *) vspace_new_pages(&env->vspace, seL4_AllRights, 1, seL4_PageBits); 166 | if (local_current_time == NULL) { 167 | ZF_LOGF("Failed to allocate page"); 168 | } 169 | 170 | /* first run the benchmark between two threads in the current address space */ 171 | benchmark_configure_thread(env, endpoint.cptr, seL4_MaxPrio - 1, "ticker", &ticker); 172 | benchmark_configure_thread(env, endpoint.cptr, seL4_MaxPrio - 2, "spinner", &spinner); 173 | 174 | /* Test timing with FPU enabled for normal code and disabled for IRQ handler */ 175 | configure_fpu(spinner.tcb.cptr, true); 176 | ticker_tcb = ticker.tcb.cptr; 177 | 178 | error = sel4utils_start_thread(&ticker, (sel4utils_thread_entry_fn) ticker_fn, (void *) results->thread_results, 179 | (void *) local_current_time, true); 180 | if (error) { 181 | ZF_LOGF("Failed to start ticker"); 182 | } 183 | 184 | char strings[1][WORD_STRING_SIZE]; 185 | char *spinner_argv[1]; 186 | 187 | sel4utils_create_word_args(strings, spinner_argv, 1, (seL4_Word) local_current_time); 188 | error = sel4utils_start_thread(&spinner, (sel4utils_thread_entry_fn) spinner_fn, (void *) 1, (void *) spinner_argv, 189 | true); 190 | assert(!error); 191 | 192 | benchmark_wait_children(endpoint.cptr, "child of irq-user", 1); 193 | 194 | /* stop spinner thread */ 195 | error = seL4_TCB_Suspend(spinner.tcb.cptr); 196 | assert(error == seL4_NoError); 197 | 198 | error = seL4_TCB_Suspend(ticker.tcb.cptr); 199 | assert(error == seL4_NoError); 200 | 201 | /* run the benchmark again with early processing */ 202 | char ticker_ep_strings[5][WORD_STRING_SIZE]; 203 | char *ticker_ep_argv[5]; 204 | sel4utils_create_word_args(ticker_ep_strings, ticker_ep_argv, 5, (seL4_Word) results->overhead_min, 205 | &results->thread_results_ep_sum, 206 | &results->thread_results_ep_sum2, &results->thread_results_ep_num, (seL4_Word) local_current_time); 207 | error = sel4utils_start_thread(&ticker, (sel4utils_thread_entry_fn) ticker_fn_ep, (void *) 5, (void *) ticker_ep_argv, 208 | true); 209 | if (error) { 210 | ZF_LOGF("Failed to start ticker"); 211 | } 212 | 213 | error = sel4utils_start_thread(&spinner, (sel4utils_thread_entry_fn) spinner_fn, (void *) 1, (void *) spinner_argv, 214 | true); 215 | assert(!error); 216 | 217 | benchmark_wait_children(endpoint.cptr, "child of irq-user", 1); 218 | 219 | /* stop spinner thread */ 220 | error = seL4_TCB_Suspend(spinner.tcb.cptr); 221 | assert(error == seL4_NoError); 222 | 223 | error = seL4_TCB_Suspend(ticker.tcb.cptr); 224 | assert(error == seL4_NoError); 225 | 226 | /* now run the benchmark again, but run the spinner in another address space */ 227 | 228 | /* restart ticker */ 229 | error = sel4utils_start_thread(&ticker, (sel4utils_thread_entry_fn) ticker_fn, (void *) results->process_results, 230 | (void *) local_current_time, true); 231 | assert(!error); 232 | 233 | sel4utils_process_t spinner_process; 234 | benchmark_shallow_clone_process(env, &spinner_process, seL4_MaxPrio - 2, spinner_fn, "spinner"); 235 | 236 | /* share the current time variable with the spinner process */ 237 | void *current_time_remote = vspace_share_mem(&env->vspace, &spinner_process.vspace, 238 | (void *) local_current_time, 1, seL4_PageBits, 239 | seL4_AllRights, true); 240 | assert(current_time_remote != NULL); 241 | 242 | /* start the spinner process */ 243 | sel4utils_create_word_args(strings, spinner_argv, 1, (seL4_Word) current_time_remote); 244 | error = benchmark_spawn_process(&spinner_process, &env->slab_vka, &env->vspace, 1, spinner_argv, 1); 245 | if (error) { 246 | ZF_LOGF("Failed to start spinner process"); 247 | } 248 | 249 | benchmark_wait_children(endpoint.cptr, "child of irq-user", 1); 250 | 251 | /* stop threads */ 252 | error = seL4_TCB_Suspend(spinner_process.thread.tcb.cptr); 253 | assert(error == seL4_NoError); 254 | 255 | error = seL4_TCB_Suspend(ticker.tcb.cptr); 256 | assert(error == seL4_NoError); 257 | 258 | /* run the benchmark again but with early processing */ 259 | sel4utils_create_word_args(ticker_ep_strings, ticker_ep_argv, 5, (seL4_Word) results->overhead_min, 260 | &results->process_results_ep_sum, 261 | &results->process_results_ep_sum2, &results->process_results_ep_num, (seL4_Word) local_current_time); 262 | error = sel4utils_start_thread(&ticker, (sel4utils_thread_entry_fn) ticker_fn_ep, (void *) 5, (void *) ticker_ep_argv, 263 | true); 264 | assert(!error); 265 | 266 | /* start the spinner process */ 267 | sel4utils_create_word_args(strings, spinner_argv, 1, (seL4_Word) current_time_remote); 268 | error = benchmark_spawn_process(&spinner_process, &env->slab_vka, &env->vspace, 1, spinner_argv, 1); 269 | if (error) { 270 | ZF_LOGF("Failed to start spinner process"); 271 | } 272 | 273 | benchmark_wait_children(endpoint.cptr, "child of irq-user", 1); 274 | 275 | /* done -> results are stored in shared memory so we can now return */ 276 | benchmark_finished(EXIT_SUCCESS); 277 | return 0; 278 | } 279 | --------------------------------------------------------------------------------