From 10e61662dd423b321117085a070df720840455e9 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Thu, 31 Oct 2024 05:05:22 -0700 Subject: [PATCH 1/8] nix: Clean up Rust toolchain expressions Signed-off-by: Nick Spinale --- hacking/nix/scope/default.nix | 8 ++++++++ hacking/nix/scope/kani/default.nix | 17 +++++++---------- hacking/nix/scope/verus/default.nix | 6 ++++-- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/hacking/nix/scope/default.nix b/hacking/nix/scope/default.nix index 300d6f6c8..7ffa10063 100644 --- a/hacking/nix/scope/default.nix +++ b/hacking/nix/scope/default.nix @@ -98,6 +98,14 @@ superCallPackage ../rust-utils {} self // in toolchain.withComponents filteredComponents; + parseStructuredChannel = unstructuredChannel: + let + parts = builtins.match ''(nightly)-(.*)'' unstructuredChannel; + in + if parts == null + then { channel = unstructuredChannel; date = null; } + else { channel = lib.elemAt parts 0; date = lib.elemAt parts 1; }; + defaultRustEnvironment = let inherit (scopeConfig.rustEnvironmentSelector) tracks upstream; diff --git a/hacking/nix/scope/kani/default.nix b/hacking/nix/scope/kani/default.nix index a3c3dfed9..eb78c57c3 100644 --- a/hacking/nix/scope/kani/default.nix +++ b/hacking/nix/scope/kani/default.nix @@ -16,7 +16,8 @@ , crateUtils , vendorLockfile , sources -, fenix +, assembleRustToolchain +, parseStructuredChannel , elaborateRustEnvironment , mkDefaultElaborateRustEnvironmentArgs , mkMkCustomTargetPathForEnvironment @@ -27,20 +28,16 @@ let rustToolchainAttrs = builtins.fromTOML (builtins.readFile (src + "/rust-toolchain.toml")); - rustToolchain = fenix.fromToolchainFile { - file = crateUtils.toTOMLFile "rust-toolchain.toml" (crateUtils.clobber [ - rustToolchainAttrs - { - toolchain.components = rustToolchainAttrs.toolchain.components ++ [ "rust-src" ]; - } - ]); + inherit (rustToolchainAttrs.toolchain) channel; + + rustToolchain = assembleRustToolchain (parseStructuredChannel channel // { sha256 = "sha256-opDDHyN+Xa9kcjdHwGl3IpBsUw7ikGU+Ng00JeCdkMA="; - }; + }); rustEnvironment = lib.fix (self: elaborateRustEnvironment (mkDefaultElaborateRustEnvironmentArgs { inherit rustToolchain; } // { - inherit (rustToolchainAttrs.toolchain) channel; + inherit channel; mkCustomTargetPath = mkMkCustomTargetPathForEnvironment { rustEnvironment = self; }; diff --git a/hacking/nix/scope/verus/default.nix b/hacking/nix/scope/verus/default.nix index 5fe844282..b1da14fc4 100644 --- a/hacking/nix/scope/verus/default.nix +++ b/hacking/nix/scope/verus/default.nix @@ -23,15 +23,17 @@ let rustToolchainAttrs = builtins.fromTOML (builtins.readFile (src + "/rust-toolchain.toml")); + inherit (rustToolchainAttrs.toolchain) channel; + rustToolchain = assembleRustToolchain { - channel = "1.76.0"; + inherit channel; sha256 = "sha256-e4mlaJehWBymYxJGgnbuCObVlqMlQSilZ8FljG9zPHY="; }; rustEnvironment = lib.fix (self: elaborateRustEnvironment (mkDefaultElaborateRustEnvironmentArgs { inherit rustToolchain; } // { - inherit (rustToolchainAttrs.toolchain) channel; + inherit channel; backwardsCompatibilityHacks = { outDirInsteadOfArtifactDir = true; noLibraryWorkspace = true; From ced71f3f1765d620f109d877a1ffeff79a2b2f60 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Thu, 31 Oct 2024 05:44:19 -0700 Subject: [PATCH 2/8] Use rustversion instead of rustc_version crate Signed-off-by: Nick Spinale --- Cargo.lock | 12 +++++-- crates/sel4-generate-target-specs/Cargo.nix | 2 +- crates/sel4-generate-target-specs/Cargo.toml | 2 +- crates/sel4-generate-target-specs/build.rs | 32 ++++++----------- crates/sel4-generate-target-specs/src/main.rs | 2 +- crates/sel4-panicking/Cargo.nix | 2 +- crates/sel4-panicking/Cargo.toml | 2 +- crates/sel4-panicking/build.rs | 35 ++++++++----------- crates/sel4-panicking/src/lib.rs | 6 ++-- crates/sel4/bitfield-ops/Cargo.nix | 2 +- crates/sel4/bitfield-ops/Cargo.toml | 2 +- crates/sel4/bitfield-ops/build.rs | 21 +++-------- .../direct-dependency-allow-list.toml | 1 + 13 files changed, 49 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0877d3302..25787d2b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1802,6 +1802,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + [[package]] name = "ruzstd" version = "0.7.2" @@ -2022,7 +2028,7 @@ dependencies = [ name = "sel4-bitfield-ops" version = "0.1.0" dependencies = [ - "rustc_version", + "rustversion", ] [[package]] @@ -2260,7 +2266,7 @@ name = "sel4-generate-target-specs" version = "0.1.0" dependencies = [ "clap", - "rustc_version", + "rustversion", "serde_json", ] @@ -2485,7 +2491,7 @@ name = "sel4-panicking" version = "0.1.0" dependencies = [ "cfg-if", - "rustc_version", + "rustversion", "sel4-immediate-sync-once-cell", "sel4-panicking-env", "unwinding", diff --git a/crates/sel4-generate-target-specs/Cargo.nix b/crates/sel4-generate-target-specs/Cargo.nix index 10fcd2e53..3bf9ed028 100644 --- a/crates/sel4-generate-target-specs/Cargo.nix +++ b/crates/sel4-generate-target-specs/Cargo.nix @@ -12,7 +12,7 @@ mk { inherit (versions) serde_json clap; }; build-dependencies = { - inherit (versions) rustc_version; + inherit (versions) rustversion; }; package.metadata.rust-analyzer = { rustc_private = true; diff --git a/crates/sel4-generate-target-specs/Cargo.toml b/crates/sel4-generate-target-specs/Cargo.toml index 9c99e52e5..9be77277b 100644 --- a/crates/sel4-generate-target-specs/Cargo.toml +++ b/crates/sel4-generate-target-specs/Cargo.toml @@ -24,4 +24,4 @@ clap = "4.4.6" serde_json = "1.0.87" [build-dependencies] -rustc_version = "0.4.0" +rustversion = "1.0.18" diff --git a/crates/sel4-generate-target-specs/build.rs b/crates/sel4-generate-target-specs/build.rs index 98c870d56..105587134 100644 --- a/crates/sel4-generate-target-specs/build.rs +++ b/crates/sel4-generate-target-specs/build.rs @@ -4,28 +4,18 @@ // SPDX-License-Identifier: BSD-2-Clause // -use core::cmp::Reverse; - -// Determine whether rustc includes https://github.com/rust-lang/rust/pull/122305 - fn main() { - let key = { - let version_meta = rustc_version::version_meta().unwrap(); - let semver = version_meta.semver; - let commit_date = order_date(version_meta.commit_date); - (semver.major, semver.minor, semver.patch, commit_date) - }; - let check_cfg_required = (1, 80, 0, order_date(Some("2024-05-05".to_owned()))); - let target_spec_has_metadata = (1, 78, 0, order_date(Some("2024-03-15".to_owned()))); - if key >= check_cfg_required { - println!("cargo:rustc-check-cfg=cfg(target_spec_has_metadata)"); + let key = "target_spec_has_metadata"; + if rustversion::cfg!(any( + all(not(nightly), since(1.80)), + all(nightly, since(2024 - 05 - 05)) + )) { + println!("cargo:rustc-check-cfg=cfg({key})"); } - if key >= target_spec_has_metadata { - println!("cargo:rustc-cfg=target_spec_has_metadata"); + if rustversion::cfg!(any( + all(not(nightly), since(1.78)), + all(nightly, since(2024 - 03 - 15)) + )) { + println!("cargo:rustc-cfg={key}"); } } - -// no build date means more recent -fn order_date(date: Option) -> Reverse>> { - Reverse(date.map(Reverse)) -} diff --git a/crates/sel4-generate-target-specs/src/main.rs b/crates/sel4-generate-target-specs/src/main.rs index e554bce95..65f1e2359 100644 --- a/crates/sel4-generate-target-specs/src/main.rs +++ b/crates/sel4-generate-target-specs/src/main.rs @@ -257,7 +257,7 @@ impl Context { } fn builtin(triple: &str) -> Target { - #[cfg_attr(not(target_spec_has_metadata), allow(unused_mut))] + #[allow(unused_mut)] let mut target = Target::expect_builtin(&TargetTriple::from_triple(triple)); #[cfg(target_spec_has_metadata)] { diff --git a/crates/sel4-panicking/Cargo.nix b/crates/sel4-panicking/Cargo.nix index 36ea86f7d..cbe040efb 100644 --- a/crates/sel4-panicking/Cargo.nix +++ b/crates/sel4-panicking/Cargo.nix @@ -16,7 +16,7 @@ mk { ; }; build-dependencies = { - inherit (versions) rustc_version; + inherit (versions) rustversion; }; target."cfg(all(panic = \"unwind\", not(target_arch = \"arm\")))".dependencies = { unwinding = unwindingWith [ "personality" ]; diff --git a/crates/sel4-panicking/Cargo.toml b/crates/sel4-panicking/Cargo.toml index 42df92319..2d3f1adf8 100644 --- a/crates/sel4-panicking/Cargo.toml +++ b/crates/sel4-panicking/Cargo.toml @@ -25,7 +25,7 @@ sel4-immediate-sync-once-cell = { path = "../sel4-immediate-sync-once-cell" } sel4-panicking-env = { path = "env" } [build-dependencies] -rustc_version = "0.4.0" +rustversion = "1.0.18" [target."cfg(all(panic = \"unwind\", not(target_arch = \"arm\")))".dependencies.unwinding] version = "0.2.3" diff --git a/crates/sel4-panicking/build.rs b/crates/sel4-panicking/build.rs index 5ff5e56e6..7f4f06b84 100644 --- a/crates/sel4-panicking/build.rs +++ b/crates/sel4-panicking/build.rs @@ -4,36 +4,29 @@ // SPDX-License-Identifier: BSD-2-Clause // -use core::cmp::Reverse; - // Determine whether rustc includes the following changes: // - https://blog.rust-lang.org/2024/05/06/check-cfg.html // - https://github.com/rust-lang/rust/pull/121598 // - https://github.com/rust-lang/rust/pull/126732 fn main() { - let key = { - let version_meta = rustc_version::version_meta().unwrap(); - let semver = version_meta.semver; - let commit_date = order_date(version_meta.commit_date); - (semver.major, semver.minor, semver.patch, commit_date) - }; - let check_cfg_required = (1, 80, 0, order_date(Some("2024-05-05".to_owned()))); - let unwind_intrinsic_renamed = (1, 78, 0, order_date(Some("2024-02-28".to_owned()))); - let panic_info_message_stabilized = (1, 81, 0, order_date(Some("2024-07-01".to_owned()))); - if key >= check_cfg_required { - println!("cargo:rustc-check-cfg=cfg(catch_unwind_intrinsic_still_named_try)"); + if rustversion::cfg!(any( + all(not(nightly), since(1.80)), + all(nightly, since(2024 - 05 - 05)) + )) { + println!("cargo:rustc-check-cfg=cfg(catch_unwind_intrinsic_so_named)"); println!("cargo:rustc-check-cfg=cfg(panic_info_message_stable)"); } - if key < unwind_intrinsic_renamed { - println!("cargo:rustc-cfg=catch_unwind_intrinsic_still_named_try"); + if rustversion::cfg!(any( + all(not(nightly), since(1.78)), + all(nightly, since(2024 - 02 - 28)) + )) { + println!("cargo:rustc-cfg=catch_unwind_intrinsic_so_named"); } - if key >= panic_info_message_stabilized { + if rustversion::cfg!(any( + all(not(nightly), since(1.81)), + all(nightly, since(2024 - 07 - 01)) + )) { println!("cargo:rustc-cfg=panic_info_message_stable"); } } - -// no build date means more recent -fn order_date(date: Option) -> Reverse>> { - Reverse(date.map(Reverse)) -} diff --git a/crates/sel4-panicking/src/lib.rs b/crates/sel4-panicking/src/lib.rs index 41b01af37..43bc96bee 100644 --- a/crates/sel4-panicking/src/lib.rs +++ b/crates/sel4-panicking/src/lib.rs @@ -124,10 +124,10 @@ fn do_panic(info: ExternalPanicInfo) -> ! { } cfg_if! { - if #[cfg(catch_unwind_intrinsic_still_named_try)] { - use core::intrinsics::r#try as catch_unwind_intrinsic; - } else { + if #[cfg(catch_unwind_intrinsic_so_named)] { use core::intrinsics::catch_unwind as catch_unwind_intrinsic; + } else { + use core::intrinsics::r#try as catch_unwind_intrinsic; } } diff --git a/crates/sel4/bitfield-ops/Cargo.nix b/crates/sel4/bitfield-ops/Cargo.nix index 6faedbead..06aeafef3 100644 --- a/crates/sel4/bitfield-ops/Cargo.nix +++ b/crates/sel4/bitfield-ops/Cargo.nix @@ -9,6 +9,6 @@ mk { package.name = "sel4-bitfield-ops"; build-dependencies = { - inherit (versions) rustc_version; + inherit (versions) rustversion; }; } diff --git a/crates/sel4/bitfield-ops/Cargo.toml b/crates/sel4/bitfield-ops/Cargo.toml index 30ff03652..f88aa9f4e 100644 --- a/crates/sel4/bitfield-ops/Cargo.toml +++ b/crates/sel4/bitfield-ops/Cargo.toml @@ -17,4 +17,4 @@ edition = "2021" license = "BSD-2-Clause" [build-dependencies] -rustc_version = "0.4.0" +rustversion = "1.0.18" diff --git a/crates/sel4/bitfield-ops/build.rs b/crates/sel4/bitfield-ops/build.rs index ea87b9449..f16f976de 100644 --- a/crates/sel4/bitfield-ops/build.rs +++ b/crates/sel4/bitfield-ops/build.rs @@ -4,24 +4,11 @@ // SPDX-License-Identifier: BSD-2-Clause // -use core::cmp::Reverse; - -// Determine whether rustc includes https://github.com/rust-lang/rust/pull/121598 - fn main() { - let key = { - let version_meta = rustc_version::version_meta().unwrap(); - let semver = version_meta.semver; - let commit_date = order_date(version_meta.commit_date); - (semver.major, semver.minor, semver.patch, commit_date) - }; - let check_cfg_required = (1, 80, 0, order_date(Some("2024-05-05".to_owned()))); - if key >= check_cfg_required { + if rustversion::cfg!(any( + all(not(nightly), since(1.80)), + all(nightly, since(2024 - 05 - 05)) + )) { println!("cargo:rustc-check-cfg=cfg(kani)"); } } - -// no build date means more recent -fn order_date(date: Option) -> Reverse>> { - Reverse(date.map(Reverse)) -} diff --git a/hacking/cargo-manifest-management/direct-dependency-allow-list.toml b/hacking/cargo-manifest-management/direct-dependency-allow-list.toml index 9d03d2d35..d8c116cbf 100644 --- a/hacking/cargo-manifest-management/direct-dependency-allow-list.toml +++ b/hacking/cargo-manifest-management/direct-dependency-allow-list.toml @@ -54,6 +54,7 @@ riscv = "0.12.1" rsa = "0.9.6" rtcc = "0.3.2" rustc_version = "0.4.0" +rustversion = "1.0.18" rustls = "0.23.5" rustls-pemfile = "2.0.0" sbi = "0.2.0" From 81e5d72afd07237fe71b55099c2ba17bdf53ea85 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Thu, 31 Oct 2024 16:20:56 -0700 Subject: [PATCH 3/8] nix: Don't use minimal target in microkit tests Signed-off-by: Nick Spinale --- hacking/nix/scope/world/instances/microkit/default.nix | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hacking/nix/scope/world/instances/microkit/default.nix b/hacking/nix/scope/world/instances/microkit/default.nix index b21be769f..b6a5aee72 100644 --- a/hacking/nix/scope/world/instances/microkit/default.nix +++ b/hacking/nix/scope/world/instances/microkit/default.nix @@ -37,7 +37,7 @@ let # }; # } # ]; - targetTriple = mkSeL4RustTargetTriple { microkit = true; minimal = true; }; + targetTriple = mkSeL4RustTargetTriple { microkit = true; }; } // args); inherit (worldConfig) isMicrokit; @@ -83,9 +83,7 @@ in { pd = mkPD rec { inherit (verus) rustEnvironment; rootCrate = crates.tests-microkit-minimal; - extraProfile = { - panic = "abort"; - }; + targetTriple = mkSeL4RustTargetTriple { microkit = true; minimal = true; }; }; in callPlatform { From 80552c7c5b6238d86d6a42ae942c68bdd3e9f0d5 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Thu, 31 Oct 2024 16:35:06 -0700 Subject: [PATCH 4/8] Add microkit unwind test Signed-off-by: Nick Spinale --- Cargo.lock | 7 +++ Cargo.toml | 1 + .../private/tests/microkit/unwind/Cargo.nix | 16 ++++++ .../private/tests/microkit/unwind/Cargo.toml | 20 +++++++ .../tests/microkit/unwind/src/bin/test.rs | 54 +++++++++++++++++++ crates/private/tests/microkit/unwind/x.system | 11 ++++ .../world/instances/microkit/default.nix | 23 +++++++- 7 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 crates/private/tests/microkit/unwind/Cargo.nix create mode 100644 crates/private/tests/microkit/unwind/Cargo.toml create mode 100644 crates/private/tests/microkit/unwind/src/bin/test.rs create mode 100644 crates/private/tests/microkit/unwind/x.system diff --git a/Cargo.lock b/Cargo.lock index 25787d2b1..f4f3d6a72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3121,6 +3121,13 @@ dependencies = [ "sel4-reset", ] +[[package]] +name = "tests-microkit-unwind" +version = "0.1.0" +dependencies = [ + "sel4-microkit", +] + [[package]] name = "tests-root-task-backtrace" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index f777c53c0..5c5637445 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ members = [ "crates/private/tests/microkit/passive-server-with-deferred-action/pds/client", "crates/private/tests/microkit/passive-server-with-deferred-action/pds/server", "crates/private/tests/microkit/reset", + "crates/private/tests/microkit/unwind", "crates/private/tests/root-task/backtrace", "crates/private/tests/root-task/c", "crates/private/tests/root-task/config", diff --git a/crates/private/tests/microkit/unwind/Cargo.nix b/crates/private/tests/microkit/unwind/Cargo.nix new file mode 100644 index 000000000..92a657479 --- /dev/null +++ b/crates/private/tests/microkit/unwind/Cargo.nix @@ -0,0 +1,16 @@ +# +# Copyright 2024, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# + +{ mk, localCrates }: + +mk { + package.name = "tests-microkit-unwind"; + dependencies = { + inherit (localCrates) + sel4-microkit + ; + }; +} diff --git a/crates/private/tests/microkit/unwind/Cargo.toml b/crates/private/tests/microkit/unwind/Cargo.toml new file mode 100644 index 000000000..e86c69aa6 --- /dev/null +++ b/crates/private/tests/microkit/unwind/Cargo.toml @@ -0,0 +1,20 @@ +# +# 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 = "tests-microkit-unwind" +version = "0.1.0" +authors = ["Nick Spinale "] +edition = "2021" +license = "BSD-2-Clause" + +[dependencies] +sel4-microkit = { path = "../../../../sel4-microkit" } diff --git a/crates/private/tests/microkit/unwind/src/bin/test.rs b/crates/private/tests/microkit/unwind/src/bin/test.rs new file mode 100644 index 000000000..9c08671ea --- /dev/null +++ b/crates/private/tests/microkit/unwind/src/bin/test.rs @@ -0,0 +1,54 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +#![no_std] +#![no_main] + +use core::sync::atomic::{AtomicBool, Ordering}; + +use sel4_microkit::{debug_println, panicking, protection_domain, NullHandler}; + +static F1_DROPPED: AtomicBool = AtomicBool::new(false); + +#[protection_domain] +fn init() -> NullHandler { + let _ = panicking::catch_unwind(|| { + f1(); + }); + assert!(F1_DROPPED.load(Ordering::SeqCst)); + let r = panicking::catch_unwind(|| { + panicking::panic_any(Foo(1337)); + }); + assert!(matches!( + r.err().unwrap().downcast::().ok().unwrap(), + Foo(1337) + )); + debug_println!("TEST_PASS"); + NullHandler::new() +} + +fn f1() { + [()].iter().for_each(f1_helper); +} + +fn f1_helper(_: &()) { + let _ = F1Drop; + panic!("test"); +} + +struct F1Drop; + +impl Drop for F1Drop { + fn drop(&mut self) { + debug_println!("F1Drop::drop()"); + F1_DROPPED.store(true, Ordering::SeqCst); + } +} + +#[derive(Copy, Clone)] +struct Foo(usize); + +impl panicking::SmallPayload for Foo {} diff --git a/crates/private/tests/microkit/unwind/x.system b/crates/private/tests/microkit/unwind/x.system new file mode 100644 index 000000000..245545c3b --- /dev/null +++ b/crates/private/tests/microkit/unwind/x.system @@ -0,0 +1,11 @@ + + + + + + + diff --git a/hacking/nix/scope/world/instances/microkit/default.nix b/hacking/nix/scope/world/instances/microkit/default.nix index b6a5aee72..33c64bb4b 100644 --- a/hacking/nix/scope/world/instances/microkit/default.nix +++ b/hacking/nix/scope/world/instances/microkit/default.nix @@ -81,7 +81,6 @@ in { minimal = maybe isMicrokit ( let pd = mkPD rec { - inherit (verus) rustEnvironment; rootCrate = crates.tests-microkit-minimal; targetTriple = mkSeL4RustTargetTriple { microkit = true; minimal = true; }; }; @@ -101,6 +100,28 @@ in { } ); + unwind = maybe isMicrokit ( + let + pd = mkPD rec { + rootCrate = crates.tests-microkit-unwind; + targetTriple = mkSeL4RustTargetTriple { microkit = true; unwind = true; }; + }; + in + callPlatform { + system = microkit.mkSystem { + searchPath = [ + "${pd}/bin" + ]; + systemXML = sources.srcRoot + "/crates/private/tests/microkit/unwind/x.system"; + }; + extraPlatformArgs = lib.optionalAttrs canSimulate { + canAutomateSimply = true; + }; + } // { + inherit pd; + } + ); + passive-server-with-deferred-action = maybe isMicrokit ( let mkCrateName = role: "tests-microkit-passive-server-with-deferred-action-pds-${role}"; From 520abe0a73e148faa35bf38c30d4000e01d7a7a0 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Fri, 1 Nov 2024 01:10:14 -0700 Subject: [PATCH 5/8] crates/sel4-initialize-tls: Leverage Layout type Signed-off-by: Nick Spinale --- crates/sel4-initialize-tls/src/lib.rs | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/crates/sel4-initialize-tls/src/lib.rs b/crates/sel4-initialize-tls/src/lib.rs index 8dc475776..efbd316b0 100644 --- a/crates/sel4-initialize-tls/src/lib.rs +++ b/crates/sel4-initialize-tls/src/lib.rs @@ -126,34 +126,26 @@ 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()); + let tcb_layout = Layout::from_size_align(tcb_size, tcb_size).unwrap(); + let (footprint, segment_offset) = tcb_layout.extend(segment_layout).unwrap(); Self { - footprint: Layout::from_size_align( - segment_offset + segment_layout.size(), - segment_layout.align().max(tcb_size), - ) - .unwrap(), + footprint, 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(), + footprint: segment_layout, 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 - let thread_pointer_offset = segment_layout - .size() - .next_multiple_of(segment_layout.align()); + let tcb_layout = + Layout::from_size_align(2 * mem::size_of::(), mem::size_of::()) + .unwrap(); // could probably get away with just 1x word size for size (keeping 2x word size alignment) + let (footprint, thread_pointer_offset) = segment_layout.extend(tcb_layout).unwrap(); Self { - footprint: Layout::from_size_align( - thread_pointer_offset + tcb_size, - segment_layout.align(), - ) - .unwrap(), + footprint, segment_offset: 0, thread_pointer_offset, } From 8df3fda1e2196bb444f1a4cb83d6964ee1da6c89 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Fri, 1 Nov 2024 01:18:24 -0700 Subject: [PATCH 6/8] crates/sel4-initialize-tls: Refactor image checking Signed-off-by: Nick Spinale --- crates/sel4-initialize-tls/src/lib.rs | 30 ++++++++++++--------------- crates/sel4-runtime-common/src/tls.rs | 2 +- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/crates/sel4-initialize-tls/src/lib.rs b/crates/sel4-initialize-tls/src/lib.rs index efbd316b0..1a4e03007 100644 --- a/crates/sel4-initialize-tls/src/lib.rs +++ b/crates/sel4-initialize-tls/src/lib.rs @@ -52,7 +52,7 @@ mod on_heap; #[cfg(feature = "on-heap")] pub use on_heap::*; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct UncheckedTlsImage { pub vaddr: usize, pub filesz: usize, @@ -61,27 +61,22 @@ pub struct UncheckedTlsImage { } impl UncheckedTlsImage { - pub fn check(&self) -> Option { + pub fn check(&self) -> Result { if self.memsz >= self.filesz && self.align.is_power_of_two() && self.align > 0 { - Some(TlsImage { - vaddr: self.vaddr, - filesz: self.filesz, - memsz: self.memsz, - align: self.align, - }) + Ok(TlsImage { checked: *self }) } else { - None + Err(InvalidTlsImageError(())) } } } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidTlsImageError(()); + #[repr(C)] #[derive(Debug, Clone, PartialEq, Eq)] pub struct TlsImage { - vaddr: usize, - filesz: usize, - memsz: usize, - align: usize, + checked: UncheckedTlsImage, } impl TlsImage { @@ -90,19 +85,20 @@ impl TlsImage { } fn segment_layout(&self) -> Layout { - Layout::from_size_align(self.memsz, self.align).unwrap() + Layout::from_size_align(self.checked.memsz, self.checked.align).unwrap() } #[allow(clippy::missing_safety_doc)] 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 image_data_window = + slice::from_raw_parts(self.checked.vaddr as *mut u8, self.checked.filesz); let segment_start = tls_reservation_start.wrapping_byte_add(reservation_layout.segment_offset()); - let segment_window = slice::from_raw_parts_mut(segment_start, self.memsz); - let (tdata, tbss) = segment_window.split_at_mut(self.filesz); + let segment_window = slice::from_raw_parts_mut(segment_start, self.checked.memsz); + let (tdata, tbss) = segment_window.split_at_mut(self.checked.filesz); tdata.copy_from_slice(image_data_window); tbss.fill(0); diff --git a/crates/sel4-runtime-common/src/tls.rs b/crates/sel4-runtime-common/src/tls.rs index 800eebcf8..445a5efee 100644 --- a/crates/sel4-runtime-common/src/tls.rs +++ b/crates/sel4-runtime-common/src/tls.rs @@ -28,7 +28,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?}")) + .unwrap_or_else(|_| abort!("invalid TLS image: {unchecked:#x?}")) .initialize_on_stack(CHOSEN_SET_THREAD_POINTER_FN, cont_fn, cont_arg) } From 7b647f67c5d1196a03539cee953fe37b5304f037 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Fri, 1 Nov 2024 01:28:07 -0700 Subject: [PATCH 7/8] crates/sel4-initialize-tls: Clean up Signed-off-by: Nick Spinale --- crates/sel4-initialize-tls/src/lib.rs | 33 +++++++++++++++------------ 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/crates/sel4-initialize-tls/src/lib.rs b/crates/sel4-initialize-tls/src/lib.rs index 1a4e03007..917450ccb 100644 --- a/crates/sel4-initialize-tls/src/lib.rs +++ b/crates/sel4-initialize-tls/src/lib.rs @@ -19,6 +19,7 @@ use core::alloc::Layout; use core::mem; +use core::ptr; use core::slice; #[cfg(feature = "alloc")] @@ -88,25 +89,27 @@ impl TlsImage { Layout::from_size_align(self.checked.memsz, self.checked.align).unwrap() } + fn image_data(&self) -> *const [u8] { + ptr::slice_from_raw_parts(self.checked.vaddr as *mut u8, self.checked.filesz) + } + #[allow(clippy::missing_safety_doc)] - pub unsafe fn initialize_tls_reservation(&self, tls_reservation_start: *mut u8) { + pub unsafe fn initialize_tls_reservation(&self, reservation_start: *mut u8) { let reservation_layout = self.reservation_layout(); - - let image_data_window = - slice::from_raw_parts(self.checked.vaddr as *mut u8, self.checked.filesz); - - let segment_start = - tls_reservation_start.wrapping_byte_add(reservation_layout.segment_offset()); - let segment_window = slice::from_raw_parts_mut(segment_start, self.checked.memsz); - let (tdata, tbss) = segment_window.split_at_mut(self.checked.filesz); - - tdata.copy_from_slice(image_data_window); + let reservation = + slice::from_raw_parts_mut(reservation_start, reservation_layout.footprint().size()); + let (tdata, tbss) = reservation[reservation_layout.segment_offset()..] + [..self.checked.memsz] + .split_at_mut(self.checked.filesz); + tdata.copy_from_slice(self.image_data().as_ref().unwrap()); 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); + let thread_pointer = (reservation_start as usize) + .checked_add(reservation_layout.thread_pointer_offset()) + .unwrap(); + let thread_pointer_slice = &mut reservation + [reservation_layout.thread_pointer_offset()..][..mem::size_of::()]; + thread_pointer_slice.copy_from_slice(&thread_pointer.to_ne_bytes()); } } } From 68e7f6cebdf01b3057a342947970e81a031634ad Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Fri, 1 Nov 2024 02:19:23 -0700 Subject: [PATCH 8/8] crates/sel4-initialize-tls: Refactor interface Signed-off-by: Nick Spinale --- crates/sel4-initialize-tls/src/lib.rs | 126 ++++++++++++++++-- crates/sel4-initialize-tls/src/on_heap.rs | 27 ++-- .../sel4-initialize-tls/src/on_stack/mod.rs | 2 +- .../src/static_allocation.rs | 37 +---- 4 files changed, 141 insertions(+), 51 deletions(-) diff --git a/crates/sel4-initialize-tls/src/lib.rs b/crates/sel4-initialize-tls/src/lib.rs index 917450ccb..b0f021072 100644 --- a/crates/sel4-initialize-tls/src/lib.rs +++ b/crates/sel4-initialize-tls/src/lib.rs @@ -66,16 +66,22 @@ impl UncheckedTlsImage { if self.memsz >= self.filesz && self.align.is_power_of_two() && self.align > 0 { Ok(TlsImage { checked: *self }) } else { - Err(InvalidTlsImageError(())) + Err(InvalidTlsImageError::new()) } } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct InvalidTlsImageError(()); +impl InvalidTlsImageError { + fn new() -> Self { + Self(()) + } +} + #[repr(C)] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct TlsImage { checked: UncheckedTlsImage, } @@ -94,7 +100,7 @@ impl TlsImage { } #[allow(clippy::missing_safety_doc)] - pub unsafe fn initialize_tls_reservation(&self, reservation_start: *mut u8) { + pub unsafe fn initialize_reservation(&self, reservation_start: *mut u8) -> usize { let reservation_layout = self.reservation_layout(); let reservation = slice::from_raw_parts_mut(reservation_start, reservation_layout.footprint().size()); @@ -103,18 +109,54 @@ impl TlsImage { .split_at_mut(self.checked.filesz); tdata.copy_from_slice(self.image_data().as_ref().unwrap()); tbss.fill(0); + let thread_pointer = (reservation_start as usize) + .checked_add(reservation_layout.thread_pointer_offset()) + .unwrap(); // TODO return error if cfg!(target_arch = "x86_64") { - let thread_pointer = (reservation_start as usize) - .checked_add(reservation_layout.thread_pointer_offset()) - .unwrap(); let thread_pointer_slice = &mut reservation [reservation_layout.thread_pointer_offset()..][..mem::size_of::()]; thread_pointer_slice.copy_from_slice(&thread_pointer.to_ne_bytes()); } + thread_pointer + } + + #[allow(clippy::missing_safety_doc)] + pub unsafe fn initialize_exact_reservation_region( + &self, + exact_reservation: &Region, + ) -> Result { + if exact_reservation.fits_exactly(self.reservation_layout().footprint()) { + Ok(self.initialize_reservation(exact_reservation.start())) + } else { + Err(RegionLayoutError::new()) + } + } + + #[allow(clippy::missing_safety_doc)] + pub unsafe fn initialize_inexact_reservation_region( + &self, + inexact_reservation: &Region, + ) -> Result { + if let Ok(TrimmedRegion { trimmed, .. }) = + inexact_reservation.trim(self.reservation_layout().footprint()) + { + Ok(self.initialize_exact_reservation_region(&trimmed).unwrap()) + } else { + Err(RegionLayoutError::new()) + } } } -#[derive(Copy, Clone, Debug)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct RegionLayoutError(()); + +impl RegionLayoutError { + fn new() -> Self { + Self(()) + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct TlsReservationLayout { footprint: Layout, segment_offset: usize, @@ -165,3 +207,71 @@ impl TlsReservationLayout { self.thread_pointer_offset } } + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct Region { + start: *mut u8, + size: usize, +} + +impl Region { + pub const fn new(start: *mut u8, size: usize) -> Self { + Self { start, size } + } + + pub const fn start(&self) -> *mut u8 { + self.start + } + + pub const fn size(&self) -> usize { + self.size + } + + fn fits_exactly(&self, layout: Layout) -> bool { + self.size() == layout.size() && self.start().align_offset(layout.align()) == 0 + } + + fn trim(&self, layout: Layout) -> Result { + let start_addr = self.start() as usize; + let trimmed_start_addr = start_addr + .checked_next_multiple_of(layout.align()) + .ok_or(TrimRegionError::new())?; + let remainder_start_addr = trimmed_start_addr + .checked_add(layout.size()) + .ok_or(TrimRegionError::new())?; + let remainder_end_addr = start_addr + .checked_add(self.size()) + .ok_or(TrimRegionError::new())?; + if remainder_start_addr > remainder_end_addr { + return Err(TrimRegionError::new()); + } + Ok(TrimmedRegion { + padding: Region::new(start_addr as *mut u8, trimmed_start_addr - start_addr), + trimmed: Region::new( + trimmed_start_addr as *mut u8, + remainder_start_addr - trimmed_start_addr, + ), + remainder: Region::new( + remainder_start_addr as *mut u8, + remainder_end_addr - remainder_start_addr, + ), + }) + } +} + +struct TrimmedRegion { + #[allow(dead_code)] + padding: Region, + trimmed: Region, + #[allow(dead_code)] + remainder: Region, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct TrimRegionError(()); + +impl TrimRegionError { + fn new() -> Self { + Self(()) + } +} diff --git a/crates/sel4-initialize-tls/src/on_heap.rs b/crates/sel4-initialize-tls/src/on_heap.rs index c62390c3a..7df2e19d9 100644 --- a/crates/sel4-initialize-tls/src/on_heap.rs +++ b/crates/sel4-initialize-tls/src/on_heap.rs @@ -4,32 +4,39 @@ // SPDX-License-Identifier: BSD-2-Clause // -use crate::{TlsImage, TlsReservationLayout}; +use core::alloc::Layout; + +use crate::{Region, TlsImage}; pub struct HeapTlsReservation { start: *mut u8, - layout: TlsReservationLayout, + layout: Layout, + thread_pointer: usize, } impl HeapTlsReservation { fn initialize(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 } + let layout = tls_image.reservation_layout().footprint(); + let start = unsafe { ::alloc::alloc::alloc(layout) }; + let region = Region::new(start, layout.size()); + let thread_pointer = + unsafe { tls_image.initialize_exact_reservation_region(®ion) }.unwrap(); + Self { + start, + layout, + thread_pointer, + } } pub fn thread_pointer(&self) -> usize { - (self.start as usize) + self.layout.thread_pointer_offset() + self.thread_pointer } } impl Drop for HeapTlsReservation { fn drop(&mut self) { unsafe { - ::alloc::alloc::dealloc(self.start, self.layout.footprint()); + ::alloc::alloc::dealloc(self.start, self.layout); } } } diff --git a/crates/sel4-initialize-tls/src/on_stack/mod.rs b/crates/sel4-initialize-tls/src/on_stack/mod.rs index c4335ad8f..bb32e7a4f 100644 --- a/crates/sel4-initialize-tls/src/on_stack/mod.rs +++ b/crates/sel4-initialize-tls/src/on_stack/mod.rs @@ -44,7 +44,7 @@ impl TlsImage { cont_fn: ContFn, cont_arg: *mut ContArg, ) -> ! { - self.initialize_tls_reservation(tls_reservation_start); + self.initialize_reservation(tls_reservation_start); let thread_pointer = tls_reservation_start .wrapping_byte_add(self.reservation_layout().thread_pointer_offset()); diff --git a/crates/sel4-initialize-tls/src/static_allocation.rs b/crates/sel4-initialize-tls/src/static_allocation.rs index c4ab3ef9f..427bc4be0 100644 --- a/crates/sel4-initialize-tls/src/static_allocation.rs +++ b/crates/sel4-initialize-tls/src/static_allocation.rs @@ -4,10 +4,9 @@ // SPDX-License-Identifier: BSD-2-Clause // -use core::alloc::Layout; use core::cell::UnsafeCell; -use crate::TlsImage; +use crate::Region; #[repr(C)] pub struct StaticTlsAllocation { @@ -32,6 +31,10 @@ impl StaticTlsAllocation { const fn start(&self) -> *mut u8 { self.space.get().cast() } + + pub const fn region(&self) -> Region { + Region::new(self.start(), self.size()) + } } impl Default for StaticTlsAllocation { @@ -39,33 +42,3 @@ impl Default for StaticTlsAllocation { Self::new() } } - -impl TlsImage { - pub fn initialize_static_allocation( - &self, - allocation: &StaticTlsAllocation, - ) -> Result { - let layout = self.reservation_layout(); - let footprint = layout.footprint(); - let align_offset = allocation.start().align_offset(layout.footprint().align()); - if align_offset + footprint.size() > allocation.size() { - return Err(InitializeStaticTlsAllocationError::AllocationTooSmall { - requested_footprint: footprint, - align_offset, - }); - } - let start = allocation.start().wrapping_byte_add(align_offset); - unsafe { - self.initialize_tls_reservation(start); - }; - Ok((allocation.start() as usize) + layout.thread_pointer_offset()) - } -} - -#[derive(Debug, Copy, Clone)] -pub enum InitializeStaticTlsAllocationError { - AllocationTooSmall { - requested_footprint: Layout, - align_offset: usize, - }, -}