From 2fadeb6937ac64dccbccdf28b91c9f012072b0f3 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Fri, 23 Feb 2024 19:57:20 +0000 Subject: [PATCH 1/7] crates/sel4-elf-header: Split out from sel4-runtime-common Signed-off-by: Nick Spinale --- Cargo.lock | 5 +++ Cargo.toml | 1 + crates/sel4-elf-header/Cargo.nix | 11 ++++++ crates/sel4-elf-header/Cargo.toml | 17 +++++++++ .../elf.rs => sel4-elf-header/src/lib.rs} | 38 ++++++++----------- crates/sel4-runtime-common/Cargo.nix | 2 +- crates/sel4-runtime-common/Cargo.toml | 1 + crates/sel4-runtime-common/src/phdrs/mod.rs | 5 +-- crates/sel4-runtime-common/src/phdrs/tls.rs | 11 +++--- .../src/phdrs/unwinding.rs | 7 ++-- 10 files changed, 62 insertions(+), 36 deletions(-) create mode 100644 crates/sel4-elf-header/Cargo.nix create mode 100644 crates/sel4-elf-header/Cargo.toml rename crates/{sel4-runtime-common/src/phdrs/elf.rs => sel4-elf-header/src/lib.rs} (69%) diff --git a/Cargo.lock b/Cargo.lock index 6d33477e3..146e5c470 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2180,6 +2180,10 @@ dependencies = [ "lock_api", ] +[[package]] +name = "sel4-elf-header" +version = "0.1.0" + [[package]] name = "sel4-externally-shared" version = "0.1.0" @@ -2452,6 +2456,7 @@ version = "0.1.0" dependencies = [ "cfg-if", "sel4", + "sel4-elf-header", "sel4-initialize-tls-on-stack", "sel4-panicking-env", "unwinding", diff --git a/Cargo.toml b/Cargo.toml index f4a9ba661..17921a816 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,6 +88,7 @@ members = [ "crates/sel4-capdl-initializer/with-embedded-spec/embedded-spec", "crates/sel4-capdl-initializer/with-embedded-spec/embedded-spec/validate", "crates/sel4-dlmalloc", + "crates/sel4-elf-header", "crates/sel4-externally-shared", "crates/sel4-generate-target-specs", "crates/sel4-hal-adapters", diff --git a/crates/sel4-elf-header/Cargo.nix b/crates/sel4-elf-header/Cargo.nix new file mode 100644 index 000000000..9483e202f --- /dev/null +++ b/crates/sel4-elf-header/Cargo.nix @@ -0,0 +1,11 @@ +# +# Copyright 2024, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# + +{ mk }: + +mk { + package.name = "sel4-elf-header"; +} diff --git a/crates/sel4-elf-header/Cargo.toml b/crates/sel4-elf-header/Cargo.toml new file mode 100644 index 000000000..d99c3cf0c --- /dev/null +++ b/crates/sel4-elf-header/Cargo.toml @@ -0,0 +1,17 @@ +# +# Copyright 2023, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# +# +# This file is generated from './Cargo.nix'. You can edit this file directly +# if you are not using this project's Cargo manifest management tools. +# See 'hacking/cargo-manifest-management/README.md' for more information. +# + +[package] +name = "sel4-elf-header" +version = "0.1.0" +authors = ["Nick Spinale "] +edition = "2021" +license = "BSD-2-Clause" diff --git a/crates/sel4-runtime-common/src/phdrs/elf.rs b/crates/sel4-elf-header/src/lib.rs similarity index 69% rename from crates/sel4-runtime-common/src/phdrs/elf.rs rename to crates/sel4-elf-header/src/lib.rs index 884190f28..1a0867497 100644 --- a/crates/sel4-runtime-common/src/phdrs/elf.rs +++ b/crates/sel4-elf-header/src/lib.rs @@ -1,22 +1,16 @@ // -// Copyright 2023, Colias Group, LLC +// Copyright 2024, Colias Group, LLC // // SPDX-License-Identifier: BSD-2-Clause // +#![no_std] #![allow(dead_code)] use core::ops::Range; +use core::ptr; use core::slice; -use sel4_panicking_env::abort; - -#[cfg(target_pointer_width = "32")] -pub type Word = u32; - -#[cfg(target_pointer_width = "64")] -pub type Word = u64; - #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub struct ElfHeader { @@ -24,9 +18,9 @@ pub struct ElfHeader { pub e_type: u16, pub e_machine: u16, pub e_version: u32, - pub e_entry: Word, - pub e_phoff: Word, - pub e_shoff: Word, + pub e_entry: usize, + pub e_phoff: usize, + pub e_shoff: usize, pub e_flags: u32, pub e_ehsize: u16, pub e_phentsize: u16, @@ -55,11 +49,11 @@ impl ElfHeader { self.e_ident.magic == ELFMAG } - pub fn locate_phdrs(&self) -> &'static [ProgramHeader] { + pub fn locate_phdrs(&'static self) -> &'static [ProgramHeader] { unsafe { - let ptr = (self as *const Self) + let ptr = ptr::from_ref(self) .cast::() - .offset(self.e_phoff.try_into().unwrap_or_else(|_| abort!())) + .wrapping_byte_offset(self.e_phoff as isize) .cast::(); slice::from_raw_parts(ptr, self.e_phnum.into()) } @@ -72,14 +66,14 @@ pub struct ProgramHeader { pub p_type: u32, #[cfg(target_pointer_width = "64")] pub p_flags: u32, - pub p_offset: Word, - pub p_vaddr: Word, - pub p_paddr: Word, - pub p_filesz: Word, - pub p_memsz: Word, + pub p_offset: usize, + pub p_vaddr: usize, + pub p_paddr: usize, + pub p_filesz: usize, + pub p_memsz: usize, #[cfg(target_pointer_width = "32")] pub p_flags: u32, - pub p_align: Word, + pub p_align: usize, } pub const PT_NULL: u32 = 0; @@ -91,6 +85,6 @@ impl ProgramHeader { pub fn vaddr_range(&self) -> Range { let start = self.p_vaddr; let end = start + self.p_memsz; - start.try_into().unwrap_or_else(|_| abort!())..end.try_into().unwrap_or_else(|_| abort!()) + start..end } } diff --git a/crates/sel4-runtime-common/Cargo.nix b/crates/sel4-runtime-common/Cargo.nix index 7cb593f89..8461ef8ae 100644 --- a/crates/sel4-runtime-common/Cargo.nix +++ b/crates/sel4-runtime-common/Cargo.nix @@ -10,7 +10,7 @@ mk { package.name = "sel4-runtime-common"; dependencies = { inherit (versions) cfg-if; - inherit (localCrates) sel4-panicking-env; + inherit (localCrates) sel4-panicking-env sel4-elf-header; sel4 = localCrates.sel4 // { default-features = false; optional = true; }; sel4-initialize-tls-on-stack = localCrates.sel4-initialize-tls-on-stack // { optional = true; }; }; diff --git a/crates/sel4-runtime-common/Cargo.toml b/crates/sel4-runtime-common/Cargo.toml index 048afaaf5..e1dc62273 100644 --- a/crates/sel4-runtime-common/Cargo.toml +++ b/crates/sel4-runtime-common/Cargo.toml @@ -23,6 +23,7 @@ tls = ["dep:sel4-initialize-tls-on-stack", "dep:sel4"] [dependencies] cfg-if = "1.0.0" sel4 = { path = "../sel4", default-features = false, optional = true } +sel4-elf-header = { path = "../sel4-elf-header" } sel4-initialize-tls-on-stack = { path = "../sel4-initialize-tls-on-stack", optional = true } sel4-panicking-env = { path = "../sel4-panicking/env" } diff --git a/crates/sel4-runtime-common/src/phdrs/mod.rs b/crates/sel4-runtime-common/src/phdrs/mod.rs index 03d7c20d1..43f415359 100644 --- a/crates/sel4-runtime-common/src/phdrs/mod.rs +++ b/crates/sel4-runtime-common/src/phdrs/mod.rs @@ -4,12 +4,9 @@ // SPDX-License-Identifier: BSD-2-Clause // +use sel4_elf_header::{ElfHeader, ProgramHeader}; use sel4_panicking_env::abort; -mod elf; - -use elf::{ElfHeader, ProgramHeader}; - #[cfg(all(feature = "tls", target_thread_local))] mod tls; diff --git a/crates/sel4-runtime-common/src/phdrs/tls.rs b/crates/sel4-runtime-common/src/phdrs/tls.rs index 44eb06a9d..d6f561ccb 100644 --- a/crates/sel4-runtime-common/src/phdrs/tls.rs +++ b/crates/sel4-runtime-common/src/phdrs/tls.rs @@ -4,6 +4,7 @@ // SPDX-License-Identifier: BSD-2-Clause // +use sel4_elf_header::PT_TLS; use sel4_panicking_env::abort; #[allow(unused_imports)] @@ -13,7 +14,7 @@ use sel4_initialize_tls_on_stack::{ pub use sel4_initialize_tls_on_stack::{ContArg, ContFn}; -use crate::phdrs::{elf::PT_TLS, locate_phdrs}; +use crate::phdrs::locate_phdrs; #[allow(clippy::missing_safety_doc)] pub unsafe fn initialize_tls_on_stack_and_continue(cont_fn: ContFn, cont_arg: *mut ContArg) -> ! { @@ -22,10 +23,10 @@ pub unsafe fn initialize_tls_on_stack_and_continue(cont_fn: ContFn, cont_arg: *m .find(|phdr| phdr.p_type == PT_TLS) .unwrap_or_else(|| abort!("no PT_TLS segment")); let unchecked = UncheckedTlsImage { - vaddr: phdr.p_vaddr.try_into().unwrap(), - filesz: phdr.p_filesz.try_into().unwrap(), - memsz: phdr.p_memsz.try_into().unwrap(), - align: phdr.p_align.try_into().unwrap(), + vaddr: phdr.p_vaddr, + filesz: phdr.p_filesz, + memsz: phdr.p_memsz, + align: phdr.p_align, }; unchecked .check() diff --git a/crates/sel4-runtime-common/src/phdrs/unwinding.rs b/crates/sel4-runtime-common/src/phdrs/unwinding.rs index 3c5eeef59..8c20385fe 100644 --- a/crates/sel4-runtime-common/src/phdrs/unwinding.rs +++ b/crates/sel4-runtime-common/src/phdrs/unwinding.rs @@ -9,10 +9,9 @@ use unwinding::custom_eh_frame_finder::{ SetCustomEhFrameFinderError, }; -use crate::phdrs::{ - elf::{PT_GNU_EH_FRAME, PT_LOAD}, - locate_phdrs, -}; +use sel4_elf_header::{PT_GNU_EH_FRAME, PT_LOAD}; + +use crate::phdrs::locate_phdrs; struct EhFrameFinderImpl; From dfa31e3b35fe885f4013191abb6e2690b47a14b4 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Fri, 23 Feb 2024 20:23:17 +0000 Subject: [PATCH 2/7] crates/sel4-runtime-common: Flatten module structure Signed-off-by: Nick Spinale --- crates/sel4-runtime-common/src/lib.rs | 43 +++++++++++++------ crates/sel4-runtime-common/src/phdrs/mod.rs | 32 -------------- .../src/{phdrs => }/tls.rs | 2 +- .../src/{phdrs => }/unwinding.rs | 2 +- 4 files changed, 31 insertions(+), 48 deletions(-) delete mode 100644 crates/sel4-runtime-common/src/phdrs/mod.rs rename crates/sel4-runtime-common/src/{phdrs => }/tls.rs (97%) rename crates/sel4-runtime-common/src/{phdrs => }/unwinding.rs (97%) diff --git a/crates/sel4-runtime-common/src/lib.rs b/crates/sel4-runtime-common/src/lib.rs index c549d31d7..a36dffa79 100644 --- a/crates/sel4-runtime-common/src/lib.rs +++ b/crates/sel4-runtime-common/src/lib.rs @@ -7,6 +7,9 @@ #![no_std] #![feature(cfg_target_thread_local)] +use sel4_elf_header::{ElfHeader, ProgramHeader}; +use sel4_panicking_env::abort; + mod ctors; pub use ctors::run_ctors; @@ -14,22 +17,28 @@ pub use ctors::run_ctors; #[cfg(feature = "start")] mod start; -#[cfg(any( - all(feature = "tls", target_thread_local), - all(feature = "unwinding", panic = "unwind") -))] -mod phdrs; +#[cfg(all(feature = "tls", target_thread_local))] +mod tls; -#[cfg(any( - all(feature = "tls", target_thread_local), - all(feature = "unwinding", panic = "unwind") -))] -pub use phdrs::*; +#[cfg(all(feature = "tls", target_thread_local))] +pub use tls::{initialize_tls_on_stack_and_continue, ContArg, ContFn}; -#[doc(hidden)] -pub mod _private { - #[cfg(feature = "start")] - pub use crate::start::_private as start; +#[cfg(all(feature = "unwinding", panic = "unwind"))] +mod unwinding; + +#[cfg(all(feature = "unwinding", panic = "unwind"))] +pub use self::unwinding::set_eh_frame_finder; + +pub(crate) fn locate_phdrs() -> &'static [ProgramHeader] { + extern "C" { + static __ehdr_start: ElfHeader; + } + unsafe { + if !__ehdr_start.check_magic() { + abort!("ELF header magic mismatch") + } + __ehdr_start.locate_phdrs() + } } #[cfg(target_arch = "arm")] @@ -44,3 +53,9 @@ core::arch::global_asm! { bx lr "# } + +#[doc(hidden)] +pub mod _private { + #[cfg(feature = "start")] + pub use crate::start::_private as start; +} diff --git a/crates/sel4-runtime-common/src/phdrs/mod.rs b/crates/sel4-runtime-common/src/phdrs/mod.rs deleted file mode 100644 index 43f415359..000000000 --- a/crates/sel4-runtime-common/src/phdrs/mod.rs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright 2023, Colias Group, LLC -// -// SPDX-License-Identifier: BSD-2-Clause -// - -use sel4_elf_header::{ElfHeader, ProgramHeader}; -use sel4_panicking_env::abort; - -#[cfg(all(feature = "tls", target_thread_local))] -mod tls; - -#[cfg(all(feature = "tls", target_thread_local))] -pub use tls::{initialize_tls_on_stack_and_continue, ContArg, ContFn}; - -#[cfg(all(feature = "unwinding", panic = "unwind"))] -mod unwinding; - -#[cfg(all(feature = "unwinding", panic = "unwind"))] -pub use self::unwinding::set_eh_frame_finder; - -pub(crate) fn locate_phdrs() -> &'static [ProgramHeader] { - extern "C" { - static __ehdr_start: ElfHeader; - } - unsafe { - if !__ehdr_start.check_magic() { - abort!("ELF header magic mismatch") - } - __ehdr_start.locate_phdrs() - } -} diff --git a/crates/sel4-runtime-common/src/phdrs/tls.rs b/crates/sel4-runtime-common/src/tls.rs similarity index 97% rename from crates/sel4-runtime-common/src/phdrs/tls.rs rename to crates/sel4-runtime-common/src/tls.rs index d6f561ccb..d458fd6e3 100644 --- a/crates/sel4-runtime-common/src/phdrs/tls.rs +++ b/crates/sel4-runtime-common/src/tls.rs @@ -14,7 +14,7 @@ use sel4_initialize_tls_on_stack::{ pub use sel4_initialize_tls_on_stack::{ContArg, ContFn}; -use crate::phdrs::locate_phdrs; +use crate::locate_phdrs; #[allow(clippy::missing_safety_doc)] pub unsafe fn initialize_tls_on_stack_and_continue(cont_fn: ContFn, cont_arg: *mut ContArg) -> ! { diff --git a/crates/sel4-runtime-common/src/phdrs/unwinding.rs b/crates/sel4-runtime-common/src/unwinding.rs similarity index 97% rename from crates/sel4-runtime-common/src/phdrs/unwinding.rs rename to crates/sel4-runtime-common/src/unwinding.rs index 8c20385fe..f05f6c195 100644 --- a/crates/sel4-runtime-common/src/phdrs/unwinding.rs +++ b/crates/sel4-runtime-common/src/unwinding.rs @@ -11,7 +11,7 @@ use unwinding::custom_eh_frame_finder::{ use sel4_elf_header::{PT_GNU_EH_FRAME, PT_LOAD}; -use crate::phdrs::locate_phdrs; +use crate::locate_phdrs; struct EhFrameFinderImpl; From 659ed732e4d8a64f8fb8c05965a1558b52406aff Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Fri, 23 Feb 2024 20:27:07 +0000 Subject: [PATCH 3/7] crates/sel4-initialize-tls: Rename crate Signed-off-by: Nick Spinale --- Cargo.lock | 5 ++--- Cargo.toml | 2 +- crates/private/support/sel4-simple-task/runtime/Cargo.nix | 1 - crates/private/support/sel4-simple-task/runtime/Cargo.toml | 1 - .../Cargo.nix | 5 ++++- .../Cargo.toml | 5 ++++- .../src/lib.rs | 0 crates/sel4-runtime-common/Cargo.nix | 4 ++-- crates/sel4-runtime-common/Cargo.toml | 4 ++-- crates/sel4-runtime-common/src/tls.rs | 6 ++---- 10 files changed, 17 insertions(+), 16 deletions(-) rename crates/{sel4-initialize-tls-on-stack => sel4-initialize-tls}/Cargo.nix (69%) rename crates/{sel4-initialize-tls-on-stack => sel4-initialize-tls}/Cargo.toml (89%) rename crates/{sel4-initialize-tls-on-stack => sel4-initialize-tls}/src/lib.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 146e5c470..2ec854029 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2225,7 +2225,7 @@ name = "sel4-immutable-cell" version = "0.1.0" [[package]] -name = "sel4-initialize-tls-on-stack" +name = "sel4-initialize-tls" version = "0.1.0" dependencies = [ "cfg-if", @@ -2457,7 +2457,7 @@ dependencies = [ "cfg-if", "sel4", "sel4-elf-header", - "sel4-initialize-tls-on-stack", + "sel4-initialize-tls", "sel4-panicking-env", "unwinding", ] @@ -2550,7 +2550,6 @@ dependencies = [ "sel4-backtrace-simple", "sel4-dlmalloc", "sel4-immediate-sync-once-cell", - "sel4-initialize-tls-on-stack", "sel4-panicking", "sel4-panicking-env", "sel4-runtime-common", diff --git a/Cargo.toml b/Cargo.toml index 17921a816..81e608f49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,7 +94,7 @@ members = [ "crates/sel4-hal-adapters", "crates/sel4-immediate-sync-once-cell", "crates/sel4-immutable-cell", - "crates/sel4-initialize-tls-on-stack", + "crates/sel4-initialize-tls", "crates/sel4-kernel-loader", "crates/sel4-kernel-loader/add-payload", "crates/sel4-kernel-loader/config-types", diff --git a/crates/private/support/sel4-simple-task/runtime/Cargo.nix b/crates/private/support/sel4-simple-task/runtime/Cargo.nix index 8f47be387..5ed0c91aa 100644 --- a/crates/private/support/sel4-simple-task/runtime/Cargo.nix +++ b/crates/private/support/sel4-simple-task/runtime/Cargo.nix @@ -20,7 +20,6 @@ mk { sel4-immediate-sync-once-cell sel4-panicking sel4-panicking-env - sel4-initialize-tls-on-stack sel4-simple-task-runtime-config-types sel4-simple-task-runtime-macros sel4-simple-task-threading diff --git a/crates/private/support/sel4-simple-task/runtime/Cargo.toml b/crates/private/support/sel4-simple-task/runtime/Cargo.toml index 163b5e7e7..7f9303cf9 100644 --- a/crates/private/support/sel4-simple-task/runtime/Cargo.toml +++ b/crates/private/support/sel4-simple-task/runtime/Cargo.toml @@ -33,7 +33,6 @@ sel4-backtrace = { path = "../../../../sel4-backtrace", features = ["unwinding", sel4-backtrace-simple = { path = "../../../../sel4-backtrace/simple" } sel4-dlmalloc = { path = "../../../../sel4-dlmalloc" } sel4-immediate-sync-once-cell = { path = "../../../../sel4-immediate-sync-once-cell" } -sel4-initialize-tls-on-stack = { path = "../../../../sel4-initialize-tls-on-stack" } sel4-panicking = { path = "../../../../sel4-panicking" } sel4-panicking-env = { path = "../../../../sel4-panicking/env" } sel4-runtime-common = { path = "../../../../sel4-runtime-common", features = ["tls", "unwinding"] } diff --git a/crates/sel4-initialize-tls-on-stack/Cargo.nix b/crates/sel4-initialize-tls/Cargo.nix similarity index 69% rename from crates/sel4-initialize-tls-on-stack/Cargo.nix rename to crates/sel4-initialize-tls/Cargo.nix index 12d5c0138..1d7d3014d 100644 --- a/crates/sel4-initialize-tls-on-stack/Cargo.nix +++ b/crates/sel4-initialize-tls/Cargo.nix @@ -7,8 +7,11 @@ { mk, localCrates, versions }: mk { - package.name = "sel4-initialize-tls-on-stack"; + package.name = "sel4-initialize-tls"; dependencies = { inherit (versions) cfg-if; }; + features = { + on-stack = []; + }; } diff --git a/crates/sel4-initialize-tls-on-stack/Cargo.toml b/crates/sel4-initialize-tls/Cargo.toml similarity index 89% rename from crates/sel4-initialize-tls-on-stack/Cargo.toml rename to crates/sel4-initialize-tls/Cargo.toml index 56a829cab..26195c523 100644 --- a/crates/sel4-initialize-tls-on-stack/Cargo.toml +++ b/crates/sel4-initialize-tls/Cargo.toml @@ -10,11 +10,14 @@ # [package] -name = "sel4-initialize-tls-on-stack" +name = "sel4-initialize-tls" version = "0.1.0" authors = ["Nick Spinale "] edition = "2021" license = "BSD-2-Clause" +[features] +on-stack = [] + [dependencies] cfg-if = "1.0.0" diff --git a/crates/sel4-initialize-tls-on-stack/src/lib.rs b/crates/sel4-initialize-tls/src/lib.rs similarity index 100% rename from crates/sel4-initialize-tls-on-stack/src/lib.rs rename to crates/sel4-initialize-tls/src/lib.rs diff --git a/crates/sel4-runtime-common/Cargo.nix b/crates/sel4-runtime-common/Cargo.nix index 8461ef8ae..c9636d70a 100644 --- a/crates/sel4-runtime-common/Cargo.nix +++ b/crates/sel4-runtime-common/Cargo.nix @@ -12,13 +12,13 @@ mk { inherit (versions) cfg-if; inherit (localCrates) sel4-panicking-env sel4-elf-header; sel4 = localCrates.sel4 // { default-features = false; optional = true; }; - sel4-initialize-tls-on-stack = localCrates.sel4-initialize-tls-on-stack // { optional = true; }; + sel4-initialize-tls = localCrates.sel4-initialize-tls // { features = [ "on-stack" ]; optional = true; }; }; target."cfg(not(target_arch = \"arm\"))".dependencies = { unwinding = unwindingWith [] // { optional = true; }; }; features = { - tls = [ "dep:sel4-initialize-tls-on-stack" "dep:sel4" ]; + tls = [ "dep:sel4-initialize-tls" "dep:sel4" ]; start = []; }; } diff --git a/crates/sel4-runtime-common/Cargo.toml b/crates/sel4-runtime-common/Cargo.toml index e1dc62273..a94de4448 100644 --- a/crates/sel4-runtime-common/Cargo.toml +++ b/crates/sel4-runtime-common/Cargo.toml @@ -18,13 +18,13 @@ license = "BSD-2-Clause" [features] start = [] -tls = ["dep:sel4-initialize-tls-on-stack", "dep:sel4"] +tls = ["dep:sel4-initialize-tls", "dep:sel4"] [dependencies] cfg-if = "1.0.0" sel4 = { path = "../sel4", default-features = false, optional = true } sel4-elf-header = { path = "../sel4-elf-header" } -sel4-initialize-tls-on-stack = { path = "../sel4-initialize-tls-on-stack", optional = true } +sel4-initialize-tls = { path = "../sel4-initialize-tls", features = ["on-stack"], optional = true } sel4-panicking-env = { path = "../sel4-panicking/env" } [target."cfg(not(target_arch = \"arm\"))".dependencies.unwinding] diff --git a/crates/sel4-runtime-common/src/tls.rs b/crates/sel4-runtime-common/src/tls.rs index d458fd6e3..38fa10c46 100644 --- a/crates/sel4-runtime-common/src/tls.rs +++ b/crates/sel4-runtime-common/src/tls.rs @@ -8,11 +8,9 @@ use sel4_elf_header::PT_TLS; use sel4_panicking_env::abort; #[allow(unused_imports)] -use sel4_initialize_tls_on_stack::{ - SetThreadPointerFn, UncheckedTlsImage, DEFAULT_SET_THREAD_POINTER_FN, -}; +use sel4_initialize_tls::{SetThreadPointerFn, UncheckedTlsImage, DEFAULT_SET_THREAD_POINTER_FN}; -pub use sel4_initialize_tls_on_stack::{ContArg, ContFn}; +pub use sel4_initialize_tls::{ContArg, ContFn}; use crate::locate_phdrs; From 778b1bbcab52b4d31cac2b524745d447874ae44a Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Fri, 23 Feb 2024 20:33:51 +0000 Subject: [PATCH 4/7] crates/sel4-initialize-tls: Refactor module structure Signed-off-by: Nick Spinale --- crates/sel4-initialize-tls/src/lib.rs | 223 +------------------- crates/sel4-initialize-tls/src/on_stack.rs | 227 +++++++++++++++++++++ 2 files changed, 233 insertions(+), 217 deletions(-) create mode 100644 crates/sel4-initialize-tls/src/on_stack.rs diff --git a/crates/sel4-initialize-tls/src/lib.rs b/crates/sel4-initialize-tls/src/lib.rs index f9e6e8997..46ff720e4 100644 --- a/crates/sel4-initialize-tls/src/lib.rs +++ b/crates/sel4-initialize-tls/src/lib.rs @@ -4,14 +4,6 @@ // SPDX-License-Identifier: BSD-2-Clause // -#![no_std] - -use core::arch::{asm, global_asm}; -use core::ptr; -use core::slice; - -use cfg_if::cfg_if; - // NOTE // // - aarch64 and arm use variant 1 defined in [1][2]. @@ -23,28 +15,15 @@ use cfg_if::cfg_if; // [2] https://fuchsia.dev/fuchsia-src/development/kernel/threads/tls#implementation // [3] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#thread-local-storage -const STACK_ALIGNMENT: usize = { - cfg_if! { - if #[cfg(any( - target_arch = "aarch64", - target_arch = "riscv32", - target_arch = "riscv64", - target_arch = "x86_64", - ))] { - 16 - } else if #[cfg(target_arch = "arm")] { - 8 - } else { - compile_error!("unsupported architecture") - } - } -}; +#![no_std] -pub type SetThreadPointerFn = unsafe extern "C" fn(thread_pointer: usize); +use core::slice; -pub type ContFn = unsafe extern "C" fn(cont_arg: *mut ContArg) -> !; +#[cfg(feature = "on-stack")] +mod on_stack; -pub enum ContArg {} +#[cfg(feature = "on-stack")] +pub use on_stack::*; #[derive(Debug, Clone, PartialEq, Eq)] pub struct UncheckedTlsImage { @@ -79,49 +58,6 @@ pub struct TlsImage { } impl TlsImage { - #[allow(clippy::missing_safety_doc)] - pub unsafe fn initialize_on_stack_and_continue( - &self, - set_thread_pointer_fn: SetThreadPointerFn, - cont_fn: ContFn, - cont_arg: *mut ContArg, - ) -> ! { - let args = InternalContArgs { - tls_image: ptr::addr_of!(*self), - set_thread_pointer_fn, - cont_fn, - cont_arg, - }; - let segment_size = self.memsz; - let segment_align_down_mask = !(self.align - 1); - let stack_align_down_mask = !(STACK_ALIGNMENT - 1); - __sel4_initialize_tls_on_stack__reserve( - ptr::addr_of!(args), - segment_size, - segment_align_down_mask, - stack_align_down_mask, - ) - } - - unsafe fn continue_with( - &self, - set_thread_pointer_fn: SetThreadPointerFn, - cont_fn: ContFn, - cont_arg: *mut ContArg, - thread_pointer: usize, - tls_base_addr: usize, - ) -> ! { - self.initialize(tls_base_addr); - - if cfg!(target_arch = "x86_64") { - (thread_pointer as *mut usize).write(thread_pointer); - } - - (set_thread_pointer_fn)(thread_pointer); - - (cont_fn)(cont_arg) - } - unsafe fn initialize(&self, tls_base_addr: usize) { let image_data_window = slice::from_raw_parts(self.vaddr as *mut u8, self.filesz); let tls_window = slice::from_raw_parts_mut(tls_base_addr as *mut u8, self.memsz); @@ -130,150 +66,3 @@ impl TlsImage { tbss.fill(0); } } - -#[repr(C)] -#[derive(Debug, Clone, PartialEq, Eq)] -struct InternalContArgs { - tls_image: *const TlsImage, - set_thread_pointer_fn: SetThreadPointerFn, - cont_fn: ContFn, - cont_arg: *mut ContArg, -} - -#[no_mangle] -unsafe extern "C" fn __sel4_initialize_tls_on_stack__continue( - args: *const InternalContArgs, - thread_pointer: usize, - tls_base_addr: usize, -) -> ! { - let args = args.as_ref().unwrap(); - let tls_image = args.tls_image.as_ref().unwrap(); - tls_image.continue_with( - args.set_thread_pointer_fn, - args.cont_fn, - args.cont_arg, - thread_pointer, - tls_base_addr, - ) -} - -extern "C" { - fn __sel4_initialize_tls_on_stack__reserve( - args: *const InternalContArgs, - segment_size: usize, - segment_align_down_mask: usize, - stack_align_down_mask: usize, - ) -> !; -} - -macro_rules! common_asm { - () => { - r#" - .extern __sel4_initialize_tls_on_stack__continue - - .global __sel4_initialize_tls_on_stack__reserve - - .section .text - - __sel4_initialize_tls_on_stack__reserve: - "# - }; -} - -cfg_if! { - if #[cfg(target_arch = "aarch64")] { - global_asm! { - common_asm!(), - r#" - mov x9, sp - sub x9, x9, x1 // x1: segment_size - and x9, x9, x2 // x2: segment_align_down_mask - mov x10, x9 // save tls_base_addr for later - sub x9, x9, #16 // reserve for TCB - and x9, x9, x2 // x2: segment_align_down_mask - mov x11, x9 // save thread_pointer for later - and x9, x9, x3 // x3: stack_align_down_mask - mov sp, x9 - mov x1, x11 // pass thread_pointer to continuation - mov x2, x10 // pass tls_base_addr to continuation - b __sel4_initialize_tls_on_stack__continue - "# - } - } else if #[cfg(target_arch = "arm")] { - global_asm! { - common_asm!(), - r#" - mov r4, sp - sub r4, r4, r1 // r1: segment_size - and r4, r4, r2 // r2: segment_align_down_mask - mov r5, r4 // save tls_base_addr for later - sub r4, r4, #8 // reserve for TCB - and r4, r4, r2 // r2: segment_align_down_mask - mov r6, r4 // save thread_pointer for later - and r4, r4, r3 // r3: stack_align_down_mask - mov sp, r4 - mov r1, r6 // pass thread_pointer to continuation - mov r2, r5 // pass tls_base_addr to continuation - b __sel4_initialize_tls_on_stack__continue - "# - } - } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { - global_asm! { - common_asm!(), - r#" - mv t0, sp - sub t0, t0, a1 // a1: segment_size - and t0, t0, a2 // a2: segment_align_down_mask - mv t1, t0 // save thread_pointer and tls_base_addr, which are equal, for later - and t0, t0, a3 // a3: stack_align_down_mask - mv sp, t0 - mv a1, t1 // pass thread_pointer to continuation - mv a2, t1 // pass tls_base_addr to continuation - j __sel4_initialize_tls_on_stack__continue - "# - } - } else if #[cfg(target_arch = "x86_64")] { - global_asm! { - common_asm!(), - r#" - mov r10, rsp - sub r10, 0x8 // reserve for TCB (TODO is 8 bytes enough?) - and r10, rdx // rdx: segment_align_down_mask - mov r11, r10 // save thread_pointer for later - sub r10, rsi // rsi: segment_size - and r10, rdx // rdx: segment_align_down_mask - mov rax, r10 // save tls_base_addr for later - and r10, rcx // rcx: stack_align_down_mask - mov rsp, r10 - mov rsi, r11 // pass thread_pointer to continuation - mov rdx, rax // pass tls_base_addr to continuation - mov rbp, rsp - sub rsp, 0x8 // stack must be 16-byte aligned before call - push rbp - call __sel4_initialize_tls_on_stack__continue - "# - } - } else { - compile_error!("unsupported architecture"); - } -} - -pub const DEFAULT_SET_THREAD_POINTER_FN: SetThreadPointerFn = default_set_thread_pointer; - -unsafe extern "C" fn default_set_thread_pointer(thread_pointer: usize) { - let val = thread_pointer; - - cfg_if! { - if #[cfg(target_arch = "aarch64")] { - asm!("msr tpidr_el0, {val}", val = in(reg) val); - } else if #[cfg(target_arch = "arm")] { - asm!("mcr p15, 0, {val}, c13, c0, 2", val = in(reg) val); - } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { - asm!("mv tp, {val}", val = in(reg) val); - } else if #[cfg(target_arch = "x86_64")] { - asm!("wrfsbase {val}", val = in(reg) val); - } else { - compile_error!("unsupported architecture"); - } - } -} diff --git a/crates/sel4-initialize-tls/src/on_stack.rs b/crates/sel4-initialize-tls/src/on_stack.rs new file mode 100644 index 000000000..25ef2a97c --- /dev/null +++ b/crates/sel4-initialize-tls/src/on_stack.rs @@ -0,0 +1,227 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use core::arch::{asm, global_asm}; +use core::ptr; + +use cfg_if::cfg_if; + +use crate::TlsImage; + +const STACK_ALIGNMENT: usize = { + cfg_if! { + if #[cfg(any( + target_arch = "aarch64", + target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "x86_64", + ))] { + 16 + } else if #[cfg(target_arch = "arm")] { + 8 + } else { + compile_error!("unsupported architecture") + } + } +}; + +pub type SetThreadPointerFn = unsafe extern "C" fn(thread_pointer: usize); + +pub type ContFn = unsafe extern "C" fn(cont_arg: *mut ContArg) -> !; + +pub enum ContArg {} + +impl TlsImage { + #[allow(clippy::missing_safety_doc)] + pub unsafe fn initialize_on_stack_and_continue( + &self, + set_thread_pointer_fn: SetThreadPointerFn, + cont_fn: ContFn, + cont_arg: *mut ContArg, + ) -> ! { + let args = InternalContArgs { + tls_image: ptr::addr_of!(*self), + set_thread_pointer_fn, + cont_fn, + cont_arg, + }; + let segment_size = self.memsz; + let segment_align_down_mask = !(self.align - 1); + let stack_align_down_mask = !(STACK_ALIGNMENT - 1); + __sel4_initialize_tls_on_stack__reserve( + ptr::addr_of!(args), + segment_size, + segment_align_down_mask, + stack_align_down_mask, + ) + } + + unsafe fn continue_with( + &self, + set_thread_pointer_fn: SetThreadPointerFn, + cont_fn: ContFn, + cont_arg: *mut ContArg, + thread_pointer: usize, + tls_base_addr: usize, + ) -> ! { + self.initialize(tls_base_addr); + + if cfg!(target_arch = "x86_64") { + (thread_pointer as *mut usize).write(thread_pointer); + } + + (set_thread_pointer_fn)(thread_pointer); + + (cont_fn)(cont_arg) + } +} + +#[repr(C)] +#[derive(Debug, Clone, PartialEq, Eq)] +struct InternalContArgs { + tls_image: *const TlsImage, + set_thread_pointer_fn: SetThreadPointerFn, + cont_fn: ContFn, + cont_arg: *mut ContArg, +} + +#[no_mangle] +unsafe extern "C" fn __sel4_initialize_tls_on_stack__continue( + args: *const InternalContArgs, + thread_pointer: usize, + tls_base_addr: usize, +) -> ! { + let args = args.as_ref().unwrap(); + let tls_image = args.tls_image.as_ref().unwrap(); + tls_image.continue_with( + args.set_thread_pointer_fn, + args.cont_fn, + args.cont_arg, + thread_pointer, + tls_base_addr, + ) +} + +extern "C" { + fn __sel4_initialize_tls_on_stack__reserve( + args: *const InternalContArgs, + segment_size: usize, + segment_align_down_mask: usize, + stack_align_down_mask: usize, + ) -> !; +} + +macro_rules! common_asm { + () => { + r#" + .extern __sel4_initialize_tls_on_stack__continue + + .global __sel4_initialize_tls_on_stack__reserve + + .section .text + + __sel4_initialize_tls_on_stack__reserve: + "# + }; +} + +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + global_asm! { + common_asm!(), + r#" + mov x9, sp + sub x9, x9, x1 // x1: segment_size + and x9, x9, x2 // x2: segment_align_down_mask + mov x10, x9 // save tls_base_addr for later + sub x9, x9, #16 // reserve for TCB + and x9, x9, x2 // x2: segment_align_down_mask + mov x11, x9 // save thread_pointer for later + and x9, x9, x3 // x3: stack_align_down_mask + mov sp, x9 + mov x1, x11 // pass thread_pointer to continuation + mov x2, x10 // pass tls_base_addr to continuation + b __sel4_initialize_tls_on_stack__continue + "# + } + } else if #[cfg(target_arch = "arm")] { + global_asm! { + common_asm!(), + r#" + mov r4, sp + sub r4, r4, r1 // r1: segment_size + and r4, r4, r2 // r2: segment_align_down_mask + mov r5, r4 // save tls_base_addr for later + sub r4, r4, #8 // reserve for TCB + and r4, r4, r2 // r2: segment_align_down_mask + mov r6, r4 // save thread_pointer for later + and r4, r4, r3 // r3: stack_align_down_mask + mov sp, r4 + mov r1, r6 // pass thread_pointer to continuation + mov r2, r5 // pass tls_base_addr to continuation + b __sel4_initialize_tls_on_stack__continue + "# + } + } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + global_asm! { + common_asm!(), + r#" + mv t0, sp + sub t0, t0, a1 // a1: segment_size + and t0, t0, a2 // a2: segment_align_down_mask + mv t1, t0 // save thread_pointer and tls_base_addr, which are equal, for later + and t0, t0, a3 // a3: stack_align_down_mask + mv sp, t0 + mv a1, t1 // pass thread_pointer to continuation + mv a2, t1 // pass tls_base_addr to continuation + j __sel4_initialize_tls_on_stack__continue + "# + } + } else if #[cfg(target_arch = "x86_64")] { + global_asm! { + common_asm!(), + r#" + mov r10, rsp + sub r10, 0x8 // reserve for TCB (TODO is 8 bytes enough?) + and r10, rdx // rdx: segment_align_down_mask + mov r11, r10 // save thread_pointer for later + sub r10, rsi // rsi: segment_size + and r10, rdx // rdx: segment_align_down_mask + mov rax, r10 // save tls_base_addr for later + and r10, rcx // rcx: stack_align_down_mask + mov rsp, r10 + mov rsi, r11 // pass thread_pointer to continuation + mov rdx, rax // pass tls_base_addr to continuation + mov rbp, rsp + sub rsp, 0x8 // stack must be 16-byte aligned before call + push rbp + call __sel4_initialize_tls_on_stack__continue + "# + } + } else { + compile_error!("unsupported architecture"); + } +} + +pub const DEFAULT_SET_THREAD_POINTER_FN: SetThreadPointerFn = default_set_thread_pointer; + +unsafe extern "C" fn default_set_thread_pointer(thread_pointer: usize) { + let val = thread_pointer; + + cfg_if! { + if #[cfg(target_arch = "aarch64")] { + asm!("msr tpidr_el0, {val}", val = in(reg) val); + } else if #[cfg(target_arch = "arm")] { + asm!("mcr p15, 0, {val}, c13, c0, 2", val = in(reg) val); + } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + asm!("mv tp, {val}", val = in(reg) val); + } else if #[cfg(target_arch = "x86_64")] { + asm!("wrfsbase {val}", val = in(reg) val); + } else { + compile_error!("unsupported architecture"); + } + } +} From c3b3ba6add092cdd3fd2abde380f997e70e43206 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Sat, 24 Feb 2024 23:35:44 +0000 Subject: [PATCH 5/7] crates/sel4-initialize-tls: Improve design Signed-off-by: Nick Spinale --- crates/sel4-initialize-tls/Cargo.nix | 2 +- crates/sel4-initialize-tls/src/lib.rs | 94 +++++++- crates/sel4-initialize-tls/src/on_stack.rs | 227 ------------------ .../sel4-initialize-tls/src/on_stack/mod.rs | 105 ++++++++ .../src/on_stack/reserve.rs | 118 +++++++++ crates/sel4-runtime-common/src/lib.rs | 1 + crates/sel4-runtime-common/src/tls.rs | 2 +- 7 files changed, 317 insertions(+), 232 deletions(-) delete mode 100644 crates/sel4-initialize-tls/src/on_stack.rs create mode 100644 crates/sel4-initialize-tls/src/on_stack/mod.rs create mode 100644 crates/sel4-initialize-tls/src/on_stack/reserve.rs diff --git a/crates/sel4-initialize-tls/Cargo.nix b/crates/sel4-initialize-tls/Cargo.nix index 1d7d3014d..6e22f34f8 100644 --- a/crates/sel4-initialize-tls/Cargo.nix +++ b/crates/sel4-initialize-tls/Cargo.nix @@ -4,7 +4,7 @@ # SPDX-License-Identifier: BSD-2-Clause # -{ mk, localCrates, versions }: +{ mk, versions }: mk { package.name = "sel4-initialize-tls"; diff --git a/crates/sel4-initialize-tls/src/lib.rs b/crates/sel4-initialize-tls/src/lib.rs index 46ff720e4..cde67b1ad 100644 --- a/crates/sel4-initialize-tls/src/lib.rs +++ b/crates/sel4-initialize-tls/src/lib.rs @@ -17,8 +17,19 @@ #![no_std] +use core::alloc::Layout; +use core::mem; use core::slice; +#[cfg(not(any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "x86_64", +)))] +compile_error!("unsupported architecture"); + #[cfg(feature = "on-stack")] mod on_stack; @@ -58,11 +69,88 @@ pub struct TlsImage { } impl TlsImage { - unsafe fn initialize(&self, tls_base_addr: usize) { + pub fn reservation_layout(&self) -> TlsReservationLayout { + TlsReservationLayout::from_segment_layout(self.segment_layout()) + } + + fn segment_layout(&self) -> Layout { + Layout::from_size_align(self.memsz, self.align).unwrap() + } + + pub unsafe fn initialize_tls_reservation(&self, tls_reservation_start: *mut u8) { + let reservation_layout = self.reservation_layout(); + let image_data_window = slice::from_raw_parts(self.vaddr as *mut u8, self.filesz); - let tls_window = slice::from_raw_parts_mut(tls_base_addr as *mut u8, self.memsz); - let (tdata, tbss) = tls_window.split_at_mut(self.filesz); + + let segment_start = + tls_reservation_start.wrapping_byte_add(reservation_layout.segment_offset()); + let segment_window = slice::from_raw_parts_mut(segment_start as *mut u8, self.memsz); + let (tdata, tbss) = segment_window.split_at_mut(self.filesz); + tdata.copy_from_slice(image_data_window); tbss.fill(0); + + if cfg!(target_arch = "x86_64") { + let thread_pointer = + tls_reservation_start.wrapping_byte_add(reservation_layout.thread_pointer_offset()); + (thread_pointer.cast::<*mut u8>()).write(thread_pointer); + } + } +} + +#[derive(Copy, Clone, Debug)] +pub struct TlsReservationLayout { + footprint: Layout, + segment_offset: usize, + thread_pointer_offset: usize, +} + +impl TlsReservationLayout { + fn from_segment_layout(segment_layout: Layout) -> Self { + if cfg!(any(target_arch = "arm", target_arch = "aarch64")) { + let tcb_size = 2 * mem::size_of::(); + let segment_offset = tcb_size.next_multiple_of(segment_layout.align()); + Self { + footprint: Layout::from_size_align( + segment_offset + segment_layout.size(), + segment_layout.align().max(tcb_size), + ) + .unwrap(), + segment_offset, + thread_pointer_offset: 0, + } + } else if cfg!(any(target_arch = "riscv32", target_arch = "riscv64")) { + Self { + footprint: Layout::from_size_align(segment_layout.size(), segment_layout.align()) + .unwrap(), + segment_offset: 0, + thread_pointer_offset: 0, + } + } else if cfg!(target_arch = "x86_64") { + let tcb_size = 2 * mem::size_of::(); // could probably get away with just 1x word size + Self { + footprint: Layout::from_size_align( + segment_layout.size() + tcb_size, + segment_layout.align(), + ) + .unwrap(), + segment_offset: 0, + thread_pointer_offset: segment_layout.size(), + } + } else { + unreachable!(); + } + } + + pub fn footprint(&self) -> Layout { + self.footprint + } + + pub fn segment_offset(&self) -> usize { + self.segment_offset + } + + pub fn thread_pointer_offset(&self) -> usize { + self.thread_pointer_offset } } diff --git a/crates/sel4-initialize-tls/src/on_stack.rs b/crates/sel4-initialize-tls/src/on_stack.rs deleted file mode 100644 index 25ef2a97c..000000000 --- a/crates/sel4-initialize-tls/src/on_stack.rs +++ /dev/null @@ -1,227 +0,0 @@ -// -// Copyright 2024, Colias Group, LLC -// -// SPDX-License-Identifier: BSD-2-Clause -// - -use core::arch::{asm, global_asm}; -use core::ptr; - -use cfg_if::cfg_if; - -use crate::TlsImage; - -const STACK_ALIGNMENT: usize = { - cfg_if! { - if #[cfg(any( - target_arch = "aarch64", - target_arch = "riscv32", - target_arch = "riscv64", - target_arch = "x86_64", - ))] { - 16 - } else if #[cfg(target_arch = "arm")] { - 8 - } else { - compile_error!("unsupported architecture") - } - } -}; - -pub type SetThreadPointerFn = unsafe extern "C" fn(thread_pointer: usize); - -pub type ContFn = unsafe extern "C" fn(cont_arg: *mut ContArg) -> !; - -pub enum ContArg {} - -impl TlsImage { - #[allow(clippy::missing_safety_doc)] - pub unsafe fn initialize_on_stack_and_continue( - &self, - set_thread_pointer_fn: SetThreadPointerFn, - cont_fn: ContFn, - cont_arg: *mut ContArg, - ) -> ! { - let args = InternalContArgs { - tls_image: ptr::addr_of!(*self), - set_thread_pointer_fn, - cont_fn, - cont_arg, - }; - let segment_size = self.memsz; - let segment_align_down_mask = !(self.align - 1); - let stack_align_down_mask = !(STACK_ALIGNMENT - 1); - __sel4_initialize_tls_on_stack__reserve( - ptr::addr_of!(args), - segment_size, - segment_align_down_mask, - stack_align_down_mask, - ) - } - - unsafe fn continue_with( - &self, - set_thread_pointer_fn: SetThreadPointerFn, - cont_fn: ContFn, - cont_arg: *mut ContArg, - thread_pointer: usize, - tls_base_addr: usize, - ) -> ! { - self.initialize(tls_base_addr); - - if cfg!(target_arch = "x86_64") { - (thread_pointer as *mut usize).write(thread_pointer); - } - - (set_thread_pointer_fn)(thread_pointer); - - (cont_fn)(cont_arg) - } -} - -#[repr(C)] -#[derive(Debug, Clone, PartialEq, Eq)] -struct InternalContArgs { - tls_image: *const TlsImage, - set_thread_pointer_fn: SetThreadPointerFn, - cont_fn: ContFn, - cont_arg: *mut ContArg, -} - -#[no_mangle] -unsafe extern "C" fn __sel4_initialize_tls_on_stack__continue( - args: *const InternalContArgs, - thread_pointer: usize, - tls_base_addr: usize, -) -> ! { - let args = args.as_ref().unwrap(); - let tls_image = args.tls_image.as_ref().unwrap(); - tls_image.continue_with( - args.set_thread_pointer_fn, - args.cont_fn, - args.cont_arg, - thread_pointer, - tls_base_addr, - ) -} - -extern "C" { - fn __sel4_initialize_tls_on_stack__reserve( - args: *const InternalContArgs, - segment_size: usize, - segment_align_down_mask: usize, - stack_align_down_mask: usize, - ) -> !; -} - -macro_rules! common_asm { - () => { - r#" - .extern __sel4_initialize_tls_on_stack__continue - - .global __sel4_initialize_tls_on_stack__reserve - - .section .text - - __sel4_initialize_tls_on_stack__reserve: - "# - }; -} - -cfg_if! { - if #[cfg(target_arch = "aarch64")] { - global_asm! { - common_asm!(), - r#" - mov x9, sp - sub x9, x9, x1 // x1: segment_size - and x9, x9, x2 // x2: segment_align_down_mask - mov x10, x9 // save tls_base_addr for later - sub x9, x9, #16 // reserve for TCB - and x9, x9, x2 // x2: segment_align_down_mask - mov x11, x9 // save thread_pointer for later - and x9, x9, x3 // x3: stack_align_down_mask - mov sp, x9 - mov x1, x11 // pass thread_pointer to continuation - mov x2, x10 // pass tls_base_addr to continuation - b __sel4_initialize_tls_on_stack__continue - "# - } - } else if #[cfg(target_arch = "arm")] { - global_asm! { - common_asm!(), - r#" - mov r4, sp - sub r4, r4, r1 // r1: segment_size - and r4, r4, r2 // r2: segment_align_down_mask - mov r5, r4 // save tls_base_addr for later - sub r4, r4, #8 // reserve for TCB - and r4, r4, r2 // r2: segment_align_down_mask - mov r6, r4 // save thread_pointer for later - and r4, r4, r3 // r3: stack_align_down_mask - mov sp, r4 - mov r1, r6 // pass thread_pointer to continuation - mov r2, r5 // pass tls_base_addr to continuation - b __sel4_initialize_tls_on_stack__continue - "# - } - } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { - global_asm! { - common_asm!(), - r#" - mv t0, sp - sub t0, t0, a1 // a1: segment_size - and t0, t0, a2 // a2: segment_align_down_mask - mv t1, t0 // save thread_pointer and tls_base_addr, which are equal, for later - and t0, t0, a3 // a3: stack_align_down_mask - mv sp, t0 - mv a1, t1 // pass thread_pointer to continuation - mv a2, t1 // pass tls_base_addr to continuation - j __sel4_initialize_tls_on_stack__continue - "# - } - } else if #[cfg(target_arch = "x86_64")] { - global_asm! { - common_asm!(), - r#" - mov r10, rsp - sub r10, 0x8 // reserve for TCB (TODO is 8 bytes enough?) - and r10, rdx // rdx: segment_align_down_mask - mov r11, r10 // save thread_pointer for later - sub r10, rsi // rsi: segment_size - and r10, rdx // rdx: segment_align_down_mask - mov rax, r10 // save tls_base_addr for later - and r10, rcx // rcx: stack_align_down_mask - mov rsp, r10 - mov rsi, r11 // pass thread_pointer to continuation - mov rdx, rax // pass tls_base_addr to continuation - mov rbp, rsp - sub rsp, 0x8 // stack must be 16-byte aligned before call - push rbp - call __sel4_initialize_tls_on_stack__continue - "# - } - } else { - compile_error!("unsupported architecture"); - } -} - -pub const DEFAULT_SET_THREAD_POINTER_FN: SetThreadPointerFn = default_set_thread_pointer; - -unsafe extern "C" fn default_set_thread_pointer(thread_pointer: usize) { - let val = thread_pointer; - - cfg_if! { - if #[cfg(target_arch = "aarch64")] { - asm!("msr tpidr_el0, {val}", val = in(reg) val); - } else if #[cfg(target_arch = "arm")] { - asm!("mcr p15, 0, {val}, c13, c0, 2", val = in(reg) val); - } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { - asm!("mv tp, {val}", val = in(reg) val); - } else if #[cfg(target_arch = "x86_64")] { - asm!("wrfsbase {val}", val = in(reg) val); - } else { - compile_error!("unsupported architecture"); - } - } -} diff --git a/crates/sel4-initialize-tls/src/on_stack/mod.rs b/crates/sel4-initialize-tls/src/on_stack/mod.rs new file mode 100644 index 000000000..2ba1f43c0 --- /dev/null +++ b/crates/sel4-initialize-tls/src/on_stack/mod.rs @@ -0,0 +1,105 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use core::arch::asm; +use core::ptr; + +use cfg_if::cfg_if; + +use crate::TlsImage; + +mod reserve; + +use reserve::{reserve_on_stack, ReserveOnStackContArg}; + +pub type ContFn = unsafe extern "C" fn(cont_arg: *mut ContArg) -> !; + +pub enum ContArg {} + +impl TlsImage { + #[allow(clippy::missing_safety_doc)] + pub unsafe fn initialize_on_stack( + &self, + set_thread_pointer_fn: SetThreadPointerFn, + cont_fn: ContFn, + cont_arg: *mut ContArg, + ) -> ! { + let mut cont_arg = InternalContArg { + tls_image: ptr::addr_of!(*self), + set_thread_pointer_fn, + cont_fn, + cont_arg, + }; + reserve_on_stack( + self.reservation_layout().footprint(), + reserve_on_stack_cont_fn, + ptr::addr_of_mut!(cont_arg).cast(), + ) + } + + unsafe fn continue_with( + &self, + tls_reservation_start: *mut u8, + set_thread_pointer_fn: SetThreadPointerFn, + cont_fn: ContFn, + cont_arg: *mut ContArg, + ) -> ! { + self.initialize_tls_reservation(tls_reservation_start); + + let thread_pointer = tls_reservation_start + .wrapping_byte_add(self.reservation_layout().thread_pointer_offset()); + + (set_thread_pointer_fn)(thread_pointer as usize); + + (cont_fn)(cont_arg) + } +} + +#[repr(C)] +#[derive(Debug, Clone, PartialEq, Eq)] +struct InternalContArg { + tls_image: *const TlsImage, + set_thread_pointer_fn: SetThreadPointerFn, + cont_fn: ContFn, + cont_arg: *mut ContArg, +} + +unsafe extern "C" fn reserve_on_stack_cont_fn( + reservation_start: *mut u8, + arg: *mut ReserveOnStackContArg, +) -> ! { + let arg = arg.cast::().as_ref().unwrap(); + let tls_image = arg.tls_image.as_ref().unwrap(); + tls_image.continue_with( + reservation_start, + arg.set_thread_pointer_fn, + arg.cont_fn, + arg.cont_arg, + ) +} + +pub type SetThreadPointerFn = unsafe extern "C" fn(thread_pointer: usize); + +pub const DEFAULT_SET_THREAD_POINTER_FN: SetThreadPointerFn = default_set_thread_pointer; + +unsafe extern "C" fn default_set_thread_pointer(thread_pointer: usize) { + let val = thread_pointer; + + cfg_if! { + if #[cfg(target_arch = "aarch64")] { + asm!("msr tpidr_el0, {val}", val = in(reg) val); + } else if #[cfg(target_arch = "arm")] { + // TODO which register to use must match with LLVM -mtp, I think + asm!("mcr p15, 0, {val}, c13, c0, 2", val = in(reg) val); + } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + asm!("mv tp, {val}", val = in(reg) val); + } else if #[cfg(target_arch = "x86_64")] { + asm!("wrfsbase {val}", val = in(reg) val); + } else { + compile_error!("unsupported architecture"); + } + } +} diff --git a/crates/sel4-initialize-tls/src/on_stack/reserve.rs b/crates/sel4-initialize-tls/src/on_stack/reserve.rs new file mode 100644 index 000000000..d36a82c36 --- /dev/null +++ b/crates/sel4-initialize-tls/src/on_stack/reserve.rs @@ -0,0 +1,118 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use core::alloc::Layout; +use core::arch::global_asm; + +use cfg_if::cfg_if; + +pub(crate) type ReserveOnStackContFn = + unsafe extern "C" fn(reservation_start: *mut u8, cont_arg: *mut ReserveOnStackContArg) -> !; + +pub(crate) enum ReserveOnStackContArg {} + +pub(crate) unsafe fn reserve_on_stack( + layout: Layout, + cont_fn: ReserveOnStackContFn, + cont_arg: *mut ReserveOnStackContArg, +) -> ! { + let reservation_size = layout.size(); + let reservation_align_down_mask = !(layout.align() - 1); + __sel4_reserve_on_stack( + reservation_size, + reservation_align_down_mask, + cont_fn, + cont_arg, + ) +} + +extern "C" { + fn __sel4_reserve_on_stack( + reservation_size: usize, + reservation_align_down_mask: usize, + cont_fn: ReserveOnStackContFn, + cont_arg: *mut ReserveOnStackContArg, + ) -> !; +} + +macro_rules! common_asm { + () => { + r#" + .section .text + .global __sel4_reserve_on_stack + __sel4_reserve_on_stack: + "# + }; +} + +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + global_asm! { + common_asm!(), + r#" + mov x9, sp + sub x9, x9, x0 // x0: reservation_size + and x9, x9, x1 // x1: reservation_align_down_mask + mov x10, x9 // save reservation_start for later + and x9, x9, ~(16 - 1) // align stack + mov sp, x9 + mov x0, x10 // pass reservation_start + mov x1, x3 // pass cont_arg + br x2 // call cont_fn + "# + } + } else if #[cfg(target_arch = "arm")] { + global_asm! { + common_asm!(), + r#" + mov r4, sp + sub r4, r4, r0 // r0: reservation_size + and r4, r4, r1 // r1: reservation_align_down_mask + mov r6, r4 // save reservation_start for later + and r4, r4, ~(4 - 1) // align stack + mov sp, r4 + mov r0, r6 // pass reservation_start + mov r1, r3 // pass cont_arg + bx r2 // call cont_fn + "# + } + } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + global_asm! { + common_asm!(), + r#" + mv t0, sp + sub t0, t0, a0 // a0: reservation_size + and t0, t0, a1 // a1: reservation_align_down_mask + mv t1, t0 // save reservation_start for later + and t0, t0, ~(16 - 1) // align stack + mv sp, t0 + mv a0, t1 // pass reservation_start + mv a1, a3 // pass cont_arg + jr a2 // call cont_fn + "# + } + } else if #[cfg(target_arch = "x86_64")] { + global_asm! { + common_asm!(), + r#" + mov r10, rsp + sub r10, rdi // rdi: segment_size + and r10, rsi // rsi: segment_align_down_mask + mov rax, r10 // save reservation_start for later + and r10, ~(16 - 1) // align stack + mov rsp, r10 + mov rdi, rax // pass reservation_start + mov rsi, rcx // pass cont_arg + mov rbp, rsp + sub rsp, 0x8 // preserve stack alignment + push rbp + call rdx // call cont_fn + "# + } + } else { + compile_error!("unsupported architecture"); + } +} diff --git a/crates/sel4-runtime-common/src/lib.rs b/crates/sel4-runtime-common/src/lib.rs index a36dffa79..832599ed7 100644 --- a/crates/sel4-runtime-common/src/lib.rs +++ b/crates/sel4-runtime-common/src/lib.rs @@ -49,6 +49,7 @@ core::arch::global_asm! { .section .text __aeabi_read_tp: + // TODO which register to use must match with LLVM -mtp, I think mrc p15, 0, r0, c13, c0, 2 bx lr "# diff --git a/crates/sel4-runtime-common/src/tls.rs b/crates/sel4-runtime-common/src/tls.rs index 38fa10c46..0ce8e8568 100644 --- a/crates/sel4-runtime-common/src/tls.rs +++ b/crates/sel4-runtime-common/src/tls.rs @@ -29,7 +29,7 @@ pub unsafe fn initialize_tls_on_stack_and_continue(cont_fn: ContFn, cont_arg: *m unchecked .check() .unwrap_or_else(|| abort!("invalid TLS image: {unchecked:#x?}")) - .initialize_on_stack_and_continue(CHOSEN_SET_THREAD_POINTER_FN, cont_fn, cont_arg) + .initialize_on_stack(CHOSEN_SET_THREAD_POINTER_FN, cont_fn, cont_arg) } sel4::sel4_cfg_if! { From cbb8f84f68ef0cf7538e80c22976b959ca6e7049 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Sun, 25 Feb 2024 22:51:09 +0000 Subject: [PATCH 6/7] crates/sel4: Derive Default instance for IpcBuffer Signed-off-by: Nick Spinale --- crates/sel4/src/ipc_buffer.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/sel4/src/ipc_buffer.rs b/crates/sel4/src/ipc_buffer.rs index 0fde5433e..c69b755b2 100644 --- a/crates/sel4/src/ipc_buffer.rs +++ b/crates/sel4/src/ipc_buffer.rs @@ -11,6 +11,7 @@ use core::slice; use crate::{newtype_methods, sys, AbsoluteCPtr, CNode, Word}; /// Corresponds to `seL4_IPCBuffer`. +#[derive(Default)] #[repr(transparent)] pub struct IpcBuffer(sys::seL4_IPCBuffer); From 8293bb2ac6b1b01fea2b9f3937592326255b4393 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Thu, 22 Feb 2024 23:23:50 +0000 Subject: [PATCH 7/7] Add spawn-thread example Signed-off-by: Nick Spinale --- Cargo.lock | 11 + Cargo.toml | 1 + .../examples/root-task/spawn-thread/Cargo.nix | 20 ++ .../root-task/spawn-thread/Cargo.toml | 24 ++ .../root-task/spawn-thread/src/main.rs | 299 ++++++++++++++++++ hacking/nix/scope/world/instances/default.nix | 13 +- 6 files changed, 366 insertions(+), 2 deletions(-) create mode 100644 crates/examples/root-task/spawn-thread/Cargo.nix create mode 100644 crates/examples/root-task/spawn-thread/Cargo.toml create mode 100644 crates/examples/root-task/spawn-thread/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 2ec854029..4bacc2d68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2735,6 +2735,17 @@ dependencies = [ "managed", ] +[[package]] +name = "spawn-thread" +version = "0.1.0" +dependencies = [ + "cfg-if", + "sel4", + "sel4-elf-header", + "sel4-initialize-tls", + "sel4-root-task", +] + [[package]] name = "spin" version = "0.5.2" diff --git a/Cargo.toml b/Cargo.toml index 81e608f49..0deab4829 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ members = [ "crates/examples/root-task/example-root-task", "crates/examples/root-task/example-root-task-without-runtime", "crates/examples/root-task/hello", + "crates/examples/root-task/spawn-thread", "crates/private/meta", "crates/private/support/sel4-simple-task/config-types", "crates/private/support/sel4-simple-task/rpc", diff --git a/crates/examples/root-task/spawn-thread/Cargo.nix b/crates/examples/root-task/spawn-thread/Cargo.nix new file mode 100644 index 000000000..7f6fc9406 --- /dev/null +++ b/crates/examples/root-task/spawn-thread/Cargo.nix @@ -0,0 +1,20 @@ +# +# Copyright 2024, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# + +{ mk, versions, localCrates }: + +mk { + package.name = "spawn-thread"; + dependencies = { + inherit (versions) cfg-if; + inherit (localCrates) + sel4 + sel4-root-task + sel4-elf-header + sel4-initialize-tls + ; + }; +} diff --git a/crates/examples/root-task/spawn-thread/Cargo.toml b/crates/examples/root-task/spawn-thread/Cargo.toml new file mode 100644 index 000000000..95100b49a --- /dev/null +++ b/crates/examples/root-task/spawn-thread/Cargo.toml @@ -0,0 +1,24 @@ +# +# Copyright 2023, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# +# +# This file is generated from './Cargo.nix'. You can edit this file directly +# if you are not using this project's Cargo manifest management tools. +# See 'hacking/cargo-manifest-management/README.md' for more information. +# + +[package] +name = "spawn-thread" +version = "0.1.0" +authors = ["Nick Spinale "] +edition = "2021" +license = "BSD-2-Clause" + +[dependencies] +cfg-if = "1.0.0" +sel4 = { path = "../../../sel4" } +sel4-elf-header = { path = "../../../sel4-elf-header" } +sel4-initialize-tls = { path = "../../../sel4-initialize-tls" } +sel4-root-task = { path = "../../../sel4-root-task" } diff --git a/crates/examples/root-task/spawn-thread/src/main.rs b/crates/examples/root-task/spawn-thread/src/main.rs new file mode 100644 index 000000000..a6a4866fd --- /dev/null +++ b/crates/examples/root-task/spawn-thread/src/main.rs @@ -0,0 +1,299 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +#![no_std] +#![no_main] +#![feature(never_type)] + +extern crate alloc; + +use alloc::boxed::Box; +use core::cell::UnsafeCell; +use core::mem; +use core::ops::Range; +use core::panic::UnwindSafe; +use core::ptr; + +use cfg_if::cfg_if; + +use sel4::SizedFrameType; +use sel4_elf_header::{ElfHeader, PT_TLS}; +use sel4_initialize_tls::{TlsImage, TlsReservationLayout, UncheckedTlsImage}; +use sel4_root_task::{ + abort, panicking::catch_unwind, root_task, set_global_allocator_mutex_notification, Never, +}; + +static SECONDARY_THREAD_STACK: Stack<4096> = Stack::new(); + +static SECONDARY_THREAD_IPC_BUFFER_FRAME: IpcBufferFrame = IpcBufferFrame::new(); + +#[root_task(heap_size = 1024 * 64)] +fn main(bootinfo: &sel4::BootInfoPtr) -> sel4::Result { + sel4::debug_println!("In primary thread"); + + let (ut_ix, _desc) = bootinfo + .untyped_list() + .iter() + .enumerate() + .filter(|(_i, desc)| !desc.is_device()) + .max_by_key(|(_i, desc)| desc.size_bits()) + .unwrap(); + + let ut = bootinfo.untyped().index(ut_ix).cap(); + + let mut empty_slots = bootinfo + .empty() + .range() + .map(sel4::init_thread::Slot::from_index); + + let mut create_object = |blueprint| { + let slot = empty_slots.next().unwrap(); + ut.untyped_retype( + &blueprint, + &sel4::init_thread::slot::CNODE.cap().relative_self(), + slot.index(), + 1, + )?; + Ok(slot.cap()) + }; + + set_global_allocator_mutex_notification( + create_object(sel4::ObjectBlueprint::Notification)? + .downcast::(), + ); + + let inter_thread_nfn = create_object(sel4::ObjectBlueprint::Notification)? + .downcast::(); + + let secondary_thread_tcb = + create_object(sel4::ObjectBlueprint::Tcb)?.downcast::(); + + secondary_thread_tcb.tcb_configure( + sel4::init_thread::slot::NULL.cptr(), + sel4::init_thread::slot::CNODE.cap(), + sel4::CNodeCapData::new(0, 0), + sel4::init_thread::slot::VSPACE.cap(), + SECONDARY_THREAD_IPC_BUFFER_FRAME.ptr() as sel4::Word, + SECONDARY_THREAD_IPC_BUFFER_FRAME.cap(bootinfo), + )?; + + let secondary_thread_fn = SecondaryThreadFn::new(move || { + unsafe { sel4::set_ipc_buffer(SECONDARY_THREAD_IPC_BUFFER_FRAME.ptr().as_mut().unwrap()) } + sel4::debug_println!("In secondary thread"); + inter_thread_nfn.signal(); + secondary_thread_tcb.tcb_suspend().unwrap(); + unreachable!() + }); + + secondary_thread_tcb + .tcb_write_all_registers(true, &mut create_user_context(secondary_thread_fn))?; + + inter_thread_nfn.wait(); + + sel4::debug_println!("TEST_PASS"); + + sel4::init_thread::suspend_self() +} + +fn create_user_context(f: SecondaryThreadFn) -> sel4::UserContext { + let mut ctx = sel4::UserContext::default(); + + *ctx.sp_mut() = SECONDARY_THREAD_STACK.top().try_into().unwrap(); + *ctx.pc_mut() = secondary_thread_entrypoint as sel4::Word; + + *user_context_arg_mut(&mut ctx, 0) = f.into_arg(); + + let tls_reservation = TlsReservation::new(&get_tls_image()); + *user_context_thread_pointer_mut(&mut ctx) = tls_reservation.thread_pointer() as sel4::Word; + mem::forget(tls_reservation); + + cfg_if! { + if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + ctx.inner_mut().gp = riscv_get_gp(); + } + } + + ctx +} + +fn user_context_arg_mut(ctx: &mut sel4::UserContext, i: sel4::Word) -> &mut sel4::Word { + cfg_if! { + if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + ctx.gpr_a_mut(i) + } else { + ctx.gpr_mut(i) + } + } +} + +fn user_context_thread_pointer_mut(ctx: &mut sel4::UserContext) -> &mut sel4::Word { + cfg_if! { + if #[cfg(target_arch = "aarch64")] { + &mut ctx.inner_mut().tpidr_el0 + } else if #[cfg(target_arch = "arm")] { + &mut ctx.inner_mut().tpidrurw + } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + &mut ctx.inner_mut().tp + } else if #[cfg(target_arch = "x86_64")] { + &mut ctx.inner_mut().fs_base + } else { + compile_error!("unsupported architecture"); + } + } +} + +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] +fn riscv_get_gp() -> sel4::Word { + let val: sel4::Word; + unsafe { + core::arch::asm!("mv {}, gp", out(reg) val); + } + val +} + +// // // + +unsafe extern "C" fn secondary_thread_entrypoint(arg: sel4::Word) -> ! { + let f = SecondaryThreadFn::from_arg(arg); + let _ = catch_unwind(|| f.run()); + abort!("secondary thread panicked") +} + +struct SecondaryThreadFn(Box ! + UnwindSafe + Send + 'static>); + +impl SecondaryThreadFn { + fn new(f: impl FnOnce() -> ! + UnwindSafe + Send + 'static) -> Self { + Self(Box::new(f)) + } + + fn run(self) -> ! { + (self.0)() + } + + fn into_arg(self) -> sel4::Word { + Box::into_raw(Box::new(self)) as sel4::Word + } + + unsafe fn from_arg(arg: sel4::Word) -> Self { + *Box::from_raw(arg as *mut Self) + } +} + +// // // + +struct TlsReservation { + start: *mut u8, + layout: TlsReservationLayout, +} + +impl TlsReservation { + fn new(tls_image: &TlsImage) -> Self { + let layout = tls_image.reservation_layout(); + let start = unsafe { ::alloc::alloc::alloc(layout.footprint()) }; + unsafe { + tls_image.initialize_tls_reservation(start); + }; + Self { start, layout } + } + + fn thread_pointer(&self) -> usize { + (self.start as usize) + self.layout.thread_pointer_offset() + } +} + +impl Drop for TlsReservation { + fn drop(&mut self) { + unsafe { + ::alloc::alloc::dealloc(self.start, self.layout.footprint()); + } + } +} + +fn get_tls_image() -> TlsImage { + extern "C" { + static __ehdr_start: ElfHeader; + } + let phdrs = unsafe { + assert!(__ehdr_start.check_magic()); + __ehdr_start.locate_phdrs() + }; + let phdr = phdrs.iter().find(|phdr| phdr.p_type == PT_TLS).unwrap(); + let unchecked = UncheckedTlsImage { + vaddr: phdr.p_vaddr, + filesz: phdr.p_filesz, + memsz: phdr.p_memsz, + align: phdr.p_align, + }; + unchecked.check().unwrap() +} + +// // // + +#[repr(C, align(16))] +struct Stack(UnsafeCell<[u8; N]>); + +unsafe impl Sync for Stack {} + +impl Stack { + const fn new() -> Self { + Self(UnsafeCell::new([0; N])) + } + + fn top(&self) -> usize { + (self.0.get() as usize) + N + } +} + +// // // + +#[repr(C, align(4096))] +struct IpcBufferFrame(UnsafeCell<[u8; GRANULE_SIZE]>); + +unsafe impl Sync for IpcBufferFrame {} + +impl IpcBufferFrame { + const fn new() -> Self { + Self(UnsafeCell::new([0; GRANULE_SIZE])) + } + + const fn ptr(&self) -> *mut sel4::IpcBuffer { + self.0.get().cast() + } + + fn cap(&self, bootinfo: &sel4::BootInfo) -> sel4::Granule { + get_user_image_frame_slot(bootinfo, self.ptr() as usize).cap() + } +} + +fn get_user_image_frame_slot( + bootinfo: &sel4::BootInfo, + addr: usize, +) -> sel4::init_thread::Slot { + assert_eq!(addr % GRANULE_SIZE, 0); + let user_image_footprint = get_user_image_footprint(); + let num_user_frames = bootinfo.user_image_frames().len(); + assert_eq!(user_image_footprint.len(), num_user_frames * GRANULE_SIZE); + let ix = (addr - user_image_footprint.start) / GRANULE_SIZE; + bootinfo.user_image_frames().index(ix) +} + +fn get_user_image_footprint() -> Range { + extern "C" { + static __executable_start: u64; + static _end: u64; + } + unsafe { + let start = round_down(ptr::addr_of!(__executable_start) as usize, GRANULE_SIZE); + let end = (ptr::addr_of!(_end) as usize).next_multiple_of(GRANULE_SIZE); + start..end + } +} + +const fn round_down(n: usize, b: usize) -> usize { + n - n % b +} + +const GRANULE_SIZE: usize = sel4::cap_type::Granule::FRAME_SIZE.bytes(); diff --git a/hacking/nix/scope/world/instances/default.nix b/hacking/nix/scope/world/instances/default.nix index 559e0af36..f6385e6f9 100644 --- a/hacking/nix/scope/world/instances/default.nix +++ b/hacking/nix/scope/world/instances/default.nix @@ -90,6 +90,7 @@ in rec { examples.root-task.hello examples.root-task.example-root-task examples.root-task.example-root-task-without-runtime + examples.root-task.spawn-thread ]; allAutomationScripts = map @@ -321,9 +322,7 @@ in rec { release = false; }; }); - }; - root-task = { example-root-task = maybe haveFullRuntime (mkInstance { rootTask = mkTask { rootCrate = crates.example-root-task; @@ -344,6 +343,16 @@ in rec { canAutomateSimply = true; }; }); + + spawn-thread = maybe haveFullRuntime (mkInstance { + rootTask = mkTask { + rootCrate = crates.spawn-thread; + release = false; + }; + extraPlatformArgs = lib.optionalAttrs canSimulate { + canAutomateSimply = true; + }; + }); }; }; }