Skip to content

Loader slimming stage 1: the RTC is UTC, KernelArgs refuses another layout by name, IA32_TSC_ADJUST moves to the kernel - #583

Merged
Japabu merged 11 commits into
mainfrom
wt/toyos-loader1
Sep 29, 2026
Merged

Japabu merged 11 commits into
mainfrom
wt/toyos-loader1

Conversation

@Japabu

@Japabu Japabu commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Stage 1 of the loader slimming: the audit rows that depend on nothing else. Rows 15, 5 and 17 landed, plus the ten comments, and KernelArgs gained the layout word row 15's move made necessary. Row 13 is left out, for the reason below.

Lines against origin/main (git diff --numstat, matching tests/ anywhere in the path, .md and issues/ as docs, everything else as production): production +149 −718 in 27 files; tests +238 −212 in 10 files, of which the variable-store module's move out of tests/common/update.rs is about 115 each way; issues and docs +22 −5 in 3 files, of which one is issues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md, filed by this branch.

Row 15: the RTC keeps UTC

This follows the owner's ruling that the hardware clock is always UTC.

  • Loader: it no longer asks GetTime for EFI_TIME::TimeZone (rtc_utc_offset and its call site are gone).
  • Boot ABI (toyos-abi/src/boot.rs): KernelArgs loses rtc_utc_offset_minutes, rtc_utc_offset_known and the rtc_utc_offset() getter. Every field from cmdline_addr on moves 8 bytes down, and the size goes from 1280 to 1272. The three hand-coded _start reads (16/32/40) and aarch64's offset_of! reads sit in front of the removed fields, so they do not move.
  • Kernel: it keeps one UTC anchor. UTC_OFFSET_SECS, local_secs and the rtc-zone-east actuator are gone. FAT stamps, SYS_CLOCK_REALTIME and SYS_CLOCK_EPOCH all read clock::utc_secs. The boot: rtc utc offset record is now boot: cmdline …. fat32_adapter.rs's now() names the refusal: FAT specifies local time, and this stamps UTC because the owner ruled the hardware clock is UTC.
  • logd: it names its file from SYS_CLOCK_EPOCH alone. userland/logd/src/wall.rs is deleted, and so are toyos_wallclock::resolve, Recovery, MAX_EAST_SECS/MAX_WEST_SECS and their six tests. The startup line says (<civil> UTC).
  • Tests: wall_clock_zone tested the deleted feature and is deleted. wall_clock_utc (Weekly) stages the host's -rtc base= instant and a zone the way firmware names one, then judges the log file's name (date and hhmmss), its FAT stamp, SYS_CLOCK_EPOCH and SYS_CLOCK_REALTIME (the probe's realtime=, formerly local=).
    • The zone is staged in the boot's own variable store as OVMF's RTC driver keeps it. edk2 PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c, at the edk2 commit QEMU 11.1.1 pins (4dfdca63), reads the RTC variable under the driver's FILE_GUID 378D7B65-8DA9-4773-B6E4-A47826A833E1 in PcRtcInit. The value is a UINT32 holding (Daylight << 16) | (UINT16)TimeZone, which GetTime then returns. OvmfPkgX64.fdf includes that driver. The staged value is −120 (UTC+2).
    • The planter is tests/common/fwvars.rs, moved out of tests/common/update.rs and given a vendor parameter.
  • SYS_CLOCK_REALTIME is now a plain format of SYS_CLOCK_EPOCH (both read clock::utc_secs), and retiring it is an ABI discussion this PR does not open: filed as issues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md (kind: defect, status: open; its exit condition names both callers, userland/compositor/src/render.rs and tests/toyos-rust-tests/src/bin/wall_clock_now.rs, and toyos::system::clock_realtime itself).

Boot ABI: KernelArgs names its layout, and the kernel refuses another

update rewrites only the slot (kernel, cmdline, ROOT) and leaves the ESP loader. So a loader built to origin/main's layout can hand this kernel 1280 bytes whose cmdline_addr sits where this kernel reads rtc_utc_offset_known.

  • The word: KernelArgs::layout: u32 at offset 164, the padding hole the removed fields left. No field moves and the size stays 1272.
  • Its value: LAYOUT = 0x5459_0000 | size_of::<KernelArgs>() as u32 — the struct's own size folded in. At today's 1272-byte size that is 0x5459_04f8. An origin/main loader writes the firmware zone in minutes there, 0 on OVMF. A const assert keeps LAYOUT outside −1440..=1440 as an i32, so no such loader can write it, and 0x5459_04f8 is neither 0 nor in that range. Deriving it from the size catches a change to the size; it does not catch a reorder at equal size, a type swap, or a field added into padding (as layout itself was) — the track's stage 4 (LAST_LAYOUT, typed KernelArgs) is what closes that.
  • The kernel's check: kernel_main compares the word right after arming the panel. That is before blackbox::arm reads the boot parameter, the first field after the word. On a mismatch it starts the UART from rsdp_addr, which sits below the word, and panics with boot: the loader wrote KernelArgs layout {found:#x} and this kernel reads layout {LAYOUT:#x}. The same code covers both architectures: one loader writes the struct, and kernel_main is shared.
  • The negative control on the loader side: the actuator loader-writes-no-layout (toyos_abi::boot::WRITE_NO_LAYOUT_PARAM) makes the loader write 0. The kernel panics by name if it is armed and the check passed anyway.
  • The test: kernel_args_layout_refused (Nightly) boots with it, and now asserts the refusal's exact text including toyos_abi::boot::LAYOUT's own hex digits, not merely the message's fixed prefix — a kernel that printed its own kernel_args.layout a second time instead of LAYOUT would still match the prefix (both are 0x0 on this control) and is now caught. It also asserts that no black box: record appeared, since that record is the kernel's first read of a moved field.

Row 5: the root-bridge hex dump

The per-bridge hex dump in bootloader/src/rootbridge.rs is deleted. Refusals and the "no memory window" line are still printed.

With the dump gone, toyos_acpi::Walk::bytes had no reader. The field, its seven assignments and its six test asserts are deleted. Walk then wrapped a single Result, so memory_windows returns Result<usize, ResourceError>. the_bytes_a_walk_reports_cover_the_descriptor_it_refused, which tested only the byte count, is deleted.

Row 17: IA32_TSC_ADJUST is read by the kernel

The kernel now reads the MSR beside report_power_on, in arch::boot::report_counter_origin, and logs it as boot: IA32_TSC_ADJUST <n> (or … not on this CPU). The loader's Loader TSC: line carries its two counts only.

On aarch64 the loader's counter_origin is deleted, since the kernel already reads CNTFRQ_EL0. The kernel's aarch64 hook is empty.

No test judges the moved line. boot_from_power_on only prints it in its summary.

The ten worst comments (+4 −106)

Each was deleted, not rewritten. Where one held a real invariant, only that clause stays. Commit 6d422562 lists all ten. For the two duplicates, the copy kept is in toyos_update::policy's header.

Row 13: not done

Deferred; the record is #582, item 8.

Each control patch below was applied as a checked patch (git apply/manual edit, then git diff EXIT=0), built (cargo run -- --build-only EXIT=0), and reverted in the same script, leaving git status --porcelain empty for tracked files.

Guest runs (the orchestrator's, at 87a94578)

run exit
kernel_args_layout_refused 0
kernel-prints-args-word.patch 1
wall_clock_utc 0
wall_clock_rtc_dead 0
wall_clock_rtc_unstable 0
wall_clock_no_century 0
wall_clock_century_register 0
realtime-plus-7200.patch 1
Fast 0

The only change since these runs is the deleted watchdog_fed line in tests/test-durations (main's #562 removed it; the merge brought it back by mistake).

Under layout-check-removed.patch, kernel_args_layout_refused was EXIT=1 with "Boot timed out waiting for boot: the loader wrote KernelArgs layout 0x0 and this kernel reads layout 0x" on the console. The kept UART showed "Kernel arguments: layout 0 on loader-writes-no-layout", then "black box: 0x8000000 is this boot's", then "panicked at src/main.rs:284:9: boot: loader-writes-no-layout is armed and the loader wrote this kernel's layout anyway" — the kernel's own check, not the black-box tripwire, is what turns the test red.

High-risk: the boot ABI and the wall clock

The wall clock

  • Negative control: utc-whole-revert.patch is git diff HEAD origin/main over everything outside tests/ and issues/. It reverts the branch's whole production change onto origin/main (bc9ccad8) and keeps this head's tests. On that tree the loader reads the staged −120, so SYS_CLOCK_EPOCH lands 7200 s behind the instant. Measured: EXIT=1, SYS_CLOCK_EPOCH answered 1993792480, −7185s from the staged instant — the whole revert goes red, and the staged firmware zone does reach GetTime. wall_clock_utc is green at this head.
  • The review's mutation: realtime-plus-7200.patch (SYS_CLOCK_REALTIME => crate::clock::utc_secs().map(|s| s + 7200).map_or(). Measured: EXIT=1, SYS_CLOCK_REALTIME answered a time of day 7202s from the staged instant's.
  • Independent oracle: the instant the host stages with QEMU's -rtc base=2033-03-07T09:14:25, and the zone as edk2's own RTC driver reads it from its variable store — the CMOS RTC's documented UTC convention, as the owner decided it. Both are set outside the guest and read back off the disk image and the guest's prints.

The layout word

  • Negative control: layout-check-removed.patch deletes only kernel_main's comparison block (kernel/src/main.rs, the two comment lines and the if kernel_args.layout != toyos_abi::boot::LAYOUT { .. panic!(..) }), keeping the word, LAYOUT, the loader's write, the loader-writes-no-layout actuator and the tripwire that panics if that actuator armed and the check passed anyway. Measured at 4e07c4df (above): the boot times out, refused by name.
  • Round 4's mutation: the round-3 assertion matched only the refusal's fixed prefix, so a kernel that printed its own kernel_args.layout a second time in place of toyos_abi::boot::LAYOUT still read "…reads layout 0x0" on this control and passed. scratchpad/loader1-r4/kernel-prints-args-word.patch makes that swap in kernel/src/main.rs; applied, built (cargo run -- --build-only EXIT=0), and reverted, leaving the tree clean. kernel_args_layout_refused now asserts the message's exact hex digits and must turn red under it.
  • No independent layout oracle. Nothing outside this file says what LAYOUT should be: no external spec, no real hardware, no differential implementation. old-layout-loader.patch, which hands the kernel origin/main's 1280-byte layout as pinned by origin/main's own offset asserts (164, 168, and 176 on), reads the same 0 at offset 164 that the plain loader-writes-no-layout control does, so it is not independent evidence of the check either — only of the fact that a genuinely stale loader is refused by name. Measured: EXIT=0, refusal naming 0x0.

Unsure

  • The mixed pair is emulated byte for byte, not built from origin/main.
  • The T14 has not run this. On a machine whose RTC keeps local time (dual-boot with Windows), ToyOS's clock is now off by the zone; that follows from the ruling.

🤖 Generated with Claude Code

Japabu and others added 3 commits September 28, 2026 19:56
…elds that carried it go

Owner ruling: the hardware clock is always UTC. The loader no longer asks
firmware's GetTime for EFI_TIME::TimeZone, KernelArgs loses
rtc_utc_offset_minutes and rtc_utc_offset_known (every field after them moves
eight bytes down, the size goes 1280 -> 1272; the const asserts in
toyos-abi/src/boot.rs pin each offset, and the three _start reads by hand at
16/32/40 are unmoved), and the kernel anchors one UTC clock off the RTC:
UTC_OFFSET_SECS, local_secs and the rtc-zone-east actuator go, and FAT stamps,
SYS_CLOCK_REALTIME and SYS_CLOCK_EPOCH all read clock::utc_secs.

wall_clock_zone tested the deleted feature and goes; wall_clock_utc (Weekly,
as its predecessor) asserts the UTC behaviour that stays: with the host's
-rtc base= instant staged, the log file's name, its FAT stamp and
SYS_CLOCK_EPOCH all sit within 0..300 s of that instant.

Filed: logd still recovers a zone offset from the two clock calls, which is
now always zero (issues/design-debt/logd-recovers-a-zone-offset-the-kernel-no-longer-has.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
rootbridge::windows printed every byte of each bridge's Configuration()
answer. Nothing reads that line; the windows it decodes and every refusal are
still said.

Filed: toyos_acpi::Walk::bytes existed for that dump and now has no reader
outside its own tests (issues/design-debt/toyos-acpi-walk-bytes-has-no-reader.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
Deleted, never rewritten; where one held a real invariant, that clause stays.

1. loaderlog.rs: open's doc, misplaced on volume_handle.
2. main.rs boot_partition: "the one function in this file that does not
   [panic]", which was false.
3. main.rs load_kernel_elf: the restatement of toyos-elf's refusals; the
   p_filesz <= p_memsz bound is stated where the copy is.
4. main.rs MAX_ESP_FILE: the file-wide philosophy; its one-line doc stays.
5. attempt.rs: the 29-line module essay; "one hand per hang" stays.
6. blackbox.rs harvest: the war story; "a record belongs to the stick that
   wrote it" stays.
7. loaderlog.rs ENDS_AT_CHAIN: the philosophy; its one-line doc stays.
8. main.rs start_kernel: two of three unrelated comments over `let loader`
   (the println-after-exit fact is stated at the exit); the one about the
   loader image stays.
9. main.rs: end_this_pass's second paragraph, and main's copy of the same
   explanation over uefi_services::init.
10. Duplicates, one copy kept in toyos_update::policy's header: "firmware
    variables can be reset" (toyos-update lib.rs, bootloader floor.rs) and
    "the record names only a slot and a digest" (toyos-update record.rs,
    bootloader slot.rs's proven).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
@Japabu
Japabu marked this pull request as ready for review September 28, 2026 17:59
@Japabu

Japabu commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator Author

Review, round 1, at 6d42256

Gate: CI host SUCCESS at 6d42256 (run 36462038776). git merge-tree --write-tree origin/main HEAD (762e4ba) is clean, and the merged tree has no rtc_utc_offset, rtc-zone-east, wall_clock_zone or UTC_OFFSET_SECS. Guest: the orchestrator's 11 targeted runs and Fast are EXIT=0, and the mutation run is EXIT=1 ("FAT timestamp is -7199s"). Net: production +37 −272, tests +16 −41, issues +32.

BLOCKER

  • tests/common/wallclock.rs:204 — rtc_is_utc checks only the date prefix of the log's name and never reads the probe's local=. With kernel/src/syscall/dispatch.rs:281 patched to SYS_CLOCK_REALTIME => crate::clock::utc_secs().map(|s| s + 7200).map_or(, --weekly wall_clock_utc stays green: logd recovers UTC+2 and names 2033-03-07-111427.log, and the FAT stamp and epoch do not move. Why it matters: the change moves SYS_CLOCK_REALTIME from local time to UTC, an ABI meaning, and nothing checks it. Fix: judge the name's hhmmss and local= against RTC_BASE within MAX_BOOT_DRIFT_SECS. That patch must turn the test red.
  • toyos-abi/src/boot.rs:204-214 — every field from cmdline_addr on moves 8 bytes, and the kernel has nothing to refuse a loader built to the other layout. update rewrites only the slot (kernel, cmdline, ROOT) and leaves the ESP loader in place. So this head's image, installed by update on a machine whose loader is origin/main's, reads cmdline_addr out of the old rtc_utc_offset_known word. kernel/src/main.rs:255-260 then builds a slice from phys 0/1 whose length is the old cmdline_addr: garbage, with no refusal by name. This is the first KernelArgs layout change since update landed (8c0fa9d). Close it one of two ways: a refusal by name, measured by booting a mixed pair (loader at origin/main, kernel at head) that goes red with that name; or the skew recorded in issues/ with evidence and an exit condition, with the PR body's lockstep sentence deleted.

NOTE

  • userland/logd/src/wall.rs:97-124 — logd still reads a zone. It recovers an offset that can now only be 0, and prints "at UTC+0 recovered from two readings" (583-utc-control.log). Delete the recovery, toyos_wallclock::resolve/Recovery and their whole-domain test, and name the file from SYS_CLOCK_EPOCH alone. That replaces issues/design-debt/logd-recovers-a-zone-offset-the-kernel-no-longer-has.md instead of adding it.
  • toyos-acpi/src/resource.rs:113 — Walk::bytes is dead now that its only reader is gone. Delete the field, its seven assignments and its six test asserts, instead of filing issues/design-debt/toyos-acpi-walk-bytes-has-no-reader.md.
  • bootloader/src/arch/x86_64.rs:27 — leaving row 17 out rests on a wrong premise. Moving counter_origin is a read beside report_power_on (kernel/src/main.rs:195), not an entry in control_regs. boot_from_power_on would read the kernel's line.
  • Track (The loader-slimming track, and the firmware rule in CLAUDE.md #582) — neither deferral is recorded. Stage 1 still lists the TCO-arm deletion and the counter_origin move, and its exit still reads "bootloader/src holds no TCO access, no counter_origin". Leaving row 13 is right: the track's own text accepts an unbounded handoff→arch::watchdog::init span, against "ends at least as secure". The track needs amending before stage 1 is called done.
  • PR body "Negative control" — utc-negative-control.patch is a one-line mutation, not the whole change reverted. The claim that the whole revert "would pass too" is unmeasured. A firmware-named zone staged through the per-test writable OVMF variable store would make a real control: OVMF's RTC driver keeps TimeZone in its NV RTC variable. That boot should be green at head and red at bde7b56 (epoch −7200). It is also the only QEMU boot on which this change is not neutral.
  • PR body — it carries no guest measurement. The orchestrator's runs, with their exit codes and the control's EXIT=1 line, belong there in place of the queue.
  • No T14 reading. A base-era T14 loader.log "RTC zone:" line would show whether the owner's firmware names a zone, which is the one kind of machine where this change is not neutral.
  • toyos-abi/src/syscall.rs:1106 — SYS_CLOCK_REALTIME is now utc_secs formatted as h:m:s, derivable from SYS_CLOCK_EPOCH. Once logd no longer reads it, its readers are the compositor panel and the probe. Retiring it is an ABI discussion for an issue, not for this branch.

REMOVE

  • kernel/src/arch/x86_64/boot.rs:105 — comment rewritten rather than deleted; the call names ACPI.
  • tests/toyos-rust-tests/src/bin/wall_clock_now.rs:3-5 — paragraph reworded; "both" now names nothing.
  • tests/common/wallclock.rs:190-191 — false as the test stands: the name is not checked against the instant.
  • tests/common/wallclock.rs:158 — "the two clock syscalls": the test judges only one.
  • userland/logd/src/wall.rs:5-16 — false now: clock::local_secs() is deleted and clock_realtime is not local.
  • userland/logd/src/wall.rs:64-67 — edited into a wrong "clean fix".
  • toyos-wallclock/src/lib.rs:15-27 — "SYS_CLOCK_REALTIME, which is local h:m:s": false.
  • toyos-abi/src/syscall.rs:1100 — "in the zone the machine keeps its clock in": there is one zone.
  • toyos-acpi/src/resource.rs:110-111 — "what the bootloader logs the raw bytes of": nothing logs them.
  • PR body "Correction to commit 26ad88cf's message" — a prose correction.
  • PR body "Audit claims found false" — chronology, not main's record.
  • PR body "No guest test has been run by me…" and "Guest runs to queue" — no longer true or needed.
  • PR body "Unsure", first bullet — now measured.
  • PR body "Loader and kernel share the struct, so they change together" — false at the update boundary.
  • PR body "if loader and kernel disagreed on offsets this test would red" — unmeasured, and a single build cannot disagree.

SEND BACK

Japabu added a commit that referenced this pull request Sep 28, 2026
… rebuilt on the owner's rulings

CLAUDE.md: ToyOS calls no UEFI runtime service; every UEFI call is the
loader's. PSCI on ARM64 and the xHCI legacy-ownership handshake are not
UEFI calls, which closes both CLAUDE.md blockers.

The track:
- Stage 1 is what #583 lands: UTC, the hex dump, ten comments, the
  KernelArgs layout identity, IA32_TSC_ADJUST read by the kernel. The
  loader's TCO arm stays; wall_clock_utc is the test a zone reds.
- Stage 2 scopes every volume lookup to the boot disk with exactly one
  match, and asks firmware once per pass.
- Stage 3 compares one floor per key on a signed security version; the
  accepted cost of refusing older builds is gone with the build time.
- Stage 4 is new: current uefi, the loader's own panic handler, the
  unsound allocations and relocation unsafes gone, typed KernelArgs,
  one CRC32.
- Stage 5 adopts the Android/libabr tries rules as pure host-tested
  toyos-update decisions: fresh slot A untried with 3 tries, no bootable
  slot powers off, the good flag set only past a health gate, and
  controls for a good flag left set and a floor raised to the table's
  version.
- Stage 8 is new: the kernel arms the TCO before mm::init and takes the
  read-back the TCO issue's exit needs; only then does the loader's arm go.
- Stage 9 rewrites the wedged-report issue's exit and gives the kernel
  harvest's stale-record check.
- Every #539 piece is placed or listed as deleted.

the-machine-updates-itself-without-ubuntu.md: stage 2 gets its exit back,
and names its wait on the track's --boot-first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
Japabu and others added 2 commits September 28, 2026 20:38
… Walk::bytes go

The RTC is UTC, so the offset logd recovered from SYS_CLOCK_EPOCH and
SYS_CLOCK_REALTIME could only be zero. Deleted instead of filed:

- userland/logd/src/wall.rs, and toyos_wallclock's resolve, Recovery,
  MAX_EAST_SECS/MAX_WEST_SECS and their six tests. boot_stamp reads
  clock_epoch once; the startup line says "<civil> UTC". boot_local is
  boot_secs, since nothing in it is local.
- The false zone clauses in toyos-abi's and toyos's clock_realtime docs
  and toyos-wallclock's header.
- toyos_acpi::Walk: with its bytes field gone (its only reader was the
  loader's hex dump) it wrapped one Result, so memory_windows returns
  Result<usize, ResourceError>. The six byte asserts go, and so does
  the_bytes_a_walk_reports_cover_the_descriptor_it_refused, which tested
  nothing else.
- The two issue files the last round filed for these.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
…ck_utc judges SYS_CLOCK_REALTIME with a firmware zone staged

Boot ABI. `update` replaces the slot's kernel and leaves the ESP loader,
so an old loader can hand a new kernel the old layout. KernelArgs gains
`layout: u32` at offset 164, the padding hole the removed zone fields
left, so no field moves. The loader writes `LAYOUT` (0x5459_0001); the
kernel compares it right after arming the panel, before `blackbox::arm`
reads the boot parameter, and on a mismatch starts the UART from
`rsdp_addr` (below the word) and panics naming both values. An
origin/main loader writes the firmware zone in minutes there (0 on
OVMF), which `LAYOUT` can never equal: a const assert keeps it outside
-1440..=1440. The actuator `loader-writes-no-layout` makes the loader
write 0, and the Nightly test kernel_args_layout_refused boots it and
asserts the refusal and that no `black box:` record, the first read of
a field after the word, came before it.

IA32_TSC_ADJUST is read by the kernel beside report_power_on
(`arch::boot::report_counter_origin`, a `boot: IA32_TSC_ADJUST` record)
and no longer by the loader. On aarch64 the loader's counter_origin
goes and the kernel's hook is empty.

wall_clock_utc stages a zone the way firmware names one: a fresh variable
store with PcRtc's `RTC` variable (vendor 378D7B65-...-A47826A833E1,
UINT32 zone, per edk2 PcRtc.c at QEMU 11.1.1's edk2 4dfdca63) holding
-120 minutes. It then judges the log name's hhmmss and the probe's
`realtime=` (was `local=`) against the staged instant within
MAX_BOOT_DRIFT_SECS, beside the FAT stamp and SYS_CLOCK_EPOCH. The
variable-store reader and planter move from update.rs to
tests/common/fwvars.rs and take the vendor.

Deleted: the rewritten century comment in x86_64/boot.rs, the probe's
"both" paragraph, rtc_is_utc's doc and the "two clock syscalls" comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
@Japabu Japabu changed the title Loader slimming stage 1: the RTC keeps UTC, the root-bridge hex dump and ten comments go Loader slimming stage 1: the RTC is UTC, KernelArgs refuses another layout by name, IA32_TSC_ADJUST moves to the kernel Sep 28, 2026
Japabu added a commit that referenced this pull request Sep 28, 2026
…s controls can fail

CLAUDE.md's Firmware paragraph now reads as the orchestrator ruled: the
kernel calls no UEFI service, and every UEFI call is the loader's, before
ExitBootServices. The loader's GetVariable, SetVariable, GetTime and
ResetSystem come before the handover, so the old wording was false of it.

The track:
- Stage 1 matches #583 at 8565cc5: KernelArgs::layout (0x5459_0001),
  kernel_args_layout_refused with the loader-writes-no-layout actuator,
  the probe's realtime=, and the kernel's IA32_TSC_ADJUST line. No test
  fails without that line, and the stage says so.
- Stage 3 drops "why nothing is weaker". A security version admits an
  older build the same key signed at that version. The floor issue records
  that as the owner's accepted cost. Raising the version is a reviewed PR
  that edits one constant and names the security fix. The loader deletes
  the build-time ToyOSImageFloor- variables instead of leaving them behind.
- Stage 4's panic handler writes loader.log and powers off, never resets.
  Its test panics on a floor planted in 9 bytes, a failure the machine
  causes. KernelArgs' layout word rises to 0x5459_0002, and
  kernel_args_last_layout_refused fails if it does not.
- Stage 5 refuses a signed kernel the loader cannot load inside verify,
  so the other slot boots instead of the pass bricking the machine. An
  install's priority rises above the kept slot's. update --good, run by
  init at the health gate under the slots claim, writes the good flag, and
  an image without that claim is never good. Each rule gets a named guest
  control: update_floor_waits_for_good, update_readonly_stick_boots_nothing
  (red under `let persisted = true;`) and
  update_unloadable_kernel_boots_the_other_slot. The slot-table oracle is
  decoded without production code.
- Every #539 piece the review listed is placed or deleted. The #539-only
  issue names and the stack-offset closure (#584's) are gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu

Japabu commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator Author

Review, round 2, at 8565cc5

Gate: CI host SUCCESS at 8565cc5 (run 36468110845). git merge-tree --write-tree origin/main 8565cc59 is clean (fd668198), and the merged tree has no rtc_utc_offset, local_secs, rtc_zone_east, toyos_wallclock::resolve or counter_origin() reader left. Guest runs by the orchestrator at 8565cc5: wall_clock_utc, kernel_args_layout_refused, boot_from_power_on, bar_placement_is_proven, root_withheld_refused, wall_clock_rtc_dead/rtc_unstable/no_century/century_register, update_floor_is_the_images_own and Fast are all EXIT=0. Net: production +148 −712, tests +235 −212.

Round 1

  • CLOSED — tests/common/wallclock.rs rtc_is_utc: realtime-plus-7200.patch EXIT=1 with "SYS_CLOCK_REALTIME answered a time of day 7202s from the staged instant's" (583r2-realtime-plus-7200.log:59). The whole revert, utc-whole-revert.patch, is EXIT=1 with "SYS_CLOCK_EPOCH answered 1993792480, -7185s from the staged instant", so the staged firmware zone does reach GetTime. The head is EXIT=0.
  • CLOSED as a refusal by name — toyos-abi/src/boot.rs KernelArgs skew: kernel_args_layout_refused EXIT=0 at head, and EXIT=0 under old-layout-loader.patch. Its pass line "[boot] a loader that wrote layout 0 was refused by name before the boot parameter" is printed only after log.contains("boot: the loader wrote KernelArgs layout 0x0 and this kernel reads layout 0x") held and no black box: appeared (tests/toyos.rs kernel_args_layout_refused). The harness does not echo the guest's console, so a grep of the run log cannot find the kernel's line. The assertion is the proof. Its negative control is open; see below.
  • Round-1 NOTEs on logd's zone recovery, Walk::bytes, row 17 and the whole-revert control are closed. The track NOTE is closed in The loader-slimming track, and the firmware rule in CLAUDE.md #582, item 8. Every round-1 REMOVE is gone from the tree and the body.

BLOCKER

  • kernel/src/main.rs:254 — the layout refusal has no valid negative control. layout-word-reverted.patch also deletes the loader-writes-no-layout actuator, and its EXIT=1 is a setup refusal: ""loader-writes-no-layout" is a kernel_params and the kernel declares no such actuator or parameter" (583r2-layout-word-reverted.log:267). The test never booted. Why it blocks: this is a high-risk ABI change, and no measured arm shows that the kernel's check is what turns the test red. The control is layout-check-removed.patch, which deletes only kernel/src/main.rs:252-261 (the two comment lines and the if kernel_args.layout != toyos_abi::boot::LAYOUT { serial::init(..); panic!(..) } block). It keeps the word, LAYOUT, the loader's write, the actuator and the tripwire at :294. On that tree kernel_args_layout_refused must go red with "Boot timed out waiting for boot: the loader wrote KernelArgs layout 0x0…", and the console must carry black box: and "loader-writes-no-layout is armed and the loader wrote this kernel's layout anyway". That red arm goes in the PR body, and layout-word-reverted.patch comes out of it.

NOTE

  • toyos-abi/src/boot.rs:116 — the layout word is sound against the one skew there is. origin/main's loader writes rtc_utc_offset.unwrap_or(0), range-checked to ±1440, at 164. The const assert keeps LAYOUT outside that range. Every field the kernel reads before the check is below 164: the memory map, GOP, rsdp_addr, and the _start/aarch64 reads at 16/32/40/112. But "bumped by any change to its layout" is enforced by nothing. A PR that moves cmdline_len and edits the offset asserts without bumping LAYOUT passes every gate and reopens round 1's hole. Derive the value from the layout, e.g. 0x5459_0000 | size_of::<KernelArgs>() as u32, which catches every add or remove, or make the bump unskippable in the offset-assert block.
  • old-layout-loader.patch — it is not an independent oracle. The actuator is still armed in that run, so the word at 164 is the same 0 as in the plain run, and the shifted fields after it are never read. The run therefore adds no evidence over kernel_args_layout_refused. The independent arm is origin/main's own built bootloader.efi on this head's ESP.
  • Deployment — every machine installed from origin/main that takes this image through update refuses it until its ESP is reflashed. Whether the loader then falls back to the other slot is unmeasured for a kernel that dies before its own blackbox::arm. root_withheld_refused dies after that point.
  • kernel/src/main.rs:196 — nothing judges the moved boot: IA32_TSC_ADJUST line. Deleting arch::boot::report_counter_origin(); leaves every suite green. Either assert the line in boot_from_power_on or accept it as a diagnostic.
  • kernel/src/fat32_adapter.rs:658 — FAT stamps are now UTC where FAT specifies local time, and nothing records that choice. On OVMF this is behaviour-neutral. On a machine whose firmware names a zone it is not.
  • toyos-abi/src/syscall.rs clock_realtime — SYS_CLOCK_REALTIME is now utc_secs formatted as h:m:s, a sibling of SYS_CLOCK_EPOCH. Retiring it is an ABI discussion, and it is still not filed in issues/.
  • PR body — it carries no measurement at 8565cc5. The 583r2 runs, with their exit codes and the failing lines quoted above, replace the 6d42256 table.
  • No T14 reading. That is still the only machine where this change is not neutral.

REMOVE

  • userland/CLAUDE.md:9 — "Local time is recovered, not asked for …" is false now, since nothing recovers a zone. Delete it in this PR. This is a named change: an agent may edit a CLAUDE.md only when briefed, so the orchestrator briefs it.
  • issues/filesystem/where-everything-lives.md:86-89 — "rather than recovered by subtracting SYS_CLOCK_REALTIME from SYS_CLOCK_EPOCH" and "and nothing recovers the zone by subtraction" rest on the deleted recovery.
  • toyos-wallclock/src/lib.rs:6-9 — "Before this crate there was one implementation … whose tests could not run." is chronology, in a line this branch edited.
  • tests/toyos.rs:19589 — the LOADER_TSC doc was rewritten rather than deleted.
  • kernel/src/main.rs:193-194 — the report_power_on doc clause was rewritten rather than deleted.
  • PR body "None of these ran at this round's head." and every "Not yet run." — false at 8565cc5.
  • PR body "Guest runs (the orchestrator's, at 6d422562, before this round)" — a stale head.
  • PR body "Unsure", first bullet — measured by utc-whole-revert.patch EXIT=1 (−7185s).
  • PR body "The layout word", "Negative control: layout-word-reverted.patch …" — it is not one.
  • PR body "Row 13" bullets — the deferral's record is The loader-slimming track, and the firmware rule in CLAUDE.md #582, item 8. One line pointing there is enough.

SEND BACK

Japabu added a commit that referenced this pull request Sep 28, 2026
…not a copy

The inline predicate in kernel_main's reservation loop duplicated
toyos_rootimage::handoff::held without its checked_add, and no test covered
the copy. Both crates were already kernel dependencies, so the loop now
builds a Descriptor iterator and calls held(..., block=1) — block 1 because
the ELF region is not page-aligned — the same call kernel/src/rootfs.rs
already makes for ROOT's image.

The architecture's own page is now named (a `loader` array of the four
loader allocations, checked, with arch::boot::reserved() appended after) so
a later region can't land inside the exempted slot by position.

Files the misleading kernel_stack_addr name (toyos-abi/src/boot.rs:8) as an
issue for after #583, and removes the tracker entry this branch's exit
condition already closes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Japabu and others added 2 commits September 28, 2026 22:13
…ames its refusal, and the stale prose the review named goes

LAYOUT folds size_of::<KernelArgs>() into the fixed word instead of a
hand-bumped constant, so any field added or removed moves it without
relying on someone remembering to bump it by hand.

fat32_adapter.rs's now() records why FAT gets UTC stamps despite FAT
naming local time: the owner ruled the hardware clock is UTC.

SYS_CLOCK_REALTIME is now a plain format of SYS_CLOCK_EPOCH; filed as
issues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md
for the ABI discussion its retirement needs, not retired here.

Deleted, not rewritten: userland/CLAUDE.md's stale zone-recovery
caveat, where-everything-lives.md's zone-recovery clauses,
toyos-wallclock's chronology, tests/toyos.rs's rewritten LOADER_TSC
doc, and main.rs's rewritten report_power_on clause tying to the
moved, untested IA32_TSC_ADJUST read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Japabu added a commit that referenced this pull request Sep 28, 2026
…d-picked

Restates the track's LAYOUT/LAST_LAYOUT literals as
`0x5459_0000 | size_of::<KernelArgs>()`, so a size change moves the word on
its own and `kernel_args_last_layout_refused` catches it; names the
remaining gap a same-size reorder or equal-size type swap leaves, closed by
pinning every field's offset (not only the prefix's) and
`assert!(LAYOUT != LAST_LAYOUT)`; states how stage 5's once variant, which
keeps the struct's size, still moves the word and how the kernel refuses an
unrecognized discriminant by name instead of reading it out of range; gives
`update_dead_service_is_never_good`'s image a live service beside the dead
one, so "any named service wrote its byte" is distinguished from "every
one did"; has stage 5's PR list which `start_kernel` refusals are the
image's; and drops the PR body's Unsure bullet on #583's pushed head, now
stale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu

Japabu commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator Author

Review, round 3, at 4e07c4d

Gate: CI host SUCCESS at 4e07c4d. git merge-tree --write-tree origin/main 4e07c4df is clean (5069dbe2), and #582's track merges without conflict. The merged tree has no rtc_utc_offset, rtc-zone-east, wall_clock_zone, UTC_OFFSET_SECS, local_secs or toyos_wallclock::resolve outside the track's own text. Guest runs by the orchestrator at 4e07c4d: kernel_args_layout_refused EXIT=0, wall_clock_utc EXIT=0, Fast EXIT=0, and layout-check-removed.patch EXIT=1. Round 3 changes only LAYOUT's value and prose, so the 583r2 UTC controls, wall-clock tests, boot_from_power_on, bar_placement_is_proven and root_withheld_refused still stand. Net against origin/main: production +149 −715, tests +234 −212, issues and docs +24 −5.

Round 2

  • CLOSED — kernel/src/main.rs:244, the layout refusal's negative control. layout-check-removed.patch deletes only the comparison block and keeps the word, LAYOUT, the loader's write, the actuator and the tripwire. Under it, --nightly kernel_args_layout_refused is EXIT=1 with "Boot timed out waiting for boot: the loader wrote KernelArgs layout 0x0 and this kernel reads layout 0x" (583r3-layout-check-removed.log:36). The kept UART (red-run-serial/toyos-tmp-35924-0/lane-0/uart-0.log) shows "Kernel arguments: layout 0 on loader-writes-no-layout", then "black box: 0x8000000 is this boot's", then "panicked at src/main.rs:284:9: boot: loader-writes-no-layout is armed and the loader wrote this kernel's layout anyway". So the kernel's check is what turns the test red.

BLOCKER

  • tests/toyos.rs:19660 — kernel_args_layout_refused checks the kernel's own word only as the prefix 0x. Mutation: at kernel/src/main.rs:249, - toyos_abi::boot::LAYOUT / + kernel_args.layout. The refusal then reads "…reads layout 0x0" and the test stays green. The track's stage-1 exit on main requires "the kernel's refusal naming both words". Fix: assert format!("{LAYOUT_REFUSAL}{:x}", toyos_abi::boot::LAYOUT). The mutation above must turn the test red.
  • issues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md:2-3,11 — the file records the sibling syscall this branch creates as status: owner / kind: question. That files work as the owner's decision and drops it out of rg '^status: open'. "Owner: whoever takes the ABI discussion" names nobody. Fix: kind: defect, status: open, and delete the Owner line. The exit's "the one caller each" misnames what goes: two callers and toyos::system::clock_realtime.

NOTE

  • kernel/src/main.rs:244 — if kernel_args.layout == 0 {, or a magic-only kernel_args.layout >> 16 != 0x5459, keeps kernel_args_layout_refused green, because the actuator writes only 0. "Refuses any other value" is measured at one value until the track's stage-4 kernel_args_last_layout_refused (0x5459_04f8) lands.
  • toyos-abi/src/boot.rs:117 — the size alone misses three changes: a reorder at equal size, a type swap, and a field added into padding. layout itself went in that last way, at 164, with the size unchanged. The track's stage 4 covers this with LAST_LAYOUT. The offset-assert block is the real layout and could be what LAYOUT folds.
  • tests/toyos.rs:19657 — LAYOUT_ZERO_PARAM is a literal copy of toyos_abi::boot::WRITE_NO_LAYOUT_PARAM. Its sibling ROOT_WITHHELD_PARAM (:19551) reads the constant; this should too.
  • PR body — it carries no measurement at 4e07c4d. The four 583r3 runs belong there, with the red arm's lines quoted above.
  • Layout oracle — there is still no independent one: origin/main's own built bootloader.efi on this head's ESP would be one.
  • Deployment — the refusing kernel holds the panel ("nothing here can time a wait", uart-0.log). The only way out is the loader's TCO arm and its black-box record, and whether that falls back to the other slot is unmeasured.
  • No T14 reading.

REMOVE

  • toyos-abi/src/boot.rs:114 — "so any field added or removed moves it": false for a field added into padding, as layout was.
  • toyos-abi/src/boot.rs:207-209 — "They share this file, so they cannot disagree about the layout": false at update, and that is why layout exists.
  • issues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md:10-16 — the line locators (dispatch.rs:271, syscall.rs:1104, :1119, render.rs:262, wall_clock_now.rs:22) will rot.
  • PR body "no issue file added or left" — false: this branch adds one.
  • PR body "production +148 −712 … tests +235 −212" — stale.
  • PR body layout-word-reverted.patch table row and its parenthesis — it is not a control; round 2 named it out.
  • PR body "Queued for the orchestrator's next pass…" and "queued for the orchestrator's guest run, where it must turn … red" — both have been measured.
  • PR body "Oracle: old-layout-loader.patch …" — not independent: that run reads the same 0 at 164 as the plain run.

SEND BACK

… exactly, SYS_CLOCK_REALTIME's issue reopens as a defect naming every caller, and two false layout-doc clauses go

kernel_args_layout_refused matched only the refusal's prefix, so a kernel that
printed its own kernel_args.layout in place of toyos_abi::boot::LAYOUT would
still pass; it now asserts the full message with LAYOUT's own hex digits.
LAYOUT_ZERO_PARAM reads WRITE_NO_LAYOUT_PARAM instead of copying its literal.

The SYS_CLOCK_REALTIME issue was status: owner / kind: question, which drops
it out of `rg -l '^status: open'` and named no owner; it is a defect nobody is
holding, so it is status: open / kind: defect, with the Owner line gone and an
exit condition that names toyos::system::clock_realtime and both its callers.

toyos-abi/src/boot.rs loses two false doc clauses: LAYOUT's own size folded in
does not move on a field added into padding, as `layout` itself was; and two
binaries sharing this file does not mean they cannot disagree about the
layout, which is why `layout` exists at all.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Japabu added a commit that referenced this pull request Sep 29, 2026
`reserved`'s construction copied `loader` by position, so a fifth region
added to `loader` compiled and passed the containment check but was silently
dropped from what `mm::init` withholds — exactly what mutation-r2.patch had
done to `root_image`. Destructuring `loader` by name (`image`, `elf`,
`black_box`, `root`) makes a fifth element a compile error instead.

The issue's owner line named a role ("whoever lands #583"), not a concrete
owner; it now names PR #583 (wt/toyos-loader1) itself, and drops the line
number citation that rots with the next edit to toyos-abi/src/boot.rs. The
same rotting citation is dropped from main.rs's comment on the
architecture's own reserved page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu

Japabu commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator Author

Review, round 4, at 9efc01c

CI has no run at 9efc01c: gh pr checks 583 says "no checks reported", and the check-runs API for 9efc01c is empty. GitHub reports the PR mergeable: CONFLICTING / DIRTY against origin/main 3d90247. git merge-tree --write-tree origin/main 9efc01cb conflicts in tests/common/wallclock.rs and tests/test-durations. The last green host is run 36481277392, and it was at 4e07c4d, not at this head. Merge origin/main, resolve both files and push. Round 4 reviews that head once host is green on it.

NOT READY FOR REVIEW

Both sides touched tests/common/wallclock.rs's clock-drift checks and
tests/test-durations; every hunk of both survives.

tests/common/wallclock.rs: main's #562 ("No QEMU test measures time") replaced
the fixed MAX_BOOT_DRIFT_SECS budget with after_the_base(secs, lived), a
causality bound measured from the actual elapsed wall time since QEMU's
launch. This branch's own commit 1090cf6 ("The RTC keeps UTC") ruled the
hardware clock is always UTC and replaced main's zone_from_firmware test (and
its rtc-zone-east actuator) with rtc_is_utc, which plants a firmware RTC
timezone variable directly via fwvars::plant and asserts the kernel ignores it
— FAT name, FAT stamp, SYS_CLOCK_EPOCH and SYS_CLOCK_REALTIME all sit on the
staged instant with no offset applied. Kept this branch's rtc_is_utc body
(the ABI decision it tests is this branch's own and main never saw it) but
put every one of its drift checks on main's after_the_base/lived measurement
instead of the deleted MAX_BOOT_DRIFT_SECS, so the branch's checks fit main's
"no QEMU test measures time" rule. boot_and_read keeps both signature changes:
this branch's firmware_vars: Option<PathBuf> parameter and main's returned
Duration (elapsed since launch). undated, no_century and century_from_the_register
keep this branch's extra None argument and main's three-way destructure.

tests/test-durations: kept watchdog_fed (this branch's own addition, whose
test still exists at the merged head). Dropped wall_clock_zone: its test,
zone_from_firmware, was deleted by 1090cf6 and replaced by wall_clock_utc,
so the entry names a test that no longer exists.

Verified on the merged tree: `cargo run -- --ci host` exit 0, `cargo run --
--build-only` exit 0, `cargo test --test toyos-build -- --list` exit 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu

Japabu commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator Author

Review, round 5, at 87a9457

Gate: mergeable MERGEABLE; CI host success on run 36516716620, headSha 87a9457. Orchestrator's guest runs at 87a9457: kernel_args_layout_refused, wall_clock_utc, wall_clock_rtc_dead, wall_clock_rtc_unstable, wall_clock_no_century, wall_clock_century_register, Fast all EXIT=0; kernel-prints-args-word.patch EXIT=1, realtime-plus-7200.patch EXIT=1 (583r5-*.log). Net against origin/main: production +149 −718, tests +240 −212, issues and docs +22 −5.

Round 3

  • CLOSED — tests/toyos.rs kernel_args_layout_refused prefix-only match. loader1-r4/kernel-prints-args-word.patch swaps toyos_abi::boot::LAYOUT for kernel_args.layout at kernel/src/main.rs:258; under it the test is EXIT=1 with no "boot: the loader wrote KernelArgs layout 0x0 and this kernel reads layout 0x545904f8" in the boot log (583r5-kernel-prints-args-word.log:30), green without it (583r5-kernel_args_layout_refused.log:37).
  • CLOSED — issues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md: status: open, kind: defect, Owner line gone, exit names toyos::system::clock_realtime and both callers.

Merge 87a9457

tests/common/wallclock.rs keeps both sides: main's after_the_base(secs, lived) and launched.elapsed() return, the branch's firmware_vars parameter and rtc_is_utc, with every one of rtc_is_utc's four drift checks on after_the_base; realtime-plus-7200.patch still reds through it (583r5-realtime-plus-7200.log:30, 7203 s). kernel/src/actuator.rs and tests/toyos.rs MACHINE_TESTS take main's side cleanly.

BLOCKER

None.

NOTE

  • tests/test-durations:383 — watchdog_fed 23405 re-adds the row main's ad3448d (No QEMU test measures time, and audio is judged on metal only #562) deleted when it moved watchdog_fed to metal only (tests/toyos.rs:1755, 2054); it is not this branch's addition, as the merge message says, so the resolution reverts one of main's hunks. Delete the line. wall_clock_utc (tests/toyos.rs:1231) has no row; wall_clock_zone 9347 renamed to it is what the resolution meant.
  • Carried from round 3, unchanged: the refusal is measured at layout 0 only; LAYOUT misses reorder/type-swap/padding additions until stage 4; no independent layout oracle; the refusing kernel's recovery path to the other slot is unmeasured; no T14 reading.

REMOVE

  • PR body "each within 0..300 s of that instant" — false since the merge; the bound is after_the_base.
  • PR body "— queued for the orchestrator's guest run." and "The orchestrator re-runs the suite at this round's head, 9efc01cb." — measured since.
  • PR body "Gates (host, at 9efc01cb)" table and both guest-run tables at 8565cc59 and 4e07c4df — stale heads; the 87a9457 runs above are the record.

LAND AFTER NAMED CHANGES

Main's #562 deleted this row when it moved watchdog_fed to metal-only;
the merge into this branch resurrected it by mistake. Nothing else in
the file changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Japabu
Japabu added this pull request to the merge queue Sep 29, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to invalid changes in the merge commit Sep 29, 2026
@Japabu
Japabu added this pull request to the merge queue Sep 29, 2026
Merged via the queue into main with commit 7e15181 Sep 29, 2026
1 check passed
@Japabu
Japabu deleted the wt/toyos-loader1 branch September 29, 2026 07:06
Japabu added a commit that referenced this pull request Sep 29, 2026
main's #583 made the RTC UTC: `clock` keeps one anchor, BOOT_SECS, and
the firmware zone, UTC_OFFSET_SECS and local_secs are gone. The mtime
now comes from that same anchor.

- kernel/src/clock.rs: main's `init_wall(century_reg)`, BOOT_SECS and
  its "reads {civil} UTC" line are kept. This branch's utc_nanos is
  BOOT_SECS * 10^9 plus nanos_since_boot, and utc_secs stays its whole
  seconds, which is the value main's utc_secs computed. mtime_now stays
  utc_nanos, or 0 (undated) when the RTC never answered.
  local_secs_of and mtime_of_local are deleted because no zone is left
  to convert through. NANOS_PER_SEC becomes pub for the FAT adapter.
- kernel/src/fat32_adapter.rs: this branch's `stamp(mtime)` and
  `now() = stamp(mtime_now())` are kept, now as whole UTC seconds of
  the mtime. main's refusal-reason moves onto `stamp`: FAT specifies
  local time, and this stamps UTC because the owner ruled the hardware
  clock is UTC. `file_mtime` answers modified_unix * 10^9. An undated
  0 clamps to FatTime::EPOCH, which is what main's now() gave with no
  RTC.
- tests/toyos.rs: main's wall_clock_utc row, CARRIES entry and dispatch
  arm replace wall_clock_zone, which main deleted. This branch's
  file_mtime_survives_a_reboot and file_mtime_undated are kept beside
  them.
- rust: main's pin 9c3eea441d8 (#597) is merged into the fork's
  wt-toyos-mtime as 90697f1401a, with no conflicts.
- issues/filesystem/a-fat-files-mtime-reads-finer-...: "two seconds of
  local time" is no longer true, so it now reads "two-second units".

issues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md
is unchanged. Both handlers still read clock::utc_secs, and its value
did not change. This branch adds no caller of clock_realtime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Japabu added a commit that referenced this pull request Sep 29, 2026
One conflict, kernel/src/arch/aarch64/boot.rs, both hunks kept: main's
(#583) new `report_counter_origin`, empty on AArch64 because no register
says where the generic timer counts from, which main.rs's
`report_power_on` calls on both architectures; and this branch's
`timer()`, its doc and its body (the EL1 virtual timer, logged, stopped
until the scheduler arms it) in place of main's `owed!` stub.

#583's KernelArgs layout word needs nothing on the AArch64 side: the
loader writes it in the portable bootloader/src/main.rs, the kernel
refuses a foreign one in the portable `kernel_main`, which AArch64's
`_start` reaches, and that `_start` reads its four fields by
`offset_of!`, so the layout moves under it by construction.

Auto-merged, each checked against the branch's own hunk: actuator.rs
(main's layout actuator beside this branch's irq-storm and timer-floor),
main.rs (main's layout refusal and power-on report beside this branch's
`mod hw` and headless GOP), x86_64/boot.rs (main's UTC `clock` and
`report_counter_origin` beside this branch's irq-storm/timer-floor
refusal), aarch64/mod.rs (#586 drops log-shared-reservation's window
from `percpu_fetch_add`; this branch's percpu.rs still calls
`log::nested::reserve_window`, which main keeps), clock.rs,
sched/kthread.rs, src/build.rs, src/sourcegate.rs, tests/toyos.rs.
kernel/src/hw.rs is this branch's alone: main touched neither it nor
either architecture's hw.rs. The rust gitlink takes main's 9c3eea44.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Japabu added a commit that referenced this pull request Sep 29, 2026
Brings #583, #586, #593, #597, #555, #600, #610 and #611. Every conflicted
hunk, and where it went:

- rust: 1471893e39c, which merges main's pin 9c3eea441d8 into this branch's
  62fa74d7a50 with no conflict (main's three bootstrap commits and this
  branch's six std files do not meet). Pushed to ToyOSOrg/rust wt-toyos-fsd.
- kernel/src/actuator.rs: #583 deletes `rtc-zone-east`, and that deletion
  stands. This branch's doc for `leak-rollback-selftest` stands, since the
  FAT reopen control went with the kernel's FAT adapter.
- kernel/src/fat32_adapter.rs (modify/delete): the deletion stands. #583's
  hunk made FAT stamp UTC (`clock::utc_secs`) with the refusal reason at the
  site. FAT stamping is fsd's on this branch, so it is carried there:
  `local_secs`, which recovered a zone through `toyos_wallclock::resolve`
  (deleted by #583) and cited logd's `wall.rs` (deleted by #583), becomes
  `utc_secs`, `clock_epoch()` alone, with main's reason. fsd no longer
  depends on toyos-wallclock; userland/Cargo.lock drops the edge.
- kernel/src/sched/kthread.rs: #586 deleted `lognest` and `log-storm`, and
  this branch deleted `iod`, so klogd is the one kernel thread in every
  build: MAX_KERNEL_TASKS = 1, with no feature split.
- issues/kernel/the-kernel-still-creates-threads.md: #586 met K3 and deleted
  it; this branch meets K5 and deletes it. K6 is blocked on K2 and K4.
- userland/logd/src/main.rs: #583's `boot_secs` rename, beside this branch's
  `Published::new()`, which takes no argument here. The `owed` and
  `retrying_since` fields stay deleted (this branch).
- userland/logd/src/serve.rs: this branch's `serving` flag, with #583's
  `boot_secs`.
- tests/test-durations: #586 deleted `log_conservation_smp1` and this branch
  deleted `log_backing_read_error`; neither row stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U6SVYFkdvV2t38KzNrESxs
Japabu added a commit that referenced this pull request Sep 29, 2026
The review's blocker: no AArch64 test could fail on `leaf()`'s Write
check. `test_rs_abuse_readonly_copyout` issued its calls with the x86
`syscall` instruction; it now goes through `toyos_abi::syscall`'s typed
wrappers, with the target named by a slice over the read-only address
(as `tls_dtv_race` does), so it builds for both architectures and its
row in the source gate's assembly exemptions goes.

- The typed-value arm was `fstat`, whose wrapper returns its `Stat`
  rather than taking an address. It is now `process_stats` of a child
  the test spawns first: the same `copy_out` path, reachable through a
  wrapper that takes the caller's `&mut`.
- Every arm runs; the exit status carries one bit per arm that let a
  write through (1 read-only mmap, 2 own text, 4 straddle, 8 clock
  page), which the kernel's own exit record prints even once a
  rewritten clock page has taken logd down. The straddle arm's search
  for the first unwritable page reports rather than panics when no page
  refuses, so a kernel that grants every write still reaches the clock
  arm.
- `tests/virtjobcase` runs it as its last job; `virt_job` builds that
  one binary for AArch64 (`build::build_toyos_bin`, the crate's other
  binaries do not all build there) and puts it on ROOT for every boot of
  the case. `virt_readonly_copyout` judges it. The x86 shared run stays
  and is declared in DRIVEN_AND_SHARED.

Also: the device-memory issue now names `user_ptr`'s direct-map copies
and `dump_crash_diagnostics` beside `read_user_word`; the arm64 track
drops the KernelArgs clause #583 made false; the assembly issue drops
its probe count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U6SVYFkdvV2t38KzNrESxs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant