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;
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);
}

View File

@ -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

View File

@ -1,5 +1,5 @@
pub mod i8253;
pub mod i8259;
pub mod ps2;
// pub mod rtc;
pub mod rtc;
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::{
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::{
use crate::arch::x86::{
intrinsics::{io_wait, IoPort, IoPortAccess},
ISA_IRQ_OFFSET,
},
device::timer::GLOBAL_TIME,
};
const NMI_DISABLE: u8 = 1 << 7;
@ -130,13 +127,13 @@ impl Inner {
}
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();
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<Self>) -> 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<SystemTime, Error> {
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<Arc<Self>, Error> {
let this = Arc::new(Self::new());
unsafe { this.clone().init_irq() }?;
Ok(this)
}
}
impl From<DateTime> 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();

View File

@ -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()?;
}

View File

@ -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<SystemTime>) -> Result<(), Error> {
let time = match ty {
ClockType::RealTime => todo!(),
ClockType::RealTime => real_time(),
ClockType::Monotonic => monotonic_time(),
};
value.write(time);