docs(B5): closure trio — security + performance + business (close Milestone B5)#35
Conversation
Standalone consolidated security pass over the B5 syscall boundary (T-020 IpcError split + Capability/CapObject Debug redaction K3-9; T-021 EL0→EL1 SVC dispatch), merged via PR #34 (f98e1af). Performed with a fresh 8-axis checklist after the PR's three code-review rounds + the adversarial multi-agent pass. Verdict: **Approve.** All eight applicable axes pass (cryptography N/A). The dispatcher is panic-free on every register-supplied input; every object-naming syscall is capability-gated before any effect (console_write on the new debug-console cap, closing the ambient-authority slip caught before ADR Accept); copy-from/to-user never dereferences an unvalidated user pointer, with the soundness basis honestly recorded as the user/kernel disjointness invariant (an empirical Miri probe disproved an earlier "overlap-tolerant" over-claim — overlap is UB regardless of the copy primitive via the &mut/& borrow exclusivity); T-020's Debug redaction closes the K3-9 secrets-leak path exactly where B5 first creates a userspace-reachable log channel. Both new unsafe entries (UNSAFE-2026-0029 trampoline asm, UNSAFE-2026-0030 copy-user) are policy-conformant; 0029 carries the required second-reviewer sign-off. Gates: host-test 240, test --release green, miri --workspace clean (0 UB), QEMU +0x200 proxy round-trip byte-stable with no new fault class. B5 builds the boundary mechanism but the real EL0 +0x400 transition is B6; three B6 carry-forward gates (per-task console_write window + per-page translation; SP_EL1 init; SYSCALL_STUB_TABLE → current-task table) are tracked in phase-b.md §B6. This pass can serve as the security leg of the eventual B5 closure trio (business + performance legs deferred — "security review first"). Refs: ADR-0013, ADR-0030, ADR-0031, ADR-0014 Security-Review: @cemililik (+ Claude Opus 4.8 agent) Audit: UNSAFE-2026-0029, UNSAFE-2026-0030 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…0036 (B5 review finding) The B5 syscall-boundary security review (this PR) re-surfaced the one finding actionable outside a phase gate: security-model.md §threat-model #7 + §Open questions still described QEMU `virt` as "launched with SMMUv3 and used in CI to catch driver misbehaviour" — a live contradiction with Accepted ADR-0036 (QEMU `virt` is GICv2 / no-IOMMU in v1; SMMUv3 is exposed only under an explicit `iommu=smmuv3` launch Tyrne does not use). It was N/A as a v1 *defect* (no bus-master driver exists, so the DMA boundary is inactive) but a stale doc claim, forward-flagged since the 2026-05-28 B4 closure. Reconciled conservatively: both sentences now state the v1 GICv2/no-IOMMU reality, point at ADR-0036, and reframe the SMMU-in-CI gate as a future IOMMU-equipped-target (Jetson Orin) item — preserving the model's IOMMU intent, correcting only the stale QEMU-`virt`-has-SMMUv3 claim. The review doc's §8 + forward-flags are updated to mark this RECONCILED (no longer carried forward). All other review forward-flags are correctly phase-deferred (B6 carry-forward gates / Phase-E fault containment / preemption-time ipc_send hardening / B5+ cap_map rights ADR) — no action now. Refs: ADR-0013, ADR-0036 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reviewer's GuideDocuments the consolidated security review for the B5 syscall boundary (T-020 + T-021) and reconciles the security model docs with ADR-0036 regarding QEMU File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✅ Files skipped from review due to trivial changes (2)
📝 WalkthroughWalkthroughAdds a B5 syscall-boundary security review, B5 closure business and performance artifacts, security-model/IOMMU wording fixes, index/README updates, and marks B5 CLOSED while promoting B6. ChangesB5 Syscall Boundary Security Review and Closure Artifacts
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="docs/analysis/reviews/security-reviews/2026-05-29-B5-syscall-boundary.md" line_range="90" />
<code_context>
+- **Phase-deferred placeholders unchanged.** [ADR-0033](../../../decisions/0027-kernel-virtual-memory-layout.md) (high-half migration — gates the per-task `TTBR0_EL1` swap + kernel mappings in the userspace AS, the prerequisite for ever running a real EL0 task) and ADR-0034 (kernel-image / per-section permissions — gates the first attacker-observable EL0 execution) remain slot-reserved.
</code_context>
<issue_to_address>
**issue (typo):** ADR reference label and linked filename appear inconsistent (0033 vs 0027).
The link text says ADR-0033 but the path points to `0027-kernel-virtual-memory-layout.md`. Please confirm which ADR is intended and update either the label or the target so they refer to the same ADR.
```suggestion
- **Phase-deferred placeholders unchanged.** [ADR-0027](../../../decisions/0027-kernel-virtual-memory-layout.md) (high-half migration — gates the per-task `TTBR0_EL1` swap + kernel mappings in the userspace AS, the prerequisite for ever running a real EL0 task) and ADR-0034 (kernel-image / per-section permissions — gates the first attacker-observable EL0 execution) remain slot-reserved.
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Code Review
This pull request adds the security review documentation for the B5 syscall boundary (T-020 and T-021) and updates the security model documentation to align with the GICv2/no-IOMMU configuration of the QEMU virt target. Feedback on the new security review document highlights a mismatch in a quoted assertion regarding NULL_CAP_HANDLE compared to the actual implementation in abi.rs, as well as an incorrect link for ADR-0033.
| - `task_yield` (3) / `task_exit` (4) take **no object-capability argument** — they act only on the caller's own task via the trusted current-task identity, which is the caller's inherent authority over its own execution thread (ADR-0031's "trust-boundary check is *is there a valid current task?*, plus the kernel never letting the caller name a *different* task"). No ambient authority over another object. | ||
| - **Adversarial probe — was `console_write` ever ambient authority?** It was, in the *first* ADR-0030/0031 draft (a P1/P4 violation), and was caught by the same-day maintainer review and folded into the ADR bodies **before Accept** (recorded in the 2026-05-29 `current.md` banner). The shipped code gates it on the debug-console cap. Verified by `dispatch::tests::console_write_with_no_cap_returns_cap_invalid_handle_no_output` (+ `…_wrong_kind…`, `…_without_write_right…`), each asserting the console captured **zero** bytes on a failed check. | ||
| - **The new capability surface is the narrowest possible addition, with no widening.** OK — `console_write` introduces exactly one new `CapObject::DebugConsole` (a **unit** variant — the debug console is a singleton with no per-instance kernel-object storage, so it carries no handle, the smallest object addition ADR-0031 names) + one new right `CapRights::CONSOLE_WRITE` (`1 << 7`, added to `KNOWN_BITS` so `from_raw` masks it correctly). The check requires *both* (right kind **and** the `CONSOLE_WRITE` right) — the narrowest sufficient authority; a debug-console cap minted with `CapRights::empty()` is correctly rejected (`…_without_write_right…` test). No existing check was widened. | ||
| - **`CapHandle::from_raw` (the new ABI-decode constructor) cannot forge authority.** OK — the syscall ABI decodes a userspace-supplied register word into a `CapHandle` via `CapHandle::from_raw(index, generation)` ([`cap/table.rs`](../../../../kernel/src/cap/table.rs)). The reconstructed handle is **not trusted**: every `CapHandle` is validated against the live slot's generation by `CapabilityTable::lookup` before use, so a forged / stale / out-of-range `(index, generation)` simply fails lookup with `CapError::InvalidHandle` → `SyscallError::Cap(InvalidHandle)`; it can never alias a live capability. The capability table remains per-subject and unforgeable ([ADR-0014](../../../decisions/0014-capability-representation.md)); `from_raw` only re-materialises a handle *into the caller's own table*. **Adversarial probe — can the null-handle sentinel collide with a live handle?** No — `encode_cap_handle` packs `(generation: u32) << 16 | (index: u16)` (bits 0..48); the sentinel `NULL_CAP_HANDLE = u64::MAX` sets bits 48..64. A `const _: () = assert!(NULL_CAP_HANDLE > ((u32::MAX << 16) | u16::MAX))` in [`abi.rs`](../../../../kernel/src/syscall/abi.rs) locks this at build time (added in the review-round), so a future `CapHandle` widening that could collide fails the build. |
There was a problem hiding this comment.
The quoted assertion assert!(NULL_CAP_HANDLE > ((u32::MAX << 16) | u16::MAX)) does not match the actual implementation in abi.rs, which uses as u64 casts: assert!(NULL_CAP_HANDLE > (((u32::MAX as u64) << 16) | (u16::MAX as u64))). Without these casts, u32::MAX << 16 would truncate/overflow in 32-bit arithmetic and fail to correctly represent the 48-bit maximum packed handle. The documentation should be updated to match the actual code.
| - **`CapHandle::from_raw` (the new ABI-decode constructor) cannot forge authority.** OK — the syscall ABI decodes a userspace-supplied register word into a `CapHandle` via `CapHandle::from_raw(index, generation)` ([`cap/table.rs`](../../../../kernel/src/cap/table.rs)). The reconstructed handle is **not trusted**: every `CapHandle` is validated against the live slot's generation by `CapabilityTable::lookup` before use, so a forged / stale / out-of-range `(index, generation)` simply fails lookup with `CapError::InvalidHandle` → `SyscallError::Cap(InvalidHandle)`; it can never alias a live capability. The capability table remains per-subject and unforgeable ([ADR-0014](../../../decisions/0014-capability-representation.md)); `from_raw` only re-materialises a handle *into the caller's own table*. **Adversarial probe — can the null-handle sentinel collide with a live handle?** No — `encode_cap_handle` packs `(generation: u32) << 16 | (index: u16)` (bits 0..48); the sentinel `NULL_CAP_HANDLE = u64::MAX` sets bits 48..64. A `const _: () = assert!(NULL_CAP_HANDLE > ((u32::MAX << 16) | u16::MAX))` in [`abi.rs`](../../../../kernel/src/syscall/abi.rs) locks this at build time (added in the review-round), so a future `CapHandle` widening that could collide fails the build. | |
| - **`CapHandle::from_raw` (the new ABI-decode constructor) cannot forge authority.** OK — the syscall ABI decodes a userspace-supplied register word into a `CapHandle` via `CapHandle::from_raw(index, generation)` ([`cap/table.rs`](../../../../kernel/src/cap/table.rs)). The reconstructed handle is **not trusted**: every `CapHandle` is validated against the live slot's generation by `CapabilityTable::lookup` before use, so a forged / stale / out-of-range `(index, generation)` simply fails lookup with `CapError::InvalidHandle` → `SyscallError::Cap(InvalidHandle)`; it can never alias a live capability. The capability table remains per-subject and unforgeable ([ADR-0014](../../../decisions/0014-capability-representation.md)); `from_raw` only re-materialises a handle *into the caller's own table*. **Adversarial probe — can the null-handle sentinel collide with a live handle?** No — `encode_cap_handle` packs `(generation: u32) << 16 | (index: u16)` (bits 0..48); the sentinel `NULL_CAP_HANDLE = u64::MAX` sets bits 48..64. A `const _: () = assert!(NULL_CAP_HANDLE > (((u32::MAX as u64) << 16) | (u16::MAX as u64)))` in [`abi.rs`](../../../../kernel/src/syscall/abi.rs) locks this at build time (added in the review-round), so a future `CapHandle` widening that could collide fails the build. |
| - "`unsafe` is audited" — OK (§3: UNSAFE-2026-0029/0030 land under the Operation/Invariants/Rejected-alternatives shape; 0029 second-reviewer-signed). | ||
| - "Bounded kernel state / no unbounded allocation / panic-free on untrusted input" — OK (§4: typed `SyscallError` on every path; bounded chunk loop; no heap). | ||
| - "Fault containment does not leak authority" — **partially exercised; the dispatcher is panic-free, but full fault containment is Phase E.** A *dispatcher* failure returns a typed error (done). But a crashing EL0 task's fault (illegal instruction, unmapped deref) still routes to `panic_entry` → halt — the supervisor-endpoint `TaskFault` delivery is Phase E / flag K3-4 (recorded in [phase-b.md §B5 flags](../../../roadmap/phases/phase-b.md#flags-to-resolve-during-b5)). Non-blocking for B5 (no EL0 task to crash yet); confirmed-deferred per the B5 flag. | ||
| - **Phase-deferred placeholders unchanged.** [ADR-0033](../../../decisions/0027-kernel-virtual-memory-layout.md) (high-half migration — gates the per-task `TTBR0_EL1` swap + kernel mappings in the userspace AS, the prerequisite for ever running a real EL0 task) and ADR-0034 (kernel-image / per-section permissions — gates the first attacker-observable EL0 execution) remain slot-reserved. |
There was a problem hiding this comment.
The link for ADR-0033 incorrectly points to 0027-kernel-virtual-memory-layout.md (which is the file for ADR-0027). Since ADR-0033 is described as slot-reserved (similar to ADR-0034), the link should be removed or updated to point to the correct 0033-high-half-migration.md placeholder file if it exists.
| - **Phase-deferred placeholders unchanged.** [ADR-0033](../../../decisions/0027-kernel-virtual-memory-layout.md) (high-half migration — gates the per-task `TTBR0_EL1` swap + kernel mappings in the userspace AS, the prerequisite for ever running a real EL0 task) and ADR-0034 (kernel-image / per-section permissions — gates the first attacker-observable EL0 execution) remain slot-reserved. | |
| - **Phase-deferred placeholders unchanged.** ADR-0033 (high-half migration — gates the per-task `TTBR0_EL1` swap + kernel mappings in the userspace AS, the prerequisite for ever running a real EL0 task) and ADR-0034 (kernel-image / per-section permissions — gates the first attacker-observable EL0 execution) remain slot-reserved. |
B5 closure performance baseline — the performance leg of the B5 syscall-boundary closure trio. Re-baseline of kernel footprint + boot-to-end timing after T-020 + T-021 (PR #34, f98e1af) versus the 2026-05-28 B4 closure baseline. Footprint (release): .text 34,648 (+1,524) / .rodata 4,856 (+296) / .bss 50,592 (+2,272) = ~88.0 KiB (+4.76 %) — the smallest non-refactor .text growth in Phase B (the syscall boundary is a thin validator/dispatch layer). Tests 339 (43 hal + 240 kernel + 53 test-hal + 3 doc; +53 kernel), miri clean (0 UB, run locally). Release harness band p10/p50/p90 = 17.645 / 20.300 / 24.706 ms. Verdict: baseline, no proposal. The cycle's decisive measurement was a same-host back-to-back control (the B4 binary 3ab029f rebuilt + re-measured this session): it proves the ~+2.9 ms p10/p50 delta vs B4 is REAL B5 code (the boot SVC-smoke — 2 exception round-trips + cold TCG translation), not host jitter, correcting an initial mis-read of the noisier raw band. One-time-at-boot, ~us on real hardware. The control also shows the QEMU-TCG harness is nearing its resolving floor for small milestones (per-milestone signal ~ session jitter). Adds the harness report docs/analysis/reports/perf-baseline-2026-05-29-B5-closure.md and the README index row. Refs: ADR-0013, ADR-0030, ADR-0031 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
B5 closure retrospective — the business leg of the B5 syscall-boundary closure trio — plus the roadmap forward motion it drives. Formally closes Milestone B5 (Syscall boundary): T-020 (IpcError taxonomy split + Capability/CapObject Debug redaction) + T-021 (EL0 to EL1 SVC dispatch) merged via PR #34 (f98e1af); ADR-0030 + ADR-0031 Accepted. What landed (canonical metrics, reproduced live at afeed10): 339 host tests (+53 kernel) incl. local miri 0 UB; release ELF ~88.0 KiB (+4.76 % vs B4); release smoke clean to "all tasks complete" (the release trace itself proves the console_write debug-gate — status=0x1 in release); the debug smoke shows the full console_write SVC round-trip (status=0x0, bytes=63); -d = 712/776 PL011 + 2 expected SVC exceptions (EL1 to EL1, ESR 0x15, clean ERET), zero new fault class; audit log 30 entries (29 Active) — UNSAFE-2026-0029/0030. What we learned: the pure-Rust (T-020) / hardware-boundary (T-021) split per CLAUDE.md section 6 let the most security-sensitive milestone land safely in one calendar day without skipping rigor; an adversarial pass + Miri corrected a real copy-user soundness over-claim (disjointness, not the copy primitive, is the basis); a same-host perf control corrected a host-jitter mis-attribution; ABI front-loading kept the syscall numbers a decision, not an accident. Side-effects: current.md banner + Pathfinder flipped to B5-closed / B6-next; phase-b.md section B5 status -> Closed; test-count drift (236/240 mid-arc -> live 339) reconciled; business-reviews README index row added. Next: B6 (first userspace "hello") — the deferred task_create_from_image bridge + the 3 T-021 carry-forward gates + the ADR-0033 high-half opening; B6's review is the Phase B retrospective. Refs: ADR-0013, ADR-0030, ADR-0031, ADR-0017, ADR-0033 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…quence Pre-B6 documentation preparation on the B5-closure branch (rides in PR #35), done before B6 development starts on its own branch off main. Docs-only. (1) B5-done status reconcile (drift sweep). With B5 closed, several live docs still treated the syscall boundary as future/next: - CLAUDE.md: "the syscall ABI and first userspace task are next" -> the syscall boundary is done; the first EL0 task is next. - README.md status table: "Syscall ABI + EL0 entry | Next - Phase B5" -> split into "Syscall ABI + dispatcher = Done (B5)" + "First userspace hello (EL0) = Next (B6)". - phase-b ADR ledger: ADR-0030 / ADR-0031 marked Accepted 2026-05-29; ADR-0033 / ADR-0034 triggers corrected from B5/B5+ to B6 (B5 closed via the SVC proxy without surfacing the per-task TTBR0 swap, so the trigger is now B6). - architecture docs (task-loader / memory-management / boot): "ADR-0033 gated on B5 surfacing per-task TTBR0 swap" -> B6, and "until B5 adds a per-task context surface" -> B6 — these would have misled a B6 dev about which milestone owns the EL0 context + high-half work. (2) B6 opening sequence & prerequisites — the careful B6 plan, made durable in phase-b.md section B6. States the gating prerequisite (the kernel must stay reachable from every task's active translation, else an EL0 SVC vector fetch translation-faults), the ADRs that open B6 (ADR-0033 kernel-in-every-AS + the EL0-task-context decision + optional ADR-0034), and the dependency-ordered task sequence: ADR-0033 impl -> EL0 context -> task_create_from_image -> the 3 T-021 carry-forward gates -> tyrne-user + userland/hello -> wire-up + EL0 round-trip smoke -> Phase B retrospective. Decisions remain open for their ADRs; this fixes only the order + rationale. All links resolve; docs-only, no kernel changes. Refs: ADR-0013, ADR-0027, ADR-0030, ADR-0031, ADR-0033 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/roadmap/phases/phase-b.md`:
- Around line 315-316: The table row for ADR-0034 contains an unescaped pipe
inside inline code (`USER|EXECUTE`) which makes the Markdown parser treat the
row as five columns; update the ADR-0034 row in phase-b.md to escape the pipe
inside the inline code (e.g., change `USER|EXECUTE` to `USER\|EXECUTE`) so the
table remains four columns like ADR-0033, ensuring the rest of the row text and
links (ADR-0034, ADR-0033, references to ADR-0027 and memory-management.md) are
unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 72daf8c4-4651-46fa-acea-c0d2f178f223
📒 Files selected for processing (6)
CLAUDE.mdREADME.mddocs/architecture/boot.mddocs/architecture/memory-management.mddocs/architecture/task-loader.mddocs/roadmap/phases/phase-b.md
✅ Files skipped from review due to trivial changes (5)
- docs/architecture/boot.md
- CLAUDE.md
- docs/architecture/memory-management.md
- docs/architecture/task-loader.md
- README.md
… table pipe Three review findings on the B5 closure docs, each verified against the source: - abi.rs assert quote (security review section 1): the doc quoted assert!(NULL_CAP_HANDLE > ((u32::MAX << 16) | u16::MAX)) but the actual abi.rs:42 uses `as u64` casts — (((u32::MAX as u64) << 16) | (u16::MAX as u64)) (without them the shift overflows in u32 arithmetic). Quote corrected to match. - ADR-0033 link (security review section 8): the label said "ADR-0033" but the link targeted 0027-kernel-virtual-memory-layout.md (a mismatch). ADR-0033 (high-half migration) is genuinely the right concept — 0027 only reserves the slot — so rather than relabel to ADR-0027 (which would misattribute high-half to 0027), ADR-0033 is now plain text (matching the unlinked ADR-0034 in the same sentence) with a correctly-labeled "reserved in ADR-0027" cross-reference. - ADR-0034 ledger row (phase-b.md): the inline code USER|EXECUTE (introduced in the pre-B6 prep commit) had an unescaped pipe, splitting the table row into five columns; escaped to USER\|EXECUTE. All 14 ledger rows now have 4 columns. Validated: assert quote matches abi.rs:42 verbatim; all links resolve; every ADR-ledger row is well-formed (5 delimiters = 4 columns). Docs-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
B5 closure trio — close Milestone B5 (Syscall boundary)
Docs-only. The B5 implementation (T-020 + T-021) already merged to
mainvia #34 (f98e1af); this PR lands the closure trio that formally promotes Milestone B5 from implementation-complete to Closed, plus one B4-forward-flagged doc reconcile. No kernel changes — the kernel binary is byte-identical tof98e1af.Commits
c424dcbsecurity review — Approve, eight axes; the EL0→EL1 boundary is panic-free, capability-gated, copy-user-validated; UNSAFE-2026-0029/0030 policy-conformant (0029 second-reviewer-signed).afeed10security-model.md SMMUv3 reconcile — closes a B4 forward-flag: the two stale "QEMUvirthas SMMUv3 / is the CI gate" claims now state the v1 GICv2/no-IOMMU reality and point at ADR-0036.a5395b7performance baseline — re-baseline; a same-host control (the B4 binary3ab029frebuilt + re-measured this session) proves the ~+2.9 ms p10/p50 delta vs B4 is a real one-time bootSVC-smoke cost, not host jitter (it corrected an initial mis-read of the noisier band; the B4 binary reproduced its own p50 across sessions).0b665dbbusiness retrospective + roadmap forward motion (current.mdbanner/Pathfinder → B6;phase-b.md§B5 → Closed; the mid-arc test-count drift 236/240 → live 339 reconciled).Closing metrics (reproduced live at
afeed10)cargo miri test --workspace --exclude tyrne-bsp-qemu-virtclean (0 UB, run locally — first closure to do so).fmt/host-clippy/kernel-clippy/kernel-buildclean..text 34,648 / .rodata 4,856 / .bss 50,592(~88.0 KiB, +4.8 % vs B4 — the smallest non-refactor.textgrowth in Phase B).tyrne: all tasks complete;-d int,unimp,guest_errors= 712 (release) / 776 (debug) pre-existing PL011 warnings + 2 expectedSVCexceptions (EL1→EL1,ESR 0x15/0x56000000= SVC64, cleanERET), zero new fault class.Reviews
Next
Milestone B6 (first userspace "hello", the Phase-B-closing milestone) opens on a fresh branch off this PR's merge. The openers: ADR-0033 (kernel-reachable-from-every-AS / high-half, so an EL0 task's
SVCvector fetch translates), the deferredtask_create_from_imagebridge (LoadedImage→ runnableTaskCap), and the three T-021 carry-forward gates (per-taskconsole_writewindow + per-page user-VA translation;SP_EL1init for the+0x400entry;SYSCALL_STUB_TABLE→ current-task table).🤖 Generated with Claude Code
Summary by CodeRabbit