diff --git a/kernel/libk/src/time.rs b/kernel/libk/src/time.rs index 779a52cc..df69a97a 100644 --- a/kernel/libk/src/time.rs +++ b/kernel/libk/src/time.rs @@ -2,23 +2,44 @@ use core::sync::atomic::{AtomicU64, Ordering}; use yggdrasil_abi::time::SystemTime; -static MONOTONIC_MILLIS: AtomicU64 = AtomicU64::new(0); +// Millisecond resolution +const NANOSECONDS_IN_SECOND: u64 = 1_000_000_000; +const TIME_RESOLUTION_NS: u64 = 1_000_000; +pub const TICKS_PER_SEC: u64 = NANOSECONDS_IN_SECOND / TIME_RESOLUTION_NS; -pub fn monotonic_time() -> SystemTime { - let millis = MONOTONIC_MILLIS.load(Ordering::Acquire); - let nanoseconds = (millis % 1000) * 1000000; - let seconds = millis / 1000; +static MONOTONIC_TIME: AtomicU64 = AtomicU64::new(0); +static REAL_TIME_OFFSET: AtomicU64 = AtomicU64::new(0); +static REAL_TIME: AtomicU64 = AtomicU64::new(0); +#[inline] +fn make_time(ticks: u64) -> SystemTime { SystemTime { - seconds, - nanoseconds, + seconds: ticks / TICKS_PER_SEC, + nanoseconds: (ticks % TICKS_PER_SEC) * TIME_RESOLUTION_NS, } } -pub fn add_ticks(ticks: u64) -> u64 { - MONOTONIC_MILLIS.fetch_add(ticks, Ordering::Release) +pub fn real_time() -> SystemTime { + make_time(REAL_TIME.load(Ordering::Acquire) + REAL_TIME_OFFSET.load(Ordering::Relaxed)) } -pub fn set_ticks(ticks: u64) -> u64 { - MONOTONIC_MILLIS.swap(ticks, Ordering::Release) +pub fn monotonic_time() -> SystemTime { + make_time(MONOTONIC_TIME.load(Ordering::Acquire)) +} + +pub fn add_ticks(ticks: u64) { + MONOTONIC_TIME.fetch_add(ticks, Ordering::Release); + REAL_TIME_OFFSET.fetch_add(ticks, Ordering::Release); +} + +pub fn set_real_time(ticks: u64, reset: bool) { + REAL_TIME.store(ticks, Ordering::Release); + if reset { + REAL_TIME_OFFSET.store(0, Ordering::Release); + } +} + +pub fn set_ticks(ticks: u64) { + MONOTONIC_TIME.store(ticks, Ordering::Release); + REAL_TIME_OFFSET.store(ticks, Ordering::Release); } diff --git a/kernel/src/arch/i686/mod.rs b/kernel/src/arch/i686/mod.rs index 14b235b9..f3fd5721 100644 --- a/kernel/src/arch/i686/mod.rs +++ b/kernel/src/arch/i686/mod.rs @@ -42,7 +42,7 @@ mod peripherals; use crate::{ arch::x86::{ intrinsics::IoPortAccess, - peripherals::{i8253::I8253, ps2::PS2Controller}, + peripherals::{i8253::I8253, ps2::PS2Controller, rtc::Rtc}, ISA_IRQ_OFFSET, }, fs::{Initrd, INITRD_DATA}, @@ -241,6 +241,9 @@ impl I686 { if let Err(error) = PS2Controller::setup() { log::error!("Could not initialize PS/2 Controller: {error:?}"); } + if let Err(error) = Rtc::setup() { + log::error!("RTC init error: {error:?}"); + } // Setup text framebuffer // TODO check if video mode is set from boot info diff --git a/kernel/src/arch/x86/peripherals/mod.rs b/kernel/src/arch/x86/peripherals/mod.rs index aa76d564..eb14817c 100644 --- a/kernel/src/arch/x86/peripherals/mod.rs +++ b/kernel/src/arch/x86/peripherals/mod.rs @@ -1,5 +1,5 @@ pub mod i8253; pub mod i8259; pub mod ps2; -// pub mod rtc; +pub mod rtc; pub mod serial; diff --git a/kernel/src/arch/x86/peripherals/rtc.rs b/kernel/src/arch/x86/peripherals/rtc.rs index 8003991a..215fa474 100644 --- a/kernel/src/arch/x86/peripherals/rtc.rs +++ b/kernel/src/arch/x86/peripherals/rtc.rs @@ -1,19 +1,16 @@ -use abi::{error::Error, time::SystemTime}; +use abi::error::Error; +use alloc::sync::Arc; use device_api::{ + device::Device, interrupt::{InterruptHandler, Irq}, - timer::RealTimeProviderDevice, - Device, }; use kernel_arch::{Architecture, ArchitectureImpl}; -use libk_device::{external_interrupt_controller, register_real_time_provider}; +use libk::{device::external_interrupt_controller, time}; use libk_util::sync::IrqSafeSpinlock; -use crate::{ - arch::x86::{ - intrinsics::{io_wait, IoPort, IoPortAccess}, - ISA_IRQ_OFFSET, - }, - device::timer::GLOBAL_TIME, +use crate::arch::x86::{ + intrinsics::{io_wait, IoPort, IoPortAccess}, + ISA_IRQ_OFFSET, }; const NMI_DISABLE: u8 = 1 << 7; @@ -130,13 +127,13 @@ impl Inner { } impl InterruptHandler for Rtc { - fn handle_irq(&'static self, _vector: Option) -> bool { + fn handle_irq(self: Arc, _vector: Option) -> bool { let mut inner = self.inner.lock(); if inner.counter == 0 { let time = inner.read_date_time(); inner.last_timestamp = Some(time); - GLOBAL_TIME.update_from_rtc(time.into(), false); + time::set_real_time(time.to_ticks(), true); } inner.read_reg(CMOS_REG_STATUS_C); @@ -146,38 +143,27 @@ impl InterruptHandler for Rtc { } true } + + fn display_name(&self) -> &str { + "x86 RTC IRQ" + } } impl Device for Rtc { - unsafe fn init(&'static self) -> Result<(), Error> { - register_real_time_provider(self); - Ok(()) - } - - unsafe fn init_irq(&'static self) -> Result<(), Error> { + unsafe fn init_irq(self: Arc) -> Result<(), Error> { let irq = Irq::External(ISA_IRQ_OFFSET + 8); - let intc = external_interrupt_controller(); + let intc = external_interrupt_controller()?; self.inner.lock().setup_irq(); - intc.register_irq(irq, Default::default(), self)?; + intc.register_irq(irq, Default::default(), self.clone())?; intc.enable_irq(irq)?; Ok(()) } - fn display_name(&self) -> &'static str { + fn display_name(&self) -> &str { "x86 RTC" } } -impl RealTimeProviderDevice for Rtc { - fn real_timestamp(&self) -> Result { - self.inner - .lock() - .last_timestamp - .map(Into::into) - .ok_or(Error::InvalidOperation) - } -} - impl Rtc { const fn new() -> Self { Self { @@ -189,30 +175,32 @@ impl Rtc { }), } } + + pub fn setup() -> Result, Error> { + let this = Arc::new(Self::new()); + unsafe { this.clone().init_irq() }?; + Ok(this) + } } -impl From for SystemTime { - fn from(value: DateTime) -> Self { +impl DateTime { + pub fn to_ticks(self) -> u64 { let date = chrono::NaiveDate::from_ymd_opt( - 2000 + value.year as i32, - value.month as u32, - value.day_of_month as u32, + 2000 + self.year as i32, + self.month as u32, + self.day_of_month as u32, ) .unwrap(); let time = chrono::NaiveTime::from_hms_opt( - value.hours as u32, - value.minutes as u32, - value.seconds as u32, + self.hours as u32, + self.minutes as u32, + self.seconds as u32, ) .unwrap(); let seconds = chrono::NaiveDateTime::new(date, time) .signed_duration_since(chrono::NaiveDateTime::UNIX_EPOCH) .num_seconds() as u64; - Self { - seconds, - nanoseconds: 0, - } + + seconds * time::TICKS_PER_SEC } } - -pub static RTC: Rtc = Rtc::new(); diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index be46ee2c..8e68d9c2 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -50,7 +50,7 @@ mod smp; mod syscall; use crate::{ - arch::x86::peripherals::{i8253::I8253, ps2::PS2Controller}, + arch::x86::peripherals::{i8253::I8253, ps2::PS2Controller, rtc::Rtc}, device::display::linear_fb::LinearFramebuffer, fs::{Initrd, INITRD_DATA}, }; @@ -388,10 +388,9 @@ impl X86_64 { if let Err(error) = PS2Controller::setup() { log::error!("PS/2 controller init error: {error:?}"); } - - // RTC.init_irq()?; - - // device::register_device(&PS2); + if let Err(error) = Rtc::setup() { + log::error!("RTC init error: {error:?}"); + } PciBusManager::setup_bus_devices()?; } diff --git a/kernel/src/syscall/imp/mod.rs b/kernel/src/syscall/imp/mod.rs index 7bfb1068..226e0bc4 100644 --- a/kernel/src/syscall/imp/mod.rs +++ b/kernel/src/syscall/imp/mod.rs @@ -16,7 +16,11 @@ use abi::{ process::{ExecveOptions, ProcessId}, time::{ClockType, SystemTime}, }; -use libk::{module, random, task::thread::Thread, time::monotonic_time}; +use libk::{ + module, random, + task::thread::Thread, + time::{monotonic_time, real_time}, +}; use libk_mm::phys; use crate::fs; @@ -55,7 +59,7 @@ pub(crate) fn unmount(_options: &UnmountOptions) -> Result<(), Error> { pub(crate) fn get_clock(ty: ClockType, value: &mut MaybeUninit) -> Result<(), Error> { let time = match ty { - ClockType::RealTime => todo!(), + ClockType::RealTime => real_time(), ClockType::Monotonic => monotonic_time(), }; value.write(time);