Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
2a23cb5
feat: Add Phase B.2 tasks and governance documentation
cemililik Oct 11, 2026
c794077
docs: update task files for Phase B.2 closure and readiness
cemililik Oct 11, 2026
613e698
Refactor code structure for improved readability and maintainability
cemililik Oct 11, 2026
49c7cb4
docs: update Phase B.2 documentation for clarity and accuracy
cemililik Oct 11, 2026
7786582
docs: clarify documentation requirements for CI script checks and dec…
cemililik Oct 11, 2026
fac9047
docs(roadmap): reconcile Track B.2-1 implementation contracts
cemililik Oct 11, 2026
5f809bf
docs(ci): include release smoke in Track B.2-1 plan
cemililik Oct 11, 2026
8d6fab5
docs(ci): resolve final Track B.2-1 preflight findings
cemililik Oct 11, 2026
41679c1
docs(roadmap): reconcile phase targets before ADR acceptance
cemililik Oct 11, 2026
8d2c013
docs(adr): resolve approval findings before acceptance
cemililik Oct 11, 2026
960bdef
docs(adr): accept ADR-0040 and Track B.2-1 policy
cemililik Oct 11, 2026
f2d577f
fix(userspace): restrict syscall shims to bare metal
cemililik Oct 11, 2026
69a4109
docs(userspace): reconcile T-037 review records
cemililik Oct 11, 2026
3a7c264
docs(userspace): record second T-037 review round
cemililik Oct 11, 2026
54e8f77
feat(tooling): validate QEMU core count and timeout arguments
cemililik Oct 11, 2026
d5c13a0
docs(tooling): record T-033 implementation gates
cemililik Oct 11, 2026
eede01c
docs(tooling): record first T-033 review round
cemililik Oct 11, 2026
05f1736
docs(tooling): correct completion state after T-033 review
cemililik Oct 11, 2026
82d1c42
ci: lint userland and tooling scripts
cemililik Oct 11, 2026
1cb3526
docs(standards): enforce userland and shell lint gates
cemililik Oct 11, 2026
0acf0cd
fix(ci): support hosted ShellCheck trap analysis
cemililik Oct 11, 2026
e79e10a
docs(standards): reconcile first T-031 review findings
cemililik Oct 11, 2026
8437158
docs(analysis): complete second T-031 review round
cemililik Oct 11, 2026
b8ad56f
ci: enforce release and perf build contracts
cemililik Oct 11, 2026
c716ae3
docs(standards): enforce release and perf verification gates
cemililik Oct 11, 2026
364b746
docs(analysis): record hosted T-030 gate evidence
cemililik Oct 11, 2026
5cd9ee8
docs(analysis): record first T-030 review round
cemililik Oct 11, 2026
8591ceb
docs(analysis): complete second T-030 review round
cemililik Oct 11, 2026
c3f32c8
fix(bsp-qemu-virt): enforce panic-family lint boundaries
cemililik Oct 11, 2026
b6572cc
docs(analysis): reconcile T-032 audit and evidence state
cemililik Oct 11, 2026
4f2c38c
docs(analysis): record hosted T-032 gate evidence
cemililik Oct 11, 2026
6e191e2
docs(analysis): record first T-032 review round
cemililik Oct 11, 2026
07449f1
docs(analysis): record second T-032 review round
cemililik Oct 11, 2026
6450005
ci: gate debug and release EL0 smoke under QEMU
cemililik Oct 11, 2026
41d9682
docs(analysis): record hosted T-034 guest proof
cemililik Oct 11, 2026
97a6c83
fix(ci): preserve QEMU smoke failures through logging
cemililik Oct 11, 2026
9092581
docs(analysis): verify hosted T-034 pipeline correction
cemililik Oct 11, 2026
0c86c3d
docs(analysis): record second T-034 review round
cemililik Oct 11, 2026
9c5191c
docs(ci): record required QEMU check registration
cemililik Oct 11, 2026
bf20ec9
ci: require native ARM64 workspace checks and Miri
cemililik Oct 11, 2026
5c95cd3
docs(analysis): record first T-036 review and ARM evidence
cemililik Oct 11, 2026
2d4d21e
docs(analysis): record second T-036 review round
cemililik Oct 11, 2026
69ac515
docs(ci): record required native ARM check registration
cemililik Oct 11, 2026
e873995
ci: add weekly performance reports and versioned merge policy
cemililik Oct 12, 2026
7deb16e
fix(ci): accept both proven ARM cfg rejection diagnostics
cemililik Oct 12, 2026
cfc8872
chore(ci): reconcile merged kickoff ancestry
cemililik Oct 12, 2026
67f8c9b
docs(analysis): record final Track B.2-1 review round
cemililik Oct 12, 2026
bd27fe5
docs(roadmap): reconcile Track B.2-1 implementation status
cemililik Oct 12, 2026
acd0013
docs(roadmap): reconcile final Track B.2-1 documentation
cemililik Oct 12, 2026
1e281ac
docs(roadmap): record green Track B.2-1 PR evidence
cemililik Oct 12, 2026
50ab72b
fix(ci): strengthen PR review probes and report metadata
cemililik Oct 12, 2026
683965b
docs(analysis): record PR48 tooling review and correction
cemililik Oct 12, 2026
a1eb406
docs(analysis): record fresh PR48 tooling round two
cemililik Oct 12, 2026
5816c93
docs(ci): reconcile PR48 review claims and current guidance
cemililik Oct 12, 2026
646ba33
docs(analysis): correct PR48 review wording and record round one
cemililik Oct 12, 2026
f2758e3
docs(analysis): publish PR48 follow-up completion and hosted evidence
cemililik Oct 12, 2026
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
4 changes: 4 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,23 @@ rustflags = [
# `cargo run --target aarch64-unknown-none -p tyrne-bsp-qemu-virt` boots the
# built ELF under QEMU virt with a single Cortex-A72 core, 128 MiB RAM, and
# the serial multiplexed onto the terminal. See docs/guides/run-under-qemu.md.
# This static runner stays at one core. The guide documents --smp / QEMU_SMP
# for the shell helpers and CARGO_TARGET_AARCH64_UNKNOWN_NONE_RUNNER for Cargo.
runner = "qemu-system-aarch64 -M virt -cpu cortex-a72 -m 128M -smp 1 -nographic -serial mon:stdio -kernel"

# Convenience aliases.
[alias]
# Build the kernel image for the primary development BSP.
kernel-build = "build --target aarch64-unknown-none -p tyrne-bsp-qemu-virt"
kernel-build-release = "build --target aarch64-unknown-none -p tyrne-bsp-qemu-virt --release"

# Run clippy against the kernel image with warnings as errors.
# No `--all-targets`: the BSP is no_main and has no test target to build.
kernel-clippy = "clippy --target aarch64-unknown-none -p tyrne-bsp-qemu-virt -- -D warnings"

# Boot the built image under QEMU (requires `cargo kernel-build` first).
kernel-run = "run --target aarch64-unknown-none -p tyrne-bsp-qemu-virt"
kernel-run-release = "run --target aarch64-unknown-none -p tyrne-bsp-qemu-virt --release"

# Run host-side unit tests (uses workspace default-members, which excludes
# the bare-metal BSP). Run `cargo kernel-build` separately to exercise
Expand Down
73 changes: 73 additions & 0 deletions .github/branch-protection/main.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"branch": "main",
"classic_rule": {
"bypassForcePushAllowances": {
"totalCount": 0
},
"bypassPullRequestAllowances": {
"totalCount": 0
},
"pattern": "main",
"pushAllowances": {
"totalCount": 0
},
"requiredDeploymentEnvironments": [],
"requiresApprovingReviews": true,
"requiresDeployments": false,
"restrictsPushes": false,
"restrictsReviewDismissals": false,
"reviewDismissalAllowances": {
"totalCount": 0
}
},
"protection": {
"allow_deletions": false,
"allow_force_pushes": false,
"allow_fork_syncing": false,
"block_creations": false,
"enforce_admins": false,
"lock_branch": false,
"required_conversation_resolution": true,
"required_linear_history": true,
"required_pull_request_reviews": {
"dismiss_stale_reviews": false,
"require_code_owner_reviews": false,
"require_last_push_approval": false,
"required_approving_review_count": 0
},
"required_signatures": false,
"required_status_checks": {
"checks": [
{
"app_id": 15368,
"context": "ARM64 host check + clippy + tests + Miri (nightly)"
},
{
"app_id": 15368,
"context": "QEMU debug + release smoke (nightly)"
},
{
"app_id": 15368,
"context": "aarch64-unknown-none kernel build (nightly)"
},
{
"app_id": 15368,
"context": "fmt + clippy + host tests (nightly)"
},
{
"app_id": 15368,
"context": "host crates on stable"
},
{
"app_id": 15368,
"context": "miri (Stacked Borrows)"
}
],
"strict": true
},
"restrictions": null
},
"repository": "HodeTech/Tyrne",
"rulesets": [],
"schema_version": 1
}
268 changes: 223 additions & 45 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

