Files
danos/system/kernel/wall-clock.zig
Daniel Samson 8a38540312 Phase 2d (i): a kernel wall-clock from the CMOS RTC
Adds real (calendar) time, the foundation for filesystem timestamps. Monotonic
time (`clock`) says how long since boot; this says what time it actually is.

- cpu.zig (x86_64): readRtcUnixSeconds() reads the CMOS real-time clock (ports
  0x70/0x71) — waits out an update-in-progress, reads twice until stable, handles
  BCD-vs-binary and 12-vs-24-hour per status register B — and converts to Unix
  epoch seconds (UTC).
- kernel/wall-clock.zig: reads the RTC once at boot and anchors it to the monotonic
  clock, so a query is a cheap arithmetic offset — no per-call CMOS poll, no lock,
  no SMP hazard on the shared ports. kmain calls init() once the monotonic clock is
  final and logs the epoch.
- wall_clock() syscall (33) -> Unix epoch seconds, wrapped by runtime.system
  .wallClock(). Wall-clock *seconds* are mechanism the kernel owns like the
  monotonic clock; calendars/timezones are user-space policy (the stale comment on
  systemClock that called wall-clock a "user-space service" is updated in spirit by
  the new handler's doc).
- A `wall-clock` kernel test asserts the boot RTC read is a plausible current epoch.

Verified against the host: the guest read epoch 1783971244 while `date -u +%s` gave
1783971245 (one second of boot lag) — the CMOS read + epoch conversion are correct to
the second. zig build, zig build test, and smoke/clock/init are green.
2026-07-13 20:35:03 +01:00

27 lines
1.1 KiB
Zig

//! Wall-clock time: the CMOS real-time clock read once at boot and anchored to the
//! monotonic clock, so a query is a cheap arithmetic offset — no per-call CMOS poll,
//! no lock, no SMP hazard on the shared 0x70/0x71 ports.
//!
//! Wall-clock *seconds* are mechanism the kernel owns, exactly like the monotonic
//! clock ([[time-architecture]]): reading the hardware's value is not policy.
//! Calendars, timezones, and formatting layer on top in user space. It exists so the
//! filesystem can stamp real timestamps (mtime) — see docs/zig-self-hosting.md.
const architecture = @import("architecture");
var boot_unix_seconds: u64 = 0;
var boot_nanos: u64 = 0;
/// Read the RTC once and anchor it to the monotonic clock. Call at boot, after the
/// monotonic clock is calibrated.
pub fn init() void {
boot_unix_seconds = architecture.readRtcUnixSeconds();
boot_nanos = architecture.nanos();
}
/// The current wall-clock time in Unix epoch seconds (UTC): the boot RTC value plus
/// the monotonic time elapsed since. Zero until `init` runs.
pub fn nowSeconds() u64 {
return boot_unix_seconds + (architecture.nanos() -% boot_nanos) / 1_000_000_000;
}