x86: re-enable RTC
This commit is contained in:
parent
56fbcefa80
commit
8db9c08224
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
|
||||||
|
@ -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()?;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user