├── VERSION ├── docs ├── assets │ └── microkit_flow.pdf └── style │ └── logos │ ├── seL4-key.pdf │ ├── blacktriangle.pdf │ └── seL4-Foundation-logo.pdf ├── .flake8 ├── initialiser ├── src │ └── main.rs ├── Cargo.toml └── support │ └── targets │ ├── riscv64imac-sel4-minimal.json │ ├── aarch64-sel4-minimal.json │ └── x86_64-sel4-minimal.json ├── monitor ├── src │ ├── x86_64 │ │ └── crt0.s │ ├── aarch64 │ │ └── crt0.s │ ├── util.h │ ├── riscv │ │ └── crt0.s │ └── util.c └── Makefile ├── libmicrokit ├── src │ ├── x86_64 │ │ └── crt0.s │ ├── aarch64 │ │ └── crt0.s │ ├── riscv │ │ └── crt0.s │ ├── dbg.c │ └── main.c ├── microkit.ld └── Makefile ├── tool └── microkit │ ├── tests │ └── sdf │ │ ├── sys_no_protection_domains.system │ │ ├── pd_missing_program_image.system │ │ ├── pd_parent_has_id.system │ │ ├── mr_missing_name.system │ │ ├── vm_not_child.system │ │ ├── mr_missing_size.system │ │ ├── mr_malformed_size.system │ │ ├── pd_invalid_cpu.system │ │ ├── mr_unsupported_page_size.system │ │ ├── pd_missing_path.system │ │ ├── mr_size_not_multiple_of_page_size.system │ │ ├── pd_missing_name.system │ │ ├── sys_text_elements.system │ │ ├── vm_missing_vcpu.system │ │ ├── irq_arm_on_x86.system │ │ ├── pd_invalid_attrs.system │ │ ├── irq_id_less_than_0.system │ │ ├── mr_addr_not_aligned_to_page_size.system │ │ ├── irq_id_greater_than_max.system │ │ ├── pd_small_stack_size.system │ │ ├── pd_missing_id.system │ │ ├── pd_program_image_invalid_attrs.system │ │ ├── pd_budget_gt_period.system │ │ ├── pd_missing_irq.system │ │ ├── pd_unaligned_stack_size.system │ │ ├── irq_ioapic_on_arm.system │ │ ├── vm_missing_vcpu_id.system │ │ ├── irq_msi_on_arm.system │ │ ├── irq_invalid_trigger.system │ │ ├── irq_ioapic_less_than_0.system │ │ ├── irq_ioapic_pin_less_than_0.system │ │ ├── vm_invalid_vcpu_id.system │ │ ├── irq_ioapic_vector_less_than_0.system │ │ ├── irq_msi_handle_less_than_0.system │ │ ├── irq_msi_vector_less_than_0.system │ │ ├── vm_invalid_vcpu_cpu.system │ │ ├── irq_msi_pci_bus_less_than_0.system │ │ ├── irq_msi_pci_dev_less_than_0.system │ │ ├── irq_msi_pci_func_less_than_0.system │ │ ├── pd_invalid_x86_io_port_size.system │ │ ├── irq_ioapic_invalid_polarity.system │ │ ├── irq_ioapic_invalid_trigger.system │ │ ├── sys_duplicate_irq_id.system │ │ ├── mr_invalid_attrs.system │ │ ├── pd_write_only_mr.system │ │ ├── pd_missing_region_paddr.system │ │ ├── pd_missing_symbol.system │ │ ├── sys_map_not_aligned.system │ │ ├── pd_duplicate_program_image.system │ │ ├── pd_overlapping_x86_io_ports_1.system │ │ ├── pd_child_missing_id.system │ │ ├── pd_missing_mr.system │ │ ├── pd_missing_vaddr.system │ │ ├── sys_duplicate_pd_name.system │ │ ├── mr_overlapping_phys_addr.system │ │ ├── sys_map_too_high.system │ │ ├── sys_duplicate_mr_name.system │ │ ├── ch_not_enough_ends.system │ │ ├── pd_duplicate_setvar.system │ │ ├── vm_missing_mr.system │ │ ├── sys_duplicate_irq_number.system │ │ ├── ch_missing_id.system │ │ ├── ch_missing_pd.system │ │ ├── ch_end_invalid_pp.system │ │ ├── ch_end_invalid_notify.system │ │ ├── ch_id_less_than_0.system │ │ ├── ch_invalid_element.system │ │ ├── ch_invalid_pd.system │ │ ├── ch_id_greater_than_max.system │ │ ├── ch_invalid_attrs.system │ │ ├── pd_duplicate_child_id_vcpu.system │ │ ├── pd_overlapping_maps.system │ │ ├── ch_ppcall_priority.system │ │ ├── ch_bidirectional_ppc.system │ │ ├── pd_overlapping_x86_io_ports_2.system │ │ ├── sys_map_invalid_mr.system │ │ ├── pd_duplicate_child_id.system │ │ ├── sys_channel_duplicate_a_id.system │ │ ├── sys_channel_duplicate_b_id.system │ │ ├── ch_too_many_ends.system │ │ ├── vm_duplicate_name.system │ │ └── vm_overlapping_maps.system │ ├── src │ ├── capdl │ │ ├── mod.rs │ │ ├── packaging.rs │ │ ├── spec.rs │ │ └── initialiser.rs │ ├── crc32.rs │ └── uimage.rs │ └── Cargo.toml ├── .cargo └── config.toml ├── LICENSES ├── LicenseRef-Trademark.txt └── BSD-2-Clause.txt ├── example ├── rust │ ├── .cargo │ │ └── config.toml │ ├── rust-toolchain.toml │ ├── rust.system │ ├── Cargo.toml │ ├── hello.rs │ ├── README.md │ ├── support │ │ └── targets │ │ │ ├── riscv64gc-sel4-microkit-minimal.json │ │ │ └── aarch64-sel4-microkit-minimal.json │ └── Makefile ├── hello │ ├── hello.system │ ├── hello.c │ ├── README.md │ └── Makefile ├── arm_smc │ ├── arm_smc.system │ ├── README.md │ ├── arm_smc.c │ └── Makefile ├── hierarchy │ ├── hello.c │ ├── crasher.c │ ├── hierarchy.system │ ├── README.md │ ├── restarter.c │ └── Makefile ├── x86_64_ioport │ ├── x86_64_ioport.system │ ├── README.md │ ├── x86_64_ioport.c │ └── Makefile ├── timer │ ├── timer.system │ ├── README.md │ ├── Makefile │ └── timer.c ├── passive_server │ ├── client.c │ ├── passive_server.system │ ├── README.md │ ├── server.c │ └── Makefile ├── ethernet │ ├── README.md │ ├── foo.c │ └── Makefile └── setvar │ ├── README.md │ ├── setvar.system │ ├── setvar.c │ └── Makefile ├── requirements.txt ├── .gitignore ├── tests ├── overlapping_pages │ ├── README.md │ ├── overlapping_pages.c │ ├── overlapping_pages.system │ └── Makefile ├── simplemrs │ ├── README.md │ ├── simplemrs.c │ ├── simplemrs.system │ └── Makefile └── capfault │ ├── capfault.system │ ├── README.md │ ├── capfault.c │ └── Makefile ├── ci └── dev_version.sh ├── loader ├── src │ ├── riscv │ │ ├── exceptions.c │ │ ├── init.c │ │ ├── mmu.c │ │ ├── sbi.h │ │ ├── sbi.c │ │ └── cpus.c │ ├── cutil.h │ ├── aarch64 │ │ ├── el.h │ │ ├── mmu.c │ │ ├── exceptions.c │ │ ├── el.c │ │ ├── crt0.S │ │ ├── exceptions.h │ │ ├── smc.h │ │ └── init.c │ ├── uart.h │ ├── loader.h │ ├── cutil.c │ ├── cpus.h │ └── arch.h ├── aarch64.ld ├── riscv64.ld └── Makefile ├── .github ├── CODE_OF_CONDUCT.md ├── workflows │ ├── push.yml │ └── pr.yml └── CONTRIBUTING.md ├── Cargo.toml ├── mypy.ini ├── .reuse └── dep5 ├── LICENSE.md ├── README.md ├── platforms.yml ├── dev_build.py ├── flake.lock └── flake.nix /VERSION: -------------------------------------------------------------------------------- 1 | 2.1.0-dev 2 | -------------------------------------------------------------------------------- /docs/assets/microkit_flow.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seL4/microkit/HEAD/docs/assets/microkit_flow.pdf -------------------------------------------------------------------------------- /docs/style/logos/seL4-key.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seL4/microkit/HEAD/docs/style/logos/seL4-key.pdf -------------------------------------------------------------------------------- /docs/style/logos/blacktriangle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seL4/microkit/HEAD/docs/style/logos/blacktriangle.pdf -------------------------------------------------------------------------------- /docs/style/logos/seL4-Foundation-logo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seL4/microkit/HEAD/docs/style/logos/seL4-Foundation-logo.pdf -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | [flake8] 7 | ignore = E501 8 | -------------------------------------------------------------------------------- /initialiser/src/main.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025, Colias Group, LLC 3 | // 4 | // SPDX-License-Identifier: BSD-2-Clause 5 | // 6 | 7 | #![no_std] 8 | #![no_main] 9 | 10 | extern crate sel4_capdl_initializer; 11 | -------------------------------------------------------------------------------- /monitor/src/x86_64/crt0.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | .section .text.start 8 | .globl _start 9 | _start: 10 | call main 11 | -------------------------------------------------------------------------------- /libmicrokit/src/x86_64/crt0.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | .section .text.start 8 | .globl _start 9 | _start: 10 | call main 11 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_no_protection_domains.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2024, UNSW 2 | # SPDX-License-Identifier: BSD-2-Clause 3 | 4 | [target.aarch64-unknown-linux-musl] 5 | rustflags = ["-Clinker=rust-lld"] 6 | 7 | [target.x86_64-unknown-linux-musl] 8 | rustflags = ["-Clinker=rust-lld"] 9 | -------------------------------------------------------------------------------- /LICENSES/LicenseRef-Trademark.txt: -------------------------------------------------------------------------------- 1 | For license and usage guidelines on the seL4 trademark and logo, including 2 | the seL4 Foundation logo, see https://sel4.systems/Foundation/Trademark/ 3 | 4 | No further license is granted from use in this repository. 5 | -------------------------------------------------------------------------------- /example/rust/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2023, Colias Group, LLC 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | [unstable] 8 | unstable-options = true 9 | 10 | [env] 11 | RUST_TARGET_PATH = { value = "support/targets", relative = true } 12 | -------------------------------------------------------------------------------- /example/rust/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2023, Colias Group, LLC 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | [toolchain] 8 | channel = "nightly-2025-02-26" 9 | components = [ "rustfmt", "rust-src", "rustc-dev", "llvm-tools-preview" ] 10 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | mypy==0.910 7 | black==21.7b0 8 | flake8==3.9.2 9 | ply==3.11 10 | Jinja2==3.0.3 11 | PyYAML==6.0.2 12 | pyfdt==0.3 13 | lxml==5.2.1 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | __pycache__ 8 | *-sdk-*/ 9 | build/ 10 | env/ 11 | pyenv/ 12 | release/ 13 | tmp_build/ 14 | target/ 15 | *.orig 16 | .DS_Store 17 | *.pdf 18 | -------------------------------------------------------------------------------- /monitor/src/aarch64/crt0.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | .extern main 7 | 8 | .section ".text.start" 9 | 10 | .global _start; 11 | .type _start, %function; 12 | _start: 13 | b main 14 | -------------------------------------------------------------------------------- /libmicrokit/src/aarch64/crt0.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | .extern main 7 | 8 | .section ".text.start" 9 | 10 | .global _start; 11 | .type _start, %function; 12 | _start: 13 | b main 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_missing_program_image.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_parent_has_id.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/mr_missing_name.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/vm_not_child.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/mr_missing_size.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/overlapping_pages/README.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Overlapping Pages Test 7 | 8 | The purpose of this is to test that when a user attempts to create overlapping pages in the address space a build error occurs. -------------------------------------------------------------------------------- /tests/simplemrs/README.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Simple Memory Region Tests 7 | 8 | The purpose of this is to test very simple system with two MRs and a single PD. 9 | 10 | It is a very simple smoke test. 11 | -------------------------------------------------------------------------------- /initialiser/Cargo.toml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025, Colias Group, LLC 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | [package] 8 | name = "initialiser" 9 | version = "2.1.0-dev" 10 | edition = "2021" 11 | rust-version = "1.88.0" 12 | 13 | [dependencies] 14 | sel4-capdl-initializer = { workspace = true } 15 | -------------------------------------------------------------------------------- /example/hello/hello.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/rust/rust.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tool/microkit/src/capdl/mod.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025, UNSW 3 | // 4 | // SPDX-License-Identifier: BSD-2-Clause 5 | // 6 | 7 | pub mod allocation; 8 | pub mod builder; 9 | pub mod initialiser; 10 | mod irq; 11 | mod memory; 12 | pub mod packaging; 13 | pub mod spec; 14 | mod util; 15 | 16 | pub use self::builder::*; 17 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/mr_malformed_size.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_invalid_cpu.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/arm_smc/arm_smc.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/mr_unsupported_page_size.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/hello/hello.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | void init(void) 10 | { 11 | microkit_dbg_puts("hello, world\n"); 12 | } 13 | 14 | void notified(microkit_channel ch) 15 | { 16 | } 17 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_missing_path.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/hierarchy/hello.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | void init(void) 10 | { 11 | microkit_dbg_puts("hello, world\n"); 12 | } 13 | 14 | void notified(microkit_channel ch) 15 | { 16 | } 17 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/mr_size_not_multiple_of_page_size.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_missing_name.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_text_elements.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | asdf 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ci/dev_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2024, UNSW 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | 6 | set -e 7 | 8 | VERSION=`cat VERSION` 9 | LATEST_TAG=`git describe --tags --abbrev=0` 10 | NUM_COMMITS=`git rev-list --count $LATEST_TAG..HEAD` 11 | HEAD=`git rev-parse --short HEAD` 12 | 13 | echo "$VERSION.$NUM_COMMITS+$HEAD" 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/vm_missing_vcpu.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_arm_on_x86.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_invalid_attrs.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_id_less_than_0.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/mr_addr_not_aligned_to_page_size.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/capfault/capfault.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_id_greater_than_max.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_small_stack_size.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_missing_id.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_program_image_invalid_attrs.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_budget_gt_period.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_missing_irq.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_unaligned_stack_size.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025, UNSW 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | # 7 | [package] 8 | name = "hello" 9 | version = "0.1.0" 10 | edition = "2021" 11 | license = "BSD-2-Clause" 12 | 13 | [[bin]] 14 | name = "hello" 15 | path = "hello.rs" 16 | 17 | [dependencies] 18 | sel4-microkit = { git = "https://github.com/seL4/rust-sel4" } 19 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_ioapic_on_arm.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/vm_missing_vcpu_id.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/rust/hello.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025, UNSW 3 | // 4 | // SPDX-License-Identifier: BSD-2-Clause 5 | // 6 | 7 | #![no_std] 8 | #![no_main] 9 | 10 | use sel4_microkit::{NullHandler, protection_domain, debug_println}; 11 | 12 | #[protection_domain()] 13 | fn init() -> NullHandler { 14 | debug_println!("hello, world from Rust!"); 15 | 16 | NullHandler::new() 17 | } 18 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_msi_on_arm.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_invalid_trigger.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_ioapic_less_than_0.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_ioapic_pin_less_than_0.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/vm_invalid_vcpu_id.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /loader/src/riscv/exceptions.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #include "../arch.h" 9 | 10 | void arch_set_exception_handler(void) 11 | { 12 | /* Don't do anything on RISC-V since we always are in S-mode so M-mode 13 | * will catch our faults (e.g SBI). */ 14 | } 15 | -------------------------------------------------------------------------------- /tests/simplemrs/simplemrs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | volatile uint8_t *p; 10 | volatile uint8_t *q; 11 | 12 | void 13 | init(void) 14 | { 15 | *p = 'A'; 16 | *q = 'Z'; 17 | } 18 | 19 | void 20 | notified(microkit_channel ch) 21 | { 22 | } -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_ioapic_vector_less_than_0.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_msi_handle_less_than_0.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_msi_vector_less_than_0.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/vm_invalid_vcpu_cpu.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/hierarchy/crasher.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | void init(void) 10 | { 11 | int *x = 0; 12 | microkit_dbg_puts("crasher, starting\n"); 13 | /* Crash! */ 14 | *x = 1; 15 | } 16 | 17 | void notified(microkit_channel ch) 18 | { 19 | } -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_msi_pci_bus_less_than_0.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_msi_pci_dev_less_than_0.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_msi_pci_func_less_than_0.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /monitor/src/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | void putc(uint8_t ch); 12 | void puts(const char *s); 13 | void puthex32(uint32_t val); 14 | void puthex64(uint64_t val); 15 | void fail(char *s); 16 | char* sel4_strerror(seL4_Word err); -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_invalid_x86_io_port_size.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/overlapping_pages/overlapping_pages.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | volatile uint8_t *p; 10 | volatile uint8_t *q; 11 | 12 | void 13 | init(void) 14 | { 15 | *p = 'A'; 16 | *q = 'Z'; 17 | } 18 | 19 | void 20 | notified(microkit_channel ch) 21 | { 22 | } -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_ioapic_invalid_polarity.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/irq_ioapic_invalid_trigger.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.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 | - main 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 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_duplicate_irq_id.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /monitor/src/riscv/crt0.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024, UNSW 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | .extern main 8 | .extern __global_pointer$ 9 | 10 | .section ".text.start" 11 | 12 | .global _start; 13 | .type _start, %function; 14 | _start: 15 | .option push 16 | .option norelax 17 | 1: auipc gp, %pcrel_hi(__global_pointer$) 18 | addi gp, gp, %pcrel_lo(1b) 19 | .option pop 20 | j main 21 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/mr_invalid_attrs.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /libmicrokit/src/riscv/crt0.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024, UNSW 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | .extern main 8 | .extern __global_pointer$ 9 | 10 | .section ".text.start" 11 | 12 | .global _start; 13 | .type _start, %function; 14 | _start: 15 | .option push 16 | .option norelax 17 | 1: auipc gp, %pcrel_hi(__global_pointer$) 18 | addi gp, gp, %pcrel_lo(1b) 19 | .option pop 20 | j main 21 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_write_only_mr.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_missing_region_paddr.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_missing_symbol.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_map_not_aligned.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_duplicate_program_image.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_overlapping_x86_io_ports_1.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/x86_64_ioport/x86_64_ioport.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_child_missing_id.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_missing_mr.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_missing_vaddr.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_duplicate_pd_name.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/capfault/README.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Cap Fault Test 7 | 8 | The purpose of the capfault test is to verify that the monitor will 9 | correctly detect and output debug information in case a protection 10 | domain generates a cap fault. 11 | 12 | Note: This test is (currently) expected to be run manually, and 13 | the output inspected to ensure cap fault debugging is output. 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/mr_overlapping_phys_addr.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_map_too_high.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_duplicate_mr_name.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_not_enough_ends.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_duplicate_setvar.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/capfault/capfault.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | #define ECHO_CH 2 10 | 11 | volatile uint64_t *shared_counter = (uint64_t *)(uintptr_t)0x1800000; 12 | 13 | void 14 | init(void) 15 | { 16 | microkit_dbg_puts("capfault: forcing a cap fault by notifying invalid channel 10,000\n"); 17 | microkit_notify(10000); 18 | } 19 | 20 | void 21 | notified(microkit_channel ch) 22 | { 23 | } -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/vm_missing_mr.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /example/arm_smc/README.md: -------------------------------------------------------------------------------- 1 | 5 | # Example - ARM SMC 6 | 7 | This is a basic example that performs a Secure Monitor Call. 8 | 9 | All supported ARM platforms are supported in this example. 10 | 11 | ## Building 12 | 13 | ```sh 14 | mkdir build 15 | make BUILD_DIR=build MICROKIT_BOARD= MICROKIT_CONFIG= MICROKIT_SDK=/path/to/sdk 16 | ``` 17 | 18 | ## Running 19 | 20 | See instructions for your board in the manual. 21 | -------------------------------------------------------------------------------- /example/timer/timer.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_duplicate_irq_number.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /example/passive_server/client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022, UNSW 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | 9 | #define SERVER_CH 0 10 | 11 | void init(void) 12 | { 13 | microkit_dbg_puts("CLIENT|INFO: init function running\n"); 14 | 15 | /* message the server */ 16 | (void) microkit_ppcall(SERVER_CH, microkit_msginfo_new(1, 1)); 17 | } 18 | 19 | void notified(microkit_channel ch) 20 | { 21 | microkit_dbg_puts("CLIENT|INFO: received a notification on an unexpected channel\n"); 22 | } 23 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_missing_id.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_missing_pd.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_end_invalid_pp.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_end_invalid_notify.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_id_less_than_0.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_invalid_element.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_invalid_pd.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/ethernet/README.md: -------------------------------------------------------------------------------- 1 | 5 | # Example - Ethernet 6 | 7 | This example shows an ethernet system for the TQMa8XQP platform. 8 | It also includes a driver for the general purpose timer on the platform. 9 | 10 | ## Building 11 | 12 | ```sh 13 | mkdir build 14 | make BUILD_DIR=build MICROKIT_BOARD=tqma8xqp1gb MICROKIT_CONFIG= MICROKIT_SDK=/path/to/sdk 15 | ``` 16 | 17 | ## Running 18 | 19 | See instructions for your board in the manual. 20 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_id_greater_than_max.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_invalid_attrs.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_duplicate_child_id_vcpu.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_overlapping_maps.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_ppcall_priority.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_bidirectional_ppc.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_overlapping_x86_io_ports_2.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_map_invalid_mr.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /example/hello/README.md: -------------------------------------------------------------------------------- 1 | 5 | # Example - Hello World 6 | 7 | This is a basic hello world example that has a single protection domain 8 | that simply prints "hello, world!" upon initialisation. 9 | 10 | All supported platforms are supported in this example. 11 | 12 | ## Building 13 | 14 | ```sh 15 | mkdir build 16 | make BUILD_DIR=build MICROKIT_BOARD= MICROKIT_CONFIG= MICROKIT_SDK=/path/to/sdk 17 | ``` 18 | 19 | ## Running 20 | 21 | See instructions for your board in the manual. 22 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/pd_duplicate_child_id.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025, Colias Group, LLC 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | [workspace] 8 | resolver = "3" 9 | members = [ 10 | "tool/microkit", 11 | "initialiser", 12 | ] 13 | 14 | [workspace.dependencies.sel4-capdl-initializer] 15 | git = "https://github.com/seL4/rust-seL4" 16 | rev = "0ac1c27ee6cb9edac7a1a41a69b0d421e170d6a4" 17 | 18 | [workspace.dependencies.sel4-capdl-initializer-types] 19 | git = "https://github.com/seL4/rust-seL4" 20 | rev = "0ac1c27ee6cb9edac7a1a41a69b0d421e170d6a4" 21 | 22 | [profile.release.package.microkit-tool] 23 | strip = true 24 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_channel_duplicate_a_id.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/sys_channel_duplicate_b_id.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /example/timer/README.md: -------------------------------------------------------------------------------- 1 | 5 | # Example - Timer 6 | 7 | This example shows a basic timer driver for the Odroid-C4 8 | platform. The timer driver initialises the device and then 9 | sets a regular 1 second timeout and prints the current time 10 | whenever the timeout expires. 11 | 12 | ## Building 13 | 14 | ```sh 15 | mkdir build 16 | make BUILD_DIR=build MICROKIT_BOARD=odroidc4 MICROKIT_CONFIG= MICROKIT_SDK=/path/to/sdk 17 | ``` 18 | 19 | ## Running 20 | 21 | See instructions for your board in the manual. 22 | -------------------------------------------------------------------------------- /example/x86_64_ioport/README.md: -------------------------------------------------------------------------------- 1 | 5 | # Example - Hello World 6 | 7 | This is a basic hello world example that has a single protection domain 8 | that simply prints "hello!" via the first serial I/O port (0x3F8) upon initialisation. 9 | 10 | Only x86_64 platforms are supported. 11 | 12 | ## Building 13 | 14 | ```sh 15 | mkdir build 16 | make BUILD_DIR=build MICROKIT_BOARD= MICROKIT_CONFIG= MICROKIT_SDK=/path/to/sdk 17 | ``` 18 | 19 | ## Running 20 | 21 | See instructions for your board in the manual. 22 | -------------------------------------------------------------------------------- /example/passive_server/passive_server.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/ch_too_many_ends.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tool/microkit/Cargo.toml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024, UNSW 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | 7 | [package] 8 | name = "microkit-tool" 9 | version = "2.1.0-dev" 10 | edition = "2021" 11 | rust-version = "1.88.0" 12 | 13 | [[bin]] 14 | name = "microkit" 15 | path = "src/main.rs" 16 | 17 | [dependencies] 18 | roxmltree = "0.19.0" 19 | serde = { version = "1.0.228", features = ["derive"] } 20 | serde_json = "1.0.117" 21 | rkyv = { version = "0.8.12", default-features = false, features = ["alloc", "bytecheck", "pointer_width_32"] } 22 | sel4-capdl-initializer-types = { workspace = true, features = ["serde", "deflate", "transform"] } 23 | -------------------------------------------------------------------------------- /example/hierarchy/hierarchy.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tool/microkit/src/crc32.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025, UNSW 3 | // 4 | // SPDX-License-Identifier: BSD-2-Clause 5 | // 6 | 7 | pub fn crc32(bytes: &[u8]) -> u32 { 8 | // Could be more optimised using the table approach. 9 | // Source: https://web.archive.org/web/20190108202303/http://www.hackersdelight.org/hdcodetxt/crc.c.txt 10 | let mut crc: u32 = 0xFFFF_FFFF; 11 | 12 | for &byte in bytes { 13 | crc ^= byte as u32; 14 | for _ in 0..8 { 15 | if crc & 1 != 0 { 16 | crc = (crc >> 1) ^ 0xEDB8_8320; 17 | } else { 18 | crc >>= 1; 19 | } 20 | } 21 | } 22 | 23 | !crc 24 | } 25 | -------------------------------------------------------------------------------- /tool/microkit/tests/sdf/vm_duplicate_name.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example/setvar/README.md: -------------------------------------------------------------------------------- 1 | 5 | # Example - setvar 6 | 7 | This is a basic example that demonstrate how to use some `setvar` functionalities that the Microkit provides. 8 | 9 | Only QEMU virt (AArch64) is supported in this example. Although everything will work the same way on other 10 | platforms, but on x86-64 ` 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/hierarchy/README.md: -------------------------------------------------------------------------------- 1 | 5 | # Example - Hierarchy 6 | 7 | This example shows off the parent/child PD concept in Microkit as 8 | well as fault handling. The parent 'restarter' PD receives faults 9 | from the 'crasher' PD that is intentionally crashing and then 10 | resets the crasher's program counter. 11 | 12 | All supported platforms are supported in this example. 13 | 14 | ## Building 15 | 16 | ```sh 17 | mkdir build 18 | make BUILD_DIR=build MICROKIT_BOARD= MICROKIT_CONFIG= MICROKIT_SDK=/path/to/sdk 19 | ``` 20 | 21 | ## Running 22 | 23 | See instructions for your board in the manual. 24 | -------------------------------------------------------------------------------- /loader/aarch64.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | PHDRS 7 | { 8 | all PT_LOAD AT (LINK_ADDRESS); 9 | } 10 | 11 | SECTIONS 12 | { 13 | . = LINK_ADDRESS; 14 | 15 | .text : 16 | { 17 | _text = .; 18 | *(.text.start) 19 | *(.text*) 20 | *(.rodata) 21 | _text_end = .; 22 | } :all 23 | 24 | .data : 25 | { 26 | _data = .; 27 | *(.data) 28 | _data_end = .; 29 | } :all 30 | 31 | .bss : 32 | { 33 | _bss = .; 34 | *(.bss) 35 | *(COMMON) 36 | . = ALIGN(4); 37 | _bss_end = .; 38 | } :all 39 | } 40 | -------------------------------------------------------------------------------- /loader/src/cutil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #define ALIGN(n) __attribute__((__aligned__(n))) 12 | 13 | #define BIT(n) (1UL << (n)) 14 | #define MASK(x) (BIT(x) - 1UL) 15 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) 16 | 17 | #define is_set(macro) _is_set_(macro) 18 | #define _macrotest_1 , 19 | #define _is_set_(value) _is_set__(_macrotest_##value) 20 | #define _is_set__(comma) _is_set___(comma 1, 0) 21 | #define _is_set___(_, v, ...) v 22 | 23 | void *memcpy(void *dst, const void *src, size_t sz); 24 | 25 | void *memmove(void *restrict dest, const void *restrict src, size_t n); 26 | -------------------------------------------------------------------------------- /tests/simplemrs/simplemrs.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /loader/src/aarch64/el.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | enum el { 13 | EL0 = 0, 14 | EL1 = 1, 15 | EL2 = 2, 16 | EL3 = 3, 17 | }; 18 | 19 | enum el current_el(void); 20 | int ensure_correct_el(int logical_cpu); 21 | 22 | static inline const char *el_to_string(enum el el) 23 | { 24 | switch (el) { 25 | case EL0: 26 | return "EL0"; 27 | case EL1: 28 | return "EL1"; 29 | case EL2: 30 | return "EL2"; 31 | case EL3: 32 | return "EL3"; 33 | } 34 | 35 | return ""; 36 | } 37 | -------------------------------------------------------------------------------- /tests/overlapping_pages/overlapping_pages.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/arm_smc/arm_smc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | #define PSCI_VERSION_FID 0x84000000 10 | 11 | void init(void) 12 | { 13 | microkit_dbg_puts("Getting SMC version via microkit_arm_smc_call()\n"); 14 | 15 | seL4_ARM_SMCContext args = {0}; 16 | seL4_ARM_SMCContext resp = {0}; 17 | 18 | args.x0 = PSCI_VERSION_FID; 19 | microkit_arm_smc_call(&args, &resp); 20 | 21 | microkit_dbg_puts("PSCI version: "); 22 | microkit_dbg_put32(((uint32_t) resp.x0 >> 16) & 0xFFFF); 23 | microkit_dbg_puts("."); 24 | microkit_dbg_put32((uint32_t) resp.x0 & 0xFFFF); 25 | microkit_dbg_puts("\n"); 26 | } 27 | 28 | void notified(microkit_channel ch) 29 | { 30 | } 31 | -------------------------------------------------------------------------------- /example/passive_server/README.md: -------------------------------------------------------------------------------- 1 | 5 | # Example - Passive Server 6 | 7 | This example shows a client and server PD communicating with each 8 | other where the server does not have an active scheduling context 9 | and is therefore a 'passive' server. 10 | 11 | When the client PPCs into the server, the server is executing on 12 | the client's budget. See the manual for more details on passive 13 | PDs. 14 | 15 | All supported platforms are supported in this example. 16 | 17 | ## Building 18 | 19 | ```sh 20 | mkdir build 21 | make BUILD_DIR=build MICROKIT_BOARD= MICROKIT_CONFIG= MICROKIT_SDK=/path/to/sdk 22 | ``` 23 | 24 | ## Running 25 | 26 | See instructions for your board in the manual. 27 | -------------------------------------------------------------------------------- /loader/riscv64.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | PHDRS 7 | { 8 | all PT_LOAD AT (LINK_ADDRESS); 9 | } 10 | 11 | SECTIONS 12 | { 13 | . = LINK_ADDRESS; 14 | 15 | .text : 16 | { 17 | _text = .; 18 | *(.text.start) 19 | *(.text*) 20 | *(.rodata) 21 | _text_end = .; 22 | } :all 23 | 24 | .data : 25 | { 26 | _data = .; 27 | *(.data) 28 | __global_pointer$ = . + 0x800; 29 | *(.srodata) 30 | *(.sdata) 31 | _data_end = .; 32 | } :all 33 | 34 | .bss : 35 | { 36 | _bss = .; 37 | *(.sbss) 38 | *(.bss) 39 | *(COMMON) 40 | . = ALIGN(4); 41 | _bss_end = .; 42 | } :all 43 | } 44 | -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: seL4 3 | Upstream-Contact: seL4 team 4 | Source: http://sel4.systems 5 | 6 | Files: 7 | Cargo.lock 8 | example/rust/Cargo.lock 9 | example/rust/support/*.json 10 | initialiser/support/*.json 11 | flake.lock 12 | CHANGES.md 13 | VERSION 14 | docs/assets/microkit_flow.svg 15 | docs/assets/microkit_flow.pdf 16 | Copyright: 2024, UNSW 17 | License: BSD-2-Clause 18 | 19 | Files: 20 | docs/style/logos/blacktriangle.pdf 21 | docs/style/logos/seL4-key.pdf 22 | Copyright: 2020, Data61, CSIRO (ABN 41 687 119 230) 23 | License: CC-BY-SA-4.0 24 | 25 | Files: 26 | docs/style/logos/seL4-Foundation-logo.pdf 27 | Copyright: seL4 Project a Series of LF Projects, LLC 28 | License: LicenseRef-Trademark 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # License 7 | 8 | The files in the Microkit project are released under standard open source 9 | licenses, identified by [SPDX license tags][1]. See the individual file headers 10 | for details, or use one of the publicly available SPDX tools to generate a bill 11 | of materials. The directory [`LICENSES`][2] contains the text for all licenses 12 | that are mentioned by files in this project. 13 | 14 | Code contributions to this project should be licensed under the [BSD-2-Clause] 15 | license, and documentation under the [CC-BY-SA-4.0] license. 16 | 17 | [1]: https://spdx.org 18 | [2]: LICENSES/ 19 | [BSD-2-CLAUSE]: LICENSES/BSD-2-Clause.txt 20 | [CC-BY-SA-4.0]: LICENSES/CC-BY-SA-4.0.txt 21 | -------------------------------------------------------------------------------- /initialiser/support/targets/riscv64imac-sel4-minimal.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "riscv64", 3 | "code-model": "medium", 4 | "cpu": "generic-rv64", 5 | "crt-objects-fallback": "false", 6 | "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", 7 | "emit-debug-gdb-scripts": false, 8 | "exe-suffix": ".elf", 9 | "features": "+m,+a,+c", 10 | "linker": "rust-lld", 11 | "linker-flavor": "gnu-lld", 12 | "llvm-abiname": "lp64", 13 | "llvm-target": "riscv64", 14 | "max-atomic-width": 64, 15 | "metadata": { 16 | "description": null, 17 | "host_tools": null, 18 | "std": null, 19 | "tier": null 20 | }, 21 | "panic-strategy": "abort", 22 | "relocation-model": "static", 23 | "supported-sanitizers": [ 24 | "shadow-call-stack", 25 | "kernel-address" 26 | ], 27 | "target-pointer-width": "64" 28 | } 29 | -------------------------------------------------------------------------------- /example/passive_server/server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022, UNSW 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | 9 | microkit_msginfo protected(microkit_channel ch, microkit_msginfo msginfo) 10 | { 11 | switch (microkit_msginfo_get_label(msginfo)) { 12 | case 1: 13 | microkit_dbg_puts("SERVER|INFO: running on clients scheduling context\n"); 14 | break; 15 | default: 16 | microkit_dbg_puts("SERVER|ERROR: received an unexpected message\n"); 17 | } 18 | 19 | return seL4_MessageInfo_new(0, 0, 0, 0); 20 | } 21 | 22 | void init(void) 23 | { 24 | microkit_dbg_puts("SERVER|INFO: init function running\n"); 25 | /* Nothing to initialise */ 26 | } 27 | 28 | void notified(microkit_channel ch) 29 | { 30 | microkit_dbg_puts("SERVER|ERROR: received a notification on an unexpected channel\n"); 31 | } 32 | -------------------------------------------------------------------------------- /example/rust/README.md: -------------------------------------------------------------------------------- 1 | 5 | # Example - Rust 6 | 7 | This example is the same as the 'hello' example expect that the 8 | protection domain is written in Rust instead of C. This makes 9 | use of the [rust-sel4](https://github.com/seL4/rust-sel4) Microkit 10 | support. 11 | 12 | You can find more complicated example systems written in Rust 13 | at the following links: 14 | 15 | * https://github.com/seL4/rust-microkit-demo 16 | * https://github.com/seL4/rust-microkit-http-server-demo 17 | 18 | All supported platforms are supported in this example. 19 | 20 | ## Building 21 | 22 | ```sh 23 | mkdir build 24 | make BUILD_DIR=build MICROKIT_BOARD= MICROKIT_CONFIG= MICROKIT_SDK=/path/to/sdk 25 | ``` 26 | 27 | ## Running 28 | 29 | See instructions for your board in the manual. 30 | -------------------------------------------------------------------------------- /tests/capfault/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | LIBMICROKIT := ../../libmicrokit 7 | TOOLCHAIN := aarch64-linux-gnu 8 | PYTHON := python3.8 9 | 10 | CPU := cortex-a35 11 | 12 | CC := $(TOOLCHAIN)-gcc 13 | LD := $(TOOLCHAIN)-ld 14 | AS := $(TOOLCHAIN)-as 15 | 16 | CAPFAULT_OBJS := capfault.o 17 | 18 | IMAGES := capfault.elf 19 | CFLAGS := -mcpu=$(CPU) -mstrict-align -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(SEL4_SDK)/include -I$(LIBMICROKIT)/include 20 | LDFLAGS := -L$(LIBMICROKIT) -Tmicrokit.ld 21 | LIBS := -lmicrokit 22 | 23 | 24 | all: $(IMAGES) 25 | 26 | %.o: %.c Makefile 27 | $(CC) -c $(CFLAGS) $< -o $@ 28 | 29 | %.o: %.s Makefile 30 | $(AS) -g -mcpu=$(CPU) $< -o $@ 31 | 32 | capfault.elf: $(CAPFAULT_OBJS) 33 | $(LD) $(LDFLAGS) $(CAPFAULT_OBJS) $(LIBS) -o $@ 34 | -------------------------------------------------------------------------------- /tests/simplemrs/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | LIBMICROKIT := ../../libmicrokit 7 | TOOLCHAIN := aarch64-linux-gnu 8 | PYTHON := python3.8 9 | 10 | CPU := cortex-a35 11 | 12 | CC := $(TOOLCHAIN)-gcc 13 | LD := $(TOOLCHAIN)-ld 14 | AS := $(TOOLCHAIN)-as 15 | 16 | SIMPLEMRS_OBJS := simplemrs.o 17 | 18 | IMAGES := simplemrs.elf 19 | CFLAGS := -mcpu=$(CPU) -mstrict-align -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(SEL4_SDK)/include -I$(LIBMICROKIT)/include 20 | LDFLAGS := -L$(LIBMICROKIT) -Tmicrokit.ld 21 | LIBS := -lmicrokit 22 | 23 | 24 | all: $(IMAGES) 25 | 26 | %.o: %.c Makefile 27 | $(CC) -c $(CFLAGS) $< -o $@ 28 | 29 | %.o: %.s Makefile 30 | $(AS) -g -mcpu=$(CPU) $< -o $@ 31 | 32 | simplemrs.elf: $(SIMPLEMRS_OBJS) 33 | $(LD) $(LDFLAGS) $(SIMPLEMRS_OBJS) $(LIBS) -o $@ 34 | -------------------------------------------------------------------------------- /example/rust/support/targets/riscv64gc-sel4-microkit-minimal.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "riscv64", 3 | "code-model": "medium", 4 | "cpu": "generic-rv64", 5 | "crt-objects-fallback": "false", 6 | "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", 7 | "emit-debug-gdb-scripts": false, 8 | "exe-suffix": ".elf", 9 | "features": "+m,+a,+f,+d,+c", 10 | "link-script": "__sel4_ipc_buffer_obj = (__ehdr_start & ~(4096 - 1)) - 4096;", 11 | "linker": "rust-lld", 12 | "linker-flavor": "gnu-lld", 13 | "llvm-abiname": "lp64d", 14 | "llvm-target": "riscv64", 15 | "max-atomic-width": 64, 16 | "metadata": { 17 | "description": null, 18 | "host_tools": null, 19 | "std": null, 20 | "tier": null 21 | }, 22 | "panic-strategy": "abort", 23 | "relocation-model": "static", 24 | "supported-sanitizers": [ 25 | "shadow-call-stack", 26 | "kernel-address" 27 | ], 28 | "target-pointer-width": "64" 29 | } 30 | -------------------------------------------------------------------------------- /tests/overlapping_pages/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | LIBMICROKIT := ../../libmicrokit 7 | TOOLCHAIN := aarch64-linux-gnu 8 | PYTHON := python3.8 9 | 10 | CPU := cortex-a35 11 | 12 | CC := $(TOOLCHAIN)-gcc 13 | LD := $(TOOLCHAIN)-ld 14 | AS := $(TOOLCHAIN)-as 15 | 16 | OVERLAPPING_PAGES_OBJS := overlapping_pages.o 17 | 18 | IMAGES := overlapping_pages.elf 19 | CFLAGS := -mcpu=$(CPU) -mstrict-align -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(SEL4_SDK)/include -I$(LIBMICROKIT)/include 20 | LDFLAGS := -L$(LIBMICROKIT) -Tmicrokit.ld 21 | LIBS := -lmicrokit 22 | 23 | 24 | all: $(IMAGES) 25 | 26 | %.o: %.c Makefile 27 | $(CC) -c $(CFLAGS) $< -o $@ 28 | 29 | %.o: %.s Makefile 30 | $(AS) -g -mcpu=$(CPU) $< -o $@ 31 | 32 | overlapping_pages.elf: $(OVERLAPPING_PAGES_OBJS) 33 | $(LD) $(LDFLAGS) $(OVERLAPPING_PAGES_OBJS) $(LIBS) -o $@ 34 | -------------------------------------------------------------------------------- /initialiser/support/targets/aarch64-sel4-minimal.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "crt-objects-fallback": "false", 4 | "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", 5 | "disable-redzone": true, 6 | "exe-suffix": ".elf", 7 | "features": "+v8a,+strict-align,+neon,+fp-armv8", 8 | "linker": "rust-lld", 9 | "linker-flavor": "gnu-lld", 10 | "llvm-target": "aarch64-unknown-none", 11 | "max-atomic-width": 128, 12 | "metadata": { 13 | "description": null, 14 | "host_tools": null, 15 | "std": null, 16 | "tier": null 17 | }, 18 | "panic-strategy": "abort", 19 | "pre-link-args": { 20 | "gnu-lld": [ 21 | "-z", 22 | "max-page-size=4096" 23 | ] 24 | }, 25 | "relocation-model": "static", 26 | "stack-probes": { 27 | "kind": "inline" 28 | }, 29 | "supported-sanitizers": [ 30 | "kcfi", 31 | "kernel-address" 32 | ], 33 | "target-pointer-width": "64" 34 | } 35 | -------------------------------------------------------------------------------- /initialiser/support/targets/x86_64-sel4-minimal.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "x86_64", 3 | "code-model": "small", 4 | "cpu": "x86-64", 5 | "crt-objects-fallback": "false", 6 | "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", 7 | "disable-redzone": true, 8 | "exe-suffix": ".elf", 9 | "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float", 10 | "linker": "rust-lld", 11 | "linker-flavor": "gnu-lld", 12 | "llvm-target": "x86_64-unknown-none-elf", 13 | "max-atomic-width": 64, 14 | "metadata": { 15 | "description": null, 16 | "host_tools": null, 17 | "std": null, 18 | "tier": null 19 | }, 20 | "panic-strategy": "abort", 21 | "plt-by-default": false, 22 | "relro-level": "full", 23 | "rustc-abi": "x86-softfloat", 24 | "stack-probes": { 25 | "kind": "inline" 26 | }, 27 | "supported-sanitizers": [ 28 | "kcfi", 29 | "kernel-address" 30 | ], 31 | "target-pointer-width": "64" 32 | } 33 | -------------------------------------------------------------------------------- /example/x86_64_ioport/x86_64_ioport.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | uint64_t com1_ioport_id; 10 | uint64_t com1_ioport_addr; 11 | 12 | static inline void serial_putc(char ch) 13 | { 14 | // Danger: may overflow hardware FIFO, but we are only writing a small message. 15 | microkit_x86_ioport_write_8(com1_ioport_id, com1_ioport_addr, ch); 16 | } 17 | 18 | static inline void serial_puts(const char *s) 19 | { 20 | while (*s) { 21 | if (*s == '\n') { 22 | serial_putc('\r'); 23 | } 24 | serial_putc(*s++); 25 | } 26 | } 27 | 28 | void init(void) 29 | { 30 | microkit_dbg_puts("hello, world. my name is "); 31 | microkit_dbg_puts(microkit_name); 32 | microkit_dbg_puts("\n"); 33 | 34 | microkit_dbg_puts("Now writing to serial I/O port: "); 35 | serial_puts("hello!\n"); 36 | } 37 | 38 | void notified(microkit_channel ch) 39 | { 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # seL4 Microkit 7 | 8 | The purpose of the seL4 Microkit is to enable system designers to create static software systems based on the seL4 microkernel. 9 | 10 | The seL4 Microkit consists of five components: 11 | 12 | * Microkit bootloader 13 | * CapDL initialiser 14 | * Microkit library 15 | * Microkit monitor 16 | * Microkit tool 17 | 18 | The Microkit is distributed as a software development kit (SDK). 19 | 20 | This repository is the source for the Microkit SDK. 21 | 22 | If you are a system designer and want to *use* the Microkit SDK please download a pre-built SDK from 23 | [the latest release](https://github.com/seL4/microkit/releases). 24 | 25 | If you need help getting started see the [seL4 documentation website](https://docs.sel4.systems/projects/microkit/) 26 | as well as the manual in the SDK (`doc/manual.pdf`). 27 | 28 | If you are *developing* Microkit itself see [DEVELOPER.md](./DEVELOPER.md). 29 | -------------------------------------------------------------------------------- /example/rust/support/targets/aarch64-sel4-microkit-minimal.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "crt-objects-fallback": "false", 4 | "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32", 5 | "disable-redzone": true, 6 | "exe-suffix": ".elf", 7 | "features": "+v8a,+strict-align,+neon,+fp-armv8", 8 | "link-script": "__sel4_ipc_buffer_obj = (__ehdr_start & ~(4096 - 1)) - 4096;", 9 | "linker": "rust-lld", 10 | "linker-flavor": "gnu-lld", 11 | "llvm-target": "aarch64-unknown-none", 12 | "max-atomic-width": 128, 13 | "metadata": { 14 | "description": null, 15 | "host_tools": null, 16 | "std": null, 17 | "tier": null 18 | }, 19 | "panic-strategy": "abort", 20 | "pre-link-args": { 21 | "gnu-lld": [ 22 | "-z", 23 | "max-page-size=4096" 24 | ] 25 | }, 26 | "relocation-model": "static", 27 | "stack-probes": { 28 | "kind": "inline" 29 | }, 30 | "supported-sanitizers": [ 31 | "kcfi", 32 | "kernel-address" 33 | ], 34 | "target-pointer-width": "64" 35 | } 36 | -------------------------------------------------------------------------------- /loader/src/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | #if defined(CONFIG_PRINTING) 14 | 15 | void uart_init(void); 16 | void puts(const char *s); 17 | void puthex64(uint64_t val); 18 | void puthex32(uint32_t val); 19 | /* only 0-9 allowed */ 20 | void putdecimal(uint8_t val); 21 | 22 | #define LDR_PRINT(lvl, cpu, msg) do { \ 23 | puts("LDR|" lvl "|CPU"); \ 24 | putdecimal(cpu); \ 25 | puts(": " msg); \ 26 | } while (0); 27 | 28 | #else 29 | 30 | static inline void uart_init(void) {} 31 | static inline void puts(const char *s) {} 32 | static inline void puthex64(uint64_t val) {} 33 | static inline void puthex32(uint32_t val) {} 34 | static inline void putdecimal(uint8_t val) {} 35 | 36 | #define LDR_PRINT(...) do { } while (0) 37 | 38 | #endif /* CONFIG_PRINTING */ 39 | -------------------------------------------------------------------------------- /example/setvar/setvar.system: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /loader/src/loader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #pragma once 9 | 10 | #define STACK_SIZE 4096 11 | 12 | #define REGION_TYPE_DATA 1 13 | #define REGION_TYPE_ZERO 2 14 | 15 | #ifndef __ASSEMBLER__ 16 | 17 | #include 18 | #include 19 | 20 | #include "cpus.h" 21 | 22 | 23 | struct region { 24 | uintptr_t load_addr; 25 | uintptr_t size; 26 | uintptr_t offset; 27 | uintptr_t type; 28 | }; 29 | 30 | struct loader_data { 31 | uintptr_t magic; 32 | uintptr_t size; 33 | uintptr_t kernel_entry; 34 | uintptr_t ui_p_reg_start; 35 | uintptr_t ui_p_reg_end; 36 | uintptr_t pv_offset; 37 | uintptr_t v_entry; 38 | 39 | uintptr_t num_regions; 40 | struct region regions[]; 41 | }; 42 | 43 | extern const struct loader_data *loader_data; 44 | 45 | /* Called from assembly */ 46 | void relocation_failed(void); 47 | void relocation_log(uint64_t reloc_addr, uint64_t curr_addr); 48 | 49 | extern uint64_t _stack[NUM_ACTIVE_CPUS][STACK_SIZE / sizeof(uint64_t)]; 50 | 51 | void start_kernel(int logical_cpu); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /example/setvar/setvar.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | uint64_t mr_with_paddr_vaddr; 10 | uint64_t mr_with_paddr_paddr; 11 | 12 | uint64_t small_mr_no_paddr_paddr; 13 | uint64_t large_mr_no_paddr_paddr; 14 | 15 | uint64_t pl011_paddr; 16 | 17 | void init(void) 18 | { 19 | microkit_dbg_puts("Virtual address of 'mr_with_paddr': "); 20 | microkit_dbg_put32(mr_with_paddr_vaddr); 21 | microkit_dbg_puts("\n"); 22 | microkit_dbg_puts("Physical address of 'mr_with_paddr': "); 23 | microkit_dbg_put32(mr_with_paddr_paddr); 24 | microkit_dbg_puts("\n"); 25 | 26 | microkit_dbg_puts("Physical address of 'small_mr_no_paddr': "); 27 | microkit_dbg_put32(small_mr_no_paddr_paddr); 28 | microkit_dbg_puts("\n"); 29 | microkit_dbg_puts("Physical address of 'large_mr_no_paddr': "); 30 | microkit_dbg_put32(large_mr_no_paddr_paddr); 31 | microkit_dbg_puts("\n"); 32 | 33 | microkit_dbg_puts("Physical address of 'pl011_paddr': "); 34 | microkit_dbg_put32(pl011_paddr); 35 | microkit_dbg_puts("\n"); 36 | } 37 | 38 | void notified(microkit_channel ch) 39 | { 40 | } 41 | -------------------------------------------------------------------------------- /loader/src/cutil.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #include "cutil.h" 9 | 10 | void *memcpy(void *dst, const void *src, size_t sz) 11 | { 12 | char *dst_ = dst; 13 | const char *src_ = src; 14 | while (sz-- > 0) { 15 | *dst_++ = *src_++; 16 | } 17 | 18 | return dst; 19 | } 20 | 21 | void *memmove(void *restrict dest, const void *restrict src, size_t n) 22 | { 23 | unsigned char *d = (unsigned char *)dest; 24 | const unsigned char *s = (const unsigned char *)src; 25 | 26 | /* no copying to do */ 27 | if (d == s) { 28 | return dest; 29 | } 30 | /* for non-overlapping regions, just use memcpy */ 31 | else if (s + n <= d || d + n <= s) { 32 | return memcpy(dest, src, n); 33 | } 34 | /* if copying from the start of s to the start of d, just use memcpy */ 35 | else if (s > d) { 36 | return memcpy(dest, src, n); 37 | } 38 | 39 | /* copy from end of 's' to end of 'd' */ 40 | size_t i; 41 | for (i = 1; i <= n; i++) { 42 | d[n - i] = s[n - i]; 43 | } 44 | 45 | return dest; 46 | } 47 | -------------------------------------------------------------------------------- /example/ethernet/foo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | #define ECHO_CH 2 10 | 11 | volatile uint64_t *shared_counter = (uint64_t *)(uintptr_t)0x1800000; 12 | 13 | void 14 | init(void) 15 | { 16 | microkit_dbg_puts("foo: foo protection domain init function running\n"); 17 | microkit_dbg_puts("foo: sending a notification\n"); 18 | *shared_counter = 0x37; 19 | microkit_notify(ECHO_CH); 20 | microkit_dbg_puts("foo: sent a notification\n"); 21 | } 22 | 23 | void 24 | notified(microkit_channel ch) 25 | { 26 | switch (ch) { 27 | case ECHO_CH: 28 | microkit_dbg_puts("foo: received notification on echo channel\n"); 29 | if (*shared_counter == 0x38) { 30 | microkit_dbg_puts("foo: counter is expected value\n"); 31 | } else { 32 | microkit_dbg_puts("foo: counter is unexpected value\n"); 33 | } 34 | 35 | break; 36 | 37 | default: 38 | microkit_dbg_puts("foo: received notification on unexpected channel\n"); 39 | break; 40 | /* ignore any other channels */ 41 | } 42 | } -------------------------------------------------------------------------------- /loader/src/aarch64/mmu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #include 9 | 10 | #include "el.h" 11 | #include "../arch.h" 12 | #include "../cutil.h" 13 | #include "../uart.h" 14 | 15 | void el1_mmu_enable(void); 16 | void el2_mmu_enable(void); 17 | 18 | /* Paging structures for kernel mapping */ 19 | uint64_t boot_lvl0_upper[1 << 9] ALIGN(1 << 12); 20 | uint64_t boot_lvl1_upper[1 << 9] ALIGN(1 << 12); 21 | uint64_t boot_lvl2_upper[1 << 9] ALIGN(1 << 12); 22 | 23 | /* Paging structures for identity mapping */ 24 | uint64_t boot_lvl0_lower[1 << 9] ALIGN(1 << 12); 25 | uint64_t boot_lvl1_lower[1 << 9] ALIGN(1 << 12); 26 | 27 | int arch_mmu_enable(int logical_cpu) 28 | { 29 | int r; 30 | enum el el; 31 | r = ensure_correct_el(logical_cpu); 32 | if (r != 0) { 33 | return r; 34 | } 35 | 36 | LDR_PRINT("INFO", logical_cpu, "enabling MMU\n"); 37 | el = current_el(); 38 | if (el == EL1) { 39 | el1_mmu_enable(); 40 | } else if (el == EL2) { 41 | el2_mmu_enable(); 42 | } else { 43 | LDR_PRINT("ERROR", logical_cpu, "unknown EL for MMU enable\n"); 44 | } 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /LICENSES/BSD-2-Clause.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /loader/src/riscv/init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #include "../arch.h" 9 | #include "../cpus.h" 10 | #include "../loader.h" 11 | #include "../uart.h" 12 | 13 | #include 14 | 15 | void arch_init(void) 16 | { 17 | puts("LDR|INFO: configured with FIRST_HART_ID "); 18 | puthex32(CONFIG_FIRST_HART_ID); 19 | puts("\n"); 20 | } 21 | 22 | typedef void (*sel4_entry)( 23 | uintptr_t ui_p_reg_start, 24 | uintptr_t ui_p_reg_end, 25 | intptr_t pv_offset, 26 | uintptr_t v_entry, 27 | uintptr_t dtb_addr_p, 28 | uintptr_t dtb_size 29 | #if defined(CONFIG_ENABLE_SMP_SUPPORT) 30 | , 31 | uint64_t hart_id, 32 | uint64_t core_id 33 | #endif 34 | ); 35 | 36 | void arch_jump_to_kernel(int logical_cpu) 37 | { 38 | #if defined(CONFIG_ENABLE_SMP_SUPPORT) 39 | uint64_t hart_id = plat_get_hw_id(logical_cpu); 40 | #endif 41 | 42 | ((sel4_entry)(loader_data->kernel_entry))( 43 | loader_data->ui_p_reg_start, 44 | loader_data->ui_p_reg_end, 45 | loader_data->pv_offset, 46 | loader_data->v_entry, 47 | 0, 48 | 0 49 | #if defined(CONFIG_ENABLE_SMP_SUPPORT) 50 | , 51 | hart_id, 52 | logical_cpu 53 | #endif 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /loader/src/riscv/mmu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #include 9 | 10 | #include "../arch.h" 11 | #include "../cutil.h" 12 | 13 | /* Paging structures for kernel mapping */ 14 | uint64_t boot_lvl1_pt[1 << 9] ALIGN(1 << 12); 15 | uint64_t boot_lvl2_pt[1 << 9] ALIGN(1 << 12); 16 | /* Paging structures for identity mapping */ 17 | uint64_t boot_lvl2_pt_elf[1 << 9] ALIGN(1 << 12); 18 | 19 | 20 | /* 21 | * This is the encoding for the MODE field of the satp register when 22 | * implementing 39-bit virtual address spaces (known as Sv39). 23 | */ 24 | #define VM_MODE (0x8llu << 60) 25 | 26 | #define RISCV_PGSHIFT 12 27 | 28 | int arch_mmu_enable(int logical_cpu) 29 | { 30 | // The RISC-V privileged spec (20211203), section 4.1.11 says that the 31 | // SFENCE.VMA instruction may need to be executed before or after writing 32 | // to satp. I don't understand why we do it before compared to after. 33 | // Need to understand 4.2.1 of the spec. 34 | asm volatile("sfence.vma" ::: "memory"); 35 | asm volatile( 36 | "csrw satp, %0\n" 37 | : 38 | : "r"(VM_MODE | (uintptr_t)boot_lvl1_pt >> RISCV_PGSHIFT) 39 | : 40 | ); 41 | asm volatile("fence.i" ::: "memory"); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /loader/src/cpus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | /* Define our own variant of the seL4 config */ 15 | #define NUM_ACTIVE_CPUS CONFIG_MAX_NUM_NODES 16 | 17 | /** 18 | * This is the number of cores that we are going to boot seL4 with, 19 | * i.e. the active configuration. 20 | * 21 | * NUM_ACTIVE_CPUS is passed by the build system and can be used where 22 | * compile-time constants in C are needed. 23 | **/ 24 | const inline int plat_get_active_cpus(void) 25 | { 26 | return NUM_ACTIVE_CPUS; 27 | } 28 | 29 | /** 30 | * This is the number of cores that the platform actually has. 31 | **/ 32 | const int plat_get_available_cpus(void); 33 | 34 | /** 35 | * Tell the platform specific code about the hardware ID corresponding 36 | * to the logical ID. 37 | * This will often be MPIDR on ARM. 38 | **/ 39 | void plat_save_hw_id(int logical_cpu, size_t hw_id); 40 | 41 | /** 42 | * Get the hardware ID from a logical ID from platform specific code 43 | **/ 44 | size_t plat_get_hw_id(int logical_cpu); 45 | 46 | /** 47 | * Start the CPU with the given logical ID. 48 | * Returns a non-zero integer on failure. 49 | * Note this logical_cpu is the *target* CPU. 50 | **/ 51 | int plat_start_cpu(int logical_cpu); 52 | -------------------------------------------------------------------------------- /libmicrokit/src/dbg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | 8 | #define __thread 9 | #include 10 | 11 | void microkit_dbg_putc(int c) 12 | { 13 | #if defined(CONFIG_PRINTING) 14 | seL4_DebugPutChar(c); 15 | #endif 16 | } 17 | 18 | 19 | 20 | void microkit_dbg_puts(const char *s) 21 | { 22 | while (*s) { 23 | microkit_dbg_putc(*s); 24 | s++; 25 | } 26 | } 27 | 28 | void microkit_dbg_put8(seL4_Uint8 x) 29 | { 30 | char tmp[4]; 31 | unsigned i = 3; 32 | tmp[3] = 0; 33 | do { 34 | seL4_Uint8 c = x % 10; 35 | tmp[--i] = '0' + c; 36 | x /= 10; 37 | } while (x); 38 | microkit_dbg_puts(&tmp[i]); 39 | } 40 | 41 | void microkit_dbg_put32(seL4_Uint32 x) 42 | { 43 | char tmp[11]; 44 | unsigned i = 10; 45 | tmp[10] = 0; 46 | do { 47 | seL4_Uint8 c = x % 10; 48 | tmp[--i] = '0' + c; 49 | x /= 10; 50 | } while (x); 51 | microkit_dbg_puts(&tmp[i]); 52 | } 53 | 54 | void __assert_fail(const char *str, const char *file, int line, const char *function) 55 | { 56 | microkit_dbg_puts("assert failed: "); 57 | microkit_dbg_puts(str); 58 | microkit_dbg_puts(" "); 59 | microkit_dbg_puts(file); 60 | microkit_dbg_puts(" "); 61 | microkit_dbg_puts(function); 62 | microkit_dbg_puts("\n"); 63 | } 64 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.github/workflows/pr.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 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 | 16 | clippy_check: 17 | runs-on: ubuntu-latest 18 | # Make sure CI fails on all warnings, including Clippy lints 19 | env: 20 | RUSTFLAGS: "-Dwarnings" 21 | steps: 22 | - uses: actions/checkout@v4 23 | - uses: actions/cache@v3 24 | with: 25 | path: | 26 | ~/.cargo/bin/ 27 | ~/.cargo/registry/index/ 28 | ~/.cargo/registry/cache/ 29 | ~/.cargo/git/db/ 30 | target/ 31 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 32 | - name: Run Clippy 33 | run: cd tool/microkit && cargo clippy --all-targets --all-features 34 | 35 | rustfmt_check: 36 | runs-on: ubuntu-latest 37 | steps: 38 | - uses: actions/checkout@v4 39 | - uses: actions/cache@v3 40 | with: 41 | path: | 42 | ~/.cargo/bin/ 43 | ~/.cargo/registry/index/ 44 | ~/.cargo/registry/cache/ 45 | ~/.cargo/git/db/ 46 | target/ 47 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 48 | - name: Run rustfmt 49 | run: cd tool/microkit && cargo fmt --check 50 | -------------------------------------------------------------------------------- /loader/src/riscv/sbi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #define SBI_BASE_EID 0x10 10 | #define SBI_HSM_EID 0x48534DULL 11 | #define SBI_DEBUG_CONSOLE_EID 0x4442434E 12 | 13 | /* SBI commands for the base extension */ 14 | #define SBI_BASE_PROBE_EXT_FID 3 15 | 16 | /* SBI commands for the HSM extension */ 17 | #define SBI_HSM_HART_START_FID 0 18 | #define SBI_HSM_HART_STOP_FID 1 19 | 20 | /* SBI commands for the DEBUG_CONSOLE extension */ 21 | #define SBI_DEBUG_CONSOLE_WRITE_BYTE_FID 0x2 22 | 23 | #ifndef __ASSEMBLER__ 24 | 25 | #include 26 | #include 27 | 28 | struct sbi_ret { 29 | uint64_t error; 30 | uint64_t value; 31 | }; 32 | 33 | enum sbi_error { 34 | SBI_SUCCESS = 0, 35 | SBI_ERR_FAILED = -1, 36 | SBI_ERR_NOT_SUPPORTED = -2, 37 | SBI_ERR_INVALID_PARAM = -3, 38 | SBI_ERR_DENIED = -4, 39 | SBI_ERR_INVALID_ADDRESS = -5, 40 | SBI_ERR_ALREADY_AVAILABLE = -6, 41 | SBI_ERR_ALREADY_STARTED = -7, 42 | SBI_ERR_ALREADY_STOPPED = -8, 43 | SBI_ERR_NO_SHMEM = -9, 44 | SBI_ERR_INVALID_STATE = -10, 45 | SBI_ERR_BAD_RANGE = -11, 46 | SBI_ERR_TIMEOUT = -12, 47 | SBI_ERR_IO = -13, 48 | SBI_ERR_DENIED_LOCKED = -14, 49 | }; 50 | 51 | struct sbi_ret sbi_call(uint64_t eid, uint64_t fid, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, 52 | uint64_t arg4, uint64_t arg5); 53 | char *sbi_error_as_string(long error); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /libmicrokit/microkit.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | PHDRS 7 | { 8 | text PT_LOAD; 9 | data PT_LOAD; 10 | } 11 | 12 | ENTRY(_start); 13 | 14 | SECTIONS 15 | { 16 | . = 0x200000; 17 | 18 | .text : 19 | { 20 | _text = .; 21 | *(.text.start) 22 | *(.text*) 23 | *(.rodata) 24 | _text_end = .; 25 | } :text 26 | 27 | . = ALIGN(0x1000); 28 | 29 | /* For some reason the ABI puts init array 30 | * into writable memory, so we have to follow suit */ 31 | .init_array : 32 | { 33 | PROVIDE(__init_array_start = .); 34 | KEEP (*(SORT(.init_array.*))) 35 | KEEP (*(.init_array*)) 36 | PROVIDE(__init_array_end = .); 37 | } :data 38 | 39 | .data.rel.ro : 40 | { 41 | . = ALIGN(8); 42 | __data_rel_ro_start = .; 43 | *(.data.rel.ro.local*) *(.data.rel.ro*) *(.data.rel*) 44 | __data_rel_ro_end = .; 45 | . = ALIGN(8); 46 | } :data 47 | 48 | .data : 49 | { 50 | _data = .; 51 | *(.data) 52 | . = ALIGN(8); 53 | __global_pointer$ = . + 0x800; 54 | *(.srodata) 55 | *(.sdata) 56 | _data_end = .; 57 | } :data 58 | 59 | .bss : 60 | { 61 | _bss = .; 62 | *(.sbss) 63 | *(.bss) 64 | *(.bss*) 65 | *(COMMON) 66 | . = ALIGN(4); 67 | _bss_end = .; 68 | } :data 69 | 70 | . = ALIGN(0x1000); 71 | .ipc_buffer (NOLOAD): { 72 | __sel4_ipc_buffer_obj = .; 73 | } :NONE 74 | } 75 | -------------------------------------------------------------------------------- /example/hierarchy/restarter.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | 9 | static uint8_t restart_count = 0; 10 | 11 | static char decchar(unsigned int v) 12 | { 13 | return '0' + v; 14 | } 15 | 16 | static void put8(uint8_t x) 17 | { 18 | char tmp[4]; 19 | unsigned i = 3; 20 | tmp[3] = 0; 21 | do { 22 | uint8_t c = x % 10; 23 | tmp[--i] = decchar(c); 24 | x /= 10; 25 | } while (x); 26 | microkit_dbg_puts(&tmp[i]); 27 | } 28 | 29 | void init(void) 30 | { 31 | microkit_dbg_puts("restarter: starting\n"); 32 | } 33 | 34 | void notified(microkit_channel ch) 35 | { 36 | } 37 | 38 | seL4_MessageInfo_t protected(microkit_channel ch, microkit_msginfo msginfo) 39 | { 40 | microkit_dbg_puts("restarter: received protected message\n"); 41 | 42 | return microkit_msginfo_new(0, 0); 43 | } 44 | 45 | seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo) 46 | { 47 | microkit_dbg_puts("restarter: received fault message for child pd: "); 48 | put8(child); 49 | microkit_dbg_puts("\n"); 50 | restart_count++; 51 | if (restart_count < 10) { 52 | microkit_pd_restart(child, 0x200000); 53 | microkit_dbg_puts("restarter: restarted\n"); 54 | } else { 55 | microkit_pd_stop(child); 56 | microkit_dbg_puts("restarter: too many restarts - PD stopped\n"); 57 | } 58 | 59 | /* We explicitly restart the thread so we do not need to 'reply' to the fault. */ 60 | return seL4_False; 61 | } 62 | -------------------------------------------------------------------------------- /loader/src/arch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | /** 10 | * The layout and naming scheme of the functions in these files has meaning: 11 | * 12 | * - Functions that start with `arch_`, as specified within `arch.h`, e.g. 13 | * `arch_mmu_enable`, conform to a common interface across all architectures. 14 | * Code for these functions belongs in the architecture-specific subdirectory. 15 | * 16 | * - Functions that start with `plat_` are platform/board specific, conforming 17 | * to a common interface. This is useful for code such as CPU on/offlining. 18 | * This needs to be called from common code, but has details that are arch 19 | * and/or platform specific. 20 | * 21 | * - Functions starting with `arm_` or `riscv_` correspond to architecture-specific 22 | * code that is *not* expected to conform to a common interface. For instance 23 | * `arm_secondary_cpu_entry` is prefixed as such because it needs to do ARM 24 | * specific functions and is called by an ARM-specific convention. 25 | * 26 | * - Remaining functions are somewhat of a grab bag; some code in the non-arch- 27 | * specific files are for code common between all architectures, but these 28 | * also contain architecture specific code, depending. 29 | * Also, the UART code is not prefixed with `plat_` even though it conceptually 30 | * could be that way, simply because it makes function calls more verbose, 31 | * and UART is obviously platform specific. 32 | */ 33 | 34 | void arch_init(void); 35 | void arch_set_exception_handler(void); 36 | int arch_mmu_enable(int logical_cpu); 37 | void arch_jump_to_kernel(int logical_cpu); 38 | -------------------------------------------------------------------------------- /example/setvar/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025, UNSW. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(MICROKIT_SDK)),) 11 | $(error MICROKIT_SDK must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(MICROKIT_BOARD)),) 15 | $(error MICROKIT_BOARD must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(MICROKIT_CONFIG)),) 19 | $(error MICROKIT_CONFIG must be specified) 20 | endif 21 | 22 | BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG) 23 | 24 | ARCH := ${shell grep 'CONFIG_SEL4_ARCH ' $(BOARD_DIR)/include/kernel/gen_config.h | cut -d' ' -f4} 25 | 26 | ifeq ($(ARCH),aarch64) 27 | TOOLCHAIN := aarch64-none-elf 28 | # No specific AArch64 flags 29 | CFLAGS_ARCH := 30 | else 31 | $(error Unsupported ARCH) 32 | endif 33 | 34 | CC := $(TOOLCHAIN)-gcc 35 | LD := $(TOOLCHAIN)-ld 36 | AS := $(TOOLCHAIN)-as 37 | MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit 38 | 39 | SETVAR_OBJS := setvar.o 40 | 41 | IMAGES := setvar.elf 42 | CFLAGS := -mstrict-align -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(BOARD_DIR)/include $(CFLAGS_ARCH) 43 | LDFLAGS := -L$(BOARD_DIR)/lib 44 | LIBS := -lmicrokit -Tmicrokit.ld 45 | 46 | IMAGE_FILE = $(BUILD_DIR)/loader.img 47 | REPORT_FILE = $(BUILD_DIR)/report.txt 48 | 49 | all: $(IMAGE_FILE) 50 | 51 | $(BUILD_DIR)/%.o: %.c Makefile 52 | $(CC) -c $(CFLAGS) $< -o $@ 53 | 54 | $(BUILD_DIR)/setvar.elf: $(addprefix $(BUILD_DIR)/, $(SETVAR_OBJS)) 55 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 56 | 57 | $(IMAGE_FILE) $(REPORT_FILE): $(addprefix $(BUILD_DIR)/, $(IMAGES)) setvar.system 58 | $(MICROKIT_TOOL) setvar.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE) 59 | -------------------------------------------------------------------------------- /example/arm_smc/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025, UNSW. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(MICROKIT_SDK)),) 11 | $(error MICROKIT_SDK must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(MICROKIT_BOARD)),) 15 | $(error MICROKIT_BOARD must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(MICROKIT_CONFIG)),) 19 | $(error MICROKIT_CONFIG must be specified) 20 | endif 21 | 22 | BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG) 23 | 24 | ARCH := ${shell grep 'CONFIG_SEL4_ARCH ' $(BOARD_DIR)/include/kernel/gen_config.h | cut -d' ' -f4} 25 | 26 | ifeq ($(ARCH),aarch64) 27 | TOOLCHAIN := aarch64-none-elf 28 | # No specific AArch64 flags 29 | CFLAGS_ARCH := 30 | else 31 | $(error Unsupported ARCH) 32 | endif 33 | 34 | CC := $(TOOLCHAIN)-gcc 35 | LD := $(TOOLCHAIN)-ld 36 | AS := $(TOOLCHAIN)-as 37 | MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit 38 | 39 | ARM_SMC_OBJS := arm_smc.o 40 | 41 | IMAGES := arm_smc.elf 42 | CFLAGS := -mstrict-align -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(BOARD_DIR)/include $(CFLAGS_ARCH) 43 | LDFLAGS := -L$(BOARD_DIR)/lib 44 | LIBS := -lmicrokit -Tmicrokit.ld 45 | 46 | IMAGE_FILE = $(BUILD_DIR)/loader.img 47 | REPORT_FILE = $(BUILD_DIR)/report.txt 48 | 49 | all: $(IMAGE_FILE) 50 | 51 | $(BUILD_DIR)/%.o: %.c Makefile 52 | $(CC) -c $(CFLAGS) $< -o $@ 53 | 54 | $(BUILD_DIR)/arm_smc.elf: $(addprefix $(BUILD_DIR)/, $(ARM_SMC_OBJS)) 55 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 56 | 57 | $(IMAGE_FILE) $(REPORT_FILE): $(addprefix $(BUILD_DIR)/, $(IMAGES)) arm_smc.system 58 | $(MICROKIT_TOOL) arm_smc.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE) 59 | -------------------------------------------------------------------------------- /tool/microkit/src/capdl/packaging.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025, UNSW 3 | // 4 | // SPDX-License-Identifier: BSD-2-Clause 5 | // 6 | 7 | use crate::{ 8 | capdl::{initialiser::CapDLInitialiser, CapDLSpecContainer}, 9 | elf::ElfFile, 10 | sel4::{Config, PageSize}, 11 | }; 12 | 13 | pub fn pack_spec_into_initial_task( 14 | sel4_config: &Config, 15 | build_config: &str, 16 | spec_container: &CapDLSpecContainer, 17 | system_elfs: &[ElfFile], 18 | capdl_initialiser: &mut CapDLInitialiser, 19 | ) { 20 | let compress_frames = true; 21 | let embed_frames = true; 22 | 23 | let (mut output_spec, embedded_frame_data_list) = spec_container.spec.embed_fill( 24 | PageSize::Small.fixed_size_bits(sel4_config) as u8, 25 | |_| embed_frames, 26 | |d, buf| { 27 | buf.copy_from_slice( 28 | &system_elfs[d.elf_id].segments[d.elf_seg_idx].data()[d.elf_seg_data_range.clone()], 29 | ); 30 | compress_frames 31 | }, 32 | ); 33 | 34 | let embedded_frame_data = embedded_frame_data_list 35 | .into_iter() 36 | .flatten() 37 | .collect::>(); 38 | 39 | for named_obj in output_spec.objects.iter_mut() { 40 | match build_config { 41 | "smp-debug" | "debug" => {} 42 | // We don't copy over the object names as there is no debug printing in these configuration to save memory. 43 | "release" | "benchmark" | "smp-release" | "smp-benchmark" => named_obj.name = None, 44 | _ => panic!("unknown configuration {build_config}"), 45 | }; 46 | } 47 | 48 | output_spec.cache_orig_cap_slots(); 49 | 50 | output_spec.set_log_level(capdl_initialiser.log_level as u8); 51 | 52 | let initialiser_payload = output_spec.to_bytes().unwrap(); 53 | 54 | capdl_initialiser.add_spec(initialiser_payload, embedded_frame_data); 55 | } 56 | -------------------------------------------------------------------------------- /example/timer/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(MICROKIT_SDK)),) 11 | $(error MICROKIT_SDK must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(MICROKIT_BOARD)),) 15 | $(error MICROKIT_BOARD must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(MICROKIT_CONFIG)),) 19 | $(error MICROKIT_CONFIG must be specified) 20 | endif 21 | 22 | ifneq ($(MICROKIT_BOARD),odroidc4) 23 | $(error Unsupported MICROKIT_BOARD given, only odroidc4 supported) 24 | endif 25 | 26 | TARGET_TRIPLE := aarch64-none-elf 27 | 28 | CPU := cortex-a55 29 | 30 | ifeq ($(strip $(LLVM)),True) 31 | CC := clang -target $(TARGET_TRIPLE) 32 | AS := clang -target $(TARGET_TRIPLE) 33 | LD := ld.lld 34 | else 35 | CC := $(TARGET_TRIPLE)-gcc 36 | LD := $(TARGET_TRIPLE)-ld 37 | AS := $(TARGET_TRIPLE)-as 38 | endif 39 | 40 | MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit 41 | 42 | TIMER_OBJS := timer.o 43 | 44 | BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG) 45 | 46 | IMAGES := timer.elf 47 | CFLAGS := -mcpu=$(CPU) -mstrict-align -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(BOARD_DIR)/include 48 | LDFLAGS := -L$(BOARD_DIR)/lib 49 | LIBS := -lmicrokit -Tmicrokit.ld 50 | 51 | IMAGE_FILE = $(BUILD_DIR)/loader.img 52 | REPORT_FILE = $(BUILD_DIR)/report.txt 53 | 54 | all: $(IMAGE_FILE) 55 | 56 | $(BUILD_DIR)/%.o: %.c Makefile 57 | $(CC) -c $(CFLAGS) $< -o $@ 58 | 59 | $(BUILD_DIR)/%.o: %.s Makefile 60 | $(AS) -g -mcpu=$(CPU) $< -o $@ 61 | 62 | $(BUILD_DIR)/timer.elf: $(addprefix $(BUILD_DIR)/, $(TIMER_OBJS)) 63 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 64 | 65 | $(IMAGE_FILE) $(REPORT_FILE): $(addprefix $(BUILD_DIR)/, $(IMAGES)) timer.system 66 | $(MICROKIT_TOOL) timer.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE) 67 | -------------------------------------------------------------------------------- /libmicrokit/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(ARCH)),) 11 | $(error ARCH must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(TARGET_TRIPLE)),) 15 | $(error TARGET_TRIPLE must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(LLVM)),True) 19 | CC := clang -target $(TARGET_TRIPLE) 20 | CPP := clang-cpp -target $(TARGET_TRIPLE) 21 | AS := clang -target $(TARGET_TRIPLE) 22 | LD := ld.lld 23 | AR := llvm-ar 24 | CFLAGS_TOOLCHAIN := 25 | else 26 | CC = $(TARGET_TRIPLE)-gcc 27 | CPP = $(TARGET_TRIPLE)-cpp 28 | AS = $(TARGET_TRIPLE)-as 29 | LD = $(TARGET_TRIPLE)-ld 30 | AR = $(TARGET_TRIPLE)-ar 31 | CFLAGS_TOOLCHAIN := -Wno-maybe-uninitialized 32 | endif 33 | 34 | ifeq ($(ARCH),aarch64) 35 | ASM_FLAGS := -mcpu=$(GCC_CPU) 36 | CFLAGS_AARCH64 := -mcpu=$(GCC_CPU) 37 | CFLAGS_ARCH := $(CFLAGS_AARCH64) 38 | ARCH_DIR := aarch64 39 | else ifeq ($(ARCH),riscv64) 40 | ASM_FLAGS := -march=rv64imafdc_zicsr_zifencei -mabi=lp64d 41 | CFLAGS_RISCV64 := -mcmodel=medany -march=rv64imafdc_zicsr_zifencei -mabi=lp64d 42 | CFLAGS_ARCH := $(CFLAGS_RISCV64) 43 | ARCH_DIR := riscv 44 | else ifeq ($(ARCH),x86_64) 45 | CFLAGS_ARCH := -march=x86-64 -mtune=$(GCC_CPU) 46 | ASM_FLAGS := -march=generic64 47 | ARCH_DIR := x86_64 48 | endif 49 | 50 | CFLAGS := -std=gnu11 \ 51 | -g -O3 -nostdlib \ 52 | -ffreestanding \ 53 | -Wall $(CFLAGS_TOOLCHAIN) \ 54 | -Wno-unused-function -Werror \ 55 | -Iinclude -I$(SEL4_SDK)/include \ 56 | $(CFLAGS_ARCH) 57 | 58 | LIBS := libmicrokit.a 59 | OBJS := main.o crt0.o dbg.o 60 | 61 | $(BUILD_DIR)/%.o : src/$(ARCH_DIR)/%.S 62 | $(CC) -x assembler-with-cpp -c $(CFLAGS) $< -o $@ 63 | 64 | $(BUILD_DIR)/%.o : src/$(ARCH_DIR)/%.s 65 | $(AS) -c -g $(ASM_FLAGS) $< -o $@ 66 | 67 | $(BUILD_DIR)/%.o : src/%.c 68 | $(CC) -c $(CFLAGS) $< -o $@ 69 | 70 | LIB = $(addprefix $(BUILD_DIR)/, $(LIBS)) 71 | 72 | all: $(LIB) 73 | 74 | $(LIB): $(addprefix $(BUILD_DIR)/, $(OBJS)) 75 | $(AR) -crv $@ $^ 76 | -------------------------------------------------------------------------------- /example/rust/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2023, Colias Group, LLC 3 | # Copyright 2025, UNSW 4 | # 5 | # SPDX-License-Identifier: BSD-2-Clause 6 | # 7 | 8 | ifeq ($(strip $(BUILD_DIR)),) 9 | $(error BUILD_DIR must be specified) 10 | endif 11 | 12 | ifeq ($(strip $(MICROKIT_SDK)),) 13 | $(error MICROKIT_SDK must be specified) 14 | endif 15 | 16 | ifeq ($(strip $(MICROKIT_BOARD)),) 17 | $(error MICROKIT_BOARD must be specified) 18 | endif 19 | 20 | ifeq ($(strip $(MICROKIT_CONFIG)),) 21 | $(error MICROKIT_CONFIG must be specified) 22 | endif 23 | 24 | IMAGE_FILE = $(BUILD_DIR)/loader.img 25 | REPORT_FILE = $(BUILD_DIR)/report.txt 26 | SYSTEM_FILE := rust.system 27 | 28 | all: $(IMAGE_FILE) 29 | 30 | .PHONY: clean 31 | clean: 32 | rm -rf $(BUILD_DIR) 33 | 34 | $(BUILD_DIR): 35 | mkdir -p $@ 36 | 37 | BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG) 38 | SEL4_INCLUDE_DIRS := $(BOARD_DIR)/include 39 | ARCH := ${shell grep 'CONFIG_SEL4_ARCH ' $(BOARD_DIR)/include/kernel/gen_config.h | cut -d' ' -f4} 40 | 41 | ifeq ($(ARCH),aarch64) 42 | RUST_TARGET := aarch64-sel4-microkit-minimal 43 | else ifeq ($(ARCH),riscv64) 44 | RUST_TARGET := riscv64gc-sel4-microkit-minimal 45 | else 46 | $(error Unsupported ARCH) 47 | endif 48 | 49 | crate = $(BUILD_DIR)/$(1).elf 50 | 51 | define build_crate 52 | 53 | $(crate): $(crate).intermediate 54 | 55 | .INTERMDIATE: $(crate).intermediate 56 | $(crate).intermediate: 57 | SEL4_INCLUDE_DIRS=$(abspath $(SEL4_INCLUDE_DIRS)) \ 58 | cargo build \ 59 | -Z build-std=core,alloc,compiler_builtins \ 60 | -Z build-std-features=compiler-builtins-mem \ 61 | --target-dir $(BUILD_DIR)/target \ 62 | --out-dir $(BUILD_DIR) \ 63 | --target $(RUST_TARGET) \ 64 | --release \ 65 | -p $(1) 66 | 67 | endef 68 | 69 | CRATE_NAMES := hello 70 | 71 | CRATES := $(foreach CRATE_NAME,$(CRATE_NAMES),$(call crate,$(CRATE_NAME))) 72 | 73 | $(eval $(foreach CRATE_NAME,$(CRATE_NAMES),$(call build_crate,$(CRATE_NAME)))) 74 | 75 | $(IMAGE_FILE): $(SYSTEM_FILE) $(CRATES) 76 | $(MICROKIT_SDK)/bin/microkit \ 77 | $< \ 78 | --search-path $(BUILD_DIR) \ 79 | --board $(MICROKIT_BOARD) \ 80 | --config $(MICROKIT_CONFIG) \ 81 | -r $(BUILD_DIR)/report.txt \ 82 | -o $@ 83 | -------------------------------------------------------------------------------- /example/hello/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(MICROKIT_SDK)),) 11 | $(error MICROKIT_SDK must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(MICROKIT_BOARD)),) 15 | $(error MICROKIT_BOARD must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(MICROKIT_CONFIG)),) 19 | $(error MICROKIT_CONFIG must be specified) 20 | endif 21 | 22 | BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG) 23 | 24 | ARCH := ${shell grep 'CONFIG_SEL4_ARCH ' $(BOARD_DIR)/include/kernel/gen_config.h | cut -d' ' -f4} 25 | 26 | ifeq ($(ARCH),aarch64) 27 | TARGET_TRIPLE := aarch64-none-elf 28 | CFLAGS_ARCH := -mstrict-align 29 | else ifeq ($(ARCH),riscv64) 30 | TARGET_TRIPLE := riscv64-unknown-elf 31 | CFLAGS_ARCH := -march=rv64imafdc_zicsr_zifencei -mabi=lp64d 32 | else ifeq ($(ARCH),x86_64) 33 | TARGET_TRIPLE := x86_64-linux-gnu 34 | CFLAGS_ARCH := -march=x86-64 -mtune=generic 35 | else 36 | $(error Unsupported ARCH) 37 | endif 38 | 39 | ifeq ($(strip $(LLVM)),True) 40 | CC := clang -target $(TARGET_TRIPLE) 41 | AS := clang -target $(TARGET_TRIPLE) 42 | LD := ld.lld 43 | else 44 | CC := $(TARGET_TRIPLE)-gcc 45 | LD := $(TARGET_TRIPLE)-ld 46 | AS := $(TARGET_TRIPLE)-as 47 | endif 48 | 49 | MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit 50 | 51 | HELLO_OBJS := hello.o 52 | 53 | IMAGES := hello.elf 54 | CFLAGS := -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(BOARD_DIR)/include $(CFLAGS_ARCH) 55 | LDFLAGS := -L$(BOARD_DIR)/lib 56 | LIBS := -lmicrokit -Tmicrokit.ld 57 | 58 | IMAGE_FILE = $(BUILD_DIR)/loader.img 59 | REPORT_FILE = $(BUILD_DIR)/report.txt 60 | 61 | all: $(IMAGE_FILE) 62 | 63 | $(BUILD_DIR)/%.o: %.c Makefile 64 | $(CC) -c $(CFLAGS) $< -o $@ 65 | 66 | $(BUILD_DIR)/hello.elf: $(addprefix $(BUILD_DIR)/, $(HELLO_OBJS)) 67 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 68 | 69 | $(IMAGE_FILE) $(REPORT_FILE): $(addprefix $(BUILD_DIR)/, $(IMAGES)) hello.system 70 | $(MICROKIT_TOOL) hello.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE) 71 | -------------------------------------------------------------------------------- /example/ethernet/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(MICROKIT_SDK)),) 11 | $(error MICROKIT_SDK must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(MICROKIT_BOARD)),) 15 | $(error MICROKIT_BOARD must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(MICROKIT_CONFIG)),) 19 | $(error MICROKIT_CONFIG must be specified) 20 | endif 21 | 22 | ifneq ($(MICROKIT_BOARD),tqma8xqp1gb) 23 | $(error Unsupported MICROKIT_BOARD given, only tqma8xqp1gb supported) 24 | endif 25 | 26 | TARGET_TRIPLE := aarch64-none-elf 27 | 28 | CPU := cortex-a35 29 | 30 | ifeq ($(strip $(LLVM)),True) 31 | CC := clang -target $(TARGET_TRIPLE) 32 | AS := clang -target $(TARGET_TRIPLE) 33 | LD := ld.lld 34 | else 35 | CC := $(TARGET_TRIPLE)-gcc 36 | LD := $(TARGET_TRIPLE)-ld 37 | AS := $(TARGET_TRIPLE)-as 38 | endif 39 | 40 | MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit 41 | 42 | ETH_OBJS := eth.o 43 | PASS_OBJS := pass.o 44 | GPT_OBJS := gpt.o 45 | 46 | BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG) 47 | 48 | IMAGES := eth.elf pass.elf gpt.elf 49 | CFLAGS := -mcpu=$(CPU) -mstrict-align -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(BOARD_DIR)/include 50 | LDFLAGS := -L$(BOARD_DIR)/lib 51 | LIBS := -lmicrokit -Tmicrokit.ld 52 | 53 | IMAGE_FILE = $(BUILD_DIR)/loader.img 54 | REPORT_FILE = $(BUILD_DIR)/report.txt 55 | 56 | all: $(IMAGE_FILE) 57 | 58 | $(BUILD_DIR)/%.o: %.c Makefile 59 | $(CC) -c $(CFLAGS) $< -o $@ 60 | 61 | $(BUILD_DIR)/%.o: %.s Makefile 62 | $(AS) -g -mcpu=$(CPU) $< -o $@ 63 | 64 | $(BUILD_DIR)/eth.elf: $(addprefix $(BUILD_DIR)/, $(ETH_OBJS)) 65 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 66 | 67 | $(BUILD_DIR)/pass.elf: $(addprefix $(BUILD_DIR)/, $(PASS_OBJS)) 68 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 69 | 70 | $(BUILD_DIR)/gpt.elf: $(addprefix $(BUILD_DIR)/, $(GPT_OBJS)) 71 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 72 | 73 | $(IMAGE_FILE) $(REPORT_FILE): $(addprefix $(BUILD_DIR)/, $(IMAGES)) ethernet.system 74 | $(MICROKIT_TOOL) ethernet.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE) 75 | -------------------------------------------------------------------------------- /loader/src/aarch64/exceptions.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #include "exceptions.h" 9 | 10 | #include 11 | 12 | #include "el.h" 13 | #include "../arch.h" 14 | #include "../cutil.h" 15 | #include "../loader.h" 16 | #include "../uart.h" 17 | 18 | extern char arm_vector_table[1]; 19 | 20 | 21 | void arch_set_exception_handler(void) 22 | { 23 | enum el el = current_el(); 24 | if (el == EL2) { 25 | asm volatile("msr vbar_el2, %0" :: "r"(arm_vector_table)); 26 | } 27 | /* Since we call the exception handler before we check we're at 28 | * a valid EL we shouldn't assume we are at EL1 or higher. */ 29 | if (el != EL0) { 30 | asm volatile("msr vbar_el1, %0" :: "r"(arm_vector_table)); 31 | } 32 | } 33 | 34 | uintptr_t exception_register_state[32]; 35 | 36 | void exception_handler(uintptr_t ex) 37 | { 38 | /* Read ESR/FSR based on the exception level we're at. */ 39 | uint64_t esr; 40 | uintptr_t far; 41 | 42 | if (is_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) { 43 | asm volatile("mrs %0, ESR_EL2" : "=r"(esr) :: "cc"); 44 | asm volatile("mrs %0, FAR_EL2" : "=r"(far) :: "cc"); 45 | } else { 46 | asm volatile("mrs %0, ESR_EL1" : "=r"(esr) :: "cc"); 47 | asm volatile("mrs %0, FAR_EL1" : "=r"(far) :: "cc"); 48 | } 49 | 50 | uintptr_t ec = (esr >> 26) & 0x3f; 51 | puts("\nLDR|ERROR: loader trapped exception: "); 52 | puts(ex_to_string(ex)); 53 | if (is_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) { 54 | puts("\n esr_el2: "); 55 | } else { 56 | puts("\n esr_el1: "); 57 | } 58 | puthex64(esr); 59 | puts("\n ec: "); 60 | puthex32(ec); 61 | puts(" ("); 62 | puts(ec_to_string(ec)); 63 | puts(")\n il: "); 64 | puthex64((esr >> 25) & 1); 65 | puts("\n iss: "); 66 | puthex64(esr & MASK(24)); 67 | puts("\n far: "); 68 | puthex64(far); 69 | puts("\n"); 70 | 71 | for (unsigned i = 0; i < 32; i++) { 72 | puts(" reg: "); 73 | puthex32(i); 74 | puts(": "); 75 | puthex64(exception_register_state[i]); 76 | puts("\n"); 77 | } 78 | 79 | for (;;) { 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /monitor/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(ARCH)),) 11 | $(error ARCH must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(TARGET_TRIPLE)),) 15 | $(error TARGET_TRIPLE must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(LLVM)),True) 19 | CC = clang -target $(TARGET_TRIPLE) 20 | CPP = clang-cpp -target $(TARGET_TRIPLE) 21 | AS = clang -target $(TARGET_TRIPLE) 22 | LD = ld.lld 23 | AR = llvm-ar 24 | CFLAGS_TOOLCHAIN := 25 | else 26 | CC = $(TARGET_TRIPLE)-gcc 27 | CPP = $(TARGET_TRIPLE)-cpp 28 | AS = $(TARGET_TRIPLE)-as 29 | LD = $(TARGET_TRIPLE)-ld 30 | AR = $(TARGET_TRIPLE)-ar 31 | CFLAGS_TOOLCHAIN := -Wno-maybe-uninitialized 32 | endif 33 | 34 | ifeq ($(ARCH),aarch64) 35 | CFLAGS_ARCH := -mcpu=$(GCC_CPU) 36 | ASM_CPP_FLAGS := -x assembler-with-cpp -c -g -mcpu=$(GCC_CPU) 37 | ASM_FLAGS := -mcpu=$(GCC_CPU) 38 | 39 | ARCH_DIR := aarch64 40 | else ifeq ($(ARCH),riscv64) 41 | ASM_CPP_FLAGS := -x assembler-with-cpp -c -g -march=rv64imac_zicsr_zifencei -mabi=lp64 42 | ASM_FLAGS := -march=rv64imac_zicsr_zifencei -mabi=lp64 43 | CFLAGS_ARCH := -mcmodel=medany -march=rv64imac_zicsr_zifencei -mabi=lp64 44 | 45 | ARCH_DIR := riscv 46 | else ifeq ($(ARCH),x86_64) 47 | CFLAGS_ARCH := -march=x86-64 -mtune=$(GCC_CPU) 48 | ASM_CPP_FLAGS := -x assembler-with-cpp -c -g 49 | ASM_FLAGS := -g -march=generic64 50 | 51 | ARCH_DIR := x86_64 52 | else 53 | $(error ARCH is unsupported) 54 | endif 55 | 56 | CFLAGS := -std=gnu11 -g -O3 -nostdlib -ffreestanding -Wall $(CFLAGS_TOOLCHAIN) -Werror -I$(SEL4_SDK)/include $(CFLAGS_ARCH) -DARCH_$(ARCH) 57 | 58 | PROGS := monitor.elf 59 | OBJECTS := main.o crt0.o util.o 60 | LINKSCRIPT := ../libmicrokit/microkit.ld 61 | 62 | $(BUILD_DIR)/%.o : src/$(ARCH_DIR)/%.S 63 | $(CC) $(ASM_CPP_FLAGS) $< -o $@ 64 | 65 | $(BUILD_DIR)/%.o : src/$(ARCH_DIR)/%.s 66 | $(AS) -c -g $(ASM_FLAGS) $< -o $@ 67 | 68 | $(BUILD_DIR)/%.o : src/%.c 69 | $(CC) -c $(CFLAGS) $< -o $@ 70 | 71 | OBJPROG = $(addprefix $(BUILD_DIR)/, $(PROGS)) 72 | 73 | all: $(OBJPROG) 74 | 75 | $(OBJPROG): $(addprefix $(BUILD_DIR)/, $(OBJECTS)) $(LINKSCRIPT) 76 | $(LD) -z noexecstack -T$(LINKSCRIPT) $(addprefix $(BUILD_DIR)/, $(OBJECTS)) -o $@ 77 | -------------------------------------------------------------------------------- /example/x86_64_ioport/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025, UNSW 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(MICROKIT_SDK)),) 11 | $(error MICROKIT_SDK must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(MICROKIT_BOARD)),) 15 | $(error MICROKIT_BOARD must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(MICROKIT_CONFIG)),) 19 | $(error MICROKIT_CONFIG must be specified) 20 | endif 21 | 22 | BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG) 23 | 24 | ARCH := ${shell grep 'CONFIG_SEL4_ARCH ' $(BOARD_DIR)/include/kernel/gen_config.h | cut -d' ' -f4} 25 | 26 | ifeq ($(ARCH),x86_64) 27 | TOOLCHAIN := x86_64-linux-gnu 28 | CFLAGS_ARCH := -march=x86-64 -mtune=generic 29 | else 30 | $(error Unsupported ARCH) 31 | endif 32 | 33 | CC := $(TOOLCHAIN)-gcc 34 | LD := $(TOOLCHAIN)-ld 35 | AS := $(TOOLCHAIN)-as 36 | OBJCOPY := $(TOOLCHAIN)-objcopy 37 | MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit 38 | 39 | IMAGES := x86_64_ioport.elf 40 | CFLAGS := -nostdlib -ffreestanding -g3 -O3 -I$(BOARD_DIR)/include $(CFLAGS_ARCH) 41 | LDFLAGS := -L$(BOARD_DIR)/lib -z noexecstack 42 | LIBS := -lmicrokit -Tmicrokit.ld 43 | 44 | INITIAL_TASK = $(BUILD_DIR)/initialiser.elf 45 | KERNEL = $(BUILD_DIR)/sel4.elf 46 | KERNEL_32B = $(BUILD_DIR)/sel4_32.elf 47 | REPORT = $(BUILD_DIR)/report.txt 48 | SPEC = $(BUILD_DIR)/capdl_spec.json 49 | 50 | all: $(KERNEL) $(INITIAL_TASK) 51 | qemu: $(KERNEL_32B) $(INITIAL_TASK) 52 | 53 | $(BUILD_DIR)/x86_64_ioport.o: x86_64_ioport.c Makefile 54 | $(CC) -c $(CFLAGS) -Wall -Wno-unused-function -Werror $< -o $@ 55 | 56 | $(BUILD_DIR)/x86_64_ioport.elf: $(BUILD_DIR)/x86_64_ioport.o 57 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 58 | 59 | $(KERNEL) $(KERNEL_32B) $(INITIAL_TASK): $(addprefix $(BUILD_DIR)/, $(IMAGES)) x86_64_ioport.system 60 | $(MICROKIT_TOOL) x86_64_ioport.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(INITIAL_TASK) -r $(REPORT) --capdl-json $(SPEC) 61 | 62 | qemu: 63 | qemu-system-x86_64 \ 64 | -cpu qemu64,+fsgsbase,+pdpe1gb,+xsaveopt,+xsave \ 65 | -m "1G" \ 66 | -display none \ 67 | -serial mon:stdio \ 68 | -kernel $(KERNEL_32B) \ 69 | -initrd $(INITIAL_TASK) 70 | -------------------------------------------------------------------------------- /loader/src/riscv/sbi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include "sbi.h" 8 | 9 | struct sbi_ret sbi_call(uint64_t eid, uint64_t fid, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, 10 | uint64_t arg4, uint64_t arg5) 11 | { 12 | struct sbi_ret ret; 13 | 14 | register uint64_t a0 asm("a0") = arg0; 15 | register uint64_t a1 asm("a1") = arg1; 16 | register uint64_t a2 asm("a2") = arg2; 17 | register uint64_t a3 asm("a3") = arg3; 18 | register uint64_t a4 asm("a4") = arg4; 19 | register uint64_t a5 asm("a5") = arg5; 20 | register uint64_t a6 asm("a6") = fid; 21 | register uint64_t a7 asm("a7") = eid; 22 | 23 | asm volatile("ecall" 24 | : "+r"(a0), "+r"(a1) 25 | : "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6), "r"(a7) 26 | : "memory"); 27 | 28 | ret.error = a0; 29 | ret.value = a1; 30 | 31 | return ret; 32 | } 33 | 34 | /* 35 | * Chapter 3, Table 1 of SBI specification. 36 | */ 37 | char *sbi_error_as_string(long error) 38 | { 39 | switch (error) { 40 | case SBI_SUCCESS: 41 | return "Completed successfully"; 42 | case SBI_ERR_FAILED: 43 | return "Failed"; 44 | case SBI_ERR_NOT_SUPPORTED: 45 | return "Not supported"; 46 | case SBI_ERR_INVALID_PARAM: 47 | return "Invalid parameter(s)"; 48 | case SBI_ERR_DENIED: 49 | return "Denied or not allowed"; 50 | case SBI_ERR_INVALID_ADDRESS: 51 | return "Invalid address(s)"; 52 | case SBI_ERR_ALREADY_AVAILABLE: 53 | return "Already available"; 54 | case SBI_ERR_ALREADY_STARTED: 55 | return "Already started"; 56 | case SBI_ERR_ALREADY_STOPPED: 57 | return "Already stopped"; 58 | case SBI_ERR_NO_SHMEM: 59 | return "Shared memory not available"; 60 | case SBI_ERR_INVALID_STATE: 61 | return "Invalid state"; 62 | case SBI_ERR_BAD_RANGE: 63 | return "Bad (or invalid) range"; 64 | case SBI_ERR_TIMEOUT: 65 | return "Failed due to timeout"; 66 | case SBI_ERR_IO: 67 | return "Input/Output error"; 68 | case SBI_ERR_DENIED_LOCKED: 69 | return "Denied or not allowed due to lock status"; 70 | default: 71 | return ""; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /example/passive_server/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(MICROKIT_SDK)),) 11 | $(error MICROKIT_SDK must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(MICROKIT_BOARD)),) 15 | $(error MICROKIT_BOARD must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(MICROKIT_CONFIG)),) 19 | $(error MICROKIT_CONFIG must be specified) 20 | endif 21 | 22 | BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG) 23 | 24 | ARCH := ${shell grep 'CONFIG_SEL4_ARCH ' $(BOARD_DIR)/include/kernel/gen_config.h | cut -d' ' -f4} 25 | 26 | ifeq ($(ARCH),aarch64) 27 | TARGET_TRIPLE := aarch64-none-elf 28 | CFLAGS_ARCH := -mstrict-align 29 | else ifeq ($(ARCH),riscv64) 30 | TARGET_TRIPLE := riscv64-unknown-elf 31 | CFLAGS_ARCH := -march=rv64imafdc_zicsr_zifencei -mabi=lp64d 32 | else 33 | $(error Unsupported ARCH) 34 | endif 35 | 36 | ifeq ($(strip $(LLVM)),True) 37 | CC := clang -target $(TARGET_TRIPLE) 38 | AS := clang -target $(TARGET_TRIPLE) 39 | LD := ld.lld 40 | else 41 | CC := $(TARGET_TRIPLE)-gcc 42 | LD := $(TARGET_TRIPLE)-ld 43 | AS := $(TARGET_TRIPLE)-as 44 | endif 45 | 46 | MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit 47 | 48 | SERVER_OBJS := server.o 49 | CLIENT_OBJS := client.o 50 | 51 | IMAGES := server.elf client.elf 52 | CFLAGS := -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(BOARD_DIR)/include $(CFLAGS_ARCH) 53 | LDFLAGS := -L$(BOARD_DIR)/lib 54 | LIBS := -lmicrokit -Tmicrokit.ld 55 | 56 | IMAGE_FILE = $(BUILD_DIR)/loader.img 57 | REPORT_FILE = $(BUILD_DIR)/report.txt 58 | 59 | all: $(IMAGE_FILE) 60 | 61 | $(BUILD_DIR)/%.o: %.c Makefile 62 | $(CC) -c $(CFLAGS) $< -o $@ 63 | 64 | $(BUILD_DIR)/%.o: %.s Makefile 65 | $(AS) -g -mcpu=$(CPU) $< -o $@ 66 | 67 | $(BUILD_DIR)/server.elf: $(addprefix $(BUILD_DIR)/, $(SERVER_OBJS)) 68 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 69 | 70 | $(BUILD_DIR)/client.elf: $(addprefix $(BUILD_DIR)/, $(CLIENT_OBJS)) 71 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 72 | 73 | $(IMAGE_FILE) $(REPORT_FILE): $(addprefix $(BUILD_DIR)/, $(IMAGES)) passive_server.system 74 | $(MICROKIT_TOOL) passive_server.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE) 75 | -------------------------------------------------------------------------------- /platforms.yml: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-2-Clause 2 | # Copyright 2025 Ivan Velickovic 3 | 4 | # This YAML file describes the supported platforms in Microkit. 5 | # It mainly exists so that the seL4 documentation website can list 6 | # the supported platforms in a data-oriented way. 7 | # 8 | # For each new platform, please at least supply the following: 9 | # name: the Microkit name in build_sdk.py 10 | # cmake_plat: the name of the platform in the seL4 kernel build-system 11 | # since: if this is a new platform, put 'dev' otherwise put what the 12 | # first released Microkit version the platform was available in. 13 | # 14 | # This list is ordered based on the order in what the platforms were added 15 | # in. 16 | platforms: 17 | - name: serengeti 18 | cmake_plat: cheshire 19 | since: 2.1.0 20 | - name: imx8mp_iotgate 21 | cmake_plat: imx8mp-evk 22 | since: 2.1.0 23 | - name: rpi4b_2gb 24 | cmake_plat: rpi4 25 | since: 2.1.0 26 | - name: rpi4b_4gb 27 | cmake_plat: rpi4 28 | since: 2.1.0 29 | - name: rpi4b_8gb 30 | cmake_plat: rpi4 31 | since: 2.1.0 32 | - name: hifive_p550 33 | cmake_plat: hifive-p550 34 | since: 2.1.0 35 | - name: ultra96v2 36 | cmake_plat: ultra96v2 37 | since: 2.1.0 38 | - name: ariane 39 | cmake_plat: ariane 40 | since: 2.0.0 41 | - name: cheshire 42 | cmake_plat: cheshire 43 | since: 2.0.0 44 | - name: rockpro64 45 | cmake_plat: rockpro64 46 | since: 2.0.0 47 | - name: rpi4b_1gb 48 | cmake_plat: rpi4 49 | since: 2.0.0 50 | - name: imx8mm_evk 51 | cmake_plat: imx8mm-evk 52 | since: 1.3.0 53 | - name: imx8mp_evk 54 | cmake_plat: imx8mp-evk 55 | since: 2.0.0 56 | - name: star64 57 | cmake_plat: star64 58 | since: 1.4.0 59 | - name: qemu_virt_riscv64 60 | cmake_plat: qemu-riscv-virt 61 | cpu: rv64 62 | since: 1.4.0 63 | - name: imx8mq_evk 64 | cmake_plat: imx8mq-evk 65 | since: 1.3.0 66 | - name: maaxboard 67 | cmake_plat: maaxboard 68 | since: 1.3.0 69 | - name: odroidc2 70 | cmake_plat: odroidc2 71 | since: 1.3.0 72 | - name: odroidc4 73 | cmake_plat: odroidc4 74 | since: 1.3.0 75 | - name: qemu_virt_aarch64 76 | cmake_plat: qemu-arm-virt 77 | cpu: Cortext-A53 78 | since: 1.3.0 79 | - name: tqma8xqp1gb 80 | cmake_plat: tqma8xqp1gb 81 | since: 1.3.0 82 | - name: zcu102 83 | cmake_plat: zcu102 84 | since: 1.3.0 85 | -------------------------------------------------------------------------------- /loader/src/aarch64/el.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #include "el.h" 9 | 10 | #include 11 | 12 | #include "../cutil.h" 13 | #include "../loader.h" 14 | #include "../uart.h" 15 | 16 | void switch_to_el1(void); 17 | void switch_to_el2(void); 18 | 19 | /* Returns the current exception level */ 20 | enum el current_el(void) 21 | { 22 | /* See: C5.2.1 CurrentEL */ 23 | uint32_t val; 24 | asm volatile("mrs %x0, CurrentEL" : "=r"(val) :: "cc"); 25 | /* bottom two bits are res0 */ 26 | return (enum el) val >> 2; 27 | } 28 | 29 | 30 | int ensure_correct_el(int logical_cpu) 31 | { 32 | enum el el = current_el(); 33 | 34 | LDR_PRINT("INFO", logical_cpu, "CurrentEL="); 35 | puts(el_to_string(el)); 36 | puts("\n"); 37 | 38 | if (el == EL0) { 39 | LDR_PRINT("ERROR", logical_cpu, "Unsupported initial exception level\n"); 40 | return 1; 41 | } 42 | 43 | if (el == EL3) { 44 | LDR_PRINT("INFO", logical_cpu, "Dropping from EL3 to EL2(NS)\n"); 45 | switch_to_el2(); 46 | LDR_PRINT("INFO", logical_cpu, "Dropped from EL3 to EL2(NS)\n"); 47 | el = EL2; 48 | } 49 | 50 | if (is_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) { 51 | if (el != EL2) { 52 | LDR_PRINT("ERROR", logical_cpu, "seL4 configured as a hypervisor, but not in EL2\n"); 53 | return 1; 54 | } else { 55 | LDR_PRINT("INFO", logical_cpu, "Resetting CNTVOFF\n"); 56 | asm volatile("msr cntvoff_el2, xzr"); 57 | } 58 | } else { 59 | if (el == EL2) { 60 | /* seL4 relies on the timer to be set to a useful value */ 61 | LDR_PRINT("INFO", logical_cpu, "Resetting CNTVOFF\n"); 62 | asm volatile("msr cntvoff_el2, xzr"); 63 | LDR_PRINT("INFO", logical_cpu, "Dropping from EL2 to EL1\n"); 64 | switch_to_el1(); 65 | LDR_PRINT("INFO", logical_cpu, "CurrentEL="); 66 | el = current_el(); 67 | puts(el_to_string(el)); 68 | puts("\n"); 69 | if (el == EL1) { 70 | LDR_PRINT("INFO", logical_cpu, "Dropped to EL1 successfully\n"); 71 | } else { 72 | LDR_PRINT("ERROR", logical_cpu, "Failed to switch to EL1\n"); 73 | return 1; 74 | } 75 | } 76 | } 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /example/hierarchy/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(MICROKIT_SDK)),) 11 | $(error MICROKIT_SDK must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(MICROKIT_BOARD)),) 15 | $(error MICROKIT_BOARD must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(MICROKIT_CONFIG)),) 19 | $(error MICROKIT_CONFIG must be specified) 20 | endif 21 | 22 | BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG) 23 | 24 | ARCH := ${shell grep 'CONFIG_SEL4_ARCH ' $(BOARD_DIR)/include/kernel/gen_config.h | cut -d' ' -f4} 25 | 26 | ifeq ($(ARCH),aarch64) 27 | TARGET_TRIPLE := aarch64-none-elf 28 | CFLAGS_ARCH := -mstrict-align 29 | else ifeq ($(ARCH),riscv64) 30 | TARGET_TRIPLE := riscv64-unknown-elf 31 | CFLAGS_ARCH := -march=rv64imafdc_zicsr_zifencei -mabi=lp64d 32 | else 33 | $(error Unsupported ARCH) 34 | endif 35 | 36 | ifeq ($(strip $(LLVM)),True) 37 | CC := clang -target $(TARGET_TRIPLE) 38 | AS := clang -target $(TARGET_TRIPLE) 39 | LD := ld.lld 40 | else 41 | CC := $(TARGET_TRIPLE)-gcc 42 | LD := $(TARGET_TRIPLE)-ld 43 | AS := $(TARGET_TRIPLE)-as 44 | endif 45 | 46 | MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit 47 | 48 | RESTARTER_OBJS := restarter.o 49 | CRASHER_OBJS := crasher.o 50 | HELLO_OBJS := hello.o 51 | 52 | IMAGES := restarter.elf crasher.elf hello.elf 53 | CFLAGS := -nostdlib -ffreestanding -g -O3 -Wall -Wno-unused-function -Werror -I$(BOARD_DIR)/include $(CFLAGS_ARCH) 54 | LDFLAGS := -L$(BOARD_DIR)/lib 55 | LIBS := -lmicrokit -Tmicrokit.ld 56 | 57 | IMAGE_FILE = $(BUILD_DIR)/loader.img 58 | REPORT_FILE = $(BUILD_DIR)/report.txt 59 | 60 | all: $(IMAGE_FILE) 61 | 62 | $(BUILD_DIR)/%.o: %.c Makefile 63 | $(CC) -c $(CFLAGS) $< -o $@ 64 | 65 | $(BUILD_DIR)/%.o: %.s Makefile 66 | $(AS) -g -mcpu=$(CPU) $< -o $@ 67 | 68 | $(BUILD_DIR)/restarter.elf: $(addprefix $(BUILD_DIR)/, $(RESTARTER_OBJS)) 69 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 70 | 71 | $(BUILD_DIR)/crasher.elf: $(addprefix $(BUILD_DIR)/, $(CRASHER_OBJS)) 72 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 73 | 74 | $(BUILD_DIR)/hello.elf: $(addprefix $(BUILD_DIR)/, $(HELLO_OBJS)) 75 | $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 76 | 77 | $(IMAGE_FILE) $(REPORT_FILE): $(addprefix $(BUILD_DIR)/, $(IMAGES)) hierarchy.system 78 | $(MICROKIT_TOOL) hierarchy.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE) 79 | -------------------------------------------------------------------------------- /monitor/src/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | 8 | #include "util.h" 9 | 10 | void putc(uint8_t ch) 11 | { 12 | #if defined(CONFIG_PRINTING) 13 | seL4_DebugPutChar(ch); 14 | #endif 15 | } 16 | 17 | void puts(const char *s) 18 | { 19 | while (*s) { 20 | putc(*s); 21 | s++; 22 | } 23 | } 24 | 25 | static char hexchar(unsigned int v) 26 | { 27 | return v < 10 ? '0' + v : ('a' - 10) + v; 28 | } 29 | 30 | void puthex32(uint32_t val) 31 | { 32 | char buffer[8 + 3]; 33 | buffer[0] = '0'; 34 | buffer[1] = 'x'; 35 | buffer[8 + 3 - 1] = 0; 36 | for (unsigned i = 8 + 1; i > 1; i--) { 37 | buffer[i] = hexchar(val & 0xf); 38 | val >>= 4; 39 | } 40 | puts(buffer); 41 | } 42 | 43 | void puthex64(uint64_t val) 44 | { 45 | char buffer[16 + 3]; 46 | buffer[0] = '0'; 47 | buffer[1] = 'x'; 48 | buffer[16 + 3 - 1] = 0; 49 | for (unsigned i = 16 + 1; i > 1; i--) { 50 | buffer[i] = hexchar(val & 0xf); 51 | val >>= 4; 52 | } 53 | puts(buffer); 54 | } 55 | 56 | void fail(char *s) 57 | { 58 | puts("FAIL: "); 59 | puts(s); 60 | puts("\n"); 61 | for (;;) {} 62 | } 63 | 64 | char *sel4_strerror(seL4_Word err) 65 | { 66 | switch (err) { 67 | case seL4_NoError: 68 | return "seL4_NoError"; 69 | case seL4_InvalidArgument: 70 | return "seL4_InvalidArgument"; 71 | case seL4_InvalidCapability: 72 | return "seL4_InvalidCapability"; 73 | case seL4_IllegalOperation: 74 | return "seL4_IllegalOperation"; 75 | case seL4_RangeError: 76 | return "seL4_RangeError"; 77 | case seL4_AlignmentError: 78 | return "seL4_AlignmentError"; 79 | case seL4_FailedLookup: 80 | return "seL4_FailedLookup"; 81 | case seL4_TruncatedMessage: 82 | return "seL4_TruncatedMessage"; 83 | case seL4_DeleteFirst: 84 | return "seL4_DeleteFirst"; 85 | case seL4_RevokeFirst: 86 | return "seL4_RevokeFirst"; 87 | case seL4_NotEnoughMemory: 88 | return "seL4_NotEnoughMemory"; 89 | } 90 | 91 | return ""; 92 | } 93 | 94 | char *strcpy(char *restrict dst, const char *restrict src) 95 | { 96 | int i = 0; 97 | while (src[i]) { 98 | dst[i] = src[i]; 99 | i++; 100 | } 101 | dst[i] = '\0'; 102 | 103 | return dst; 104 | } 105 | -------------------------------------------------------------------------------- /loader/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | # 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ifeq ($(strip $(BUILD_DIR)),) 7 | $(error BUILD_DIR must be specified) 8 | endif 9 | 10 | ifeq ($(strip $(ARCH)),) 11 | $(error ARCH must be specified) 12 | endif 13 | 14 | ifeq ($(strip $(BOARD)),) 15 | $(error BOARD must be specified) 16 | endif 17 | 18 | ifeq ($(strip $(LINK_ADDRESS)),) 19 | $(error LINK_ADDRESS must be specified) 20 | endif 21 | 22 | ifeq ($(strip $(TARGET_TRIPLE)),) 23 | $(error TARGET_TRIPLE must be specified) 24 | endif 25 | 26 | ifeq ($(strip $(LLVM)),True) 27 | CC = clang -target $(TARGET_TRIPLE) 28 | CPP = clang-cpp -target $(TARGET_TRIPLE) 29 | AS = clang -target $(TARGET_TRIPLE) 30 | LD = ld.lld 31 | else 32 | CC = $(TARGET_TRIPLE)-gcc 33 | CPP = $(TARGET_TRIPLE)-cpp 34 | AS = $(TARGET_TRIPLE)-as 35 | LD = $(TARGET_TRIPLE)-ld 36 | endif 37 | 38 | ifeq ($(ARCH),aarch64) 39 | CFLAGS_AARCH64 := -mcpu=$(GCC_CPU) -mgeneral-regs-only -mstrict-align -mno-outline-atomics 40 | CFLAGS_ARCH := $(CFLAGS_AARCH64) -DARCH_aarch64 41 | ASM_FLAGS_ARCH := -mcpu=$(GCC_CPU) 42 | ARCH_DIR := aarch64 43 | else ifeq ($(ARCH),riscv64) 44 | CFLAGS_RISCV64 := -mcmodel=medany -march=rv64imac_zicsr_zifencei -mabi=lp64 45 | CFLAGS_ARCH := $(CFLAGS_RISCV64) -DARCH_riscv64 46 | ASM_FLAGS_ARCH := -march=rv64imac_zicsr_zifencei -mabi=lp64 47 | ARCH_DIR := riscv 48 | endif 49 | 50 | CFLAGS := -std=gnu11 -g -O3 -nostdlib -ffreestanding \ 51 | -MP -MD $(CFLAGS_ARCH) -I$(SEL4_SDK)/include \ 52 | -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations \ 53 | -Wundef -Wno-nonnull -Wnested-externs 54 | 55 | ASM_FLAGS := $(ASM_FLAGS_ARCH) -g -MP -MD -I$(SEL4_SDK)/include 56 | 57 | PROGS := loader.elf 58 | OBJECTS := loader.o crt0.o uart.o cutil.o 59 | 60 | ifeq ($(ARCH),aarch64) 61 | OBJECTS += util64.o el.o exceptions.o init.o mmu.o cpus.o 62 | else ifeq ($(ARCH),riscv64) 63 | OBJECTS += exceptions.o init.o mmu.o cpus.o sbi.o 64 | endif 65 | 66 | LINKSCRIPT_INPUT := $(ARCH).ld 67 | LINKSCRIPT := $(BUILD_DIR)/link.ld 68 | 69 | .SECONDARY: 70 | 71 | $(BUILD_DIR)/%.o : src/$(ARCH_DIR)/%.S 72 | $(CC) -DLINK_ADDRESS=$(LINK_ADDRESS) -x assembler-with-cpp -c $(ASM_FLAGS) $< -o $@ 73 | 74 | $(BUILD_DIR)/%.o : src/$(ARCH_DIR)/%.s 75 | $(AS) -c $< -o $@ 76 | 77 | $(BUILD_DIR)/%.o : src/$(ARCH_DIR)/%.c 78 | $(CC) -c $(CFLAGS) $< -o $@ 79 | 80 | $(BUILD_DIR)/%.o : src/%.c 81 | $(CC) -c $(CFLAGS) $< -o $@ 82 | 83 | -include $(BUILD_DIR)/*.d 84 | 85 | OBJPROG = $(addprefix $(BUILD_DIR)/, $(PROGS)) 86 | 87 | all: $(OBJPROG) 88 | 89 | $(LINKSCRIPT): $(LINKSCRIPT_INPUT) 90 | $(CPP) -DLINK_ADDRESS=$(LINK_ADDRESS) $< | grep -v "^#" > $@ 91 | 92 | $(OBJPROG): $(addprefix $(BUILD_DIR)/, $(OBJECTS)) $(LINKSCRIPT) 93 | $(LD) -T$(LINKSCRIPT) $(addprefix $(BUILD_DIR)/, $(OBJECTS)) -o $@ 94 | -------------------------------------------------------------------------------- /loader/src/aarch64/crt0.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | .extern main 7 | 8 | #include "../loader.h" 9 | 10 | .section ".text.start" 11 | 12 | .global _start; 13 | .type _start, %function; 14 | _start: 15 | /* This assumes that the entry CPU is logical CPU0, the base of the stack*/ 16 | adrp x1, _stack 17 | add x1, x1, STACK_SIZE 18 | mov sp, x1 19 | /* May not have been loaded in the right location. 20 | * Try and move ourselves so we're in the right place 21 | */ 22 | bl relocate 23 | cmp x0, #1 24 | beq 1f 25 | /* Otherwise, jump to the start of the new loader */ 26 | br x0 27 | 1: 28 | b main 29 | 30 | relocate: 31 | stp x29, x30, [sp, #-16]! 32 | mov x29, sp 33 | /* Check if the image is already at the correct location */ 34 | ldr x0, =LINK_ADDRESS 35 | adr x1, _start 36 | cmp x0, x1 37 | beq image_ok 38 | 39 | /* Log that we are being relocated */ 40 | bl relocation_log 41 | 42 | /* Restore x0 and x1 */ 43 | ldr x0, =LINK_ADDRESS 44 | adr x1, _start 45 | 46 | /* Sanity check: We don't want to overwrite ourselves! We assume that 47 | * everything between _start (src_start) and _bss_end (src_end) is important (i.e. 48 | * something that might be run while relocating) but allow overlap for 49 | * things after _bss_end i.e. the loader_data. 50 | */ 51 | adrp x2, _bss_end 52 | add x2, x2, #:lo12:_bss_end 53 | 54 | /* The loader_data is directly after _bss_end, with the first 55 | * value being the loader_data struct. The second field of 56 | * this struct is the size of the loader_data region, so we 57 | * add this to _bss_end to get the real end of the image 58 | */ 59 | ldr x3, [x2, #+8] 60 | add x2, x2, x3 61 | sub x2, x2, x1 62 | 63 | adrp x3, _bss_end 64 | add x3, x3, #:lo12:_bss_end 65 | 66 | sub x5, x3, x1 67 | add x4, x0, x5 /* dst_end */ 68 | 69 | /* At this point: 70 | * x0: dst_code_start (LINK_ADDRESS) 71 | * x1: src_code_start (_start) 72 | * x2: image_size 73 | * x3: src_code_end (_bss_end) 74 | * x4: dst_code_end (LINK_ADDRESS + (_bss_end - _start)) 75 | */ 76 | 77 | /* check: if (dst_end >= src_start && dst_end < src_end) { abort } */ 78 | cmp x4, x1 79 | blt 1f 80 | 81 | cmp x4, x3 82 | bge 1f 83 | 84 | b cant_reloc 85 | 1: 86 | 87 | /* check: if (dst_start >= src_start && dest_start < src_end) { abort } */ 88 | cmp x0, x1 89 | blt 2f 90 | 91 | cmp x0, x3 92 | bge 2f 93 | cant_reloc: 94 | b relocation_failed 95 | 96 | 2: 97 | /* x0 = desired image base */ 98 | /* x1 = current image base */ 99 | /* x2 = image size */ 100 | bl memmove 101 | 102 | /* x0 = dest, save it to a callee-saved register while we invalidate icache */ 103 | mov x19, x0 104 | bl flush_dcache 105 | bl invalidate_icache 106 | mov x0, x19 107 | b 1f 108 | 109 | image_ok: 110 | /* Already in the right place, keep booting */ 111 | mov x0, #1 112 | 113 | 1: 114 | ldp x29, x30, [sp], #16 115 | ret 116 | -------------------------------------------------------------------------------- /dev_build.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021, Breakaway Consulting Pty. Ltd. 2 | # SPDX-License-Identifier: BSD-2-Clause 3 | 4 | """Build a specific example during development. 5 | 6 | This is designed to make it easy to build and run examples during development. 7 | """ 8 | from argparse import ArgumentParser 9 | from os import environ, system 10 | from pathlib import Path 11 | from shutil import rmtree 12 | from subprocess import run 13 | 14 | CWD = Path(__file__).parent 15 | BUILD_DIR = CWD / "tmp_build" 16 | 17 | 18 | def find_releases(): 19 | releases = [] 20 | for f in (CWD / "release").iterdir(): 21 | if not f.is_dir(): 22 | continue 23 | if not f.name.startswith("microkit-sdk-"): 24 | # All directories in here should match this, but 25 | # skip just iun case someone added junk 26 | continue 27 | releases.append(f) 28 | 29 | def release_sort_key(rel): 30 | ver_str = rel.name.split("-")[2] 31 | ver = tuple(int(x) for x in ver_str.split(".")) 32 | return ver 33 | 34 | releases.sort(key=release_sort_key, reverse=True) 35 | return releases 36 | 37 | 38 | def main(): 39 | parser = ArgumentParser() 40 | parser.add_argument( 41 | "--rebuild", 42 | action="store_true", 43 | default=False, 44 | help="Force a rebuild of the example", 45 | ) 46 | parser.add_argument( 47 | "--example-from-sdk", 48 | action="store_true", 49 | default=False, 50 | help="Build the example from the SDK build rather than directly from source directory", 51 | ) 52 | parser.add_argument( 53 | "--board", 54 | help="Target board", 55 | required=True 56 | ) 57 | parser.add_argument( 58 | "--example", 59 | help="Example to build", 60 | required=True 61 | ) 62 | parser.add_argument( 63 | "--config", 64 | default="debug", 65 | help="Config option to be passed to the tool" 66 | ) 67 | parser.add_argument( 68 | "--llvm", 69 | action="store_true", 70 | help="Build with LLVM/Clang toolchain" 71 | ) 72 | args = parser.parse_args() 73 | 74 | # TODO: Support choosing a release by specifying on command line 75 | releases = find_releases() 76 | release = releases[0] 77 | 78 | if args.rebuild and BUILD_DIR.exists(): 79 | rmtree(BUILD_DIR) 80 | 81 | if not BUILD_DIR.exists(): 82 | BUILD_DIR.mkdir() 83 | 84 | tool_rebuild = f"cd {CWD / 'tool/microkit'} && cargo build --release" 85 | r = system(tool_rebuild) 86 | assert r == 0 87 | 88 | make_env = environ.copy() 89 | make_env["BUILD_DIR"] = str(BUILD_DIR.absolute()) 90 | make_env["MICROKIT_BOARD"] = args.board 91 | make_env["MICROKIT_CONFIG"] = args.config 92 | make_env["MICROKIT_SDK"] = str(release) 93 | make_env["MICROKIT_TOOL"] = (CWD / "target/release/microkit").absolute() 94 | make_env["LLVM"] = str(args.llvm) 95 | 96 | # Choose the makefile based on the `--example-from-sdk` command line flag 97 | makefile_directory = ( 98 | f"{release}/example/{args.example}" 99 | if args.example_from_sdk 100 | else f"{CWD.absolute()}/example/{args.example}" 101 | ) 102 | 103 | cmd = ["make", "-C", makefile_directory] 104 | 105 | run(cmd, env=make_env, check=True) 106 | 107 | 108 | if __name__ == "__main__": 109 | main() 110 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1748026580, 6 | "narHash": "sha256-rWtXrcIzU5wm/C8F9LWvUfBGu5U5E7cFzPYT1pHIJaQ=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "11cb3517b3af6af300dd6c055aeda73c9bf52c48", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "ref": "25.05", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "nixpkgs_2": { 20 | "locked": { 21 | "lastModified": 1744536153, 22 | "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", 23 | "owner": "NixOS", 24 | "repo": "nixpkgs", 25 | "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", 26 | "type": "github" 27 | }, 28 | "original": { 29 | "owner": "NixOS", 30 | "ref": "nixpkgs-unstable", 31 | "repo": "nixpkgs", 32 | "type": "github" 33 | } 34 | }, 35 | "root": { 36 | "inputs": { 37 | "nixpkgs": "nixpkgs", 38 | "rust-overlay": "rust-overlay", 39 | "treefmt-nix": "treefmt-nix", 40 | "utils": "utils" 41 | } 42 | }, 43 | "rust-overlay": { 44 | "inputs": { 45 | "nixpkgs": "nixpkgs_2" 46 | }, 47 | "locked": { 48 | "lastModified": 1753671061, 49 | "narHash": "sha256-IU4eBWfe9h2QejJYST+EAlhg8a1H6mh9gbcmWgZ2/mQ=", 50 | "owner": "oxalica", 51 | "repo": "rust-overlay", 52 | "rev": "40065d17ee4dbec3ded8ca61236132aede843fab", 53 | "type": "github" 54 | }, 55 | "original": { 56 | "owner": "oxalica", 57 | "repo": "rust-overlay", 58 | "type": "github" 59 | } 60 | }, 61 | "systems": { 62 | "locked": { 63 | "lastModified": 1681028828, 64 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 65 | "owner": "nix-systems", 66 | "repo": "default", 67 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 68 | "type": "github" 69 | }, 70 | "original": { 71 | "owner": "nix-systems", 72 | "repo": "default", 73 | "type": "github" 74 | } 75 | }, 76 | "treefmt-nix": { 77 | "inputs": { 78 | "nixpkgs": [ 79 | "nixpkgs" 80 | ] 81 | }, 82 | "locked": { 83 | "lastModified": 1729613947, 84 | "narHash": "sha256-XGOvuIPW1XRfPgHtGYXd5MAmJzZtOuwlfKDgxX5KT3s=", 85 | "owner": "numtide", 86 | "repo": "treefmt-nix", 87 | "rev": "aac86347fb5063960eccb19493e0cadcdb4205ca", 88 | "type": "github" 89 | }, 90 | "original": { 91 | "owner": "numtide", 92 | "repo": "treefmt-nix", 93 | "type": "github" 94 | } 95 | }, 96 | "utils": { 97 | "inputs": { 98 | "systems": "systems" 99 | }, 100 | "locked": { 101 | "lastModified": 1726560853, 102 | "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", 103 | "owner": "numtide", 104 | "repo": "flake-utils", 105 | "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", 106 | "type": "github" 107 | }, 108 | "original": { 109 | "owner": "numtide", 110 | "repo": "flake-utils", 111 | "type": "github" 112 | } 113 | } 114 | }, 115 | "root": "root", 116 | "version": 7 117 | } 118 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024, UNSW 3 | # SPDX-License-Identifier: BSD-2-Clause 4 | # 5 | { 6 | description = "A flake for building microkit"; 7 | 8 | inputs = { 9 | nixpkgs.url = "github:NixOS/nixpkgs/25.05"; 10 | utils.url = "github:numtide/flake-utils"; 11 | rust-overlay.url = "github:oxalica/rust-overlay"; 12 | treefmt-nix = { 13 | url = "github:numtide/treefmt-nix"; 14 | inputs.nixpkgs.follows = "nixpkgs"; 15 | }; 16 | }; 17 | 18 | outputs = { self, nixpkgs, rust-overlay, treefmt-nix, ... }@inputs: inputs.utils.lib.eachSystem [ 19 | "x86_64-linux" 20 | "aarch64-linux" 21 | "x86_64-darwin" 22 | "aarch64-darwin" 23 | ] 24 | (system: 25 | let 26 | pkgs = import nixpkgs { 27 | inherit system; 28 | 29 | overlays = [ (import rust-overlay) ]; 30 | }; 31 | 32 | treefmtEval = treefmt-nix.lib.evalModule pkgs ( 33 | { ... }: 34 | { 35 | projectRootFile = "flake.nix"; 36 | programs.nixpkgs-fmt.enable = true; 37 | } 38 | ); 39 | 40 | pythonTool = pkgs.python312.withPackages (ps: [ 41 | ps.mypy 42 | ps.black 43 | ps.flake8 44 | ps.ply 45 | ps.jinja2 46 | ps.pyaml 47 | ps.lxml 48 | ps.pyfdt 49 | ps.setuptools 50 | ]); 51 | 52 | microkitToolToml = nixpkgs.lib.trivial.importTOML ./tool/microkit/Cargo.toml; 53 | microkitToolVersion = microkitToolToml.package.rust-version; 54 | 55 | # Unfortunately Cargo does not support all targets by default so for cross-compiling 56 | # we must explicitly add certain targets. 57 | rustAdditionalTargets = { 58 | aarch64-darwin = [ "x86_64-apple-darwin" "x86_64-unknown-linux-musl" "aarch64-unknown-linux-musl" ]; 59 | x86_64-darwin = [ "aarch64-apple-darwin" "x86_64-unknown-linux-musl" "aarch64-unknown-linux-musl" ]; 60 | x86_64-linux = []; 61 | aarch64-linux = []; 62 | }.${system} or (throw "Unsupported system: ${system}"); 63 | 64 | rustTool = pkgs.rust-bin.stable.${microkitToolVersion}.default.override { 65 | extensions = [ "rust-src" ]; 66 | targets = [ pkgs.pkgsStatic.hostPlatform.rust.rustcTarget ] ++ rustAdditionalTargets; 67 | }; 68 | in 69 | { 70 | # for `nix fmt` 71 | formatter = treefmtEval.config.build.wrapper; 72 | # for `nix flake check` 73 | checks.formatting = treefmtEval.config.build.check self; 74 | 75 | devShells.default = pkgs.mkShell rec { 76 | name = "microkit-shell"; 77 | 78 | nativeBuildInputs = with pkgs; [ 79 | pkgsCross.x86_64-embedded.stdenv.cc.bintools.bintools 80 | pkgsCross.x86_64-embedded.stdenv.cc.cc 81 | pkgsCross.aarch64-embedded.stdenv.cc.bintools.bintools 82 | pkgsCross.aarch64-embedded.stdenv.cc.cc 83 | pkgsCross.riscv64-embedded.stdenv.cc.bintools.bintools 84 | pkgsCross.riscv64-embedded.stdenv.cc.cc 85 | gnumake 86 | dtc 87 | expect 88 | pythonTool 89 | git 90 | rustTool 91 | pandoc 92 | (texlive.combine { 93 | inherit (texlive) scheme-medium titlesec enumitem sfmath roboto fontaxes isodate substr tcolorbox environ pdfcol; 94 | }) 95 | cmake 96 | ninja 97 | libxml2 98 | qemu 99 | gnutar 100 | ]; 101 | 102 | # Necessary for Rust bindgen 103 | LIBCLANG_PATH = "${pkgs.llvmPackages_18.libclang.lib}/lib"; 104 | }; 105 | }); 106 | } 107 | -------------------------------------------------------------------------------- /example/timer/timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024, UNSW 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | /* 12 | * This is a very simple timer driver with the intention of showing 13 | * how to do MMIO and handle interrupts in Microkit. 14 | */ 15 | 16 | uintptr_t timer_regs; 17 | 18 | #define TIMER_IRQ_CH 0 19 | 20 | #define TIMER_REG_START 0x140 21 | 22 | #define TIMER_A_INPUT_CLK 0 23 | #define TIMER_E_INPUT_CLK 8 24 | #define TIMER_A_EN (1 << 16) 25 | #define TIMER_A_MODE (1 << 12) 26 | 27 | #define TIMESTAMP_TIMEBASE_SYSTEM 0b000 28 | #define TIMESTAMP_TIMEBASE_1_US 0b001 29 | #define TIMESTAMP_TIMEBASE_10_US 0b010 30 | #define TIMESTAMP_TIMEBASE_100_US 0b011 31 | #define TIMESTAMP_TIMEBASE_1_MS 0b100 32 | 33 | #define TIMEOUT_TIMEBASE_1_US 0b00 34 | #define TIMEOUT_TIMEBASE_10_US 0b01 35 | #define TIMEOUT_TIMEBASE_100_US 0b10 36 | #define TIMEOUT_TIMEBASE_1_MS 0b11 37 | 38 | #define NS_IN_US 1000ULL 39 | #define NS_IN_MS 1000000ULL 40 | 41 | typedef struct { 42 | uint32_t mux; 43 | uint32_t timer_a; 44 | uint32_t timer_b; 45 | uint32_t timer_c; 46 | uint32_t timer_d; 47 | uint32_t unused[13]; 48 | uint32_t timer_e; 49 | uint32_t timer_e_hi; 50 | uint32_t mux1; 51 | uint32_t timer_f; 52 | uint32_t timer_g; 53 | uint32_t timer_h; 54 | uint32_t timer_i; 55 | } meson_timer_reg_t; 56 | 57 | typedef struct { 58 | volatile meson_timer_reg_t *regs; 59 | bool disable; 60 | } meson_timer_t; 61 | 62 | meson_timer_t timer; 63 | 64 | static char hexchar(unsigned int v) 65 | { 66 | return v < 10 ? '0' + v : ('a' - 10) + v; 67 | } 68 | 69 | static void puthex64(uint64_t val) 70 | { 71 | char buffer[16 + 3]; 72 | buffer[0] = '0'; 73 | buffer[1] = 'x'; 74 | buffer[16 + 3 - 1] = 0; 75 | for (unsigned i = 16 + 1; i > 1; i--) { 76 | buffer[i] = hexchar(val & 0xf); 77 | val >>= 4; 78 | } 79 | microkit_dbg_puts(buffer); 80 | } 81 | 82 | uint64_t meson_get_time() 83 | { 84 | uint64_t initial_high = timer.regs->timer_e_hi; 85 | uint64_t low = timer.regs->timer_e; 86 | uint64_t high = timer.regs->timer_e_hi; 87 | if (high != initial_high) { 88 | low = timer.regs->timer_e; 89 | } 90 | 91 | uint64_t ticks = (high << 32) | low; 92 | uint64_t time = ticks * NS_IN_US; 93 | return time; 94 | } 95 | 96 | void meson_set_timeout(uint16_t timeout, bool periodic) 97 | { 98 | if (periodic) { 99 | timer.regs->mux |= TIMER_A_MODE; 100 | } else { 101 | timer.regs->mux &= ~TIMER_A_MODE; 102 | } 103 | 104 | timer.regs->timer_a = timeout; 105 | 106 | if (timer.disable) { 107 | timer.regs->mux |= TIMER_A_EN; 108 | timer.disable = false; 109 | } 110 | } 111 | 112 | void meson_stop_timer() 113 | { 114 | timer.regs->mux &= ~TIMER_A_EN; 115 | timer.disable = true; 116 | } 117 | 118 | void init() 119 | { 120 | timer.regs = (void *)(timer_regs + TIMER_REG_START); 121 | 122 | timer.regs->mux = TIMER_A_EN | (TIMESTAMP_TIMEBASE_1_US << TIMER_E_INPUT_CLK) | 123 | (TIMEOUT_TIMEBASE_1_MS << TIMER_A_INPUT_CLK); 124 | 125 | timer.regs->timer_e = 0; 126 | 127 | // Have a timeout of 1 second, and have it be periodic so that it will keep recurring. 128 | microkit_dbg_puts("Setting a timeout of 1 second.\n"); 129 | meson_set_timeout(1000, true); 130 | } 131 | 132 | void notified(microkit_channel ch) 133 | { 134 | switch (ch) { 135 | case TIMER_IRQ_CH: 136 | microkit_dbg_puts("Got timer interrupt!\n"); 137 | microkit_irq_ack(ch); 138 | microkit_dbg_puts("Current time is: "); 139 | puthex64(meson_get_time()); 140 | microkit_dbg_puts("\n"); 141 | break; 142 | default: 143 | microkit_dbg_puts("TIMER|ERROR: unexpected channel!\n"); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /tool/microkit/src/capdl/spec.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025, UNSW 3 | // 4 | // SPDX-License-Identifier: BSD-2-Clause 5 | // 6 | 7 | use std::ops::Range; 8 | 9 | use sel4_capdl_initializer_types::{Cap, Object, Rights, Word}; 10 | use serde::Serialize; 11 | 12 | use crate::{ 13 | capdl::{FrameFill, SLOT_BITS}, 14 | sel4::{Config, ObjectType, PageSize}, 15 | }; 16 | 17 | #[derive(Clone, Serialize)] 18 | pub struct ElfContent { 19 | pub elf_id: usize, 20 | pub elf_seg_idx: usize, 21 | pub elf_seg_data_range: Range, 22 | } 23 | 24 | /// CNode and SchedContext are quirky as they have variable size. 25 | pub fn capdl_obj_physical_size_bits(obj: &Object, sel4_config: &Config) -> u64 { 26 | match obj { 27 | Object::Endpoint => ObjectType::Endpoint.fixed_size_bits(sel4_config).unwrap(), 28 | Object::Notification => ObjectType::Notification 29 | .fixed_size_bits(sel4_config) 30 | .unwrap(), 31 | Object::CNode(cnode) => cnode.size_bits as u64 + SLOT_BITS, 32 | Object::Tcb(_) => ObjectType::Tcb.fixed_size_bits(sel4_config).unwrap(), 33 | Object::VCpu => ObjectType::Vcpu.fixed_size_bits(sel4_config).unwrap(), 34 | Object::Frame(frame) => frame.size_bits as u64, 35 | Object::PageTable(pt) => { 36 | if pt.is_root { 37 | ObjectType::VSpace.fixed_size_bits(sel4_config).unwrap() 38 | } else { 39 | ObjectType::PageTable.fixed_size_bits(sel4_config).unwrap() 40 | } 41 | } 42 | Object::AsidPool(_) => ObjectType::AsidPool.fixed_size_bits(sel4_config).unwrap(), 43 | Object::SchedContext(sched_context) => sched_context.size_bits as u64, 44 | Object::Reply => ObjectType::Reply.fixed_size_bits(sel4_config).unwrap(), 45 | _ => 0, 46 | } 47 | } 48 | 49 | pub fn capdl_obj_human_name(obj: &Object, sel4_config: &Config) -> &'static str { 50 | match obj { 51 | Object::Endpoint => "Endpoint", 52 | Object::Notification => "Notification", 53 | Object::CNode(_) => "CNode", 54 | Object::Tcb(_) => "TCB", 55 | Object::VCpu => "VCPU", 56 | Object::Frame(frame) => { 57 | if frame.size_bits == PageSize::Small.fixed_size_bits(sel4_config) as u8 { 58 | "Page(4 KiB)" 59 | } else if frame.size_bits == PageSize::Large.fixed_size_bits(sel4_config) as u8 { 60 | "Page(2 MiB)" 61 | } else { 62 | unreachable!("unknown frame size bits {}", frame.size_bits); 63 | } 64 | } 65 | Object::PageTable(_) => "PageTable", 66 | Object::AsidPool(_) => "AsidPool", 67 | Object::ArmIrq(_) => "ARM IRQ", 68 | Object::IrqMsi(_) => "x86 MSI IRQ", 69 | Object::IrqIOApic(_) => "x86 IOAPIC IRQ", 70 | Object::RiscvIrq(_) => "RISC-V IRQ", 71 | Object::IOPorts(_) => "x86 I/O Ports", 72 | Object::SchedContext(_) => "SchedContext", 73 | Object::Reply => "Reply", 74 | Object::ArmSmc => "ARM SMC", 75 | Object::Untyped(_) => "Untyped", 76 | Object::Irq(_) => "IRQ", 77 | } 78 | } 79 | 80 | pub fn capdl_cap_badge(cap: &Cap) -> Option { 81 | match cap { 82 | Cap::Endpoint(endpoint) => Some(endpoint.badge), 83 | Cap::Notification(notification) => Some(notification.badge), 84 | _ => None, 85 | } 86 | } 87 | 88 | pub fn capdl_cap_rights(cap: &Cap) -> Option { 89 | match cap { 90 | Cap::Endpoint(endpoint) => Some(endpoint.rights), 91 | Cap::Notification(notification) => Some(notification.rights), 92 | Cap::Frame(frame) => Some(frame.rights), 93 | _ => None, 94 | } 95 | } 96 | 97 | pub fn capdl_rights_to_human_repr(rights: &Rights) -> String { 98 | let mut repr: String = "".into(); 99 | 100 | if rights.read { 101 | repr += "Read, "; 102 | } 103 | if rights.write { 104 | repr += "Write, "; 105 | } 106 | if rights.grant { 107 | repr += "Grant, "; 108 | } 109 | if rights.grant_reply { 110 | repr += "Grant Reply, "; 111 | } 112 | 113 | repr.pop(); 114 | repr.pop(); 115 | 116 | repr 117 | } 118 | -------------------------------------------------------------------------------- /loader/src/aarch64/exceptions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | /** Called from assembly **/ 13 | void exception_handler(uintptr_t ex); 14 | 15 | static inline const char *ex_to_string(uintptr_t ex) 16 | { 17 | switch (ex) { 18 | case 0: 19 | return "Synchronous (Current Exception level with SP_EL0)"; 20 | case 1: 21 | return "IRQ (Current Exception level with SP_EL0)"; 22 | case 2: 23 | return "FIQ (Current Exception level with SP_EL0)"; 24 | case 3: 25 | return "SError (Current Exception level with SP_EL0)"; 26 | case 4: 27 | return "Synchronous (Current Exception level with SP_ELx)"; 28 | case 5: 29 | return "IRQ (Current Exception level with SP_ELx)"; 30 | case 6: 31 | return "FIQ (Current Exception level with SP_ELx)"; 32 | case 7: 33 | return "SError (Current Exception level with SP_ELx)"; 34 | case 8: 35 | return "Synchronous 64-bit EL0"; 36 | case 9: 37 | return "IRQ 64-bit EL0"; 38 | case 10: 39 | return "FIQ 64-bit EL0"; 40 | case 11: 41 | return "SError 64-bit EL0"; 42 | case 12: 43 | return "Synchronous 32-bit EL0"; 44 | case 13: 45 | return "IRQ 32-bit EL0"; 46 | case 14: 47 | return "FIQ 32-bit EL0"; 48 | case 15: 49 | return "SError 32-bit EL0"; 50 | } 51 | return ""; 52 | } 53 | 54 | static inline const char *ec_to_string(uintptr_t ec) 55 | { 56 | switch (ec) { 57 | case 0: 58 | return "Unknown reason"; 59 | case 1: 60 | return "Trapped WFI or WFE instruction execution"; 61 | case 3: 62 | return "Trapped MCR or MRC access with (coproc==0b1111) this is not reported using EC 0b000000"; 63 | case 4: 64 | return "Trapped MCRR or MRRC access with (coproc==0b1111) this is not reported using EC 0b000000"; 65 | case 5: 66 | return "Trapped MCR or MRC access with (coproc==0b1110)"; 67 | case 6: 68 | return "Trapped LDC or STC access"; 69 | case 7: 70 | return "Access to SVC, Advanced SIMD or floating-point functionality trapped"; 71 | case 12: 72 | return "Trapped MRRC access with (coproc==0b1110)"; 73 | case 13: 74 | return "Branch Target Exception"; 75 | case 17: 76 | return "SVC instruction execution in AArch32 state"; 77 | case 21: 78 | return "SVC instruction execution in AArch64 state"; 79 | case 24: 80 | return "Trapped MSR, MRS or System instruction exuection in AArch64 state, this is not reported using EC 0xb000000, 0b000001 or 0b000111"; 81 | case 25: 82 | return "Access to SVE functionality trapped"; 83 | case 28: 84 | return "Exception from a Pointer Authentication instruction authentication failure"; 85 | case 32: 86 | return "Instruction Abort from a lower Exception level"; 87 | case 33: 88 | return "Instruction Abort taken without a change in Exception level"; 89 | case 34: 90 | return "PC alignment fault exception"; 91 | case 36: 92 | return "Data Abort from a lower Exception level"; 93 | case 37: 94 | return "Data Abort taken without a change in Exception level"; 95 | case 38: 96 | return "SP alignment faultr exception"; 97 | case 40: 98 | return "Trapped floating-point exception taken from AArch32 state"; 99 | case 44: 100 | return "Trapped floating-point exception taken from AArch64 state"; 101 | case 47: 102 | return "SError interrupt"; 103 | case 48: 104 | return "Breakpoint exception from a lower Exception level"; 105 | case 49: 106 | return "Breakpoint exception taken without a change in Exception level"; 107 | case 50: 108 | return "Software Step exception from a lower Exception level"; 109 | case 51: 110 | return "Software Step exception taken without a change in Exception level"; 111 | case 52: 112 | return "Watchpoint exception from a lower Exception level"; 113 | case 53: 114 | return "Watchpoint exception taken without a change in Exception level"; 115 | case 56: 116 | return "BKPT instruction execution in AArch32 state"; 117 | case 60: 118 | return "BRK instruction execution in AArch64 state"; 119 | } 120 | return ""; 121 | } 122 | -------------------------------------------------------------------------------- /libmicrokit/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | #include 7 | #include 8 | #include 9 | 10 | #define __thread 11 | #include 12 | 13 | #include 14 | 15 | #define INPUT_CAP 1 16 | #define REPLY_CAP 4 17 | 18 | #define PD_MASK 0xff 19 | #define CHANNEL_MASK 0x3f 20 | 21 | /* All globals are prefixed with microkit_* to avoid clashes with user defined globals. */ 22 | 23 | bool microkit_passive; 24 | char microkit_name[MICROKIT_PD_NAME_LENGTH]; 25 | /* We use seL4 typedefs as this variable is exposed to the libmicrokit header 26 | * and we do not want to rely on compiler built-in defines. */ 27 | seL4_Bool microkit_have_signal = seL4_False; 28 | seL4_CPtr microkit_signal_cap; 29 | seL4_MessageInfo_t microkit_signal_msg; 30 | 31 | seL4_Word microkit_irqs; 32 | seL4_Word microkit_notifications; 33 | seL4_Word microkit_pps; 34 | seL4_Word microkit_ioports; 35 | 36 | extern seL4_IPCBuffer __sel4_ipc_buffer_obj; 37 | 38 | seL4_IPCBuffer *__sel4_ipc_buffer = &__sel4_ipc_buffer_obj; 39 | 40 | extern const void (*const __init_array_start [])(void); 41 | extern const void (*const __init_array_end [])(void); 42 | 43 | __attribute__((weak)) microkit_msginfo protected(microkit_channel ch, microkit_msginfo msginfo) 44 | { 45 | microkit_dbg_puts(microkit_name); 46 | microkit_dbg_puts(" is missing the 'protected' entry point\n"); 47 | microkit_internal_crash(0); 48 | return seL4_MessageInfo_new(0, 0, 0, 0); 49 | } 50 | 51 | __attribute__((weak)) seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo) 52 | { 53 | microkit_dbg_puts(microkit_name); 54 | microkit_dbg_puts(" is missing the 'fault' entry point\n"); 55 | microkit_internal_crash(0); 56 | return seL4_False; 57 | } 58 | 59 | static void run_init_funcs(void) 60 | { 61 | size_t count = __init_array_end - __init_array_start; 62 | for (size_t i = 0; i < count; i++) { 63 | __init_array_start[i](); 64 | } 65 | } 66 | 67 | static void handler_loop(void) 68 | { 69 | bool have_reply = false; 70 | seL4_MessageInfo_t reply_tag; 71 | 72 | /** 73 | * Because of https://github.com/seL4/seL4/issues/1536 74 | * let's acknowledge all the IRQs after we've started. 75 | */ 76 | { 77 | seL4_Word irqs_to_ack = microkit_irqs; 78 | unsigned int idx = 0; 79 | do { 80 | if (irqs_to_ack & 1) { 81 | microkit_irq_ack(idx); 82 | } 83 | 84 | irqs_to_ack >>= 1; 85 | idx++; 86 | } while (irqs_to_ack != 0); 87 | } 88 | 89 | for (;;) { 90 | seL4_Word badge; 91 | seL4_MessageInfo_t tag; 92 | 93 | if (have_reply) { 94 | tag = seL4_ReplyRecv(INPUT_CAP, reply_tag, &badge, REPLY_CAP); 95 | } else if (microkit_have_signal) { 96 | tag = seL4_NBSendRecv(microkit_signal_cap, microkit_signal_msg, INPUT_CAP, &badge, REPLY_CAP); 97 | microkit_have_signal = seL4_False; 98 | } else { 99 | tag = seL4_Recv(INPUT_CAP, &badge, REPLY_CAP); 100 | } 101 | 102 | uint64_t is_endpoint = badge >> 63; 103 | uint64_t is_fault = (badge >> 62) & 1; 104 | 105 | have_reply = false; 106 | 107 | if (is_fault) { 108 | seL4_Bool reply_to_fault = fault(badge & PD_MASK, tag, &reply_tag); 109 | if (reply_to_fault) { 110 | have_reply = true; 111 | } 112 | } else if (is_endpoint) { 113 | have_reply = true; 114 | reply_tag = protected(badge & CHANNEL_MASK, tag); 115 | } else { 116 | unsigned int idx = 0; 117 | do { 118 | if (badge & 1) { 119 | notified(idx); 120 | } 121 | badge >>= 1; 122 | idx++; 123 | } while (badge != 0); 124 | } 125 | } 126 | } 127 | 128 | void main(void) 129 | { 130 | run_init_funcs(); 131 | init(); 132 | 133 | /* 134 | * If we are passive, now our initialisation is complete we can 135 | * signal the monitor to unbind our scheduling context and bind 136 | * it to our notification object. 137 | * We delay this signal so we are ready waiting on a recv() syscall 138 | */ 139 | if (microkit_passive) { 140 | microkit_have_signal = seL4_True; 141 | microkit_signal_msg = seL4_MessageInfo_new(0, 0, 0, 0); 142 | microkit_signal_cap = MONITOR_EP; 143 | } 144 | 145 | handler_loop(); 146 | } 147 | -------------------------------------------------------------------------------- /loader/src/riscv/cpus.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "../cpus.h" 11 | #include "../cutil.h" 12 | #include "../loader.h" 13 | #include "../uart.h" 14 | #include "sbi.h" 15 | 16 | /* 17 | * On RISC-V the hart IDs represent any hardware thread in the system, including 18 | * ones that we do not intend to run on. 19 | * Typically the main CPU may have something like 4 cores that we intend to run 20 | * seL4 on but an additional S-mode only monitor core, this is the case on certain 21 | * CPUs such as the SiFive U74. The problematic part is that the monitor core has 22 | * a hart ID of zero and hart IDs are not guaranteed to be contiguous. 23 | * This is why we must explitly list all the hart IDs that we want to boot on. 24 | * To figure this out for your platform, the best way is to look at the Device Tree, 25 | * each CPU will have a 'reg' field where the value is the hart ID. 26 | */ 27 | #if defined(CONFIG_PLAT_STAR64) 28 | static const uint64_t hart_ids[4] = {0x1, 0x2, 0x3, 0x4}; 29 | #elif defined(CONFIG_PLAT_QEMU_RISCV_VIRT) || defined(CONFIG_PLAT_HIFIVE_P550) 30 | static const uint64_t hart_ids[4] = {0x0, 0x1, 0x2, 0x3}; 31 | #else 32 | 33 | _Static_assert(!is_set(CONFIG_ENABLE_SMP_SUPPORT), 34 | "unknown board fallback not allowed for smp targets; " \ 35 | "please define hart_ids"); 36 | 37 | static const size_t hart_ids[1] = { CONFIG_FIRST_HART_ID }; 38 | #endif 39 | 40 | _Static_assert(NUM_ACTIVE_CPUS <= ARRAY_SIZE(hart_ids), 41 | "active CPUs cannot be more than available CPUs"); 42 | 43 | void plat_save_hw_id(int logical_cpu, uint64_t hart_id) 44 | { 45 | /** RISC-V appears to be nice and the hart_id given by the entrypoint 46 | * should always match that of the IDs we use to start it. Here we don't 47 | * need to do anything, but we can check that we are correct 48 | **/ 49 | 50 | if (hart_ids[logical_cpu] != hart_id) { 51 | LDR_PRINT("ERROR", logical_cpu, "runtime hart id "); 52 | puthex64(hart_id); 53 | puts("does not match build-time value "); 54 | puthex64(hart_ids[logical_cpu]); 55 | puts("\n"); 56 | 57 | for (;;) {} 58 | } 59 | } 60 | 61 | uint64_t plat_get_hw_id(int logical_cpu) 62 | { 63 | return hart_ids[logical_cpu]; 64 | } 65 | 66 | /** defined in crt0.S */ 67 | extern char riscv_secondary_cpu_entry_asm[1]; 68 | /** called from crt0.S */ 69 | void riscv_secondary_cpu_entry(uint64_t hart_id, int logical_cpu); 70 | 71 | void riscv_secondary_cpu_entry(uint64_t hart_id, int logical_cpu) 72 | { 73 | LDR_PRINT("INFO", logical_cpu, "secondary CPU entry with hart id "); 74 | puthex64(hart_id); 75 | puts("\n"); 76 | 77 | if (logical_cpu == 0) { 78 | LDR_PRINT("ERROR", logical_cpu, "secondary CPU should not have logical id 0!!!\n"); 79 | goto fail; 80 | } else if (logical_cpu >= NUM_ACTIVE_CPUS) { 81 | LDR_PRINT("ERROR", logical_cpu, "secondary CPU should not be >NUM_ACTIVE_CPUS\n"); 82 | goto fail; 83 | } 84 | 85 | start_kernel(logical_cpu); 86 | 87 | fail: 88 | for (;;) {} 89 | } 90 | 91 | int plat_start_cpu(int logical_cpu) 92 | { 93 | LDR_PRINT("INFO", 0, "starting CPU "); 94 | putdecimal(logical_cpu); 95 | puts("\n"); 96 | 97 | if (logical_cpu >= NUM_ACTIVE_CPUS) { 98 | LDR_PRINT("ERROR", 0, "starting a CPU with number above the active CPU count\n"); 99 | return 1; 100 | } 101 | 102 | uint64_t *stack_base = _stack[logical_cpu]; 103 | /* riscv expects stack to be 128-bit (16 byte) aligned, and we push to the stack 104 | to have space for the arguments to the entrypoint */ 105 | uint64_t *sp = (uint64_t *)((uintptr_t)stack_base + STACK_SIZE - 2 * sizeof(uint64_t)); 106 | /* store the logical cpu on the stack */ 107 | sp[0] = logical_cpu; 108 | /* zero out what was here before */ 109 | sp[1] = 0; 110 | 111 | uint64_t hart_id = plat_get_hw_id(logical_cpu); 112 | 113 | struct sbi_ret ret = sbi_call( 114 | SBI_HSM_EID, 115 | SBI_HSM_HART_START_FID, 116 | /* hartid */ hart_id, 117 | /* start_addr */ (uint64_t)riscv_secondary_cpu_entry_asm, 118 | /* opaque */ (uint64_t)sp, 119 | /* unused for this call */ 0, 0, 0); 120 | 121 | if (ret.error != SBI_SUCCESS) { 122 | LDR_PRINT("ERROR", 0, "could not start CPU, SBI call returned: "); 123 | puts(sbi_error_as_string(ret.error)); 124 | puts("\n"); 125 | } 126 | 127 | return 0; 128 | } 129 | -------------------------------------------------------------------------------- /loader/src/aarch64/smc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, UNSW. 3 | * 4 | * SPDX-License-Identifier: BSD-2-Clause 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include "../cutil.h" 12 | #include "../uart.h" 13 | 14 | /** 15 | * The Power State Coordinate Interface (DEN0022F.b) document in §5.2.1 16 | * specifies that 17 | * 18 | * For PSCI functions that use only 32-bit parameters, the arguments are 19 | * passed in R0 to R3 (AArch32) or W0 to W3 (AArch64), with return values 20 | * in R0 or W0. For versions using 64-bit parameters, the arguments are 21 | * passed in X0 to X3, with return values in X0. In line with the SMC 22 | * Calling Conventions, the immediate value used with an SMC (or HVC) 23 | * instruction must be 0. 24 | * 25 | * Hence we need both the SMC64 and SMC32 conventions implemented, with support 26 | * for up to 3 arguments. 27 | * 28 | * Table 5 Return error codes gives the error codes. 29 | * Errors are 32-bit signed integers for SMC32 functions, and 64-bit signed integers for SMC64 functions 30 | **/ 31 | 32 | #define PSCI_RETURN_SUCCESS 0 33 | #define PSCI_RETURN_NOT_SUPPORTED -1 34 | #define PSCI_RETURN_INVALID_PARAMETERS -2 35 | #define PSCI_RETURN_DENIED -3 36 | #define PSCI_RETURN_ALREADY_ON -4 37 | #define PSCI_RETURN_ON_PENDING -5 38 | #define PSCI_RETURN_INTERNAL_FAILURE -6 39 | #define PSCI_RETURN_NOT_PRESENT -7 40 | #define PSCI_RETURN_DISABLED -8 41 | #define PSCI_RETURN_INVALID_ADDRESS -9 42 | 43 | /* this is fine for both 64-bit and 32-bit return codes as a 0xFFFFFFFF'XXXXXXXX code 44 | will get truncated to the 0xXXXXXXXX which is still -1 as 32-bit */ 45 | static inline const char *psci_return_as_string(uint32_t ret) 46 | { 47 | switch (ret) { 48 | case PSCI_RETURN_SUCCESS: 49 | return "SUCCESS"; 50 | case PSCI_RETURN_NOT_SUPPORTED: 51 | return "NOT_SUPPORTED"; 52 | case PSCI_RETURN_INVALID_PARAMETERS: 53 | return "INVALID_PARAMETERS"; 54 | case PSCI_RETURN_DENIED: 55 | return "DENIED"; 56 | case PSCI_RETURN_ALREADY_ON: 57 | return "ALREADY_ON"; 58 | case PSCI_RETURN_ON_PENDING: 59 | return "ON_PENDING"; 60 | case PSCI_RETURN_INTERNAL_FAILURE: 61 | return "INTERNAL_FAILURE"; 62 | case PSCI_RETURN_NOT_PRESENT: 63 | return "NOT_PRESENT"; 64 | case PSCI_RETURN_DISABLED: 65 | return "DISABLED"; 66 | case PSCI_RETURN_INVALID_ADDRESS: 67 | return "INVALID_ADDRESS"; 68 | default: 69 | return ""; 70 | } 71 | } 72 | 73 | /* §5.1.4 of PSCI */ 74 | #define PSCI_FUNCTION_VERSION 0x84000000 75 | #define PSCI_FUNCTION_CPU_ON 0xC4000003 76 | 77 | /** 78 | * See document DEN002E SMC Calling Convention (v1.4, May 2022), 79 | * specifically §2.7 "SMC64/HVC64 argument passing". 80 | * 81 | * We only support up to 4 arguments, but the actual convention supports up 82 | * to 17, and clobbers X4--X17. The convention also supports up to 17 returns, 83 | * but we again only support 1. 84 | * 85 | **/ 86 | static inline uint64_t arm_smc64_call(uint32_t function_id, uint64_t arg0, uint64_t arg1, uint64_t arg2) 87 | { 88 | // Per Table 2-1, BIT(30)==1 defines the SMC64 calling convention 89 | if ((function_id & BIT(30)) == 0) { 90 | puts("LDR|ERROR: SMC32 function used in SMC64 call\n"); 91 | return PSCI_RETURN_INVALID_PARAMETERS; 92 | } 93 | 94 | register uint64_t x0 asm("x0") = function_id; 95 | register uint64_t x1 asm("x1") = arg0; 96 | register uint64_t x2 asm("x2") = arg1; 97 | register uint64_t x3 asm("x3") = arg2; 98 | asm volatile( 99 | "smc #0\n" 100 | : "=r"(x0) 101 | : "r"(x0), "r"(x1), "r"(x2), "r"(x3) 102 | : "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", 103 | "memory" 104 | ); 105 | 106 | return x0; 107 | } 108 | 109 | /** 110 | * Reference 2.6 "SMC32/HVC32 argument passing". 111 | **/ 112 | static inline uint32_t arm_smc32_call(uint32_t function_id, uint32_t arg0, uint32_t arg1, uint32_t arg2) 113 | { 114 | // Per Table 2-1, BIT(30)==0 defines the SMC32 calling convention 115 | if ((function_id & BIT(30)) == BIT(30)) { 116 | puts("LDR|ERROR: SMC64 function used in SMC32 call\n"); 117 | return PSCI_RETURN_INVALID_PARAMETERS; 118 | } 119 | // TODO: This only supports AArch64 mode for the moment, in AArch32 mode 120 | // we need to use the x... registers. 121 | 122 | register uint64_t w0 asm("w0") = function_id; 123 | register uint64_t w1 asm("w1") = arg0; 124 | register uint64_t w2 asm("w2") = arg1; 125 | register uint64_t w3 asm("w3") = arg2; 126 | asm volatile( 127 | "smc #0\n" 128 | : "=r"(w0) 129 | : "r"(w0), "r"(w1), "r"(w2), "r"(w3) 130 | : "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", "w16", "w17", 131 | "memory" 132 | ); 133 | 134 | return w0; 135 | } 136 | -------------------------------------------------------------------------------- /tool/microkit/src/capdl/initialiser.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025, UNSW 3 | // 4 | // SPDX-License-Identifier: BSD-2-Clause 5 | // 6 | 7 | use std::ops::Range; 8 | 9 | use rkyv::util::AlignedVec; 10 | 11 | use crate::elf::ElfSegmentData; 12 | use crate::util::round_up; 13 | use crate::{elf::ElfFile, sel4::PageSize}; 14 | use crate::{serialise_ut, UntypedObject}; 15 | 16 | // Page size used for allocating the spec and embedded frames segments. 17 | pub const INITIALISER_GRANULE_SIZE: PageSize = PageSize::Small; 18 | 19 | pub struct CapDLInitialiserSpecMetadata { 20 | pub spec_size: u64, 21 | } 22 | 23 | #[repr(u8)] 24 | #[derive(Debug, Clone, Copy)] 25 | pub enum LogLevel { 26 | Error = 1, 27 | Warn = 2, 28 | Info = 3, 29 | Debug = 4, 30 | Trace = 5, 31 | } 32 | 33 | pub struct CapDLInitialiser { 34 | pub elf: ElfFile, 35 | pub phys_base: Option, 36 | pub spec_metadata: Option, 37 | /// Log level of initialiser printing in debug mode. 38 | pub log_level: LogLevel, 39 | } 40 | 41 | impl CapDLInitialiser { 42 | pub fn new(elf: ElfFile) -> CapDLInitialiser { 43 | CapDLInitialiser { 44 | elf, 45 | phys_base: None, 46 | spec_metadata: None, 47 | log_level: LogLevel::Info, 48 | } 49 | } 50 | 51 | pub fn image_bound(&self) -> Range { 52 | self.elf.lowest_vaddr()..round_up(self.elf.highest_vaddr(), INITIALISER_GRANULE_SIZE as u64) 53 | } 54 | 55 | pub fn add_spec(&mut self, spec_payload: AlignedVec, embedded_frame_data: Vec) { 56 | if self.spec_metadata.is_some() { 57 | self.elf.segments.pop(); 58 | self.elf.segments.pop(); 59 | self.spec_metadata = None; 60 | } 61 | 62 | let spec_vaddr = self.elf.next_vaddr(INITIALISER_GRANULE_SIZE); 63 | let spec_size = spec_payload.len() as u64; 64 | self.elf.add_segment( 65 | true, 66 | false, 67 | false, 68 | spec_vaddr, 69 | ElfSegmentData::RealData(spec_payload.into()), 70 | ); 71 | 72 | let embedded_frame_data_vaddr = self.elf.next_vaddr(INITIALISER_GRANULE_SIZE); 73 | self.elf.add_segment( 74 | true, 75 | false, 76 | false, 77 | embedded_frame_data_vaddr, 78 | ElfSegmentData::RealData(embedded_frame_data), 79 | ); 80 | 81 | // These symbol names must match rust-sel4/crates/sel4-capdl-initializer/src/main.rs 82 | self.elf 83 | .write_symbol( 84 | "sel4_capdl_initializer_embedded_frames_data_start", 85 | &embedded_frame_data_vaddr.to_le_bytes(), 86 | ) 87 | .unwrap(); 88 | 89 | self.elf 90 | .write_symbol( 91 | "sel4_capdl_initializer_serialized_spec_data_start", 92 | &spec_vaddr.to_le_bytes(), 93 | ) 94 | .unwrap(); 95 | self.elf 96 | .write_symbol( 97 | "sel4_capdl_initializer_serialized_spec_data_size", 98 | &spec_size.to_le_bytes(), 99 | ) 100 | .unwrap(); 101 | 102 | self.elf 103 | .write_symbol( 104 | "sel4_capdl_initializer_image_start", 105 | &self.elf.lowest_vaddr().to_le_bytes(), 106 | ) 107 | .unwrap(); 108 | self.elf 109 | .write_symbol( 110 | "sel4_capdl_initializer_image_end", 111 | &self.elf.highest_vaddr().to_le_bytes(), 112 | ) 113 | .unwrap(); 114 | 115 | self.spec_metadata = Some(CapDLInitialiserSpecMetadata { spec_size }); 116 | } 117 | 118 | pub fn spec_metadata(&self) -> &Option { 119 | &self.spec_metadata 120 | } 121 | 122 | pub fn add_expected_untypeds(&mut self, untypeds: &[UntypedObject]) { 123 | let mut uts_desc: Vec = Vec::new(); 124 | for ut in untypeds.iter() { 125 | uts_desc.extend(serialise_ut(ut)); 126 | } 127 | 128 | // This feature is currently not in mainline rust-seL4, keep it around for potential 129 | // debugging purposes. 130 | if self 131 | .elf 132 | .find_symbol("sel4_capdl_initializer_expected_untypeds_list_num_entries") 133 | .is_ok() 134 | { 135 | self.elf 136 | .write_symbol( 137 | "sel4_capdl_initializer_expected_untypeds_list_num_entries", 138 | &(untypeds.len() as u64).to_le_bytes(), 139 | ) 140 | .unwrap(); 141 | self.elf 142 | .write_symbol("sel4_capdl_initializer_expected_untypeds_list", &uts_desc) 143 | .unwrap(); 144 | } 145 | } 146 | 147 | pub fn set_phys_base(&mut self, phys_base: u64) { 148 | self.phys_base = Some(phys_base); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /loader/src/aarch64/init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Breakaway Consulting Pty. Ltd. 3 | * Copyright 2025, UNSW 4 | * 5 | * SPDX-License-Identifier: BSD-2-Clause 6 | */ 7 | 8 | #include "../arch.h" 9 | #include "../loader.h" 10 | #include "../uart.h" 11 | #include "el.h" 12 | #include "smc.h" 13 | 14 | #include 15 | 16 | #if defined(CONFIG_PLAT_ZYNQMP_ZCU102) || defined(CONFIG_PLAT_ZYNQMP_ULTRA96V2) 17 | #define GICD_BASE 0x00F9010000UL 18 | #define GICC_BASE 0x00F9020000UL 19 | #elif defined(CONFIG_PLAT_QEMU_ARM_VIRT) 20 | #define GICD_BASE 0x8000000UL 21 | #define GICC_BASE 0x8010000UL 22 | #endif 23 | 24 | #if defined(CONFIG_PLAT_ZYNQMP_ZCU102) || defined(CONFIG_PLAT_ZYNQMP_ULTRA96V2) || defined(CONFIG_PLAT_QEMU_ARM_VIRT) 25 | static void configure_gicv2(void) 26 | { 27 | /* The ZCU102 start in EL3, and then we drop to EL1(NS). 28 | * 29 | * The GICv2 supports security extensions (as does the CPU). 30 | * 31 | * The GIC sets any interrupt as either Group 0 or Group 1. 32 | * A Group 0 interrupt can only be configured in secure mode, 33 | * while Group 1 interrupts can be configured from non-secure mode. 34 | * 35 | * As seL4 runs in non-secure mode, and we want seL4 to have 36 | * the ability to configure interrupts, at this point we need 37 | * to put all interrupts into Group 1. 38 | * 39 | * GICD_IGROUPn starts at offset 0x80. 40 | * 41 | * 0xF901_0000. 42 | * 43 | * Future work: On multicore systems the distributor setup 44 | * only needs to be called once, while the GICC registers 45 | * should be set for each CPU. 46 | */ 47 | puts("LDR|INFO: Setting all interrupts to Group 1\n"); 48 | uint32_t gicd_typer = *((volatile uint32_t *)(GICD_BASE + 0x4)); 49 | uint32_t it_lines_number = gicd_typer & 0x1f; 50 | puts("LDR|INFO: GICv2 ITLinesNumber: "); 51 | puthex32(it_lines_number); 52 | puts("\n"); 53 | 54 | for (uint32_t i = 0; i <= it_lines_number; i++) { 55 | *((volatile uint32_t *)(GICD_BASE + 0x80 + (i * 4))) = 0xFFFFFFFF; 56 | } 57 | 58 | /* For any interrupts to go through the interrupt priority mask 59 | * must be set appropriately. Only interrupts with priorities less 60 | * than this mask will interrupt the CPU. 61 | * 62 | * seL4 (effectively) sets interrupts to priority 0x80, so it is 63 | * important to make sure this is greater than 0x80. 64 | */ 65 | *((volatile uint32_t *)(GICC_BASE + 0x4)) = 0xf0; 66 | } 67 | #endif 68 | 69 | void el1_mmu_disable(void); 70 | void el2_mmu_disable(void); 71 | 72 | void arch_init(void) 73 | { 74 | #if defined(CONFIG_PLAT_ZYNQMP_ZCU102) || defined(CONFIG_PLAT_ZYNQMP_ULTRA96V2) || defined(CONFIG_PLAT_QEMU_ARM_VIRT) 75 | configure_gicv2(); 76 | #endif 77 | 78 | /* Disable the MMU, as U-Boot will start in virtual memory on some platforms 79 | * (https://docs.u-boot.org/en/latest/arch/arm64.html), which means that 80 | * certain physical memory addresses contain page table information which 81 | * the loader doesn't know about and would need to be careful not to 82 | * overwrite. 83 | * 84 | * This also means that we would need to worry about caching. 85 | * TODO: should we do that instead? 86 | * note the issues where it forces us to flush any shared addresses all the 87 | * way to cache as we might have mixed non-cached/cached access. 88 | */ 89 | puts("LDR|INFO: disabling MMU (if it was enabled)\n"); 90 | enum el el = current_el(); 91 | 92 | if (el == EL1) { 93 | el1_mmu_disable(); 94 | } else if (el == EL2) { 95 | el2_mmu_disable(); 96 | } else { 97 | puts("LDR|ERROR: unknown EL level for MMU disable\n"); 98 | } 99 | 100 | // TODO: handle non-PSCI platforms better, see https://github.com/seL4/microkit/issues/401. 101 | #if !defined(CONFIG_PLAT_BCM2711) 102 | uint32_t ret = arm_smc32_call(PSCI_FUNCTION_VERSION, /* unused */ 0, 0, 0); 103 | /* the return value has no error codes, but if we get it wrong this is what we will get */ 104 | if (ret == PSCI_RETURN_NOT_SUPPORTED) { 105 | puts("LDR|ERROR: could not determine PSCI version: "); 106 | puts(psci_return_as_string(ret)); 107 | puts("\n"); 108 | } else { 109 | uint16_t major = (ret >> 16) & 0xffff; 110 | uint16_t minor = (ret >> 0) & 0xffff; 111 | puts("LDR|INFO: PSCI version is "); 112 | putdecimal(major); 113 | puts("."); 114 | putdecimal(minor); 115 | puts("\n"); 116 | } 117 | #endif 118 | } 119 | 120 | typedef void (*sel4_entry)( 121 | uintptr_t ui_p_reg_start, 122 | uintptr_t ui_p_reg_end, 123 | intptr_t pv_offset, 124 | uintptr_t v_entry, 125 | uintptr_t dtb_addr_p, 126 | uintptr_t dtb_size 127 | ); 128 | 129 | void arch_jump_to_kernel(int logical_cpu) 130 | { 131 | /* seL4 always expects the current logical CPU number in TPIDR_EL1 */ 132 | asm volatile("msr TPIDR_EL1, %0" :: "r"(logical_cpu)); 133 | 134 | ((sel4_entry)(loader_data->kernel_entry))( 135 | loader_data->ui_p_reg_start, 136 | loader_data->ui_p_reg_end, 137 | loader_data->pv_offset, 138 | loader_data->v_entry, 139 | 0, 140 | 0 141 | ); 142 | } 143 | -------------------------------------------------------------------------------- /tool/microkit/src/uimage.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025, UNSW 3 | // 4 | // SPDX-License-Identifier: BSD-2-Clause 5 | // 6 | 7 | // Document referenced: 8 | // U-Boot: include/image.h 9 | // Linux: https://www.kernel.org/doc/html/latest/arch/riscv/boot-image-header.html 10 | 11 | use crate::struct_to_bytes; 12 | use crate::{crc32::crc32, sel4::Arch}; 13 | use std::fs::File; 14 | use std::io::Write; 15 | 16 | const UIMAGE_NAME: &str = "seL4 Microkit"; 17 | 18 | // OS-type code 19 | const IH_OS_LINUX: u8 = 5; 20 | 21 | // CPU-arch codes 22 | const IH_ARCH_RISCV: u8 = 26; 23 | 24 | // Image-type code 25 | const IH_TYPE_KERNEL: u8 = 2; 26 | 27 | // No compression 28 | const IH_COMP_NONE: u8 = 0; 29 | 30 | // Image name length max 31 | const IH_NMLEN: usize = 32; 32 | 33 | // Image magic 34 | const IH_MAGIC: u32 = 0x27051956; 35 | 36 | #[repr(C, packed)] 37 | struct UbootLegacyImgHeader { 38 | ih_magic: u32, // Image Header Magic Number 39 | ih_hcrc: u32, // Image Header CRC Checksum 40 | ih_time: u32, // Image Creation Timestamp 41 | ih_size: u32, // Image Data Size 42 | ih_load: u32, // Data Load Address 43 | ih_ep: u32, // Entry Point Address 44 | ih_dcrc: u32, // Image Data CRC Checksum 45 | ih_os: u8, // Operating System 46 | ih_arch: u8, // CPU architecture 47 | ih_type: u8, // Image Type 48 | ih_comp: u8, // Compression Type 49 | ih_name: [u8; IH_NMLEN], // Image Name 50 | } 51 | 52 | // Bits 0:15 minor, bits 16:31 major 53 | // Linux defines this to be 0.2 currently 54 | const LINUX_RISCV_HEADER_VERSION: u32 = 2; 55 | 56 | const LINUX_RISCV_HEADER_MAGIC: u64 = 0x5643534952; 57 | const LINUX_RISCV_HEADER_MAGIC2: u32 = 0x05435352; 58 | 59 | #[repr(C, packed)] 60 | struct LinuxRiscvImageHeader { 61 | code0: u32, 62 | code1: u32, 63 | text_offset: u64, // Image load offset, little endian 64 | image_size: u64, // Effective Image size, little endian 65 | flags: u64, // kernel flags, little endian 66 | version: u32, // Version of this header 67 | res1: u32, 68 | res2: u64, 69 | magic: u64, 70 | magic2: u32, 71 | res3: u32, 72 | } 73 | 74 | pub fn uimage_serialise( 75 | arch: &Arch, 76 | entry: u32, 77 | executable_payload: Vec, 78 | path: &std::path::Path, 79 | ) -> Result { 80 | let ih_arch_le = match arch { 81 | Arch::Aarch64 => unreachable!("internal bug: unimplemented uImage creation for ARM"), 82 | Arch::Riscv64 => IH_ARCH_RISCV, 83 | Arch::X86_64 => unreachable!("internal bug: unimplemented uImage creation for x86"), 84 | }; 85 | 86 | // We masquerade the Microkit loader as a Linux kernel to U-Boot, so that U-Boot follows 87 | // the Linux boot protocol and give us the HART ID in a0. If we pack the uImage as a generic `IH_OS_ELF`, 88 | // we won't get the HART ID which will be problematic for booting seL4. 89 | let linux_riscv_hdr = LinuxRiscvImageHeader { 90 | code0: 0, 91 | code1: 0, 92 | text_offset: 0, 93 | image_size: executable_payload.len() as u64, 94 | flags: 0, // little endian executable 95 | version: LINUX_RISCV_HEADER_VERSION, 96 | res1: 0, 97 | res2: 0, 98 | magic: LINUX_RISCV_HEADER_MAGIC, 99 | magic2: LINUX_RISCV_HEADER_MAGIC2, 100 | res3: 0, 101 | }; 102 | 103 | let mut linux_image_payload = Vec::new(); 104 | linux_image_payload.extend_from_slice(unsafe { struct_to_bytes(&linux_riscv_hdr) }); 105 | linux_image_payload.extend_from_slice(executable_payload.as_slice()); 106 | 107 | // The actual loader executable is after the Linux header, so we tell U-Boot to load the 108 | // uImage in a way that the loader always start at the physical address it expects. 109 | let load_paddr = entry - ::core::mem::size_of::() as u32; 110 | 111 | let mut hdr = UbootLegacyImgHeader { 112 | ih_magic: IH_MAGIC.to_be(), 113 | ih_hcrc: 0, // U-Boot clears this field before it recalculate the checksum, so do the same here 114 | ih_time: 0, 115 | ih_size: (linux_image_payload.len() as u32).to_be(), 116 | ih_load: load_paddr.to_be(), 117 | ih_ep: entry.to_be(), 118 | ih_dcrc: crc32(&linux_image_payload).to_be(), 119 | ih_os: IH_OS_LINUX.to_be(), 120 | ih_arch: ih_arch_le.to_be(), 121 | ih_type: IH_TYPE_KERNEL.to_be(), 122 | ih_comp: IH_COMP_NONE.to_be(), 123 | ih_name: [0; IH_NMLEN], 124 | }; 125 | 126 | let hdr_name_cpy_dest = &mut hdr.ih_name[0..UIMAGE_NAME.len()]; 127 | hdr_name_cpy_dest.copy_from_slice(UIMAGE_NAME.as_bytes()); 128 | 129 | let hdr_chksum = unsafe { crc32(struct_to_bytes(&hdr)) }; 130 | hdr.ih_hcrc = hdr_chksum.to_be(); 131 | 132 | let mut uimage_file = match File::create(path) { 133 | Ok(file) => file, 134 | Err(e) => return Err(format!("cannot create '{}': {}", path.display(), e)), 135 | }; 136 | 137 | uimage_file 138 | .write_all(unsafe { struct_to_bytes(&hdr) }) 139 | .unwrap_or_else(|_| panic!("Failed to write uImage header for '{}'", path.display())); 140 | 141 | uimage_file 142 | .write_all(&linux_image_payload) 143 | .unwrap_or_else(|_| panic!("Failed to write payload for '{}'", path.display())); 144 | 145 | uimage_file.flush().unwrap(); 146 | 147 | Ok(0) 148 | } 149 | --------------------------------------------------------------------------------