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.
This commit is contained in:
@@ -14,6 +14,7 @@ const boot_handoff = @import("boot-handoff");
|
||||
const abi = @import("abi");
|
||||
const device_abi = @import("device-abi");
|
||||
const architecture = @import("architecture");
|
||||
const wall_clock = @import("wall-clock.zig");
|
||||
const devices_broker = @import("devices-broker.zig");
|
||||
const platform = @import("platform");
|
||||
const pmm = @import("pmm.zig");
|
||||
@@ -66,6 +67,8 @@ pub fn run(case: []const u8, boot_information: *const BootInformation) void {
|
||||
timer();
|
||||
} else if (eql(case, "clock")) {
|
||||
clock();
|
||||
} else if (eql(case, "wall-clock")) {
|
||||
wallClock();
|
||||
} else if (eql(case, "vmm")) {
|
||||
vmm();
|
||||
} else if (eql(case, "heap")) {
|
||||
@@ -458,6 +461,17 @@ fn heapTest() void {
|
||||
/// Verify the calibrated clocks: sane measured frequencies, monotonic uptime that
|
||||
/// advances with real ticks, and — the point of the TSC clock — nanosecond
|
||||
/// resolution far finer than the 1 ms tick, with the unit functions consistent.
|
||||
fn wallClock() void {
|
||||
log("DANOS-TEST-BEGIN: wall-clock\n", .{});
|
||||
// The RTC was read and anchored at boot (kmain -> wall_clock.init()).
|
||||
const seconds = wall_clock.nowSeconds();
|
||||
log(" epoch: {d}\n", .{seconds});
|
||||
// A plausible current wall-clock: after 2020-01-01 (1577836800) and before 2050
|
||||
// (2524608000) — catches a broken CMOS read or a wrong epoch conversion.
|
||||
check("wall clock reads a plausible current epoch", seconds > 1_577_836_800 and seconds < 2_524_608_000);
|
||||
result();
|
||||
}
|
||||
|
||||
fn clock() void {
|
||||
log("DANOS-TEST-BEGIN: clock\n", .{});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user