Optional mainline K230 restart source and host evidence
Latest physical result
The 2026-10-02 clock comparison
passed automatic candidate kernel restart → SPL → protected normal recovery
with a temporary clk_ignore_unused diagnostic argument. Task 5d.4 is
proved for that boot; the baseline still stalls. Usable mainline root and
deliberate touch remain UNVERIFIED, and a proper clock-consumer fix remains.
The host-only records below retain their original limits.
On 2026-10-02, the optional DRM candidate’s K230 reset object compiled successfully against headers prepared from the exact pinned candidate source. Nix also built the patched source derivation. These are host source and object checks; automatic restart on this board remains UNVERIFIED. After the recorded GCC correction, the complete kernel and its matching trial bundle build/inspection also passed; those separate host results are recorded below. None is physical restart evidence. No serial port, board staging, flash or reboot was used for these checks.
The change is on mainline-restart-port, in
/home/jadams/tmp/k230-mainline-restart, based on
c5254075e531487af82841b3ae76582e5535f0fb. The coordinator reserved the
single build slot; every compilation/build uses /tmp/k230-nix-build.lock.
The board remains reserved to the coordinator.
Read source and boundary
The pinned vendor source is
drivers/reset/reset-k230.c,
read from the local vendor source output. Its k230_restart() maps four
bytes at 0x91102000 + 0x60, writes (1 << 0) | (1 << 16), and waits
indefinitely. Its k230_restart_register() sets priority 128. The prior
restart audit
records the vendor normal restart reaching U-Boot SPL, absent advertised
SBI SRST in the mainline logs, mainline’s peripheral-only reset controller,
and the distinct userspace refusal and operator recovery.
The mainline source remains
72d3fcf802c45d00b300f25b848a93c3a2bd7c7e (Linux 7.3-rc5).
include/linux/reboot.h
and kernel/reboot.c
provide devm_register_sys_off_handler(), a managed cleanup action and
priority selection. Its convenience restart wrapper uses priority zero;
the port instead preserves vendor priority 128. Non-default duplicate
priorities return -EBUSY, which the probe propagates.
nix/patches/mainline/k230-restart.patch adds restart support alongside the
mainline peripheral reset implementation. Only nix/kernel-mainline-drm.nix
applies it. The callback retains the vendor address, 32-bit write mask and
terminal wait (cpu_relax()); it performs no allocation or mapping.
Probe maps the vendor register with devm_ioremap(), checks failure,
registers the existing managed peripheral controller, and checks managed
restart registration. Release order unregisters the handler before either
mapping and the per-device allocation. The callback therefore has no stale
mapping after failed registration or removal. The driver already receives
the mainline canaan,k230-rst node; no device-tree change is needed. Its
peripheral resource at 0x91101000 is distinct from the boot-control
register, and the peripheral CPU0 reset ID is not used for restart.
This deliberately does not change stage 1/OpenSBI or write registers from userspace. It retains the vendor’s indefinite wait if the hardware reset does not happen; an operator power cycle remains the recovery procedure until physical reset is proved. It does not explain or claim to solve the candidate’s usable-root failure.
Initial source derivation and LLVM object proof
Commands (both exited zero):
flock /tmp/k230-nix-build.lock nix build .#kernelMainlineDrm.src \
--no-link --print-out-paths --max-jobs 1 --cores 4
flock /tmp/k230-nix-build.lock env \
MAINLINE_RESTART_SRC=/nix/store/vnzm30w6v4na0ylpw8vclyn7dn9vvkf0-linux-mainline-k230-drm-src \
bash docs/evidence/mainline-restart/object-check.sh
The first command produced
/nix/store/vnzm30w6v4na0ylpw8vclyn7dn9vvkf0-linux-mainline-k230-drm-src;
source-build.log records evaluation, source restoration
and patch application. The second prepared actual headers in an isolated
.scratch/ build directory from that exact source with RISC-V defconfig,
using host LLVM/Clang 22.1.8, then compiled only reset-k230.o with W=1.
The former full candidate’s dev output had been garbage-collected, so this
check regenerated pinned headers instead of borrowing a different kernel’s
prepared headers. It is not the Nix GCC configuration or a full link.
object-check.log records UTC 2026-10-02T15:38:08Z,
CONFIG_64BIT/RISCV/OF/RESET_CONTROLLER/RESET_K230=y, no compiler warning,
and the produced RISC-V relocatable object. The object contains
k230_rst_restart with the expected unresolved references to managed
mapping and sys-off registration (no modpost or full-kernel link claimed).
- Patched reset source SHA-256:
285e7198a1bd162a46cb8a3c1557c6a9724c0b6c9c0e8c75879659992ef46b80. - Pinned reboot header SHA-256:
48cf7704d93c9799a869759587736aa84dfaa671a8a7075ce750deb809598a85. - Object SHA-256:
357180aca45dab25c70a940df16d809d7c33afc03cd336e3c14f5ccd98a15aa2. - Object-check config SHA-256:
feae74c06f4924981806903df93e621a39413c2993fdff45ee32172bf3cc1140.
GCC failure, correction and pinned GCC object proof
The first complete Nix/GCC kernel invocation (four cores) failed in
k230_rst_restart() at -Werror=return-type. LLVM accepted the terminal
loop without an explicit return, but GCC 15.3 requires it here. The initial
port omitted the vendor’s unreachable return 0; the correction restores
it as return NOTIFY_DONE after the unchanged terminal cpu_relax() wait.
The address, write mask and priority are unchanged. This failed run is kept
in kernel-build-failure-invocation.log
and kernel-build-failure.log; the latter preserves
the complete build text with ANSI/OSC escapes removed for readability.
It is failed build evidence, not a complete kernel result.
The corrected source derivation build exited zero and produced
/nix/store/jvz4v73g8a67pqwm06v079h6s1cpqr9s-linux-mainline-k230-drm-src
(source-build-corrected.log). The pinned GCC
15.3.0 object invocation also exited zero with W=1 and no compiler warnings:
flock /tmp/k230-nix-build.lock env \
MAINLINE_RESTART_SRC=/nix/store/jvz4v73g8a67pqwm06v079h6s1cpqr9s-linux-mainline-k230-drm-src \
MAINLINE_RESTART_CONFIG=/nix/store/7zp582356s9ss40wjjc0drgxh0vihhi9-linux-config-riscv64-unknown-linux-gnu-7.3.0-rc5 \
MAINLINE_RESTART_CROSS_COMPILE=/nix/store/4j2mwxqjvnyr6da0925sp0bm4jaj5r5i-riscv64-unknown-linux-gnu-gcc-wrapper-15.3.0/bin/riscv64-unknown-linux-gnu- \
bash docs/evidence/mainline-restart/object-check.sh
gcc-object-check.log starts at UTC
2026-10-02T16:06:15Z. The script copies the actual Nix candidate config,
clears GCC plugin/debug/Rust requests unnecessary to this object check,
and regenerates headers with the pinned GCC toolchain. The resulting config
and compiler are recorded rather than claimed byte-identical to the full
Nix build. This checks the same reset source with the compiler that named
the error; it still does not link a complete kernel or execute reset.
- Corrected reset source SHA-256:
9007d8e3b4de77149bcfaf37a9148a5d8b7bdeafbe2b66b8fcd02268ee849fd8. - GCC object SHA-256:
f6ccce5cc537e390514e3eae6e361a9f4fd07dff3f964439be6fb43d5932de46. - GCC object-check config SHA-256:
40fee52e7dc0d13cc9cd98c51925da55f99c0a4a85c74b390715c264d88cf758.
The coordinator authorized --max-jobs 1 --cores 16 for the corrected full
kernel retry and subsequent matching bundle, under the same single build
lock. The first four-core failed invocation is not overwritten.
Complete corrected kernel and matching trial bundle
The corrected complete kernel invocation exited zero:
flock /tmp/k230-nix-build.lock nix build .#kernelMainlineDrm \
--no-link --print-out-paths --max-jobs 1 --cores 16 --log-format raw
kernel-build-invocation.log names output
/nix/store/4wkhxf55y1abg1kg2xd0acsfjqr64j0h-linux-riscv64-unknown-linux-gnu-7.3.0-rc5.
kernel-build.log preserves the full corrected in-tree
GCC build, including drivers/reset/reset-k230.o, final kernel link and
installation; ANSI/OSC escapes and trailing spaces were removed for
readability and repository whitespace checks. The log
contains existing prototype/unused-variable warnings in Canaan DRM, RTC and
SD/MMC files; no reset-driver warning or final-link error remains. Storage
waiting dominated link/install time; the extra cores did not remove that
limit. No kernel source, build flags or configuration were changed to work
around storage wait.
kernel-artifact-inspection.log records UTC
2026-10-02T16:48:07Z, the 38,530,560-byte Image, reset source identity and
System.map linkage. Image SHA-256 is
70a81b2172710c64463b53693e2e505a4d82ae2f7b644b2fc93cee9016b05330.
The completed dev output is
/nix/store/5wfn6k1lm9fvbwny2qk52admhwm5q4rm-linux-riscv64-unknown-linux-gnu-7.3.0-rc5-dev;
its installed .config SHA-256 is
c5c128ed8b9701f78a0b8bd4f18dacd0d2407ae90eda79a35bba2d9f5ffbeae7.
config-inspection.log confirms built-in
RESET_K230, RESET_CONTROLLER, RISCV_SBI and POWER_RESET.
The kernel derivation’s source is the corrected jvz4v73... output above;
its reset file matches the pinned GCC object check. The prepared dev output
retains the headers/build inputs needed by external modules rather than every
driver .c file, so reset source identity is checked in the derivation’s
actual source output. System.map contains k230_rst_restart and
devm_register_sys_off_handler; linkage does not prove probe-time handler
registration or a physical reset.
The matching bundle invocation and inspector both exited zero:
flock /tmp/k230-nix-build.lock nix build .#kernelMainlineDrmTrialBootFiles \
--no-link --print-out-paths --max-jobs 1 --cores 16 --log-format raw
nix shell --inputs-from . nixpkgs#dtc --command \
python3 tools/mainline-drm-trial-inspect.py \
/nix/store/asj7l4zj5jrjkgng4nrcx3y72p7jf7aa-k230-mainline-drm-trial-boot-files
bundle-build.log and bundle-inspection.log preserve the exact results:
| Artifact | Store path |
|---|---|
| Bundle | /nix/store/asj7l4zj5jrjkgng4nrcx3y72p7jf7aa-k230-mainline-drm-trial-boot-files |
| System | /nix/store/v9qc1sf0iz53s3x6g6vwfyaxghkfpnyk-nixos-system-nixos-26.11.20260919.20b1ddd |
| Kernel | /nix/store/4wkhxf55y1abg1kg2xd0acsfjqr64j0h-linux-riscv64-unknown-linux-gnu-7.3.0-rc5 |
| Base DRM DTB | /nix/store/nxbrd4smrcmknipjn4hjk32n87p4g9k6-k230-tdisplay-mainline-drm.dtb |
The bundle DTB embeds the new system’s exact init= path, while its base DTB
input is unchanged. The inspector verifies Image identity, DTB/environment
bootargs, U-Boot header/payload CRCs, the exact system initrd payload and all
629 closure paths. bundle-hashes.log records the four
boot artifacts’ SHA-256 values; the initrd wrapper hash is
2a4cc196d510bde579498c69758c9e3c52e0a23d6dda8d3297fd16280413d80e.
The kernel, dev output and bundle are protected by host GC roots under this
worktree’s ignored .scratch/mainline-restart-{kernel,kernel-dev,bundle}.
This is host artifact preservation, not board staging or deployment.
python3 docs/evidence/mainline-restart/compare-identities.py exited zero:
unchanged-identities.log compares nine exact
vendor/default/console-only derivation identities to base c5254075...,
including Image-only and full console boot-files collectors. All match.
This isolates this change against its base; other agents’ later changes to
master are outside that comparison. flake-check.log
records corrected-source nix flake check --no-build passing. Strict
OpenSpec validation also passes. Task 5d.2/5d.3 host gates are complete;
5d.4 and 5b.5 remain open.
Remaining gates
Task 5d.4 requires a reviewed, reserved operator trial and committed console proof of a real kernel restart returning through stage 1 to the protected normal system with a fresh boot ID and normal hashes/shell postflight. The operator’s serial capture command is:
flock /tmp/k230-board.lock python3 tools/console.py /dev/ttyACM0 --wait=10
The coordinator’s reviewed controller at 48c83245 accepts the exact bundle
and protected private manifest/report explicitly. Use that controller (the
older controller at this worktree’s base has no --bundle argument), without
changing global defaults:
python3 tools/mainline-drm-initrd-shell-trial.py --mode minimal \
--bundle /nix/store/asj7l4zj5jrjkgng4nrcx3y72p7jf7aa-k230-mainline-drm-trial-boot-files \
--manifest "$HOME/tmp/k230-mainline-restart-board/candidate-manifest.json" \
--normal-report "$HOME/tmp/k230-mainline-restart-board/normal-report.json" \
--log "$HOME/tmp/k230-mainline-restart-board/minimal-uart.log" \
--result "$HOME/tmp/k230-mainline-restart-board/minimal-result.json"
Those are private paths, not committed secret-bearing contents. The protected report must come from the operator’s live preflight; a host-prepared report is not board-state evidence. The controller’s own reserved serial capture must be retained; do not open the standalone console concurrently. Record the actual controller source revision, invocation and matching bundle/hash beside that capture. A systemd refusal or manual power cycle does not prove automatic restart. Task 5b.5 remains open for usable mainline root and deliberate touch as well as the other named physical observations. No archive is authorized by these host results.
Later physical minimal trial and manual recovery
The coordinator subsequently ran the inspected bundle with controller
f9759f43 and obtained physical receipt, /bin/true, proc setup and uptime
passes. The candidate printed Rebooting., but automatic return was not
observed before the operator intervention disconnected serial. Neither
callback execution nor the completed normal-return deadline is proved.
Independent manual recovery then passed protected serial postflight with
fresh boot ID 08f9455a-1044-4d72-b7ae-bc70d611a8e2, and a reviewed webcam
photo shows normal Home.
Physical observation and recovery retain exact source/artifacts, fixed console excerpt, normal postflight and photo provenance. Dispatch source audit separates userspace request, kernel preparation and callback execution. Its pending-recovery statement records the audit boundary; the later protected recovery is recorded separately above. Tasks 5d.4 and 5b.5 remain open.
Verbose trial and bounded readiness correction
The verbose physical trial started Linux 7.3 and successfully probed the reset controller, but stopped before diagnostic receipt. It requested no candidate reboot. Reviewed camera frames show boot text; subsequent 15- and 90-second receive-only captures got no output. Subsequent user power-cycle recovery passed protected serial postflight and reviewed webcam Home, separately recorded for this trial.
The host correction waits read-only for the pinned candidate shell-init entry before receipt attempts and persists a structured unknown result on minimal readiness or protocol failure. All 76 host tests pass; this source correction does not prove that a longer wait completes the physical boot. No new physical trial has been run with the correction. Tasks 5d.4 and 5b.5 remain open.
The runtime tracing source note identifies a writable runtime parameter that can enable shutdown tracing after nondebug shell readiness. Guarded sysfs/write/readback stages are now implemented and pass 87 host tests. The quiet physical attempt reached Bash but returned no reception token after corrupted early input and a continuation prompt. No runtime stage or candidate reboot was attempted. The ordinary-mode shell-init readiness correction is the next host step. Source feasibility and host simulations are not returned board proof. It also records why host serial reopening cannot establish a target kernel stop.
Quiet tracing after the common readiness correction
The new physical trial passed
fresh shell readiness, reception, minimal prerequisites and all six runtime
trace gates. A real reboot request produced seven device-shutdown entry
checkpoints, ending at mmcblk mmc1:59b4, then the complete 180-second
normal-return deadline expired. The entry narrows the source boundary but
does not prove which callback/next-device lock or PM barrier blocked. No
kernel restart announcement, SPL or normal login was observed; 5d.4 and
5b.5 remain open. Prior reset-button recovery is separately proved in the
preceding attempt’s record; recovery from this latest trial is pending.