From d2a4ab1164d754c275c72e9b74e30d54b98319d7 Mon Sep 17 00:00:00 2001 From: Cemil ILIK Date: Thu, 7 May 2026 00:33:20 +0300 Subject: [PATCH 1/4] docs(architecture,glossary): close 7 Track-E doc-drift blockers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address all seven blocker-class items from Track E of the 2026-05-06 comprehensive code review. Each is a factual statement that fell out of sync with the code at HEAD; none requires a code change. Fixes land docs-vs-code consistency at HEAD `9cbf578`. ## docs/architecture/overview.md (Track-E §Blocker #1) - BSP table row for `bsp-qemu-virt` corrected: GICv3 → GICv2. The QEMU `virt` machine defaults to GICv2; the BSP ships a v2-only driver per ADR-0011 + UNSAFE-2026-0019. GICv3 requires `-machine gic-version=3` and is out of scope for v1. ## docs/architecture/hal.md (Track-E §Blockers #2, #3, #4) - Mermaid box label: `BIrq["GICv3 / GIC-400 impl"]` → `"GICv2 / GIC-400 impl"`. There is no GICv3 impl in tree; the bsp-pi4 row at line 198 already correctly notes GIC-400 (a v2 subset). - BSP table interrupt-controller row: GICv3 → GICv2. - Timer subsection: the "`arm_deadline` / `cancel_deadline` are `unimplemented!()` in QEMU virt's BSP today" assertion is now stale — T-012 (Done 2026-04-28) implemented both bodies under UNSAFE-2026-0021. Subsection rewritten to state the real status, cite ADR-0010 §Revision notes, and note the smoke-verification gap (no v1 caller arms a deadline; `Pending QEMU smoke` notation on UNSAFE-2026-0021 records this). ## docs/architecture/scheduler.md (Track-E §Blocker #5) - Two passages still framed `wait_for_interrupt` activation as a *future* T-012 deliverable. T-012 landed 2026-04-28; the BSP's `idle_entry` body uses `cpu.wait_for_interrupt(); yield_now(...)` per UNSAFE-2026-0019/0020/0021. Both passages updated to state the current shape, cite the audit entries, and reference ADR-0022 §Revision notes 2026-04-28's first-rider Sub-rider closure. ## docs/architecture/security-model.md (Track-E §Blocker #6) - *Open questions* §"Early IRQ masking in BSP reset vectors" closed by T-013 (Done 2026-04-27, ADR-0024, UNSAFE-2026-0017): `boot.s` begins `_start` with `msr daifset, #0xf` as the literal first instruction, and the BSP boot checklist §1a now records the rule. Bullet rewritten as a closure-rider with citations. ## docs/glossary.md (Track-E §Blocker #7) - CDT entry's live Markdown link to `decisions/0023-...md` (a file that does not exist — ADR-0023 is reserved-empty / accept-deferred per Phase B0 closure) was a 404 every other reference avoided. Replaced with prose only ("see ADR-0023 (accept-deferred per Phase B0 closure; no file at HEAD, tracked in `phase-b.md` ADR ledger and the B0 closure security review)") so a Markdown reader no longer follows the link to a missing file. Refs: comprehensive-review-2026-05-06, ADR-0010, ADR-0011, ADR-0022, ADR-0024, ADR-0026 Audit: UNSAFE-2026-0017, UNSAFE-2026-0019, UNSAFE-2026-0020, UNSAFE-2026-0021 Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/architecture/hal.md | 8 ++++---- docs/architecture/overview.md | 4 ++-- docs/architecture/scheduler.md | 4 ++-- docs/architecture/security-model.md | 2 +- docs/glossary.md | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/architecture/hal.md b/docs/architecture/hal.md index f99ba8f..e599ce2 100644 --- a/docs/architecture/hal.md +++ b/docs/architecture/hal.md @@ -47,7 +47,7 @@ flowchart TB subgraph BSP["BSP (per-board, selected at build time)"] BCpu["aarch64 Cpu impl"] BMmu["VMSAv8 Mmu impl"] - BIrq["GICv3 / GIC-400 impl"] + BIrq["GICv2 / GIC-400 impl"] BTimer["ARM generic timer impl"] BConsole["PL011 / mini-UART impl"] BIommu["SMMUv3 impl (bsp-qemu-virt)"] @@ -123,9 +123,9 @@ On aarch64 the BSP reads the **virtual** counter family — `CNTVCT_EL0` for the Helper conversions live in `tyrne_hal::timer` — `ticks_to_ns(count, frequency_hz)` uses 128-bit intermediate arithmetic and a saturating cast back to `u64` so monotonicity holds at the wrap edge; `resolution_ns_for_freq(frequency_hz)` returns the round-to-nearest period in nanoseconds, clamped to a floor of 1 ns to keep callers from dividing by zero on >2 GHz counters. Both functions are pure, host-testable, and sit at 100 % region coverage per the [2026-04-27 coverage rerun](../analysis/reports/2026-04-27-coverage-rerun.md). -The IRQ-armed half of the trait — `arm_deadline` / `cancel_deadline` — is `unimplemented!()` in QEMU virt's BSP today: it depends on the GIC + EL1 exception-vector-table install that [T-012](../analysis/tasks/phase-b/T-012-exception-and-irq-infrastructure.md) (B1) will land. The time-source half is fully wired and used by performance reviews and the boot-to-end timing instrumentation. +The IRQ-armed half of the trait — `arm_deadline` / `cancel_deadline` — is fully implemented in QEMU virt's BSP as of T-012 (Done 2026-04-28); the bodies write `CNTV_CVAL_EL0` / `CNTV_CTL_EL0` and route through `gic.enable(TIMER_IRQ)` / `gic.disable(TIMER_IRQ)`, audited under [UNSAFE-2026-0021](../audits/unsafe-log.md) (timer compare-register writes). [ADR-0010 §Revision notes 2026-04-28](../decisions/0010-timer-trait.md) records the closure: the time-source half landed with T-009 and the IRQ-delivery half with T-012, so both deferred halves of ADR-0010 are now live. -The kernel will use this trait for scheduler tick, deadline-based wakeups, and the `time_now` / `time_sleep_until` syscalls. In v1 the read side is exercised by the BSP's boot-to-end measurement; the IRQ side is dormant until T-012. +The kernel will use this trait for scheduler tick, deadline-based wakeups, and the `time_now` / `time_sleep_until` syscalls. In v1 the read side is exercised by the BSP's boot-to-end measurement; the IRQ-armed bodies are kernel-build clean but not exercised by the cooperative IPC demo (no caller arms a deadline). Their `Pending QEMU smoke verification` notation in [UNSAFE-2026-0021](../audits/unsafe-log.md) records this — the deadline-fire path lights up only when a future preemption-using task arrives. #### `Console` @@ -178,7 +178,7 @@ Runtime multi-board support (one kernel binary that detects its host and selects | Architecture | aarch64 | | CPU | generic ARMv8-A (whatever QEMU exposes for `-cpu max` / `-cpu cortex-a72`) | | RAM base | `0x4000_0000` | -| Interrupt controller | GICv3 | +| Interrupt controller | GICv2 | | Console | PL011 UART at `0x0900_0000` | | Timer | ARM generic timer | | IOMMU | SMMUv3 (optional, enabled with `-device smmuv3`; CI uses it) | diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index a643d57..2ff82ca 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -64,7 +64,7 @@ The kernel is **not** responsible for: drivers (every driver is a userspace task The HAL is the trait boundary between the kernel's portable core and any one board's concrete hardware. It is not a driver layer; drivers live in userspace. It is the narrow interface the kernel needs to manipulate the CPU, the [MMU](../glossary.md), the interrupt controller, and a minimal boot-time console. -Expected HAL trait surface (final form documented in `hal.md`, planned): +HAL trait surface (final form documented in [`hal.md`](hal.md), Accepted): - `Cpu` — disable / enable interrupts at the CPU level, halt / wait-for-interrupt, context-switch primitives. - `Mmu` — translation-table layout, entry installation, TLB invalidation. @@ -74,7 +74,7 @@ Expected HAL trait surface (final form documented in `hal.md`, planned): A BSP is a crate that implements these traits for a specific target. Initial BSPs: -- `bsp-qemu-virt` — QEMU `virt` aarch64 (GICv3, PL011 UART, generic timer). +- `bsp-qemu-virt` — QEMU `virt` aarch64 (GICv2, PL011 UART, generic timer). The QEMU `virt` machine defaults to GICv2; `bsp-qemu-virt` ships a v2-only driver in [`gic.rs`](../../bsp-qemu-virt/src/gic.rs) per [ADR-0011](../decisions/0011-irq-controller-trait.md), audited under [UNSAFE-2026-0019](../audits/unsafe-log.md). GICv3 requires `-machine gic-version=3` and is out of scope for v1. - `bsp-pi4` — Raspberry Pi 4 (BCM2711, legacy + GIC-400, mini-UART or PL011). The kernel depends on HAL traits. It does not `use` a BSP directly; the BSP is selected at build time. diff --git a/docs/architecture/scheduler.md b/docs/architecture/scheduler.md index 68c9302..0d5b824 100644 --- a/docs/architecture/scheduler.md +++ b/docs/architecture/scheduler.md @@ -8,7 +8,7 @@ Three Accepted ADRs jointly fix the scheduler's design: - [ADR-0019: Scheduler shape](../decisions/0019-scheduler-shape.md) — cooperative single-core FIFO; ready queue is a fixed-capacity bounded `SchedQueue` indexed against a per-task arena. Capacity is `TASK_ARENA_CAPACITY` (currently 16). - [ADR-0020: `ContextSwitch` trait and `Cpu` v2](../decisions/0020-cpu-trait-v2-context-switch.md) — register save/restore is a HAL primitive; the scheduler holds the per-task context array and never inspects its contents. -- [ADR-0022: Idle task and typed scheduler deadlock error](../decisions/0022-idle-task-and-typed-scheduler-deadlock.md) — the BSP registers an idle task at boot so the FIFO is never structurally empty; `SchedError::Deadlock` survives as a defensive return for preemption / SMP / a misconfigured BSP. ADR-0022's first rider clarifies that the idle task's body uses `core::hint::spin_loop` until [T-012](../analysis/tasks/phase-b/T-012-exception-and-irq-infrastructure.md) wires the timer IRQ. +- [ADR-0022: Idle task and typed scheduler deadlock error](../decisions/0022-idle-task-and-typed-scheduler-deadlock.md) — the BSP registers an idle task at boot so the FIFO is never structurally empty; `SchedError::Deadlock` survives as a defensive return for preemption / SMP / a misconfigured BSP. The idle task's body uses `cpu.wait_for_interrupt()` followed by `yield_now`; the time-source half (T-009) and IRQ-delivery half (T-012) of ADR-0010 are both live, so WFI is the production form. The interim `core::hint::spin_loop()` shape ADR-0022's first rider introduced was retired by T-012 (commit `b4ed68c`); see ADR-0022 §Revision notes 2026-04-28 for the closure of the first rider's *Sub-rider* under [UNSAFE-2026-0019](../audits/unsafe-log.md) / [UNSAFE-2026-0020](../audits/unsafe-log.md) / [UNSAFE-2026-0021](../audits/unsafe-log.md). The IPC bridge from the scheduler into endpoint state is the subject of its own ADR — [ADR-0021: Raw-pointer scheduler IPC-bridge API](../decisions/0021-raw-pointer-scheduler-ipc-bridge.md). The bridge surface is summarised below; the *unsafe* discipline behind it lives in [`ipc.md`](ipc.md) (which crosses into IPC's territory) and the audit log. @@ -70,7 +70,7 @@ stateDiagram-v2 ### Idle task and structural non-emptiness -ADR-0022 mandates that the BSP register a single, lowest-priority idle task at boot. Its presence makes the FIFO ready queue structurally non-empty for the lifetime of the kernel. The idle task's body in v1 is `core::hint::spin_loop()` followed by `yield_now`, not `wait_for_interrupt`, because no IRQ source is configured before [T-012](../analysis/tasks/phase-b/T-012-exception-and-irq-infrastructure.md). When T-012 lands, the body switches to `cpu.wait_for_interrupt(); yield_now(...)` and the scheduler's behaviour is unchanged from the outside. +ADR-0022 mandates that the BSP register a single, lowest-priority idle task at boot. Its presence makes the FIFO ready queue structurally non-empty for the lifetime of the kernel. The idle task's body is `cpu.wait_for_interrupt()` followed by `yield_now` — the production form ADR-0022's *Decision outcome* originally specified. T-012 (commit `b4ed68c`, Done 2026-04-28) closed ADR-0022's first rider's *Sub-rider* by landing both halves of the wake-source precondition (T-009's `CNTVCT_EL0` time source and T-012's GIC v2 + `VBAR_EL1` IRQ delivery), so WFI is now safe to issue under v1; the interim `core::hint::spin_loop()` shape the first rider introduced is retired. Audit citations: [UNSAFE-2026-0019](../audits/unsafe-log.md) (GIC MMIO), [UNSAFE-2026-0020](../audits/unsafe-log.md) (vector table), [UNSAFE-2026-0021](../audits/unsafe-log.md) (timer compare-register writes). See [`docs/architecture/exceptions.md` §"Idle's `wfi` activation"](exceptions.md) for the cross-cutting picture. Because idle is always `Ready`, every `yield_now` that would otherwise see an empty queue instead dispatches idle. This collapses the previous "panic on empty ready queue inside yield_now" path into normal scheduling — yield never panics in production. The empty-queue panic survives only inside `start` (where the kernel programmer must register at least one task before booting; structurally required by ADR-0022's idle-at-boot rule). diff --git a/docs/architecture/security-model.md b/docs/architecture/security-model.md index 7861f06..226a93b 100644 --- a/docs/architecture/security-model.md +++ b/docs/architecture/security-model.md @@ -327,7 +327,7 @@ Each of these is a future ADR. - **IOMMU / SMMU policy per target.** Raspberry Pi 4 has no SMMU — do we accept implicit trust of all enabled bus masters, refuse to enable DMA-capable devices and force PIO, or gate DMA-capable devices behind a deployment-time opt-in? QEMU `virt` has SMMUv3 and should be the CI gate that catches driver regressions against IOMMU expectations. Jetson Orin has an SMMU and adopts the same model when its port lands. ADR required before the first driver that enables bus-master DMA. - **Concrete bounds** for the quotas under *Bounded kernel resources*: numeric defaults for each, per-target tuning policy, and how upgrades change them without invalidating running systems. - **Cross-table capability derivation tree (CDT).** Whether IPC-transferred capabilities should retain a parent-child link to the sender's entry so that the sender can revoke the copy post-transfer, and — if so — how per-task-table CDT storage scales. seL4's answer is a whole-system CDT; Phase B needs to decide before the first multi-task system uses transfer as a revoke-retained grant. See the v1 qualification on *Revocation is transitive* above. -- **Early IRQ masking in BSP reset vectors.** v1's `boot.s` on QEMU `virt` does not explicitly `msr daifset, #0xf` before stack / BSS setup — the reset state happens to leave interrupts effectively masked (no IRQ source is configured and the GIC is untouched), but this is a per-platform accident rather than a guarantee. Future BSPs should adopt "mask DAIF first, everything else after" as a standard reset-vector prologue; add the instruction to the [BSP boot checklist](../standards/bsp-boot-checklist.md) and audit the existing checklist at that time. +- **Early IRQ masking in BSP reset vectors.** ✅ **Closed by [T-013](../analysis/tasks/phase-b/T-013-el-drop-to-el1.md) (Done 2026-04-27, ADR-0024, [UNSAFE-2026-0017](../audits/unsafe-log.md)).** `bsp-qemu-virt/src/boot.s:84` now begins `_start` with `msr daifset, #0xf` as the **literal first instruction** before stack/BSS setup, and the [BSP boot checklist §1a](../standards/bsp-boot-checklist.md) records "mask DAIF first" as a standard reset-vector prologue every future BSP must observe. The previous "per-platform accident" framing is retired; DAIF masking is now a structural property of every Tyrne reset vector, with the audit trail captured under UNSAFE-2026-0017's first Amendment block. Future BSPs (`bsp-pi4`, etc.) inherit the rule via the boot checklist. ## References diff --git a/docs/glossary.md b/docs/glossary.md index f3ea0bf..ca2e54c 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -22,7 +22,7 @@ Terminology used throughout Tyrne. Entries are alphabetical. If a term appears i **Capability transfer.** The IPC operation in which a sender's `ipc_send` atomically removes a capability from its own table, embeds it in the message, and delivers it into the receiver's table on `ipc_recv`. If either half fails, neither table is left in an intermediate state. See [ADR-0017](decisions/0017-ipc-primitive-set.md). -**CDT (Capability Derivation Tree).** The parent/child tree of capabilities derived from one another via `cap_derive`. Revocation is transitive along this tree: revoking a parent revokes every descendant. In v1 the tree is per-table; cross-table transitivity is deferred (see [ADR-0023](decisions/0023-cross-table-capability-revocation-policy.md) when opened). +**CDT (Capability Derivation Tree).** The parent/child tree of capabilities derived from one another via `cap_derive`. Revocation is transitive along this tree: revoking a parent revokes every descendant. In v1 the tree is per-table; cross-table transitivity is deferred — see ADR-0023 (accept-deferred per Phase B0 closure; no file at HEAD, tracked in [`phase-b.md`](roadmap/phases/phase-b.md) ADR ledger and the [B0 closure security review](analysis/reviews/security-reviews/2026-04-27-B0-closure.md)). **`CNTFRQ_EL0`.** ARM aarch64 system register that reports the Generic Timer's counter frequency in Hz. Set by firmware before kernel entry; read at EL0/EL1 (subject to `CNTHCTL_EL2.EL1PCTEN` only in VHE mode, which Tyrne does not use). QEMU virt sets it to 62.5 MHz. On real Pi 4 / BCM2711 the rate is firmware-dependent (mainline Linux configures 54 MHz; older Pi-class boards used 19.2 MHz) — BSPs read the firmware-provided value rather than hard-coding. Tyrne reads `CNTFRQ_EL0` once at `QemuVirtCpu::new` and caches the derived `resolution_ns`. From 16ba19560bcb39b293276802c9bff6b3550fa8ac Mon Sep 17 00:00:00 2001 From: Cemil ILIK Date: Thu, 7 May 2026 00:33:39 +0300 Subject: [PATCH 2/4] docs(root): refresh README/CONTRIBUTING/SECURITY for post-B1 reality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close three non-blocker drift items from Track E of the 2026-05-06 comprehensive code review. Each was a Phase-A-era framing that no longer matches the post-B1 tree. ## README.md Repository-layout tree previously listed only `docs/` + root-level files and ended with "Source code layout … will be added after the architecture phase." Phase A and B0/B1 are closed; the Rust workspace contains four crates totalling ~9 590 LOC. Replaced with the actual top-level layout (kernel/, hal/, test-hal/, bsp-qemu-virt/, tools/, plus the docs/ subdirectories — audits, analysis, roadmap), with crate-name annotations and pointers to ADR-0006, the two-task-demo guide, and current.md. ## CONTRIBUTING.md "There is no source code to extend or refactor meaningfully yet" is no longer accurate. Reframed to describe the actual contribution expectation: source PRs welcome but should align with the active milestone in current.md to avoid premature rewrites; the kernel boots end-to-end on QEMU virt today. ## SECURITY.md "There is no runnable kernel yet" is stale (kernel boots end-to-end on QEMU and runs the two-task IPC demo). The "(planned, Phase 2)" qualifier on the threat-model document is also stale — `docs/architecture/security-model.md` is Accepted at HEAD. Sentence rewritten to acknowledge current state while preserving the "pre-alpha; no production guarantees" framing. Refs: comprehensive-review-2026-05-06, ADR-0006 Co-Authored-By: Claude Opus 4.7 (1M context) --- CONTRIBUTING.md | 2 +- README.md | 10 +++++++++- SECURITY.md | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index beb8462..901c8e8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,7 +11,7 @@ Thank you for your interest. Tyrne is currently in the **architecture phase** ## What is not useful yet -- Pull requests against source code. There is no source code to extend or refactor meaningfully yet. Adding code before the architecture settles would force premature rewrites. +- Pull requests against source code outside the active milestone scope. The Rust workspace exists and the kernel boots end-to-end on QEMU virt (Phase A + B0/B1 closed), but each subsystem is being grown along the phased roadmap in [`docs/roadmap/`](docs/roadmap/); changes outside the current milestone's scope force premature rewrites and are usually not merged. Check [`docs/roadmap/current.md`](docs/roadmap/current.md) before opening a non-trivial PR. - Feature requests for subsystems that have not yet been designed. File those as discussion issues if you want to influence the design, not as feature requests. ## When the project enters the implementation phase diff --git a/README.md b/README.md index 8100a9b..fbcc13b 100644 --- a/README.md +++ b/README.md @@ -40,11 +40,19 @@ Tiers describe the level of support committed to a target, not the quality of th ``` . +├── kernel/ # tyrne-kernel: capability tables, IPC, scheduler +├── hal/ # tyrne-hal: portable Console/Cpu/ContextSwitch/Mmu/Timer/IrqController traits +├── test-hal/ # tyrne-test-hal: in-tree fakes for the HAL traits (host tests only) +├── bsp-qemu-virt/ # tyrne-bsp-qemu-virt: QEMU virt aarch64 BSP (boot.s, vectors.s, GIC v2, PL011) +├── tools/ # run-qemu.sh and other developer-side helpers ├── docs/ # All project documentation │ ├── architecture/ # System design, components, data flow │ ├── decisions/ # Architecture Decision Records (ADRs) │ ├── guides/ # How-to guides for contributors and porters │ ├── standards/ # Coding, documentation, review standards +│ ├── audits/ # `unsafe`-block audit log +│ ├── analysis/ # Tasks, reviews, reports +│ ├── roadmap/ # Phase plans + current focus │ └── glossary.md ├── CLAUDE.md # Entry point for Claude-based AI agents ├── AGENTS.md # Entry point for all AI agents @@ -54,7 +62,7 @@ Tiers describe the level of support committed to a target, not the quality of th └── NOTICE ``` -Source code layout — the Rust workspace, HAL crates, userspace services — will be added after the architecture phase. +The Rust workspace contains four crates (`kernel`, `hal`, `test-hal`, `bsp-qemu-virt`) per [ADR-0006](docs/decisions/0006-workspace-layout.md). The kernel boots end-to-end on QEMU virt today (Phase A + B0/B1 closed); see [`docs/guides/two-task-demo.md`](docs/guides/two-task-demo.md) for the boot trace and [`docs/roadmap/current.md`](docs/roadmap/current.md) for active work. ## Where to start reading diff --git a/SECURITY.md b/SECURITY.md index d6cb86c..fbcf81d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,7 +4,7 @@ Tyrne is a security-oriented operating system project. Even while it is in pre-a ## Project status and guarantees -Tyrne is **pre-alpha**. There is no runnable kernel yet. No production use is supported, and no security guarantees are made for the current tree. The formal threat model is a work in progress and will be documented in `docs/architecture/security-model.md` (planned, Phase 2). +Tyrne is **pre-alpha**. The kernel boots end-to-end on QEMU virt aarch64 (Phase A + B0/B1 closed) and runs a two-task IPC demo through to completion, but it is not yet a userspace-bearing OS — no production use is supported, and no security guarantees are made for the current tree. The formal threat model is documented in [`docs/architecture/security-model.md`](docs/architecture/security-model.md) (Accepted) and refined as Phase B progresses; both the model and the codebase will continue to evolve until the project reaches a stable release. ## Reporting a security issue From f710881aa0df623405fbac6f2ccf381aaf2b3b47 Mon Sep 17 00:00:00 2001 From: Cemil ILIK Date: Thu, 7 May 2026 00:34:14 +0300 Subject: [PATCH 3/4] docs(standards,decisions,guides): close non-blocker doc-drift cluster MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the remaining Track-E + Track-H + Track-I non-blocker doc drift items the comprehensive code review at HEAD `9cbf578` identified. All single-edit clarifications; no policy change. ## docs/standards/README.md Standards index missed `bsp-boot-checklist.md`. The file exists, is in active use (referenced from `unsafe-policy.md §5a`, `security-model.md §Open questions`, T-013 review-history), and is genuinely a `Accepted` standard — only the index row was missing. Added. ## docs/decisions/README.md ADR index jumped 0022 → 0024 with no row for ADR-0023, while `phase-b.md`'s ADR ledger and prose elsewhere reference ADR-0023 as accept-deferred. The two indices disagreed on whether a deferred-without-file ADR appears as a row. Added an ADR-0023 row in the index (Status: Deferred, no file link) so a future reader scanning the README does not miss the deferred slot. ## docs/decisions/template.md The template's status enum implicitly listed only Proposed / Accepted / Deprecated / Superseded by NNNN. ADR-0018 and ADR-0023 both use a real `Deferred` state introduced by ADR-0025-era governance amendments. Added a comment block after the frontmatter documenting the five recognised status values, including Deferred. ## docs/architecture/overview.md The "(final form documented in `hal.md`, planned)" parenthetical on the HAL trait surface is stale — hal.md is Accepted and shipped. Replaced "planned" with "Accepted" so `overview.md`'s framing matches `hal.md`'s actual status. ## docs/guides/two-task-demo.md Expected-output table previously omitted two production lines emitted by `bsp-qemu-virt::main.rs` post-T-009: `tyrne: timer ready (...)` and `tyrne: boot-to-end elapsed = ... ns`. Added both to the trace block with a note that the values are QEMU-default-dependent. Execution-trace prose now mentions idle's fallback-slot registration per ADR-0026, replacing the obsolete "a dedicated `wfe`-based idle path is Phase B work" line — that work landed in T-012, and T-014 / ADR-0026 then moved idle out of the FIFO into a fallback slot. Per-line table gains rows for the timer-ready and boot-to-end-elapsed lines. ## docs/standards/infrastructure.md Two doc-vs-state mismatches the comprehensive review surfaced: 1. **§Continuous integration → Required gates** listed `cargo audit` / `cargo vet check` / "QEMU smoke" as merge-blockers, but `.github/workflows/ci.yml` does not run any of the three (Cargo.lock has zero external entries, so the supply-chain gates would be no-ops; the QEMU smoke is maintainer-launched). Each gate now carries an inline parenthetical noting the conditional ("currently dormant: zero external dependencies" / "maintainer-launched only; no `qemu-smoke` CI job yet"). 2. **§Configuration files** previously listed `supply-chain/config.toml`, `supply-chain/audits.toml`, and `.github/dependabot.yml` as if present; none exist at HEAD. Split the table into "Present at HEAD" and "Planned (when first extern dep lands)" sub-headings, added the trigger pointer to `add-dependency` skill, and added a sentence noting that the lint set is canonical at `code-style.md §Lints` so the two standards stay obviously in sync. The Present table also picks up a one-line note that `miri` is added on-demand by the CI job, not declared in `rust-toolchain.toml`'s components array. Refs: comprehensive-review-2026-05-06, ADR-0018, ADR-0023, ADR-0025, ADR-0026 Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/decisions/README.md | 1 + docs/decisions/template.md | 10 ++++++++++ docs/guides/two-task-demo.md | 10 +++++++--- docs/standards/README.md | 1 + docs/standards/infrastructure.md | 21 ++++++++++++++++----- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/docs/decisions/README.md b/docs/decisions/README.md index d01583e..d38c49c 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -51,6 +51,7 @@ Each ADR contains: | 0020 | [`ContextSwitch` trait and `Cpu` v2](0020-cpu-trait-v2-context-switch.md) | Accepted | 2026-04-21 | | 0021 | [Raw-pointer scheduler IPC-bridge API](0021-raw-pointer-scheduler-ipc-bridge.md) | Accepted | 2026-04-22 | | 0022 | [Idle task and typed scheduler deadlock error](0022-idle-task-and-typed-scheduler-deadlock.md) | Superseded by 0026 (idle-task-location axis only; typed-error axis stands) | 2026-04-22 | +| 0023 | Cross-table capability revocation policy *(no file at HEAD — accept-deferred per Phase B0 closure; tracked in [`phase-b.md`](../roadmap/phases/phase-b.md) ADR ledger)* | Deferred | 2026-04-27 | | 0024 | [EL drop to EL1 policy](0024-el-drop-policy.md) | Accepted | 2026-04-27 | | 0025 | [ADR governance amendments: forward-reference contract, rider hygiene](0025-adr-governance-amendments.md) | Accepted | 2026-04-27 | | 0026 | [Idle dispatch via separate fallback slot](0026-idle-dispatch-fallback.md) | Accepted | 2026-05-06 | diff --git a/docs/decisions/template.md b/docs/decisions/template.md index ae0970f..0b5b78b 100644 --- a/docs/decisions/template.md +++ b/docs/decisions/template.md @@ -4,6 +4,16 @@ - **Date:** YYYY-MM-DD - **Deciders:** @cemililik + + + ## Context diff --git a/docs/guides/two-task-demo.md b/docs/guides/two-task-demo.md index f434d28..d8176a6 100644 --- a/docs/guides/two-task-demo.md +++ b/docs/guides/two-task-demo.md @@ -36,19 +36,21 @@ grep "Taking exception" /tmp/qemu_int.log ```text tyrne: hello from kernel_main +tyrne: timer ready (62500000 Hz, resolution 16 ns) tyrne: starting cooperative scheduler tyrne: task B — waiting for IPC tyrne: task A -- sending IPC tyrne: task B — received IPC (label=0xaaaa); replying tyrne: task A — received reply (label=0xbbbb); done tyrne: all tasks complete +tyrne: boot-to-end elapsed = ns ``` -After printing "all tasks complete", Task A enters a `core::hint::spin_loop()`. The kernel halts in this state; QEMU continues running but produces no further output. The specific instruction the hint lowers to is up to the compiler and is not load-bearing — a dedicated `wfe`-based idle path is Phase B work (see ADR-0019 open questions). Terminate with **Ctrl-A x** (QEMU monitor quit). +The frequency in `timer ready` (`62500000 Hz`) and the elapsed-time figure on the last line are QEMU-default values; on real hardware the frequency varies (see [ADR-0010 §References](../decisions/0010-timer-trait.md)) and the elapsed time depends on the host's QEMU performance — single-digit-millisecond order is typical on modern laptops. After printing "all tasks complete" and the boot-to-end timing line, Task A enters a `core::hint::spin_loop()`. Idle is registered separately via [`register_idle`](../../kernel/src/sched/mod.rs) per [ADR-0026](../decisions/0026-idle-dispatch-fallback.md), so once both application tasks are stuck in their spin tails the dispatcher's fallback resolves to idle, which issues `wait_for_interrupt` (`WFI`); QEMU continues running but produces no further serial output. Terminate with **Ctrl-A x** (QEMU monitor quit). ## Execution trace -The scheduler adds **Task B first**, then Task A, so B runs first: +The scheduler adds **Task B first**, then Task A, then registers idle in a separate fallback slot per ADR-0026, so B runs first; idle is consulted only when the ready queue is empty: 1. **Task B** starts, prints "waiting for IPC", calls `ipc_recv_and_yield`. No sender is ready → endpoint transitions to `RecvWaiting` → B is marked `Blocked`, B's context is saved, Task A is dequeued and restored. @@ -63,12 +65,14 @@ The scheduler adds **Task B first**, then Task A, so B runs first: | Line | What it confirms | |------|-----------------| | `hello from kernel_main` | Boot succeeded; PL011 console is operational. | -| `starting cooperative scheduler` | Capability tables, endpoint arena, IPC queues, and scheduler are all initialised. | +| `timer ready (62500000 Hz, resolution 16 ns)` | T-009: `Timer::now_ns` reads `CNTVCT_EL0` cleanly; cached frequency / resolution computation went through. | +| `starting cooperative scheduler` | Capability tables, endpoint arena, IPC queues, scheduler, GIC v2, EL1 vector table, and DAIF unmask all initialised. | | `task B — waiting for IPC` | Task B's entry function ran; `ipc_recv_and_yield` was invoked. | | `task A -- sending IPC` | Context switch from B to A worked; A's stack is intact. | | `task B — received IPC (label=0xaaaa); replying` | Context switch back to B worked; B received A's message with correct label. | | `task A — received reply (label=0xbbbb); done` | Context switch from B to A worked a second time; IPC reply delivered with correct label. | | `all tasks complete` | Phase A exit bar met. | +| `boot-to-end elapsed = ns` | T-009 measurement scaffold: the difference between a `now_ns` snapshot taken in `kernel_entry` and a `now_ns` call after Task A's tail. Order-of-magnitude only; not a benchmark. | ## Capability setup diff --git a/docs/standards/README.md b/docs/standards/README.md index 34a2efa..e817679 100644 --- a/docs/standards/README.md +++ b/docs/standards/README.md @@ -18,6 +18,7 @@ Standards are narrow and enforceable. They are not where we discuss philosophy ( | [commit-style.md](commit-style.md) | Conventional Commits format, scopes, trailers (`Refs: ADR-NNNN`, `Audit:`, `Security-Review:`), granularity. | Accepted | | [logging-and-observability.md](logging-and-observability.md) | Structured records, five levels, secret redaction, ISR-safe ring path, spans, metrics. | Accepted | | [infrastructure.md](infrastructure.md) | Toolchain pinning, dependency policy, CI gates, supply-chain (`cargo-vet`, `cargo-audit`, SBOM), reproducibility, branch protection, secrets. | Accepted | +| [bsp-boot-checklist.md](bsp-boot-checklist.md) | The reset-vector and early-boot discipline every BSP must observe (DAIF mask, EL drop to EL1, SP / BSS, FP/SIMD enable, vector-table install, GIC init, IRQ unmask order). | Accepted | | [release.md](release.md) | Semver convention, changelog, release gates (process / content / security), signing, rollback, security releases. | Accepted | | [localization.md](localization.md) | UTF-8 internal, English kernel output, no locale in the kernel, localization is a userspace concern. | Accepted | | [documentation-style.md](documentation-style.md) | English-only docs, Mermaid-only diagrams, file structure, linking, file naming, change policy. | Accepted | diff --git a/docs/standards/infrastructure.md b/docs/standards/infrastructure.md index 15511ff..c96c1b5 100644 --- a/docs/standards/infrastructure.md +++ b/docs/standards/infrastructure.md @@ -68,9 +68,9 @@ CI is expected to be set up early in Phase 4 (Rust toolchain + workspace skeleto - `cargo clippy --workspace --all-targets -- -D warnings` - `cargo test --workspace` — host-runnable unit and integration tests. - `cargo build --workspace --target aarch64-unknown-none` — kernel builds clean. -- QEMU smoke — kernel boots under `qemu-system-aarch64 -machine virt` and reaches the success marker. -- `cargo audit` — fails on known advisories. `cargo-audit` database is updated weekly in CI. -- `cargo vet check` — fails if any dependency is not audited. +- QEMU smoke — kernel boots under `qemu-system-aarch64 -machine virt` and reaches the success marker. *(As of 2026-05: maintainer-launched only; no `qemu-smoke` CI job yet — tracked as a B2-or-later roadmap follow-up.)* +- `cargo audit` — fails on known advisories. `cargo-audit` database is updated weekly in CI. *(Conditional — currently dormant: `Cargo.lock` carries zero external dependencies, so the gate would be a no-op. The job is wired in once the first extern dep lands per [add-dependency](../../.claude/skills/add-dependency/SKILL.md).)* +- `cargo vet check` — fails if any dependency is not audited. *(Same conditional — see `cargo audit` above.)* ### Advisory gates (warn, do not block) @@ -141,17 +141,28 @@ When the project moves out of solo phase: ## Configuration files +The lint set is canonical at [`code-style.md` §Lints](code-style.md#lints); every entry below either references that policy directly or layers narrowly on top of it. Keep both standards in sync when either changes. + +### Present at HEAD + | File | Purpose | |------|---------| -| `rust-toolchain.toml` | Pinned toolchain + required components. | +| `rust-toolchain.toml` | Pinned toolchain + required components. **Note:** `miri` is not listed in the components array; the Miri CI job adds it on-demand (`rustup toolchain install $NIGHTLY_PIN --component miri`), and a workspace-local `cargo +nightly miri test` invocation requires `rustup component add miri` once. | | `rustfmt.toml` | Formatter config. | | `clippy.toml` | Linter thresholds and allowed lints. | | `.cargo/config.toml` | Target triples, linker flags per target. | +| `.github/workflows/*.yml` | CI pipelines. Active jobs at HEAD: `lint-and-host-test`, `kernel-build`, `miri`, `coverage`. | + +### Planned (when first extern dep lands) + +| File | Purpose | +|------|---------| | `supply-chain/config.toml` | `cargo-vet` trust imports and thresholds. | | `supply-chain/audits.toml` | Local audits. | -| `.github/workflows/*.yml` | CI pipelines. | | `.github/dependabot.yml` | Dependency PR automation (to be enabled once standards are enforced in CI). | +The `supply-chain/` directory does not exist at HEAD — see [add-dependency](../../.claude/skills/add-dependency/SKILL.md) for the trigger that creates it. + ## Anti-patterns to reject - Upgrading the toolchain silently in an unrelated PR. From a30fb250773669cb3af217b433ab21977c47a82d Mon Sep 17 00:00:00 2001 From: Cemil ILIK Date: Thu, 7 May 2026 00:49:35 +0300 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20PR=20#13=20review-round=20=E2=80=94?= =?UTF-8?q?=20apply=207=20of=208=20findings=20(1=20corrected=20interpretat?= =?UTF-8?q?ion)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address inline + bot comments on PR #13. Each finding verified against current code; 7 applied, 1 applied with corrected interpretation (the suggested fix did not match the source). ## Applied 1. **scheduler.md line 11 + line 73** — Idle is a fallback slot, not a FIFO resident. (User inline comment + coderabbitai-bot + gemini-code-assist-bot.) Both passages now describe idle per ADR-0026: "lives in a dedicated `Scheduler::idle: Option` fallback slot — not in the FIFO ready queue — and the dispatcher consults it only when the ready queue is empty (`ready.dequeue().or(s.idle)`)". The "structurally non-empty FIFO" framing was inherited from ADR-0022 Option A and contradicted the same file's later §Revision notes that already records the ADR-0026 supersession. Both passages also drop the hardcoded commit `b4ed68c` per gemini's suggestion (commit hashes drift when history is rewritten; T-012 + Done date is the stable identifier). 2. **security-model.md line 330** — Replace `boot.s:84` line ref with `_start` symbol reference. (gemini-code-assist-bot.) Line numbers in `boot.s` drift on every asm edit; the `_start` symbol is stable and the rule is "literal first instruction of `_start`", so the reference now reads "The `_start` symbol in `bsp-qemu-virt/src/boot.s` now begins with `msr daifset, #0xf` as the **literal first instruction**". 3. **two-task-demo.md line 47** — Honestly describe what happens after "all tasks complete". (gemini-code-assist-bot, with **corrected interpretation**.) gemini's suggested fix said "Task A enters a loop that calls `yield_now()`" — but that does not match the actual source. `bsp-qemu-virt/src/main.rs:486` ends task_a with `loop { core::hint::spin_loop(); }` (no `yield_now`). Under a cooperative scheduler this means Task A holds the CPU forever and idle is **structurally never dispatched** in this demo. Doc text updated to match: "Task A enters `loop { core::hint::spin_loop() }`. The cooperative scheduler does not preempt; Task A never yields out of this loop, so the CPU stays parked there indefinitely … idle is structurally unreached and the WFI path stays cold." Idle's fallback-slot wiring is still correctly described per ADR-0026 — it is reachable in principle, just not exercised by this demo's tail behaviour. 4. **infrastructure.md line 72 + line 156** — Spell out "extern dep" as "external dependency". (sourcery-ai-bot ×2 + matches user's inline message.) Two occurrences in the file (line 72's `cargo audit` conditional note and line 156's "Planned" sub-heading); both replaced via a `replace_all` substitution. The body of the Planned section already said "external dependency" / "external dependencies" consistently; the abbreviation was an outlier. ## Verification `cargo fmt --check` clean (no source changes); doc-only PR. Diff stat: 4 files, +6/-6. Refs: PR #13, comprehensive-review-2026-05-06, ADR-0026 Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/architecture/scheduler.md | 4 ++-- docs/architecture/security-model.md | 2 +- docs/guides/two-task-demo.md | 2 +- docs/standards/infrastructure.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/architecture/scheduler.md b/docs/architecture/scheduler.md index 0d5b824..f2f4bee 100644 --- a/docs/architecture/scheduler.md +++ b/docs/architecture/scheduler.md @@ -8,7 +8,7 @@ Three Accepted ADRs jointly fix the scheduler's design: - [ADR-0019: Scheduler shape](../decisions/0019-scheduler-shape.md) — cooperative single-core FIFO; ready queue is a fixed-capacity bounded `SchedQueue` indexed against a per-task arena. Capacity is `TASK_ARENA_CAPACITY` (currently 16). - [ADR-0020: `ContextSwitch` trait and `Cpu` v2](../decisions/0020-cpu-trait-v2-context-switch.md) — register save/restore is a HAL primitive; the scheduler holds the per-task context array and never inspects its contents. -- [ADR-0022: Idle task and typed scheduler deadlock error](../decisions/0022-idle-task-and-typed-scheduler-deadlock.md) — the BSP registers an idle task at boot so the FIFO is never structurally empty; `SchedError::Deadlock` survives as a defensive return for preemption / SMP / a misconfigured BSP. The idle task's body uses `cpu.wait_for_interrupt()` followed by `yield_now`; the time-source half (T-009) and IRQ-delivery half (T-012) of ADR-0010 are both live, so WFI is the production form. The interim `core::hint::spin_loop()` shape ADR-0022's first rider introduced was retired by T-012 (commit `b4ed68c`); see ADR-0022 §Revision notes 2026-04-28 for the closure of the first rider's *Sub-rider* under [UNSAFE-2026-0019](../audits/unsafe-log.md) / [UNSAFE-2026-0020](../audits/unsafe-log.md) / [UNSAFE-2026-0021](../audits/unsafe-log.md). +- [ADR-0022: Idle task and typed scheduler deadlock error](../decisions/0022-idle-task-and-typed-scheduler-deadlock.md) — the BSP registers a single idle task at boot, and per [ADR-0026](../decisions/0026-idle-dispatch-fallback.md) it lives in a dedicated fallback slot consulted only when the ready queue is empty (`ready.dequeue().or(s.idle)`); idle is **not** a FIFO resident. `SchedError::Deadlock` survives as a defensive return when both halves of the dispatch chain resolve to `None` — preemption / SMP / a misconfigured BSP that forgot to call `register_idle`. The idle task's body uses `cpu.wait_for_interrupt()` followed by `yield_now`; the time-source half (T-009) and IRQ-delivery half (T-012) of ADR-0010 are both live, so WFI is the production form. The interim `core::hint::spin_loop()` shape ADR-0022's first rider introduced was retired by T-012 (Done 2026-04-28); see ADR-0022 §Revision notes 2026-04-28 for the closure of the first rider's *Sub-rider* under [UNSAFE-2026-0019](../audits/unsafe-log.md) / [UNSAFE-2026-0020](../audits/unsafe-log.md) / [UNSAFE-2026-0021](../audits/unsafe-log.md). The IPC bridge from the scheduler into endpoint state is the subject of its own ADR — [ADR-0021: Raw-pointer scheduler IPC-bridge API](../decisions/0021-raw-pointer-scheduler-ipc-bridge.md). The bridge surface is summarised below; the *unsafe* discipline behind it lives in [`ipc.md`](ipc.md) (which crosses into IPC's territory) and the audit log. @@ -70,7 +70,7 @@ stateDiagram-v2 ### Idle task and structural non-emptiness -ADR-0022 mandates that the BSP register a single, lowest-priority idle task at boot. Its presence makes the FIFO ready queue structurally non-empty for the lifetime of the kernel. The idle task's body is `cpu.wait_for_interrupt()` followed by `yield_now` — the production form ADR-0022's *Decision outcome* originally specified. T-012 (commit `b4ed68c`, Done 2026-04-28) closed ADR-0022's first rider's *Sub-rider* by landing both halves of the wake-source precondition (T-009's `CNTVCT_EL0` time source and T-012's GIC v2 + `VBAR_EL1` IRQ delivery), so WFI is now safe to issue under v1; the interim `core::hint::spin_loop()` shape the first rider introduced is retired. Audit citations: [UNSAFE-2026-0019](../audits/unsafe-log.md) (GIC MMIO), [UNSAFE-2026-0020](../audits/unsafe-log.md) (vector table), [UNSAFE-2026-0021](../audits/unsafe-log.md) (timer compare-register writes). See [`docs/architecture/exceptions.md` §"Idle's `wfi` activation"](exceptions.md) for the cross-cutting picture. +ADR-0022 mandates that the BSP register a single, lowest-priority idle task at boot. Per [ADR-0026](../decisions/0026-idle-dispatch-fallback.md) idle lives in a dedicated `Scheduler::idle: Option` fallback slot — **not** in the FIFO ready queue — and the dispatcher consults it only when the ready queue is empty (`ready.dequeue().or(s.idle)`). Idle therefore never displaces a real Ready task; it runs only when no other Ready task exists. The idle task's body is `cpu.wait_for_interrupt()` followed by `yield_now` — the production form ADR-0022's *Decision outcome* originally specified. T-012 (Done 2026-04-28) closed ADR-0022's first rider's *Sub-rider* by landing both halves of the wake-source precondition (T-009's `CNTVCT_EL0` time source and T-012's GIC v2 + `VBAR_EL1` IRQ delivery), so WFI is now safe to issue under v1; the interim `core::hint::spin_loop()` shape the first rider introduced is retired. Audit citations: [UNSAFE-2026-0019](../audits/unsafe-log.md) (GIC MMIO), [UNSAFE-2026-0020](../audits/unsafe-log.md) (vector table), [UNSAFE-2026-0021](../audits/unsafe-log.md) (timer compare-register writes). See [`docs/architecture/exceptions.md` §"Idle's `wfi` activation"](exceptions.md) for the cross-cutting picture. Because idle is always `Ready`, every `yield_now` that would otherwise see an empty queue instead dispatches idle. This collapses the previous "panic on empty ready queue inside yield_now" path into normal scheduling — yield never panics in production. The empty-queue panic survives only inside `start` (where the kernel programmer must register at least one task before booting; structurally required by ADR-0022's idle-at-boot rule). diff --git a/docs/architecture/security-model.md b/docs/architecture/security-model.md index 226a93b..b665293 100644 --- a/docs/architecture/security-model.md +++ b/docs/architecture/security-model.md @@ -327,7 +327,7 @@ Each of these is a future ADR. - **IOMMU / SMMU policy per target.** Raspberry Pi 4 has no SMMU — do we accept implicit trust of all enabled bus masters, refuse to enable DMA-capable devices and force PIO, or gate DMA-capable devices behind a deployment-time opt-in? QEMU `virt` has SMMUv3 and should be the CI gate that catches driver regressions against IOMMU expectations. Jetson Orin has an SMMU and adopts the same model when its port lands. ADR required before the first driver that enables bus-master DMA. - **Concrete bounds** for the quotas under *Bounded kernel resources*: numeric defaults for each, per-target tuning policy, and how upgrades change them without invalidating running systems. - **Cross-table capability derivation tree (CDT).** Whether IPC-transferred capabilities should retain a parent-child link to the sender's entry so that the sender can revoke the copy post-transfer, and — if so — how per-task-table CDT storage scales. seL4's answer is a whole-system CDT; Phase B needs to decide before the first multi-task system uses transfer as a revoke-retained grant. See the v1 qualification on *Revocation is transitive* above. -- **Early IRQ masking in BSP reset vectors.** ✅ **Closed by [T-013](../analysis/tasks/phase-b/T-013-el-drop-to-el1.md) (Done 2026-04-27, ADR-0024, [UNSAFE-2026-0017](../audits/unsafe-log.md)).** `bsp-qemu-virt/src/boot.s:84` now begins `_start` with `msr daifset, #0xf` as the **literal first instruction** before stack/BSS setup, and the [BSP boot checklist §1a](../standards/bsp-boot-checklist.md) records "mask DAIF first" as a standard reset-vector prologue every future BSP must observe. The previous "per-platform accident" framing is retired; DAIF masking is now a structural property of every Tyrne reset vector, with the audit trail captured under UNSAFE-2026-0017's first Amendment block. Future BSPs (`bsp-pi4`, etc.) inherit the rule via the boot checklist. +- **Early IRQ masking in BSP reset vectors.** ✅ **Closed by [T-013](../analysis/tasks/phase-b/T-013-el-drop-to-el1.md) (Done 2026-04-27, ADR-0024, [UNSAFE-2026-0017](../audits/unsafe-log.md)).** The `_start` symbol in [`bsp-qemu-virt/src/boot.s`](../../bsp-qemu-virt/src/boot.s) now begins with `msr daifset, #0xf` as the **literal first instruction** before stack/BSS setup, and the [BSP boot checklist §1a](../standards/bsp-boot-checklist.md) records "mask DAIF first" as a standard reset-vector prologue every future BSP must observe. The previous "per-platform accident" framing is retired; DAIF masking is now a structural property of every Tyrne reset vector, with the audit trail captured under UNSAFE-2026-0017's first Amendment block. Future BSPs (`bsp-pi4`, etc.) inherit the rule via the boot checklist. ## References diff --git a/docs/guides/two-task-demo.md b/docs/guides/two-task-demo.md index d8176a6..4ddcd65 100644 --- a/docs/guides/two-task-demo.md +++ b/docs/guides/two-task-demo.md @@ -46,7 +46,7 @@ tyrne: all tasks complete tyrne: boot-to-end elapsed = ns ``` -The frequency in `timer ready` (`62500000 Hz`) and the elapsed-time figure on the last line are QEMU-default values; on real hardware the frequency varies (see [ADR-0010 §References](../decisions/0010-timer-trait.md)) and the elapsed time depends on the host's QEMU performance — single-digit-millisecond order is typical on modern laptops. After printing "all tasks complete" and the boot-to-end timing line, Task A enters a `core::hint::spin_loop()`. Idle is registered separately via [`register_idle`](../../kernel/src/sched/mod.rs) per [ADR-0026](../decisions/0026-idle-dispatch-fallback.md), so once both application tasks are stuck in their spin tails the dispatcher's fallback resolves to idle, which issues `wait_for_interrupt` (`WFI`); QEMU continues running but produces no further serial output. Terminate with **Ctrl-A x** (QEMU monitor quit). +The frequency in `timer ready` (`62500000 Hz`) and the elapsed-time figure on the last line are QEMU-default values; on real hardware the frequency varies (see [ADR-0010 §References](../decisions/0010-timer-trait.md)) and the elapsed time depends on the host's QEMU performance — single-digit-millisecond order is typical on modern laptops. After printing "all tasks complete" and the boot-to-end timing line, Task A enters `loop { core::hint::spin_loop() }`. The cooperative scheduler does not preempt; Task A never yields out of this loop, so the CPU stays parked there indefinitely and QEMU continues running but produces no further serial output. Idle is registered separately via [`register_idle`](../../kernel/src/sched/mod.rs) per [ADR-0026](../decisions/0026-idle-dispatch-fallback.md) and is reachable in principle through the dispatcher's `ready.dequeue().or(s.idle)` fallback — but in this demo the application tasks never yield from their tails, so idle is structurally unreached and the WFI path stays cold. Terminate with **Ctrl-A x** (QEMU monitor quit). ## Execution trace diff --git a/docs/standards/infrastructure.md b/docs/standards/infrastructure.md index c96c1b5..d33ce14 100644 --- a/docs/standards/infrastructure.md +++ b/docs/standards/infrastructure.md @@ -69,7 +69,7 @@ CI is expected to be set up early in Phase 4 (Rust toolchain + workspace skeleto - `cargo test --workspace` — host-runnable unit and integration tests. - `cargo build --workspace --target aarch64-unknown-none` — kernel builds clean. - QEMU smoke — kernel boots under `qemu-system-aarch64 -machine virt` and reaches the success marker. *(As of 2026-05: maintainer-launched only; no `qemu-smoke` CI job yet — tracked as a B2-or-later roadmap follow-up.)* -- `cargo audit` — fails on known advisories. `cargo-audit` database is updated weekly in CI. *(Conditional — currently dormant: `Cargo.lock` carries zero external dependencies, so the gate would be a no-op. The job is wired in once the first extern dep lands per [add-dependency](../../.claude/skills/add-dependency/SKILL.md).)* +- `cargo audit` — fails on known advisories. `cargo-audit` database is updated weekly in CI. *(Conditional — currently dormant: `Cargo.lock` carries zero external dependencies, so the gate would be a no-op. The job is wired in once the first external dependency lands per [add-dependency](../../.claude/skills/add-dependency/SKILL.md).)* - `cargo vet check` — fails if any dependency is not audited. *(Same conditional — see `cargo audit` above.)* ### Advisory gates (warn, do not block) @@ -153,7 +153,7 @@ The lint set is canonical at [`code-style.md` §Lints](code-style.md#lints); eve | `.cargo/config.toml` | Target triples, linker flags per target. | | `.github/workflows/*.yml` | CI pipelines. Active jobs at HEAD: `lint-and-host-test`, `kernel-build`, `miri`, `coverage`. | -### Planned (when first extern dep lands) +### Planned (when first external dependency lands) | File | Purpose | |------|---------|