Repository navigation
The x86-64 wall clock is the loader's reading of firmware, and the CMOS driver is gone - #1213
Conversation
e03485e to
32e1107
Compare
Review of #1213 at
|
…k's row carries the loader's reading, and the loss has its record B1. `a_stalled_hpet_is_told_by_the_pm_timer` names a job, `hpet_stall_read`, which reads the served log until the clock has reported after the span `hpet-stall` staged, under the runner's bound: the AMD bench's whole `shared-debug` boot at 32e1107 staged the stall at 5.387 s and rebooted at 5.929 s, before the next sample. The judge reads the staged span's record alone: left out, with the PM timer 10 ms nearer the TSC than the HPET is. A step the bench's own TSC takes passes it in another span and in the staged one, where every counter disagrees and the PM timer still tells the stall. B2. `wall_clock_is_firmwares` is two claims. ToyOS's: every dated line is the loader's reading carried on by the log's own stamps from the reading's counter at the boot's rate, within what four divisions drop; no host clock. The bench's: firmware's reading lies in the span the host saw the boot run in, 300 s either side, and a red names the bench's hardware clock. B3. `issues/chipset-counters-that-stall-together-read-as-a-tsc-step.md` records what was given up, in its three shapes, with the evidence and the documents; ACPI makes the PM timer optional, so the third takes one counter out of specification. The clock's header keeps the invariant and names the record. The guest-suite track loses the line for the row this adds. B4. `anchor` loses the arm for a reading after boot, which only the CMOS read made, and its case; three comments that still named the RTC say what is true now; `boot_file` has its doc line back. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
32e1107 to
8dbc535
Compare
Review of #1213 at
|
…OS driver is gone The loader asks firmware's GetTime on every architecture and hands the instant with the counter it was true at. AArch64 anchored on it; x86-64 ignored it and read the CMOS itself, with the FADT's century register. Both now anchor in `clock::init_wall`, which reads `KernelArgs::wall_clock_*`, and `arch/x86_64/rtc.rs`, `arch/aarch64/rtc.rs`, `acpi::rtc_century_register` and `toyos-acpi`'s century decode are deleted. The driver's other reader goes with it. The clock took the RTC's update-ended edges (IRQ8, vector 0x26) as a third reference where the HPET and the ACPI PM timer both disagreed with the TSC by the same amount: near the step, or unsure, the TSC was taken to have stepped; near zero, the chipset's two counters were taken to have stopped together and the span was left out. Now that case is always the TSC's step. What is lost is that one attribution, not a detection: every disagreement is still found within a second and logged with all three spans. A machine whose HPET and PM timer stop together while its TSC counts on would have its first stall slewed out of the clock, which then stands the stall's length behind, and a second would demote a sound TSC to the stalling HPET, loudly. Neither counter may stop in S0 (ACPI 6.5 §4.8.3.3; IA-PC HPET 1.0a §2.3.3), and no published boot of either bench has read that case: the RTC's verdict was "confirmed" or "unconfirmed" in every one, and both take the same action. A step is now slewed in the sample that finds it, not up to five seconds of edges later, and written as one line. cpu0 takes one interrupt a second fewer. `time::Bound`, whose one user was the CMOS read's wait, and the per-architecture census hook, whose one source was IRQ8, go too. Tests. `wall_clock_is_firmwares` (metal, riding `testcases`) holds the kernel's anchor to the loader's reading and the boot's last dated line to the span the host's clock saw the boot run in, which the loop now records as `back_unix_secs`. `a_stalled_hpet_is_told_by_the_pm_timer` (metal, riding `shared-debug`) stages `hpet-stall` against each bench's own PM timer, now the only arbiter. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…k's row carries the loader's reading, and the loss has its record B1. `a_stalled_hpet_is_told_by_the_pm_timer` names a job, `hpet_stall_read`, which reads the served log until the clock has reported after the span `hpet-stall` staged, under the runner's bound: the AMD bench's whole `shared-debug` boot at 32e1107 staged the stall at 5.387 s and rebooted at 5.929 s, before the next sample. The judge reads the staged span's record alone: left out, with the PM timer 10 ms nearer the TSC than the HPET is. A step the bench's own TSC takes passes it in another span and in the staged one, where every counter disagrees and the PM timer still tells the stall. B2. `wall_clock_is_firmwares` is two claims. ToyOS's: every dated line is the loader's reading carried on by the log's own stamps from the reading's counter at the boot's rate, within what four divisions drop; no host clock. The bench's: firmware's reading lies in the span the host saw the boot run in, 300 s either side, and a red names the bench's hardware clock. B3. `issues/chipset-counters-that-stall-together-read-as-a-tsc-step.md` records what was given up, in its three shapes, with the evidence and the documents; ACPI makes the PM timer optional, so the third takes one counter out of specification. The clock's header keeps the invariant and names the record. The guest-suite track loses the line for the row this adds. B4. `anchor` loses the arm for a reading after boot, which only the CMOS read made, and its case; three comments that still named the RTC say what is true now; `boot_file` has its doc line back. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…, and two say their bound's reason Comments only. The allowance's tenth of a second is for retunes and a slewed step, which move a boot's stamps far less; the staged stall's millisecond is the two counters' allowances over a second. `file_mtime`'s panic text still says "RTC": it is a string its binary carries. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
8dbc535 to
d7d8daf
Compare
|
Orchestrator verification at d7d8daf, after review r2's LAND at 8dbc535.
Queueing. |
Problem
The loader asks firmware's
GetTimeon every architecture and hands the instant inKernelArgs::wall_clock_*. AArch64 anchored its wall clock on that. x86-64 ignored it and read the CMOS itself, with the FADT's century register, so two readers kept one clock and the field was written and never read (issues/x86-64-reads-the-cmos-for-a-wall-clock-the-loader-already-hands-it.md).The CMOS driver had a second reader: the clock source took the RTC's update-ended edges on IRQ8 as a third reference.
What changes
clock::init_wallreads the loader's handoff on both architectures.arch/x86_64/rtc.rs,arch/aarch64/rtc.rs,acpi::rtc_century_registerandtoyos-acpi's century decode are deleted.rtcsource, the edge store, andkernel::clock::reference'sEdgesandthird_saysare deleted with it.time::Bound, whose one user was the CMOS read's wait, and the per-architecture census hook, whose one source was IRQ8.acpiclaim's holder: a write there sets the clock firmware answers the loader from.architecture/boot.md) says the kernel drives no real-time clock.git ls-files 'kernel/src/*.rs': 214 files and 55,303 lines on mainad5db5a65, 211 files and 54,823 after (−480).kernel/pureloses 214 more. The whole diff is +521 −990, the additions mostly the two rows, their host cases and the record.The third reference: what it protected, and why it goes
What it did. Where the TSC and the HPET disagree, the ACPI PM timer arbitrates. If the PM timer sides with the HPET, either the TSC stepped or both chipset counters stopped together. The RTC's edges, on their own 32.768 kHz crystal, chose between those two:
So the RTC changed the clock's action in exactly one case, the third row.
What the documents say of that case.
TscInvariant(Vol. 3, CPUID Fn8000_0007_EDX[8]; recalled, amd.com refuses the fetch).A TSC step and a joint stall of both counters are each a violation, and no document prefers one, so only machines decide. One shape takes less: ACPI makes the PM timer optional (the same §4.8.3.3), so on a machine without a counting one, the HPET alone standing still in S0 is read as the TSC's step. Before, the RTC decided alone there.
What the machines say. In every boot published to the evidence repository (309 branches searched):
The RTC has never changed an action on either bench. Its one result was settling, on the AMD bench, that the TSC moves and the FCH's clock does not stop. That result stays recorded in
issues/the-amd-benchs-tsc-steps-1-7-ms-forward-once-a-boot.md.Whether another reference gives the same discrimination. None present does.
Exactly what is lost. Attribution, not detection. Every disagreement is still found within a second and logged with every counter's span, and a wrong TSC is never kept where main demoted it. A sound TSC is slewed or demoted to a stalling HPET, logged
DEMOTED, in three shapes main survived while its edges worked:The record is
issues/chipset-counters-that-stall-together-read-as-a-tsc-step.md, with the evidence, the owner and the exit.What is gained besides the lines. A step is slewed in the sample that finds it, where it used to wait up to five seconds for edges while readers saw the stepped clock. cpu0 takes one interrupt a second fewer. A step is one log line, not two.
This is my decision on the evidence above, as the brief asked; it is not an owner ruling.
Tests
wall_clock_is_firmwares(metal, new, ridestestcases), two claims with their own failures:GetTime, carried on by the log's own stamps from the reading's counter at the boot's rate. The allowance is what the four divisions between the reading and a line's date drop, less three seconds and plus one, and a tenth of a second for retunes. No host clock is read.back_unix_secsfor this.a_stalled_hpet_is_told_by_the_pm_timer(metal, new, ridesshared-debug):hpet-stallstaged against each bench's own PM timer, now the only arbiter.hpet_stall_read, reads the served log until the clock has reported after the staged span, under the runner's bound, so the row holds its own boot. The AMD bench's wholeshared-debugboot at32e11074eshowed why: the stall was staged at 5.387 s and the boot rebooted at 5.929 s.a_date_off_the_loaders_reading_is_red_and_a_bench_off_utc_is_the_benchs: an anchor ten seconds off is red either way, a date one second outside the allowance is red, and a bench two hours east carries its reading and is red as the bench's.a_staged_stall_is_judged_by_its_own_span: T14-shaped and AMD-shaped logs pass; a stall read as the TSC's, a PM timer standing with neither, no report after, never read and never staged are red.Edges/third_sayscases with the code they tested,toyos-acpi's three century cases, andanchor's case for a reading after boot with its arm.Not added: a metal boot for
tsc-step. It demotes the TSC for the rest of its boot, so it cannot share one, and the AMD bench steps for real in every boot.Checks
Head
d7d8daf98, on mainad5db5a65. The bench images and their judging are at8dbc5357c. Evidence: https://github.com/ToyOSOrg/evidence/tree/d91ed9f31cf8a0a6359dfef1673a88d9891c14f9/r3 (itsREADME.mdhas every command, exit code and log;r1andr2are the earlier rounds).cargo run -- --ci hostd7d8daf98the build system, whose two failing tests areissues/the-llvm-environment-test-breaks-git-on-macos.mdon a macOS host; clippy cleancargo run -- --build-only, x86-64 and--arch aarch64d7d8daf98virt_wall_clock_utc a_stalled_hpet_is_left_out a_stepped_tsc_is_slewed_then_demoted, run 42979867354d7d8daf98testcasesandshared-debugwhole8dbc5357c8dbc5357cWhat the benches showed:
testcases: 7,204 dated lines carry the loader's reading; firmware's reading is inside the span the host saw. NoTSC STEP, noDEMOTED.shared-debug: the staged span is the "HPET moved" record, the HPET 10,005,528 ns apart and the PM timer 2,475 ns apart with 516,371 allowed; a report follows; the job exits 0.testcases: 7,226 dated lines carry the loader's reading; firmware's reading is inside the host's span. The bench's own 1,694,650 ns step is written once, in the sample that finds it, and is slewed away twelve seconds later. NoDEMOTED.shared-debug: the bench's own step landed in the staged span, so the record is "all disagree": the HPET 11,698,294 ns apart and the PM timer 1,697,502 ns, 10,000,792 ns from each other. The span is left out and that step is not slewed in that boot. NoDEMOTED; the job exits 0.8dbc5357ctod7d8daf98is a rebase over main's thirteen commits, #1210'sKernelArgslayout among them, with one conflict in an issue file, and one commit of comments in six files. The bench boots ran main's code as of9f6269832; the guest rows ran the wall clock's handoff through #1210's layout.Risks and open points
kernel/src/syscall/dispatch.rsloses one stale comment line andsdk/abi/src/syscall.rshas two doc comments reworded; both are A move names the rights it delivers: a ring and a manifest's SysCap stay where they were given #1204's files, in other hunks.KernelArgsare untouched, so nothing here meets the loader-named-facts change.back_unix_secsand is refused by name; its boot has to be run again to be judged by this harness.🤖 Generated with Claude Code