Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@ jobs:
persist-credentials: false
- name: Install pinned nightly + aarch64 target
run: |
rustup toolchain install $NIGHTLY_PIN --component clippy --no-self-update
# llvm-tools-preview provides rust-objcopy for the userland build
# step below (ADR-0039); it is pinned in rust-toolchain.toml but this
# explicit install does not read that file, so name it here.
rustup toolchain install $NIGHTLY_PIN --component clippy --component llvm-tools-preview --no-self-update
rustup override set $NIGHTLY_PIN
rustup target add aarch64-unknown-none --toolchain $NIGHTLY_PIN
- name: Cache cargo registry and build
Expand All @@ -129,6 +132,11 @@ jobs:
key: ${{ runner.os }}-cargo-aarch64-${{ env.NIGHTLY_PIN }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-aarch64-${{ env.NIGHTLY_PIN }}-
- name: build userland image (ADR-0039)
# Produces userland/hello/hello.bin (rust-objcopy of the userland crate)
# which the BSP embeds via include_bytes!; MUST run before kernel-build,
# whose build.rs panics if the .bin is absent.
run: tools/build-userland.sh
- name: cargo kernel-build
run: cargo +$NIGHTLY_PIN kernel-build
- name: cargo kernel-clippy
Expand Down Expand Up @@ -262,4 +270,8 @@ jobs:
restore-keys: |
${{ runner.os }}-llvmcov-${{ env.NIGHTLY_PIN }}-
- name: cargo llvm-cov --summary-only
run: cargo llvm-cov --workspace --exclude tyrne-bsp-qemu-virt --summary-only
# Exclude the bare-metal crates: the BSP is no_std/no_main (cannot host-
# build) and the userland crates (tyrne-user / hello) host-compile only
# as aarch64-gated stubs (ADR-0039) — coverage of never-run stubs is
# meaningless and would only dilute the metric.
run: cargo llvm-cov --workspace --exclude tyrne-bsp-qemu-virt --exclude tyrne-user --exclude tyrne-userland-hello --summary-only
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ members = [
"hal",
"bsp-qemu-virt",
"test-hal",
"userland/tyrne-user",
"userland/hello",
]
# Default set for workspace-wide commands (`cargo check`, `cargo test`, etc.):
# everything host-buildable. The BSP is #![no_std, no_main] and requires the
# explicit bare-metal target; build it via `cargo kernel-build` (or
# `cargo build --target aarch64-unknown-none -p tyrne-bsp-qemu-virt`).
# `cargo build --target aarch64-unknown-none -p tyrne-bsp-qemu-virt`). The
# userland crates (tyrne-user lib + the no_main hello bin) are likewise
# bare-metal-only — built via `tools/build-userland.sh` (ADR-0039), excluded
# here so host commands (`cargo build`/`test`/`host-clippy`) skip them.
default-members = [
"kernel",
"hal",
Expand Down
19 changes: 19 additions & 0 deletions bsp-qemu-virt/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
//! path so resolution does not depend on the linker's working directory.
//! See `docs/decisions/0012-boot-flow-qemu-virt.md` for the memory layout the
//! linker script encodes.
//!
//! Also asserts the userland image (`userland/hello/hello.bin`) that
//! `main.rs` embeds via `include_bytes!` exists, and re-runs when it changes —
//! it is produced by `tools/build-userland.sh` (ADR-0039), which must run
//! before `cargo kernel-build`.

fn main() {
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")
Expand All @@ -14,4 +19,18 @@ fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=src/boot.s");
println!("cargo:rerun-if-changed=src/vectors.s");

// Userland image (ADR-0039 / T-027): `main.rs` embeds this via
// `include_bytes!`. It is produced by `tools/build-userland.sh`
// (cargo build -> rust-objcopy) — NOT by this build script (no nested
// cargo). Fail loudly with the remedy if it is absent, rather than letting
// `include_bytes!` emit an opaque "file not found".
let hello_bin = format!("{manifest_dir}/../userland/hello/hello.bin");
println!("cargo:rerun-if-changed={hello_bin}");
assert!(
std::path::Path::new(&hello_bin).exists(),
"userland image not built: {hello_bin} is missing.\n \
Run `tools/build-userland.sh` before `cargo kernel-build` \
(ADR-0039); `tools/smoke.sh` and CI do this automatically."
);
Comment on lines +28 to +35
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Path concatenation using format! with hardcoded / separators is not platform-independent. Using std::path::Path and PathBuf is more idiomatic and robust across different host platforms.

    let hello_bin = std::path::Path::new(&manifest_dir)
        .parent()
        .unwrap()
        .join("userland")
        .join("hello")
        .join("hello.bin");
    let hello_bin_str = hello_bin.to_str().unwrap();
    println!("cargo:rerun-if-changed={}", hello_bin_str);
    assert!(
        hello_bin.exists(),
        "userland image not built: {} is missing.\n       \
         Run tools/build-userland.sh before cargo kernel-build \
         (ADR-0039); tools/smoke.sh and CI do this automatically.",
        hello_bin_str
    );

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipped — the format! path with / works on Tyrne's Unix-only dev/CI (macOS + ubuntu, per .github/workflows + the platform); it is not a bug. Path::join is an idiomatic nicety; deferred to keep the change minimal (no Windows target exists).

}
28 changes: 16 additions & 12 deletions bsp-qemu-virt/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,22 +327,26 @@ static BOOTSTRAP_AS_CAP: StaticCell<CapHandle> = StaticCell::new();
/// untyped / memory-region authority caps.
static BOOTSTRAP_AS_TABLE: StaticCell<CapabilityTable> = StaticCell::new();

// ─── T-019 task loader placeholder image (ADR-0029) ───────────────────────────
// ─── Userland image (ADR-0029 format / ADR-0039 build pipeline) ───────────────

/// Placeholder userspace image: 8 bytes of aarch64 `mov w0, #42; ret`
/// per [ADR-0029 §Decision outcome (Build pipeline — B4 / T-019)][adr-0029].
/// The real B6 "hello" userspace binary lands with `userland/hello/`
/// per [ADR-0029 §Decision outcome (Build pipeline — B6)][adr-0029];
/// T-019 ships with this hand-coded blob as the loader's smoke fixture.
/// The real B6 "hello" userspace image: the raw-flat (`rust-objcopy -O binary`)
/// output of the [`tyrne-userland-hello`] crate, embedded at compile time per
/// [ADR-0039][adr-0039]. Entry at offset 0 ([ADR-0029][adr-0029] raw-flat
/// format), mapped `USER | EXECUTE` by the loader. It replaces the B4/T-019
/// hand-coded `mov w0, #42; ret` placeholder.
///
/// **Not executed.** T-019 produces a `LoadedImage` describing a
/// populated AS; running gates on B5 (syscall ABI per ADR-0030) + B6
/// (first userspace "hello") which together provide the prerequisites
/// (kernel mappings in userspace AS, EL0-ready context, syscall
/// entry).
/// **Build dependency:** produced by `tools/build-userland.sh` (which the
/// BSP [`build.rs`] requires to have run — it `panic!`s if this `.bin` is
/// absent) before `cargo kernel-build`. `tools/smoke.sh` and the CI
/// kernel-build job both run that script first.
///
/// **Not yet executed (T-027).** Embedding is T-027; loading it into a real
/// EL0 task and running the `+0x400` round-trip is the T-028 wire-up. Today the
/// boot-time loader smoke maps it (proving it loads) and the demo then idles.
///
/// [adr-0029]: https://github.com/HodeTech/Tyrne/blob/main/docs/decisions/0029-initial-userspace-image-format.md
static USERSPACE_IMAGE: &[u8] = &[0x40, 0x05, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6];
/// [adr-0039]: https://github.com/HodeTech/Tyrne/blob/main/docs/decisions/0039-userland-build-pipeline.md
static USERSPACE_IMAGE: &[u8] = include_bytes!("../../userland/hello/hello.bin");

/// Base VA the loader places the image at — userspace VA range per
/// [ADR-0027 §Decision outcome (a)][adr-0027]'s `TTBR0_EL1` range.
Expand Down
Loading
Loading