riscv64: finish SBI timer verification and clean up stale timer docs
Punch list §25 item 0.3 complete.
The functional work (FDT reader, `time` CSR switch, SBI TIME extension
arm/re-arm, sie.STIE) was committed separately by Captain Bob as accd79f,
honestly labeled "NOT complete." This finishes it: stale documentation
cleanup, then rigorous verification against the item's literal acceptance
text, which the prior commit had not yet done.
Doc cleanup: every remaining reference to `rdcycle` / "assumed 1 GHz" in
riscv64/timer.c and riscv64/apic.c rewritten to describe the actual `time`
CSR / SBI-armed behavior. Caught and corrected my own arithmetic error in
the process: a draft claimed the ns-overflow bound improved to "~58 years"
under the new counter; direct computation shows the bound is actually
~3.26 days (2^48 ns) and is *frequency-independent* -- s_ns_per_tick and
tick rate scale inversely and cancel. Verified with a script before
writing the final comment, not asserted.
Verification, since "boots to prompt" was not sufficient for this item's
acceptance ("heartbeat_ticks() advances ... within measurement noise"):
- No FORTH word exposes heartbeat_ticks() to the REPL, and adding one would
be a new primitive outside this item's scope. GDB-over-QEMU-stub reads of
the static counter failed ("Cannot access memory"), likely a virtual-vs-
runtime address mismatch; abandoned rather than debugged further, since a
better instrument was available.
- QEMU's own `-d int` trap tracing (independent of all guest code) shows
2,797 `cause:5 desc=s_timer` interrupts delivered by the time boot reaches
the prompt, and the interleaved `desc=supervisor_ecall` entries are exactly
the SBI set_timer calls from riscv64_timer_rearm(), confirming the full
interrupt -> handler -> re-arm -> SBI loop.
- Measured rate over a real 10.127 s window: 1,013 further interrupts,
100.028 Hz observed against 100 Hz configured -- 0.03% deviation. The
sustained, non-decaying rate is itself proof the one-shot re-arm succeeds
on every cycle, not just the first.
- Confirmed regression-free on amd64 and aarch64 too: uefi_loader.c, uefi.h,
boot_info_offsets.h and the new fdt.c/fdt.h are shared across all three
builds (amd64 also consumes the offset constants via kernel_entry.S), so
all three were rebuilt and booted. Identical dict_hash
0x3d4e1daf289da94f on all three, matching the item 0.1/0.2 baseline.
Reported, not fixed, per rule 3:
- DOE_INJECT=1's EXEC-DOE now fails as "UNKNOWN WORD" against the pruned
Hera-alone capsule -- doe.4th was never loaded by init.4th even before
item 0.1's prune, so this is a pre-existing gap the prune surfaced, not a
new defect. Discovered while chasing why a 200-rep injected DoE run
produced no new CSV rows after 25 minutes; it had failed in the first
millisecond, not run the whole time.
- repl.c's own comment claims a "Heartbeat: N ticks" diagnostic prints to
the serial log; no such print exists anywhere in the tree.
- riscv64/arch.c's arch_read_timestamp() still uses rdcycle with a stale
1 GHz comment, but it has zero callers on this architecture -- dead code,
left alone.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
accd79fc70
commit
5784d8a1a8
@@ -161,19 +161,19 @@ int apic_init(BootInfo *boot_info)
|
||||
void apic_eoi(void) { }
|
||||
|
||||
/*
|
||||
* @brief Configure the periodic timer (RISC-V stub).
|
||||
* @brief Compute the expected `time`-counter ticks per heartbeat period.
|
||||
*
|
||||
* On x86-64 this calibrates and programs the APIC timer. On RISC-V the
|
||||
* SBI (Supervisor Binary Interface) @c sbi_set_timer() call or the CLINT
|
||||
* (Core Local Interrupt) would be used to schedule timer interrupts; that
|
||||
* driver is deferred. This stub computes @c s_timer_period_tsc — the
|
||||
* expected number of @c rdcycle ticks between heartbeats — which seeds
|
||||
* Unlike x86-64's APIC timer, this does not itself arm anything — RISC-V S-mode
|
||||
* cannot program the timer directly, so arming happens via SBI in
|
||||
* @c apic_timer_start() below. This function only computes
|
||||
* @c s_timer_period_tsc, the expected number of @c time-counter ticks between
|
||||
* heartbeats, which seeds both @c apic_timer_start()'s first deadline and
|
||||
* @c heartbeat_init()'s @c expected_delta.
|
||||
*
|
||||
* Falls back to 10,000,000 cycles if either frequency is zero (a safe
|
||||
* Falls back to 10,000,000 ticks if either frequency is zero (a safe
|
||||
* non-zero sentinel preventing division-by-zero in the heartbeat path).
|
||||
*
|
||||
* @param tsc_hz Cycle-counter frequency from @c timer_init() (Hz).
|
||||
* @param tsc_hz `time` counter frequency from @c timer_init() (Hz).
|
||||
* @param tick_hz Desired heartbeat rate (Hz); 0 → uses fallback.
|
||||
* @return 0 always.
|
||||
*/
|
||||
@@ -245,14 +245,14 @@ void apic_timer_stop(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the expected cycle-counter ticks per heartbeat period.
|
||||
* @brief Return the expected `time`-counter ticks per heartbeat period.
|
||||
*
|
||||
* Returns @c s_timer_period_tsc, set by @c apic_timer_init() as
|
||||
* @c tsc_hz / @c tick_hz. This value is consumed by @c heartbeat_init()
|
||||
* to seed the rolling-window @c expected_delta so that inter-tick
|
||||
* deviation measurements are relative to the correct nominal interval.
|
||||
* @c tsc_hz / @c tick_hz. Consumed by @c heartbeat_init() to seed the
|
||||
* rolling-window @c expected_delta, and by @c apic_timer_start() /
|
||||
* @c riscv64_timer_rearm() as the SBI deadline step.
|
||||
*
|
||||
* @return Expected @c rdcycle ticks per heartbeat period; 10,000,000 if
|
||||
* @return Expected `time`-counter ticks per heartbeat period; 10,000,000 if
|
||||
* frequencies were not available at init time.
|
||||
*/
|
||||
uint64_t apic_timer_period_tsc(void)
|
||||
|
||||
Reference in New Issue
Block a user