From 0bc536b80420f24018cb3751600ef11c8496f949 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 28 Oct 2026 09:34:52 +0100 Subject: [PATCH 1/6] issues: the system clock takes the TSC on one reading, and that reading misses by tens of ppm Found while measuring the AMD bench's TSC for PR #1079 (2026-10-28, tsc-drift under its Linux: 1796.6248 MHz over 10 minutes against the HPET and the ACPI PM timer, every phase alike, invariant bit set). - The system clock reads CPUID 80000007H:EDX[8] nowhere (deep idle reads it, idle.rs::facts). It checks the CPUs' TSCs against an 11 ms bracket at start only, and checks the rate against no reference after its one 50 ms calibration. - That calibration reads 40 to 66 ppm low on the AMD bench in every boot log of the session, a bias and not noise. The T14's readings sit in two clusters, 285 ppm under and 59 ppm over its CPUID-stated rate. Co-Authored-By: Claude Opus 5.5 --- ...ibration-misses-the-rate-by-tens-of-ppm.md | 42 +++++++++++++++++++ ...n-one-reading-and-never-checks-it-again.md | 42 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md create mode 100644 issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md diff --git a/issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md b/issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md new file mode 100644 index 00000000000..c530cc421c5 --- /dev/null +++ b/issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md @@ -0,0 +1,42 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# The kernel's 50 ms TSC calibration misses the rate by tens of ppm + +The kernel measures the TSC against the HPET once, over 50 ms +(`kernel/src/arch/x86_64/hpet.rs`), and keeps time at that rate for the +whole boot. On the AMD bench (Ryzen 7 4800U) that rate is consistently low. +Over 10 minutes, the TSC counted 1796.6248 MHz against the same HPET and +against the ACPI PM timer, the same in every idle and busy phase +(`tsc-drift` under the bench's Linux, 2026-10-28, PR #1079's evidence). The +kernel's calibrations in the session's AMD boot logs read 1796.506 to +1796.551 MHz, and 1796.519 to 1796.532 MHz in most of them: 40 to 66 ppm +low. None reads above the true rate; the highest, once, is 1796.597 MHz, 15 +ppm low. At 58 ppm a ToyOS clock on that machine loses about 5 s a day. +Every interval it times reads that much short. + +The error is a bias, not noise: every reading falls on one side. It is not +the window's resolution either: one step of the femtosecond period the +kernel stores is 3,227 Hz there, 1.8 ppm. Where it comes from, the HPET +reads' cost against the window or the order of the reads, is unread. + +The T14 states its TSC's rate (CPUID 15H, 2,419,200,000 Hz), and the kernel +logs its own measurement beside it. The session's T14 boot logs hold two +clusters, 285 ppm under and 59 ppm over, in 344 and 250 log files (some of +them copies of one boot), and a few readings between and beyond them. That the two clusters are two kernel +revisions is an inference no one has checked. On that machine a stated rate +is there to be used, and the kernel keeps its measurement instead. + +**Exit**: on the T14 and the AMD bench, the rate the kernel keeps is within a +bound the fix derives and logs. That bound is set by its window, its reads' +cost and the reference's own accuracy, against the rate measured over minutes +against the same reference: `tsc-drift` on the AMD bench, and CPUID 15H or +`tsc-drift` on the T14. + +Whether the TSC may keep time at all, and whether it still does, is +`issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md`. + +**Owner**: the kernel's x86-64 clock (`kernel/src/arch/x86_64/hpet.rs`). diff --git a/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md b/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md new file mode 100644 index 00000000000..2d2a42ddf6c --- /dev/null +++ b/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md @@ -0,0 +1,42 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# The system clock takes the TSC on one reading and never checks it again + +x86-64's system clock is the TSC. The boot measures it against the HPET +once, over 50 ms (`kernel/src/arch/x86_64/hpet.rs`), and `clock::set_counter` +publishes that one period for the machine's life. Three things the clock +then relies on go unchecked: + +- **That the TSC may keep time at all.** CPUID 80000007H:EDX[8], the + invariant TSC (Intel's SDM "Invariant TSC"; AMD's PPRs + `CPUID_Fn80000007_EDX[TscInvariant]`), is read only to admit deep idle + states (`kernel/src/arch/x86_64/idle.rs::facts`). The clock starts on a + TSC without it the same way. +- **That every CPU's TSC agrees.** Each AP's reading at start is checked to + fall inside a bracket of the BSP's, and that bracket is about 19.8 M cycles + wide on the AMD bench, 11 ms (the `SMP:` lines). An offset under that + passes unseen, and nothing compares the CPUs again. +- **That the rate stays the one measured.** No later reading is set against + the HPET or another reference, so a step or a change of rate after boot + goes into every timestamp, timeout and deadline unannounced. + +On the AMD bench (Ryzen 7 4800U) the one calibration is also 40 to 66 ppm +off (`issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md`). +That CPU states the invariant bit and, over 10 minutes under its Linux, +counts one rate in every phase. But that Linux's own watchdog found its TSC +1.7 ms ahead of the HPET over 502 ms early in boot, a cause not yet known +(the AMD bench's clocksource record, which lands with PR #1079). A +clock that never checks would not see that if it happened under ToyOS. + +**Exit**: the kernel keeps time on the TSC only where every CPU states it +invariant. It bounds the CPUs' offsets at start to a figure it logs and +derives, and checks the rate and offsets against a reference while it runs, +failing clearly or falling back to a counter that holds when they leave +their bound. Each part is shown on the T14 and the AMD bench. + +**Owner**: the kernel's x86-64 clock (`kernel/src/arch/x86_64/hpet.rs`, +`kernel/src/clock.rs`). From 44813af088cc20dc40f636442503c6b2bc36148d Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 28 Oct 2026 10:33:22 +0100 Subject: [PATCH 2/6] issues: the T14 control and the AMD's boot history join the clock records T14: the TSC counts 2419.2002 MHz against the HPET over 5 minutes, CPUID 15H's rate within 0.1 ppm, so the kernel's -285/+59 ppm readings are its own. AMD: in 5 of 30 boots' logs, a 1.7 ms step early in boot that no runtime probe reproduces, where ToyOS's one calibration also runs. Co-Authored-By: Claude Opus 5.5 --- ...-calibration-misses-the-rate-by-tens-of-ppm.md | 12 ++++++++---- ...sc-on-one-reading-and-never-checks-it-again.md | 15 ++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md b/issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md index c530cc421c5..a4c671475a5 100644 --- a/issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md +++ b/issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md @@ -24,11 +24,15 @@ kernel stores is 3,227 Hz there, 1.8 ppm. Where it comes from, the HPET reads' cost against the window or the order of the reads, is unread. The T14 states its TSC's rate (CPUID 15H, 2,419,200,000 Hz), and the kernel -logs its own measurement beside it. The session's T14 boot logs hold two -clusters, 285 ppm under and 59 ppm over, in 344 and 250 log files (some of -them copies of one boot), and a few readings between and beyond them. That the two clusters are two kernel +logs its own measurement beside it. Over 5 minutes against the HPET under +its Linux, the TSC counted 2419.2002 MHz, the stated rate within 0.1 ppm, +worst residual 0.2 µs (`tsc-drift`, 2026-10-28). The session's T14 boot logs +hold two clusters, 285 ppm under and 59 ppm over, in 344 and 250 log files +(some of them copies of one boot), and a few readings between and beyond +them. Those are the kernel's error. That the two clusters are two kernel revisions is an inference no one has checked. On that machine a stated rate -is there to be used, and the kernel keeps its measurement instead. +is there to be used, and right, and the kernel keeps its measurement +instead. **Exit**: on the T14 and the AMD bench, the rate the kernel keeps is within a bound the fix derives and logs. That bound is set by its window, its reads' diff --git a/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md b/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md index 2d2a42ddf6c..05e4c4c3419 100644 --- a/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md +++ b/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md @@ -26,11 +26,16 @@ then relies on go unchecked: On the AMD bench (Ryzen 7 4800U) the one calibration is also 40 to 66 ppm off (`issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md`). -That CPU states the invariant bit and, over 10 minutes under its Linux, -counts one rate in every phase. But that Linux's own watchdog found its TSC -1.7 ms ahead of the HPET over 502 ms early in boot, a cause not yet known -(the AMD bench's clocksource record, which lands with PR #1079). A -clock that never checks would not see that if it happened under ToyOS. +That CPU states the invariant bit. Under its Linux, it counts one rate in +every phase over 10 minutes, and over 15 minutes across 16 CPUs and idle +gaps up to 1 s no CPU's TSC read behind another's and no step exceeded a +read's 1.2 µs. But in 5 of 30 boots' kernel logs that Linux's watchdog saw +the TSC some 1.7 ms ahead of the HPET over half a second, 2 to 3 s into +boot. Every time it was the same size, and it came with a calibration that +was right. The cause is unknown (`tsc-probe` and the boots' figures, PR +#1079's evidence). ToyOS's one calibration also runs early in boot. A step +inside its 50 ms would be a 3% error in every timestamp after it, and a +clock that never checks would not see it. **Exit**: the kernel keeps time on the TSC only where every CPU states it invariant. It bounds the CPUs' offsets at start to a figure it logs and From 1b45a7f5abf83586483ab60dff06f7cb33bf4045 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 28 Oct 2026 11:13:01 +0100 Subject: [PATCH 3/6] review r1: the clock gains, the slug says what is true, and the figures are the evidence's - A rate read low is a period kept long, so the AMD's clock gains about 5 s a day, and the T14's -285 ppm cluster about 25. - the-kernels-50-ms-tsc-calibration-misses-the-tscs-rate: the T14's readings are hundreds of ppm off, not tens. Its citation moves with it. - 345 log files; the ACPI PM run is 5 minutes; all but one calibration in the range given; 41 to 66 ppm; "2.6 s into boot in the one boot whose dmesg was kept". - Suggestions taken: the HPET-bracket inference, labelled, and an exit whose fallback is loud and whose runtime bound cannot repeat Linux's own miscalibration. Co-Authored-By: Claude Opus 5.5 --- ...ibration-misses-the-rate-by-tens-of-ppm.md | 46 ---------------- ...ms-tsc-calibration-misses-the-tscs-rate.md | 52 +++++++++++++++++++ ...n-one-reading-and-never-checks-it-again.md | 20 ++++--- 3 files changed, 65 insertions(+), 53 deletions(-) delete mode 100644 issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md create mode 100644 issues/the-kernels-50-ms-tsc-calibration-misses-the-tscs-rate.md diff --git a/issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md b/issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md deleted file mode 100644 index a4c671475a5..00000000000 --- a/issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -status: open -kind: defect -opened: 2026-10-28 ---- - -# The kernel's 50 ms TSC calibration misses the rate by tens of ppm - -The kernel measures the TSC against the HPET once, over 50 ms -(`kernel/src/arch/x86_64/hpet.rs`), and keeps time at that rate for the -whole boot. On the AMD bench (Ryzen 7 4800U) that rate is consistently low. -Over 10 minutes, the TSC counted 1796.6248 MHz against the same HPET and -against the ACPI PM timer, the same in every idle and busy phase -(`tsc-drift` under the bench's Linux, 2026-10-28, PR #1079's evidence). The -kernel's calibrations in the session's AMD boot logs read 1796.506 to -1796.551 MHz, and 1796.519 to 1796.532 MHz in most of them: 40 to 66 ppm -low. None reads above the true rate; the highest, once, is 1796.597 MHz, 15 -ppm low. At 58 ppm a ToyOS clock on that machine loses about 5 s a day. -Every interval it times reads that much short. - -The error is a bias, not noise: every reading falls on one side. It is not -the window's resolution either: one step of the femtosecond period the -kernel stores is 3,227 Hz there, 1.8 ppm. Where it comes from, the HPET -reads' cost against the window or the order of the reads, is unread. - -The T14 states its TSC's rate (CPUID 15H, 2,419,200,000 Hz), and the kernel -logs its own measurement beside it. Over 5 minutes against the HPET under -its Linux, the TSC counted 2419.2002 MHz, the stated rate within 0.1 ppm, -worst residual 0.2 µs (`tsc-drift`, 2026-10-28). The session's T14 boot logs -hold two clusters, 285 ppm under and 59 ppm over, in 344 and 250 log files -(some of them copies of one boot), and a few readings between and beyond -them. Those are the kernel's error. That the two clusters are two kernel -revisions is an inference no one has checked. On that machine a stated rate -is there to be used, and right, and the kernel keeps its measurement -instead. - -**Exit**: on the T14 and the AMD bench, the rate the kernel keeps is within a -bound the fix derives and logs. That bound is set by its window, its reads' -cost and the reference's own accuracy, against the rate measured over minutes -against the same reference: `tsc-drift` on the AMD bench, and CPUID 15H or -`tsc-drift` on the T14. - -Whether the TSC may keep time at all, and whether it still does, is -`issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md`. - -**Owner**: the kernel's x86-64 clock (`kernel/src/arch/x86_64/hpet.rs`). diff --git a/issues/the-kernels-50-ms-tsc-calibration-misses-the-tscs-rate.md b/issues/the-kernels-50-ms-tsc-calibration-misses-the-tscs-rate.md new file mode 100644 index 00000000000..a18cc3dfb0e --- /dev/null +++ b/issues/the-kernels-50-ms-tsc-calibration-misses-the-tscs-rate.md @@ -0,0 +1,52 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# The kernel's 50 ms TSC calibration misses the TSC's rate + +The kernel measures the TSC against the HPET once, over 50 ms +(`kernel/src/arch/x86_64/hpet.rs`), and keeps time at that rate for the +whole boot. On the AMD bench (Ryzen 7 4800U) that rate is consistently low. +The TSC counted 1796.6248 MHz against the same HPET over 10 minutes and +against the ACPI PM timer over 5, the same in every idle and busy phase +(`tsc-drift` under the bench's Linux, 2026-10-28, PR #1079's evidence). All +but one of the kernel's calibrations in the session's AMD boot logs read +1796.506 to 1796.551 MHz, 41 to 66 ppm low, and 1796.519 to 1796.532 MHz in +most; the one other reads 1796.597 MHz, 15 ppm low. A rate read low is a +period kept long (`hpet.rs` stores HPET femtoseconds per TSC cycle), so every +interval reads long: at 58 ppm a ToyOS clock on that machine gains about 5 s +a day. + +The error is a bias, not noise: every reading falls on one side. It is not +the period's resolution either: one step of the femtoseconds the kernel +stores is 3,227 Hz there, 1.8 ppm, and truncation biases the other way. An +inference, not measured: the HPET is read before the first TSC read and after +the last, so the HPET interval brackets the TSC interval by up to two +uncached MMIO reads. About 1.5 µs over 50 ms is about 30 ppm low, the sign +and size seen. + +The T14 states its TSC's rate (CPUID 15H, 2,419,200,000 Hz), and the kernel +logs its own measurement beside it. Over 5 minutes against the HPET under +its Linux, the TSC counted 2419.2002 MHz, the stated rate within 0.1 ppm, +worst residual 0.2 µs (`tsc-drift`, 2026-10-28). The session's T14 boot logs +hold two clusters, 285 ppm under and 59 ppm over, in 345 and 250 log files +(some of them copies of one boot), and a few readings between and beyond +them (404 to 440 and 759 to 766 ppm under). Those are the kernel's error: the +285 ppm cluster gains about 25 s a day and the 59 ppm one loses about 5. The +bracketing above explains neither, which needs 14 µs and the other sign. +That the two clusters are two kernel revisions is an inference no one has +checked. On that machine a stated rate is there to be used, and right, and +the kernel keeps its measurement instead. + +**Exit**: on the T14 and the AMD bench, the rate the kernel keeps is within a +bound the fix derives and logs. That bound is set by its window, its reads' +cost and the reference's own accuracy, against the rate measured over minutes +against the same reference: `tsc-drift` on the AMD bench, and CPUID 15H or +`tsc-drift` on the T14. + +Whether the TSC may keep time at all, and whether it still does, is +`issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md`. + +**Owner**: the kernel's x86-64 clock (`kernel/src/arch/x86_64/hpet.rs`). diff --git a/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md b/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md index 05e4c4c3419..8ed64f701ee 100644 --- a/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md +++ b/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md @@ -24,14 +24,14 @@ then relies on go unchecked: the HPET or another reference, so a step or a change of rate after boot goes into every timestamp, timeout and deadline unannounced. -On the AMD bench (Ryzen 7 4800U) the one calibration is also 40 to 66 ppm -off (`issues/the-kernels-50-ms-tsc-calibration-misses-the-rate-by-tens-of-ppm.md`). +On the AMD bench (Ryzen 7 4800U) the one calibration is also 41 to 66 ppm +off (`issues/the-kernels-50-ms-tsc-calibration-misses-the-tscs-rate.md`). That CPU states the invariant bit. Under its Linux, it counts one rate in every phase over 10 minutes, and over 15 minutes across 16 CPUs and idle gaps up to 1 s no CPU's TSC read behind another's and no step exceeded a read's 1.2 µs. But in 5 of 30 boots' kernel logs that Linux's watchdog saw -the TSC some 1.7 ms ahead of the HPET over half a second, 2 to 3 s into -boot. Every time it was the same size, and it came with a calibration that +the TSC some 1.7 ms ahead of the HPET over half a second, 2.6 s into boot +in the one boot whose dmesg was kept. Every time it was the same size, and it came with a calibration that was right. The cause is unknown (`tsc-probe` and the boots' figures, PR #1079's evidence). ToyOS's one calibration also runs early in boot. A step inside its 50 ms would be a 3% error in every timestamp after it, and a @@ -39,9 +39,15 @@ clock that never checks would not see it. **Exit**: the kernel keeps time on the TSC only where every CPU states it invariant. It bounds the CPUs' offsets at start to a figure it logs and -derives, and checks the rate and offsets against a reference while it runs, -failing clearly or falling back to a counter that holds when they leave -their bound. Each part is shown on the T14 and the AMD bench. +derives, and checks the rate and offsets against a reference while it runs. +When they leave their bound it fails clearly, or falls back to a counter +that holds and says so in the log. The runtime bound is derived from the +reference's and the reads' own error, so the check does not mistake its +own calibration for the TSC's: 12 of the 17 times the AMD's Linux watchdog +fired, it was Linux's own calibration that was wrong. Where a vendor +documents a cheaper detector, the check prefers it, such as `IA32_TSC_ADJUST` +for a write to the TSC (Intel's SDM, Vol. 3). Each part is shown on the T14 +and the AMD bench. **Owner**: the kernel's x86-64 clock (`kernel/src/arch/x86_64/hpet.rs`, `kernel/src/clock.rs`). From de2abfd78602d8323d87b110f295c308dbbff3ca Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 28 Oct 2026 11:13:30 +0100 Subject: [PATCH 4/6] issues: the AP TSC record takes the warp measurement, and the clock record cites it issues/ap-tsc-trail-is-assumed-and-never-checked.md owns cross-CPU agreement. It gains the AMD's tsc-probe warp result (no CPU behind another's last reading, within about 200 ns) and the 11 ms bracket smp now logs. The system-clock record cites it rather than restating it. Co-Authored-By: Claude Opus 5.5 --- issues/ap-tsc-trail-is-assumed-and-never-checked.md | 12 ++++++++++++ ...e-tsc-on-one-reading-and-never-checks-it-again.md | 6 +++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/issues/ap-tsc-trail-is-assumed-and-never-checked.md b/issues/ap-tsc-trail-is-assumed-and-never-checked.md index cd0118963b2..71ebf70d9ce 100644 --- a/issues/ap-tsc-trail-is-assumed-and-never-checked.md +++ b/issues/ap-tsc-trail-is-assumed-and-never-checked.md @@ -63,3 +63,15 @@ QEMU synthesises every guest TSC from one host clock and cannot answer, so this belongs on the metal session's table beside the control-register delta (`issues/a-metal-session-runs-a-pre-flash-gate-first.md`). Owed by whoever prepares that session: build the log line first, then read it. + +**2026-10-28, part measured.** `smp` now logs each AP's `rdtsc` inside a +bracket of the BSP's, about 19.8 M cycles (11 ms) wide on the AMD bench, so +it answers "trails by more than the boot took" and no smaller offset. Under +the AMD bench's Linux, CPU 0 and each of the other 15 took turns reading +their TSCs through idle gaps up to 1 s (`tsc-probe warp`, PR #1079's +evidence). No CPU ever read behind the other's last reading, and the +smallest step was 54 cycles, so that CPU's TSCs agree to within one turn, +some 200 ns. That is that firmware's synchronisation under Linux, not a +ToyOS measurement: the log line this file owes is still a bracket, not an +offset. `issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md` +holds the clock's other unchecked assumptions. diff --git a/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md b/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md index 8ed64f701ee..583a9287b06 100644 --- a/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md +++ b/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md @@ -17,9 +17,9 @@ then relies on go unchecked: states (`kernel/src/arch/x86_64/idle.rs::facts`). The clock starts on a TSC without it the same way. - **That every CPU's TSC agrees.** Each AP's reading at start is checked to - fall inside a bracket of the BSP's, and that bracket is about 19.8 M cycles - wide on the AMD bench, 11 ms (the `SMP:` lines). An offset under that - passes unseen, and nothing compares the CPUs again. + fall inside a bracket of the BSP's, about 19.8 M cycles wide on the AMD + bench, 11 ms (the `SMP:` lines), and nothing compares the CPUs again + (`issues/ap-tsc-trail-is-assumed-and-never-checked.md`). - **That the rate stays the one measured.** No later reading is set against the HPET or another reference, so a step or a change of rate after boot goes into every timestamp, timeout and deadline unannounced. From f3680713236b638b47ac3172267d8f1d92e862bb Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 28 Oct 2026 11:28:40 +0100 Subject: [PATCH 5/6] review r2: the cross-core bound is the worst pair's, 342 cycles A non-negative step each way bounds a pair's offset by the larger of its two worst steps; across the 15 pairs that is 342 cycles (cpu0<->cpu10), about 190 ns. One line rewrapped. Co-Authored-By: Claude Opus 5.5 --- issues/ap-tsc-trail-is-assumed-and-never-checked.md | 5 ++--- ...e-tsc-on-one-reading-and-never-checks-it-again.md | 12 ++++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/issues/ap-tsc-trail-is-assumed-and-never-checked.md b/issues/ap-tsc-trail-is-assumed-and-never-checked.md index 71ebf70d9ce..a92930d3063 100644 --- a/issues/ap-tsc-trail-is-assumed-and-never-checked.md +++ b/issues/ap-tsc-trail-is-assumed-and-never-checked.md @@ -69,9 +69,8 @@ bracket of the BSP's, about 19.8 M cycles (11 ms) wide on the AMD bench, so it answers "trails by more than the boot took" and no smaller offset. Under the AMD bench's Linux, CPU 0 and each of the other 15 took turns reading their TSCs through idle gaps up to 1 s (`tsc-probe warp`, PR #1079's -evidence). No CPU ever read behind the other's last reading, and the -smallest step was 54 cycles, so that CPU's TSCs agree to within one turn, -some 200 ns. That is that firmware's synchronisation under Linux, not a +evidence). Every pair's worst step was positive, 54 to 342 cycles, which +bounds each CPU's offset from CPU 0 by 342 cycles, some 190 ns. That is that firmware's synchronisation under Linux, not a ToyOS measurement: the log line this file owes is still a bracket, not an offset. `issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md` holds the clock's other unchecked assumptions. diff --git a/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md b/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md index 583a9287b06..ee21047bf49 100644 --- a/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md +++ b/issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md @@ -30,12 +30,12 @@ That CPU states the invariant bit. Under its Linux, it counts one rate in every phase over 10 minutes, and over 15 minutes across 16 CPUs and idle gaps up to 1 s no CPU's TSC read behind another's and no step exceeded a read's 1.2 µs. But in 5 of 30 boots' kernel logs that Linux's watchdog saw -the TSC some 1.7 ms ahead of the HPET over half a second, 2.6 s into boot -in the one boot whose dmesg was kept. Every time it was the same size, and it came with a calibration that -was right. The cause is unknown (`tsc-probe` and the boots' figures, PR -#1079's evidence). ToyOS's one calibration also runs early in boot. A step -inside its 50 ms would be a 3% error in every timestamp after it, and a -clock that never checks would not see it. +the TSC some 1.7 ms ahead of the HPET over half a second, 2.6 s into boot in +the one boot whose dmesg was kept. Every time it was the same size, and it +came with a calibration that was right. The cause is unknown (`tsc-probe` +and the boots' figures, PR #1079's evidence). ToyOS's one calibration also +runs early in boot. A step inside its 50 ms would be a 3% error in every +timestamp after it, and a clock that never checks would not see it. **Exit**: the kernel keeps time on the TSC only where every CPU states it invariant. It bounds the CPUs' offsets at start to a figure it logs and From da056ab4006217e5986d1b8c70ff3da55e77eed0 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 28 Oct 2026 11:28:53 +0100 Subject: [PATCH 6/6] issues: the AP TSC record's new paragraph rewrapped Co-Authored-By: Claude Opus 5.5 --- issues/ap-tsc-trail-is-assumed-and-never-checked.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/issues/ap-tsc-trail-is-assumed-and-never-checked.md b/issues/ap-tsc-trail-is-assumed-and-never-checked.md index a92930d3063..6623469fb78 100644 --- a/issues/ap-tsc-trail-is-assumed-and-never-checked.md +++ b/issues/ap-tsc-trail-is-assumed-and-never-checked.md @@ -70,7 +70,8 @@ it answers "trails by more than the boot took" and no smaller offset. Under the AMD bench's Linux, CPU 0 and each of the other 15 took turns reading their TSCs through idle gaps up to 1 s (`tsc-probe warp`, PR #1079's evidence). Every pair's worst step was positive, 54 to 342 cycles, which -bounds each CPU's offset from CPU 0 by 342 cycles, some 190 ns. That is that firmware's synchronisation under Linux, not a -ToyOS measurement: the log line this file owes is still a bracket, not an -offset. `issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md` +bounds each CPU's offset from CPU 0 by 342 cycles, some 190 ns. That is that +firmware's synchronisation under Linux, not a ToyOS measurement: the log +line this file owes is still a bracket, not an offset. +`issues/the-system-clock-takes-the-tsc-on-one-reading-and-never-checks-it-again.md` holds the clock's other unchecked assumptions.