m³OS docs GitHub

Phase 34

Real Time Clock

The OS knows what time it is. A CMOS RTC driver reads the hardware clock at boot to establish the current wall-clock time. `clock_gettime(CLOCK_REALTIME)` returns actual Unix timestamps, distinct from `CLOCK_MONOTONIC` which tracks time since boot. The `date` command displays the current date and time.

Complete

Learning goal

Understand the difference between wall-clock time (RTC, NTP) and monotonic time (tick counter).

Category

foundations

Why this phase matters

The OS knows what time it is. A CMOS RTC driver reads the hardware clock at boot to establish the current wall-clock time. clock_gettime(CLOCK_REALTIME) returns actual Unix timestamps, distinct from CLOCK_MONOTONIC which tracks time since boot. The date command displays the current date and time.

How it works in m3OS

Phase 34 adds wall-clock time awareness to m3OS by reading the CMOS Real-Time Clock (RTC) at boot, computing the Unix epoch timestamp, and exposing it through the clock_gettime() and gettimeofday() syscalls. Userspace utilities date and uptime are provided.

How it builds on earlier phases

This phase builds on Kernel Memory Improvements and turns that foundation into Real Time Clock.

Implementation outline

  • Write CMOS RTC read functions (with BCD conversion and atomic read loop).
  • Implement rtc_to_unix_timestamp() in kernel-core (host-testable).
  • Read RTC during kernel boot and store BOOT_EPOCH_SECS.
  • Update clock_gettime() to distinguish CLOCK_REALTIME vs CLOCK_MONOTONIC.
  • Update gettimeofday() to use wall-clock time.
  • Write date userspace utility.
  • Write host-side tests for time conversion (known dates -> expected timestamps).
  • Verify: date inside the OS matches host system time (within a few seconds).

Task progress snapshot

48 of 50 tracked tasks are complete.

Documentation targets

  • Documentation deliverables have not been listed yet.

Deferred follow-on work

  • NTP time synchronization
  • High-resolution timers (HPET, TSC)
  • vDSO for fast clock_gettime
  • Timezone support
  • RTC alarm / wakeup
  • adjtimex() clock steering
  • Hardware watchdog timer

Source materials

Important code

Code spotlight cards

Code spotlight

Implement `days_in_month()` and `is_leap_year()`

kernel-core/src/time.rs L22-L45

Implement `days_in_month()` and `is_leap_year()`. Why it matters: Leap-year-aware month math is the base layer for every RTC conversion added later in the phase. Focus on `days_in_month` and `is_leap_year` in `kernel-core/src/time.rs` while you trace the snippet.

/// Returns the number of days in the given month (1-indexed) for the given year.
///
/// Panics if `month` is 0 or greater than 12.
pub fn days_in_month(year: u32, month: u32) -> u32 {
    match month {
        1 => 31,
        2 => {
            if is_leap_year(year) {
                29
            } else {
                28
            }
        }
        3 => 31,
        4 => 30,
        5 => 31,
        6 => 30,
        7 => 31,
        8 => 31,
        9 => 30,
        10 => 31,
        11 => 30,
        12 => 31,
        _ => panic!("invalid month"),

Code spotlight

Implement CMOS register read function

kernel/src/rtc.rs L21-L39

Implement CMOS register read function. Why it matters: A minimal raw CMOS accessor is the hardware boundary that the rest of the RTC driver can safely build on. Focus on `cmos_read` in `kernel/src/rtc.rs` while you trace the snippet.

/// Read a single CMOS register.
///
/// Port 0x70 is the address/NMI-disable port (bit 7 disables NMI).
/// Port 0x71 is the data port.
///
/// # Safety
///
/// Performs raw x86 port I/O. Must only be called in ring 0.
unsafe fn cmos_read(register: u8) -> u8 {
    let mut addr_port = Port::<u8>::new(0x70);
    let mut data_port = Port::<u8>::new(0x71);
    unsafe {
        addr_port.write(register | 0x80); // bit 7 = disable NMI during read
        let value = data_port.read();
        // Re-enable NMI by writing the register index with bit 7 clear.
        addr_port.write(register & 0x7F);
        value
    }
}

Code spotlight

Wire RTC module into kernel build

kernel/src/main.rs See file

Wire RTC module into kernel build. Why it matters: Boot-time RTC initialization is what replaces the earlier monotonic-only startup state with a real wall-clock epoch. Focus on `rtc::init_rtc` in `kernel/src/main.rs` while you trace the snippet.

Key files

  • kernel/src/rtc.rs — Reads the CMOS RTC via I/O ports 0x70/0x71. Implements the atomic read protocol
  • kernel-core/src/time.rs — detection. Called once during kernel boot to establish the boot epoch.
  • kernel-core/src/lib.rs — Added pub mod time
  • kernel/src/main.rs — Added mod rtc + init_rtc() call
  • kernel/src/arch/x86_64/syscall.rs — Updated clock_gettime/gettimeofday
  • kernel/src/fs/ramdisk.rs — Added date/uptime to initrd
  • userspace/syscall-lib/src/lib.rs — Added time wrappers + formatting
  • userspace/coreutils-rs/src/date.rs — New: date utility
  • userspace/coreutils-rs/src/uptime.rs — New: uptime utility
  • userspace/coreutils-rs/Cargo.toml — Added date/uptime binaries
  • xtask/src/main.rs — Added date/uptime to build list
  • kernel/Cargo.toml — Version bump 0.33.0 → 0.34.0

How real OSes differ

  • **NTP** (Network Time Protocol) to synchronize wall-clock time with atomic clocks.
  • **HPET** or **TSC** for nanosecond-resolution timekeeping (vs our 10ms LAPIC ticks).
  • **vDSO** to serve `clock_gettime()` from userspace without a syscall.
  • **Timezone databases** (tzdata) for local time conversion.
  • **RTC IRQ** (interrupt on alarm or periodic) for wakeup-from-sleep.
  • **adjtimex()** syscall for fine-grained clock steering.

Success criteria

  • `clock_gettime(CLOCK_REALTIME)` returns correct Unix timestamps (verified against host).
  • `clock_gettime(CLOCK_MONOTONIC)` returns time since boot (unchanged from current behavior).
  • `date` command displays the correct current date and time.
  • RTC read handles BCD vs binary mode correctly.
  • RTC read handles 12-hour vs 24-hour mode correctly.
  • Time conversion passes test vectors (known dates -> Unix timestamps).
  • Boot log shows the detected wall-clock time.

Related phases

Keep exploring the roadmap