x86: re-enable RTC

This commit is contained in:
Mark Poliakov 2024-12-10 12:17:52 +02:00
parent 56fbcefa80
commit 8db9c08224
6 changed files with 80 additions and 65 deletions

View File

@ -2,23 +2,44 @@ use core::sync::atomic::{AtomicU64, Ordering};
use yggdrasil_abi::time::SystemTime; 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 { static MONOTONIC_TIME: AtomicU64 = AtomicU64::new(0);
let millis = MONOTONIC_MILLIS.load(Ordering::Acquire); static REAL_TIME_OFFSET: AtomicU64 = AtomicU64::new(0);
let nanoseconds = (millis % 1000) * 1000000; static REAL_TIME: AtomicU64 = AtomicU64::new(0);
let seconds = millis / 1000;
#[inline]
fn make_time(ticks: u64) -> SystemTime {
SystemTime { SystemTime {
seconds, seconds: ticks / TICKS_PER_SEC,
nanoseconds, nanoseconds: (ticks % TICKS_PER_SEC) * TIME_RESOLUTION_NS,
} }
} }
pub fn add_ticks(ticks: u64) -> u64 { pub fn real_time() -> SystemTime {
MONOTONIC_MILLIS.fetch_add(ticks, Ordering::Release) make_time(REAL_TIME.load(Ordering::Acquire) + REAL_TIME_OFFSET.load(Ordering::Relaxed))
} }
pub fn set_ticks(ticks: u64) -> u64 { pub fn monotonic_time() -> SystemTime {
MONOTONIC_MILLIS.swap(ticks, Ordering::Release) 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);
} }

View File

@ -42,7 +42,7 @@ mod peripherals;
use crate::{ use crate::{
arch::x86::{ arch::x86::{
intrinsics::IoPortAccess, intrinsics::IoPortAccess,
peripherals::{i8253::I8253, ps2::PS2Controller}, peripherals::{i8253::I8253, ps2::PS2Controller, rtc::Rtc},
ISA_IRQ_OFFSET, ISA_IRQ_OFFSET,
}, },
fs::{Initrd, INITRD_DATA}, fs::{Initrd, INITRD_DATA},
@ -241,6 +241,9 @@ impl I686 {
if let Err(error) = PS2Controller::setup() { if let Err(error) = PS2Controller::setup() {
log::error!("Could not initialize PS/2 Controller: {error:?}"); log::error!("Could not initialize PS/2 Controller: {error:?}");
} }
if let Err(error) = Rtc::setup() {
log::error!("RTC init error: {error:?}");
}
// Setup text framebuffer // Setup text framebuffer
// TODO check if video mode is set from boot info // TODO check if video mode is set from boot info

View File

@ -1,5 +1,5 @@
pub mod i8253; pub mod i8253;
pub mod i8259; pub mod i8259;
pub mod ps2; pub mod ps2;
// pub mod rtc; pub mod rtc;
pub mod serial; pub mod serial;

View File

@ -1,19 +1,16 @@
use abi::{error::Error, time::SystemTime}; use abi::error::Error;
use alloc::sync::Arc;
use device_api::{ use device_api::{
device::Device,
interrupt::{InterruptHandler, Irq}, interrupt::{InterruptHandler, Irq},
timer::RealTimeProviderDevice,
Device,
}; };
use kernel_arch::{Architecture, ArchitectureImpl}; 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 libk_util::sync::IrqSafeSpinlock;
use crate::{ use crate::arch::x86::{
arch::x86::{ intrinsics::{io_wait, IoPort, IoPortAccess},
intrinsics::{io_wait, IoPort, IoPortAccess}, ISA_IRQ_OFFSET,
ISA_IRQ_OFFSET,
},
device::timer::GLOBAL_TIME,
}; };
const NMI_DISABLE: u8 = 1 << 7; const NMI_DISABLE: u8 = 1 << 7;
@ -130,13 +127,13 @@ impl Inner {
} }
impl InterruptHandler for Rtc { impl InterruptHandler for Rtc {
fn handle_irq(&'static self, _vector: Option<usize>) -> bool { fn handle_irq(self: Arc<Self>, _vector: Option<usize>) -> bool {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
if inner.counter == 0 { if inner.counter == 0 {
let time = inner.read_date_time(); let time = inner.read_date_time();
inner.last_timestamp = Some(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); inner.read_reg(CMOS_REG_STATUS_C);
@ -146,38 +143,27 @@ impl InterruptHandler for Rtc {
} }
true true
} }
fn display_name(&self) -> &str {
"x86 RTC IRQ"
}
} }
impl Device for Rtc { impl Device for Rtc {
unsafe fn init(&'static self) -> Result<(), Error> { unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
register_real_time_provider(self);
Ok(())
}
unsafe fn init_irq(&'static self) -> Result<(), Error> {
let irq = Irq::External(ISA_IRQ_OFFSET + 8); let irq = Irq::External(ISA_IRQ_OFFSET + 8);
let intc = external_interrupt_controller(); let intc = external_interrupt_controller()?;
self.inner.lock().setup_irq(); self.inner.lock().setup_irq();
intc.register_irq(irq, Default::default(), self)?; intc.register_irq(irq, Default::default(), self.clone())?;
intc.enable_irq(irq)?; intc.enable_irq(irq)?;
Ok(()) Ok(())
} }
fn display_name(&self) -> &'static str { fn display_name(&self) -> &str {
"x86 RTC" "x86 RTC"
} }
} }
impl RealTimeProviderDevice for Rtc {
fn real_timestamp(&self) -> Result<SystemTime, Error> {
self.inner
.lock()
.last_timestamp
.map(Into::into)
.ok_or(Error::InvalidOperation)
}
}
impl Rtc { impl Rtc {
const fn new() -> Self { const fn new() -> Self {
Self { Self {
@ -189,30 +175,32 @@ impl Rtc {
}), }),
} }
} }
pub fn setup() -> Result<Arc<Self>, Error> {
let this = Arc::new(Self::new());
unsafe { this.clone().init_irq() }?;
Ok(this)
}
} }
impl From<DateTime> for SystemTime { impl DateTime {
fn from(value: DateTime) -> Self { pub fn to_ticks(self) -> u64 {
let date = chrono::NaiveDate::from_ymd_opt( let date = chrono::NaiveDate::from_ymd_opt(
2000 + value.year as i32, 2000 + self.year as i32,
value.month as u32, self.month as u32,
value.day_of_month as u32, self.day_of_month as u32,
) )
.unwrap(); .unwrap();
let time = chrono::NaiveTime::from_hms_opt( let time = chrono::NaiveTime::from_hms_opt(
value.hours as u32, self.hours as u32,
value.minutes as u32, self.minutes as u32,
value.seconds as u32, self.seconds as u32,
) )
.unwrap(); .unwrap();
let seconds = chrono::NaiveDateTime::new(date, time) let seconds = chrono::NaiveDateTime::new(date, time)
.signed_duration_since(chrono::NaiveDateTime::UNIX_EPOCH) .signed_duration_since(chrono::NaiveDateTime::UNIX_EPOCH)
.num_seconds() as u64; .num_seconds() as u64;
Self {
seconds, seconds * time::TICKS_PER_SEC
nanoseconds: 0,
}
} }
} }
pub static RTC: Rtc = Rtc::new();