94 changes: 94 additions & 0 deletions .github/workflows/performance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Informational measurements, never a required PR/merge check (ADR-0040).
name: Performance report

on:
schedule:
- cron: '17 3 * * 1'
workflow_dispatch:
push:
branches: [development]
paths:
- '.github/workflows/performance.yml'
- 'tools/perf-harness.sh'

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
NIGHTLY_PIN: nightly-2026-01-15
CARGO_TERM_COLOR: always

jobs:
performance-report:
name: Weekly boot-to-end report (informational)
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Initialize report evidence
run: |
PERF_EVIDENCE="$RUNNER_TEMP/performance-evidence"
echo "PERF_EVIDENCE=$PERF_EVIDENCE" >> "$GITHUB_ENV"
mkdir -p "$PERF_EVIDENCE"
date +%s > "$PERF_EVIDENCE/started-seconds"
{
echo "source_sha=$(git rev-parse HEAD)"
echo "run_id=$GITHUB_RUN_ID"
echo "run_attempt=$GITHUB_RUN_ATTEMPT"
echo "started_utc=$(date -u +%FT%TZ)"
echo "Informational debug measurements; no calibrated regression threshold."
} > "$PERF_EVIDENCE/metadata.txt"
- name: Install QEMU and pinned nightly
run: |
sudo apt-get update
sudo apt-get install -y qemu-system-arm
qemu-system-aarch64 --version > "$PERF_EVIDENCE/qemu-version.txt"
rustup toolchain install "$NIGHTLY_PIN" --component llvm-tools-preview --no-self-update
rustup override set "$NIGHTLY_PIN"
rustup target add aarch64-unknown-none --toolchain "$NIGHTLY_PIN"
rustc -Vv > "$PERF_EVIDENCE/rustc-version.txt"
rustup show active-toolchain > "$PERF_EVIDENCE/toolchain.txt"
- name: Cache performance build
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-${{ runner.arch }}-performance-${{ env.NIGHTLY_PIN }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-${{ runner.arch }}-performance-${{ env.NIGHTLY_PIN }}-
- name: Build matching debug userland and kernel
run: |
tools/build-userland.sh
cargo +"$NIGHTLY_PIN" kernel-build
- name: Collect 20 debug measurements
run: |
tools/perf-harness.sh --iterations=20 --report=ci-nightly 2>&1 | tee "$PERF_EVIDENCE/harness.output.log"
REPORT_PATH="$(sed -n 's/^report written: //p' "$PERF_EVIDENCE/harness.output.log")"
[[ "$REPORT_PATH" =~ ^docs/analysis/reports/perf-baseline-[0-9]{4}-[0-9]{2}-[0-9]{2}-ci-nightly\.md$ ]]
cp "$REPORT_PATH" "$PERF_EVIDENCE/"
- name: Record wall time
if: always()
run: |
if [[ -f "$PERF_EVIDENCE/started-seconds" ]]; then
echo "finished_utc=$(date -u +%FT%TZ)" >> "$PERF_EVIDENCE/metadata.txt"
echo "wall_seconds=$(( $(date +%s) - $(cat "$PERF_EVIDENCE/started-seconds") ))" >> "$PERF_EVIDENCE/metadata.txt"
fi
- name: Upload report and available failure diagnostics
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: performance-${{ github.sha }}-${{ github.run_attempt }}
path: ${{ env.PERF_EVIDENCE }}
if-no-files-found: error
retention-days: 14
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ todo = "deny"
# the `clippy::arithmetic_side_effects = deny` posture (see
# docs/standards/code-style.md) — do not drop it to "optimize" the build.
[profile.release]
# Keep debug-assertions at Cargo's release default (false): SyscallNumber::decode
# uses it to remove console_write from the production syscall surface.
codegen-units = 1
debug = "line-tables-only"
lto = "fat"
Expand Down
8 changes: 8 additions & 0 deletions bsp-qemu-virt/src/exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ impl PanicClass {
// so the compiler does not warn while the parameter remains live in
// the signature for the trampoline's calling-convention contract.
#[unsafe(no_mangle)]
#[allow(
clippy::panic,
reason = "deliberate fatal abort after EOI for an unhandled IRQ; not a recoverable syscall error"
)]
pub unsafe extern "C" fn irq_entry(_frame: *mut TrapFrame) {
// SAFETY: producing a stable `&QemuVirtGic` from the static
// `MaybeUninit<QemuVirtGic>` in `GIC` requires `unsafe` because Rust
Expand Down Expand Up @@ -301,6 +305,10 @@ pub unsafe extern "C" fn irq_entry(_frame: *mut TrapFrame) {
///
/// Audit: UNSAFE-2026-0020.
#[unsafe(no_mangle)]
#[allow(
clippy::panic,
reason = "deliberate fatal abort for an unhandled exception class; existing BSP fault policy"
)]
pub unsafe extern "C" fn panic_entry(class: u64, esr: u64) -> ! {
let class_str = PanicClass::from_u64(class).as_str();
panic!("tyrne: {class_str}; ESR_EL1 = {esr:#018x}; class id = {class}",);
Expand Down
24 changes: 24 additions & 0 deletions bsp-qemu-virt/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@

#![no_std]
#![no_main]
// Trap and MMU paths must not acquire accidental panic-family calls. Deliberate
// fatal aborts and trusted boot/demo invariants have function-scoped exceptions.
#![deny(clippy::panic)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
// Binary crate: `pub` items serve the linker (`#[no_mangle]`) rather than
// external consumers; `unreachable_pub` is therefore expected throughout.
#![allow(unreachable_pub, reason = "binary crate; pub items are for the linker")]
Expand Down Expand Up @@ -514,6 +519,10 @@ static TASK_ARENA: StaticCell<TaskArena> = StaticCell::new();
///
/// [ADR-0022]: https://github.com/HodeTech/Tyrne/blob/main/docs/decisions/0022-idle-task-and-typed-scheduler-deadlock.md
/// [ADR-0026]: https://github.com/HodeTech/Tyrne/blob/main/docs/decisions/0026-idle-dispatch-fallback.md
#[allow(
clippy::expect_used,
reason = "trusted idle task runs only after scheduler start; NoCurrentTask is a BSP invariant violation"
)]
fn idle_entry() -> ! {
// SAFETY: CPU is fully initialised in `kernel_entry` before `start()`;
// single-core cooperative scheduling prevents concurrent access.
Expand Down Expand Up @@ -556,6 +565,11 @@ fn idle_entry() -> ! {
/// own spin loop. The tail-end `loop { spin_loop() }` therefore satisfies the
/// `fn() -> !` return type but is structurally unreachable.
#[cfg(not(feature = "perf-bench"))]
#[allow(
clippy::expect_used,
clippy::panic,
reason = "trusted one-round IPC demo aborts on violated static capability/scheduler setup or protocol invariants"
)]
fn task_b() -> ! {
// SAFETY: CONSOLE is fully initialised in `kernel_entry` before `start()`;
// single-core cooperative scheduling prevents concurrent access.
Expand Down Expand Up @@ -657,6 +671,11 @@ fn task_b() -> ! {
/// IPC demo — initiator side. Sends a message to Task B, then waits for
/// the reply. On receiving the reply, prints the Phase A completion banner.
#[cfg(not(feature = "perf-bench"))]
#[allow(
clippy::expect_used,
clippy::panic,
reason = "trusted one-round IPC demo aborts on violated static capability/scheduler setup or protocol invariants"
)]
fn task_a() -> ! {
// SAFETY: CONSOLE initialised in kernel_entry; single-core cooperative.
// Audit: UNSAFE-2026-0010.
Expand Down Expand Up @@ -974,6 +993,11 @@ pub extern "C" fn kernel_entry() -> ! {
clippy::too_many_lines,
reason = "BSP boot sequence is intentionally linear top-to-bottom for auditability — splitting into helpers obscures the order each phase depends on (per docs/standards/bsp-boot-checklist.md)"
)]
#[allow(
clippy::expect_used,
clippy::panic,
reason = "one-shot BSP boot aborts if trusted static image, capacity, or kernel-object setup invariants fail"
)]
extern "C" fn kernel_main_high() -> ! {
// ── Free TTBR0 — the low identity — T-022 / ADR-0033 §Simulation row 3 ────
//
Expand Down
9 changes: 7 additions & 2 deletions bsp-qemu-virt/src/mmu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,12 +309,17 @@ impl Mmu for QemuVirtMmu {
// clear the descriptor (zero invalidates the entry per ARM ARM
// §D5.3 — bit 0 = 0 = invalid). No intermediate-table
// allocation; `frames` is unused on the unmap path. Per-VA
// TLB invalidate via `MapperFlush`. Audit: UNSAFE-2026-0025.
// TLB invalidate via `MapperFlush`. With `unmap = true`, the
// walker never reads its `pa` argument: reuse the already-valid
// root frame instead of constructing and unwrapping a dummy zero
// frame. Allowing unwrap here would weaken this non-init path for
// no benefit. Root/table ownership and lifetime remain unchanged.
// Audit: UNSAFE-2026-0025.
let pa = unsafe {
walk_and_install_leaf(
as_.root,
va,
/* pa: ignored on unmap */ PhysFrame::from_aligned(PhysAddr(0)).unwrap(),
/* pa: ignored on unmap */ as_.root,
MappingFlags::empty(),
&mut NullFrameProvider,
/* unmap */ true,
Expand Down
17 changes: 17 additions & 0 deletions bsp-qemu-virt/src/perf_bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ static EL0_ACCUM_NS: AtomicU64 = AtomicU64::new(0);
clippy::too_many_lines,
reason = "linear measurement-build setup top-to-bottom for auditability — mirrors `kernel_main_high`; splitting into helpers would scatter the load→create→publish→schedule order each step depends on"
)]
#[allow(
clippy::expect_used,
clippy::panic,
reason = "one-shot measurement-build setup aborts if trusted static image, capacity, or object invariants fail"
)]
pub fn run(cpu: &QemuVirtCpu, console: &Pl011Uart) -> ! {
{
let mut w = FmtWriter(console);
Expand Down Expand Up @@ -431,6 +436,10 @@ fn bench_partner() -> ! {

/// One cooperative `yield_now` (used by both tasks for the ctx-switch bench).
#[inline]
#[allow(
clippy::expect_used,
reason = "trusted benchmark tasks yield only after scheduler start; NoCurrentTask is an invariant violation"
)]
fn driver_yield(cpu: &QemuVirtCpu) {
// SAFETY: per [ADR-0021] — `SCHED.as_mut_ptr()` is a pure pointer cast
// (UNSAFE-2026-0013); no `&mut` to shared kernel state is live across the
Expand All @@ -448,6 +457,10 @@ fn driver_yield(cpu: &QemuVirtCpu) {

/// One driver send (Delivered to the waiting partner, then yields to it).
#[inline]
#[allow(
clippy::expect_used,
reason = "trusted benchmark driver uses a statically provisioned SEND cap and a fixed ping-pong protocol"
)]
fn driver_send(cpu: &QemuVirtCpu) {
let msg = Message {
label: 0xBE0C,
Expand Down Expand Up @@ -477,6 +490,10 @@ fn driver_send(cpu: &QemuVirtCpu) {

/// One partner receive (blocks → yields to driver when no message is pending).
#[inline]
#[allow(
clippy::expect_used,
reason = "trusted benchmark partner uses a statically provisioned RECV cap and a fixed ping-pong protocol"
)]
fn partner_recv(cpu: &QemuVirtCpu) {
// SAFETY: per [ADR-0021] — same raw-pointer discipline as `driver_send`;
// `TABLE_B` is the partner's own table. Audit: UNSAFE-2026-0014.
Expand Down
Loading
Loading