View File

@ -50,7 +50,7 @@ mod smp;
mod syscall; mod syscall;
use crate::{ use crate::{
arch::x86::peripherals::{i8253::I8253, ps2::PS2Controller}, arch::x86::peripherals::{i8253::I8253, ps2::PS2Controller, rtc::Rtc},
device::display::linear_fb::LinearFramebuffer, device::display::linear_fb::LinearFramebuffer,
fs::{Initrd, INITRD_DATA}, fs::{Initrd, INITRD_DATA},
}; };
@ -388,10 +388,9 @@ impl X86_64 {
if let Err(error) = PS2Controller::setup() { if let Err(error) = PS2Controller::setup() {
log::error!("PS/2 controller init error: {error:?}"); log::error!("PS/2 controller init error: {error:?}");
} }
if let Err(error) = Rtc::setup() {
// RTC.init_irq()?; log::error!("RTC init error: {error:?}");
}
// device::register_device(&PS2);
PciBusManager::setup_bus_devices()?; PciBusManager::setup_bus_devices()?;
} }

View File

@ -16,7 +16,11 @@ use abi::{
process::{ExecveOptions, ProcessId}, process::{ExecveOptions, ProcessId},
time::{ClockType, SystemTime}, 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 libk_mm::phys;
use crate::fs; 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<SystemTime>) -> Result<(), Error> { pub(crate) fn get_clock(ty: ClockType, value: &mut MaybeUninit<SystemTime>) -> Result<(), Error> {
let time = match ty { let time = match ty {
ClockType::RealTime => todo!(), ClockType::RealTime => real_time(),
ClockType::Monotonic => monotonic_time(), ClockType::Monotonic => monotonic_time(),
}; };
value.write(time); value.write(time);